/******************************************************************************* * 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(new Integer(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; } }