blob: ba64805294a39a74750a0e368d56e75df0f25d63 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.help.ui.internal.views;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Observable;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.help.ui.internal.HelpUIPlugin;
import org.eclipse.help.ui.internal.IHelpUIConstants;
import org.eclipse.help.ui.internal.Messages;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class EngineDescriptorManager extends Observable implements IHelpUIConstants {
private ArrayList<EngineDescriptor> descriptors;
private EngineTypeDescriptor[] engineTypes;
private static final String USER_FILE = "userSearches.xml"; //$NON-NLS-1$
private static final String ATT_ENGINE_TYPE_ID = "engineTypeId"; //$NON-NLS-1$
public static class DescriptorEvent {
private EngineDescriptor desc;
private int kind;
public DescriptorEvent(EngineDescriptor desc, int kind) {
this.desc = desc;
this.kind = kind;
}
public EngineDescriptor getDescriptor() {
return desc;
}
public int getKind() {
return kind;
}
}
public EngineDescriptorManager() {
descriptors = new ArrayList<>();
load();
}
public void add(EngineDescriptor desc) {
descriptors.add(desc);
this.setChanged();
this.notifyObservers(new DescriptorEvent(desc, ADD));
}
public void remove(EngineDescriptor desc) {
descriptors.remove(desc);
this.setChanged();
this.notifyObservers(new DescriptorEvent(desc, REMOVE));
}
public void notifyPropertyChange(EngineDescriptor desc) {
this.setChanged();
this.notifyObservers(new DescriptorEvent(desc, CHANGE));
}
public EngineDescriptor[] getDescriptors() {
return descriptors.toArray(new EngineDescriptor[descriptors.size()]);
}
public EngineDescriptor findEngine(String engineId) {
for (int i=0; i<descriptors.size(); i++) {
EngineDescriptor desc = descriptors.get(i);
if (desc.getId().equals(engineId))
return desc;
}
return null;
}
public EngineTypeDescriptor[] getEngineTypes() {
return engineTypes;
}
public void save() {
IPath stateLoc = HelpUIPlugin.getDefault().getStateLocation();
String fileName = stateLoc.append(USER_FILE).toOSString();
FileOutputStream fos = null;
OutputStreamWriter osw = null;
try {
fos = new FileOutputStream(fileName);
osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
PrintWriter writer = new PrintWriter(osw);
writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); //$NON-NLS-1$
writer.println("<engines>"); //$NON-NLS-1$
for (int i = 0; i < descriptors.size(); i++) {
EngineDescriptor desc = descriptors.get(i);
if (desc.isUserDefined()) {
save(writer, desc);
}
}
writer.println("</engines>"); //$NON-NLS-1$
writer.flush();
}
catch (IOException e) {
HelpUIPlugin.logError(Messages.EngineDescriptorManager_errorSaving, e);
}
finally {
if (osw!=null) {
try {
osw.close();
}
catch (IOException e) {
}
}
if (fos!=null) {
try {
fos.close();
}
catch (IOException e) {
}
}
}
}
public void load() {
loadFromExtensionRegistry();
IPath stateLoc = HelpUIPlugin.getDefault().getStateLocation();
String fileName = stateLoc.append(USER_FILE).toOSString();
try {
load(fileName);
}
catch (IOException e) {
HelpUIPlugin.logError(Messages.EngineDescriptorManager_errorLoading, e);
}
}
private void loadFromExtensionRegistry() {
IConfigurationElement[] elements = Platform.getExtensionRegistry()
.getConfigurationElementsFor(ENGINE_EXP_ID);
Hashtable<String, EngineTypeDescriptor> engineTypes = loadEngineTypes(elements);
for (int i = 0; i < elements.length; i++) {
IConfigurationElement element = elements[i];
if (element.getName().equals(TAG_ENGINE)) {
EngineDescriptor desc = new EngineDescriptor(element);
String engineId = desc.getEngineTypeId();
if (engineId != null) {
EngineTypeDescriptor etdesc = engineTypes.get(engineId);
if (etdesc != null) {
desc.setEngineType(etdesc);
descriptors.add(desc);
}
}
}
}
}
private Hashtable<String, EngineTypeDescriptor> loadEngineTypes(IConfigurationElement[] elements) {
Hashtable<String, EngineTypeDescriptor> result = new Hashtable<>();
ArrayList<EngineTypeDescriptor> list = new ArrayList<>();
for (int i = 0; i < elements.length; i++) {
IConfigurationElement element = elements[i];
if (element.getName().equals("engineType")) { //$NON-NLS-1$
EngineTypeDescriptor etdesc = new EngineTypeDescriptor(element);
String id = etdesc.getId();
if (id != null) {
list.add(etdesc);
result.put(etdesc.getId(), etdesc);
}
}
}
engineTypes = list.toArray(new EngineTypeDescriptor[list.size()]);
return result;
}
public void load(Reader r) {
Document document = null;
try {
DocumentBuilder parser = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
// parser.setProcessNamespace(true);
document = parser.parse(new InputSource(r));
// Strip out any comments first
Node root = document.getFirstChild();
while (root.getNodeType() == Node.COMMENT_NODE) {
document.removeChild(root);
root = document.getFirstChild();
}
load(document, (Element) root);
} catch (ParserConfigurationException e) {
// ignore
} catch (IOException e) {
// ignore
} catch (SAXException e) {
// ignore
}
}
/*
* (non-Javadoc) Method declared on IDialogSettings.
*/
public void load(String fileName) throws IOException {
File file = new File(fileName);
if (!file.exists()) return;
FileInputStream stream = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(
stream, StandardCharsets.UTF_8));
load(reader);
reader.close();
}
private void load(Document doc, Element root) {
NodeList engines = root.getElementsByTagName(TAG_ENGINE);
for (int i=0; i<engines.getLength(); i++) {
Node node = engines.item(i);
loadUserEntry(node);
}
}
private void loadUserEntry(Node node) {
EngineDescriptor edesc = new EngineDescriptor(this);
String id = getAttribute(node, ATT_ID);
String engineTypeId = getAttribute(node, ATT_ENGINE_TYPE_ID);
EngineTypeDescriptor etdesc = findEngineType(engineTypeId);
String label = getAttribute(node, ATT_LABEL);
String desc = getDescription(node);
if (etdesc == null)
return;
edesc.setEngineType(etdesc);
edesc.setUserDefined(true);
edesc.setId(id);
edesc.setLabel(label);
edesc.setDescription(desc);
descriptors.add(edesc);
}
public String computeNewId(String typeId) {
ArrayList<Integer> used = new ArrayList<>();
for (int i=0; i<descriptors.size(); i++) {
EngineDescriptor ed = descriptors.get(i);
if (!ed.isUserDefined()) continue;
String edTypeId = ed.getEngineTypeId();
if (typeId.equals(edTypeId)) {
String edId = ed.getId();
int loc = edId.lastIndexOf('.');
if (loc!= -1) {
String cvalue = edId.substring(loc+1);
int ivalue = Integer.parseInt(cvalue);
used.add(Integer.valueOf(ivalue));
}
}
}
for (int i=1; i<Integer.MAX_VALUE; i++) {
if (!isUsed(i, used)) {
return typeId+"."+"user."+i; //$NON-NLS-1$ //$NON-NLS-2$
}
}
return typeId;
}
private boolean isUsed(int value, ArrayList<Integer> used) {
for (int i=0; i<used.size(); i++) {
Integer iv = used.get(i);
if (iv.intValue()==value)
return true;
}
return false;
}
private String getDescription(Node node) {
NodeList list = ((Element)node).getElementsByTagName(TAG_DESC);
if (list.getLength()==1) {
Node desc = list.item(0);
NodeList children = desc.getChildNodes();
for (int i=0; i<children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType()==Node.TEXT_NODE) {
String text = child.getNodeValue();
return text.trim();
}
}
}
return null;
}
private void save(PrintWriter writer, EngineDescriptor desc) {
String indent = " "; //$NON-NLS-1$
String attIndent = indent + indent;
writer.print(indent);
writer.println("<engine "); //$NON-NLS-1$
saveAttribute(writer, attIndent, "id", desc.getId()); //$NON-NLS-1$
saveAttribute(writer, attIndent, ATT_ENGINE_TYPE_ID, desc.getEngineTypeId());
saveAttribute(writer, attIndent, ATT_LABEL, desc.getLabel());
writer.println(">"); //$NON-NLS-1$
saveDescription(writer, indent+indent, desc.getDescription());
writer.print(indent);
writer.println("</engine>"); //$NON-NLS-1$
}
private String getAttribute(Node node, String name) {
Node att = node.getAttributes().getNamedItem(name);
if (att!=null)
return att.getNodeValue();
return null;
}
private void saveAttribute(PrintWriter writer, String indent, String name, String value) {
if (value==null)
return;
writer.print(indent);
writer.print(name);
writer.print("=\""); //$NON-NLS-1$
writer.print(value);
writer.println("\""); //$NON-NLS-1$
}
private void saveDescription(PrintWriter writer, String indent, String desc) {
if (desc==null)
return;
writer.print(indent);
writer.println("<description>"); //$NON-NLS-1$
writer.println(desc);
writer.print(indent);
writer.println("</description>"); //$NON-NLS-1$
}
private EngineTypeDescriptor findEngineType(String id) {
if (id == null)
return null;
for (int i = 0; i < engineTypes.length; i++) {
EngineTypeDescriptor etd = engineTypes[i];
if (etd.getId().equals(id))
return etd;
}
return null;
}
}