/****************************************************************************** * Copyright (c) 2005 BEA Systems, Inc. * 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: * Konstantin Komissarchik - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.core.classpath; import java.io.StringReader; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jdt.core.IClasspathAttribute; import org.jboss.tools.common.core.CommonCorePlugin; import org.jboss.tools.common.core.Messages; import org.osgi.service.prefs.BackingStoreException; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; /** * @author <a href="mailto:kosta@bea.com">Konstantin Komissarchik</a> */ public final class ClasspathDecorationsManager { private static final String CLASSPATH_PREFERENCES = "classpathPreferences"; //$NON-NLS-1$ private static final String SEPARATOR = System .getProperty("line.separator"); //$NON-NLS-1$ private final HashMap decorations; public ClasspathDecorationsManager() { this.decorations = read(); } private IEclipsePreferences getEclipsePreferences() { IEclipsePreferences node = (IEclipsePreferences) Platform .getPreferencesService().getRootNode() .node(InstanceScope.SCOPE).node(CommonCorePlugin.PLUGIN_ID); return node; } private String getPreferences() { return getEclipsePreferences().get(CLASSPATH_PREFERENCES, null); } public ClasspathDecorations getDecorations(final String key, final String entry) { final HashMap submap = (HashMap) this.decorations.get(key); if (submap == null) { return null; } return (ClasspathDecorations) submap.get(entry); } public void setDecorations(final String key, final String entry, final ClasspathDecorations dec) { HashMap submap = (HashMap) this.decorations.get(key); if (submap == null) { submap = new HashMap(); this.decorations.put(key, submap); } submap.put(entry, dec); } public void clearAllDecorations(final String key) { this.decorations.remove(key); } public void save() { StringBuffer buffer = new StringBuffer(); buffer.append("<classpath>"); //$NON-NLS-1$ buffer.append(SEPARATOR); for (Iterator itr1 = decorations.entrySet().iterator(); itr1.hasNext();) { final Map.Entry entry1 = (Map.Entry) itr1.next(); final Map submap = (Map) entry1.getValue(); buffer.append(" <container id=\""); //$NON-NLS-1$ buffer.append((String) entry1.getKey()); buffer.append("\">"); //$NON-NLS-1$ buffer.append(SEPARATOR); for (Iterator itr2 = submap.entrySet().iterator(); itr2.hasNext();) { final Map.Entry entry2 = (Map.Entry) itr2.next(); final ClasspathDecorations dec = (ClasspathDecorations) entry2 .getValue(); buffer.append(" <entry id=\""); //$NON-NLS-1$ buffer.append((String) entry2.getKey()); buffer.append("\">"); //$NON-NLS-1$ buffer.append(SEPARATOR); String src = ""; //$NON-NLS-1$ if (dec.getSourceAttachmentPath() != null) { src = dec.getSourceAttachmentPath().toString(); } buffer.append(" <source-attachment-path>"); //$NON-NLS-1$ buffer.append(src); buffer.append("</source-attachment-path>"); //$NON-NLS-1$ buffer.append(SEPARATOR); if (dec.getSourceAttachmentRootPath() != null) { buffer.append(" <source-attachment-root-path>"); //$NON-NLS-1$ buffer.append(dec.getSourceAttachmentRootPath().toString()); buffer.append("</source-attachment-root-path>"); //$NON-NLS-1$ buffer.append(SEPARATOR); } final IClasspathAttribute[] attrs = dec.getExtraAttributes(); for (int i = 0; i < attrs.length; i++) { final IClasspathAttribute attr = attrs[i]; buffer.append(" <attribute name=\""); //$NON-NLS-1$ buffer.append(attr.getName()); buffer.append("\">"); //$NON-NLS-1$ buffer.append(attr.getValue()); buffer.append("</attribute>"); //$NON-NLS-1$ buffer.append(SEPARATOR); } buffer.append(" </entry>"); //$NON-NLS-1$ buffer.append(SEPARATOR); } buffer.append(" </container>"); //$NON-NLS-1$ buffer.append(SEPARATOR); } buffer.append("</classpath>"); //$NON-NLS-1$ buffer.append(SEPARATOR); IEclipsePreferences ep = getEclipsePreferences(); ep.put(CLASSPATH_PREFERENCES, buffer.toString()); try { ep.flush(); } catch (BackingStoreException e) { String msg = Messages.ClasspathDecorationsManager_unexpected_exception; CommonCorePlugin.getDefault().logError(msg, e); } } private HashMap read() { final HashMap map = new HashMap(); String prefs = getPreferences(); if (prefs == null || prefs.length() <= 0) return map; Element root = null; try { final DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); final DocumentBuilder docbuilder = factory.newDocumentBuilder(); StringReader reader = new StringReader(prefs); InputSource source = new InputSource(reader); root = docbuilder.parse(source).getDocumentElement(); } catch (Exception e) { String msg = Messages.ClasspathDecorationsManager_unexpected_exception; CommonCorePlugin.getDefault().logError(msg, e); return map; } for (Iterator itr1 = elements(root, "container"); itr1.hasNext();) //$NON-NLS-1$ { final Element e1 = (Element) itr1.next(); final String cid = e1.getAttribute("id"); //$NON-NLS-1$ final HashMap submap = new HashMap(); map.put(cid, submap); for (Iterator itr2 = elements(e1, "entry"); itr2.hasNext();) //$NON-NLS-1$ { final Element e2 = (Element) itr2.next(); final String eid = e2.getAttribute("id"); //$NON-NLS-1$ final ClasspathDecorations dec = new ClasspathDecorations(); submap.put(eid, dec); for (Iterator itr3 = elements(e2); itr3.hasNext();) { final Element e3 = (Element) itr3.next(); final String n = e3.getNodeName(); String text = text(e3); if (text != null) { if (n.equals("source-attachment-path")) //$NON-NLS-1$ { dec.setSourceAttachmentPath(new Path(text(e3))); } else if (n.equals("source-attachment-root-path")) //$NON-NLS-1$ { dec.setSourceAttachmentRootPath(new Path(text(e3))); } } if (n.equals("attribute")) //$NON-NLS-1$ { final String name = e3.getAttribute("name"); //$NON-NLS-1$ dec.addExtraAttribute(name, text(e3)); } } } } return map; } private static String text(final Element el) { final NodeList nodes = el.getChildNodes(); String str = null; StringBuffer buf = null; for (int i = 0, n = nodes.getLength(); i < n; i++) { final Node node = nodes.item(i); if (node.getNodeType() == Node.TEXT_NODE) { final String val = node.getNodeValue(); if (buf != null) { buf.append(val); } else if (str != null) { buf = new StringBuffer(); buf.append(str); buf.append(val); str = null; } else { str = val; } } } if (buf != null) { return buf.toString(); } return str; } private static Iterator elements(final Element el, final String name) { return new ElementsIterator(el, name); } private static Iterator elements(final Element el) { return new ElementsIterator(el, null); } private static final class ElementsIterator implements Iterator { private final NodeList nodes; private final int length; private final String name; private int position; private Element element; public ElementsIterator(final Element parent, final String name) { this.nodes = parent.getChildNodes(); this.length = nodes.getLength(); this.position = -1; this.name = name; advance(); } private void advance() { this.element = null; this.position++; for (; this.position < this.length && this.element == null; this.position++) { final Node node = this.nodes.item(this.position); if (node.getNodeType() == Node.ELEMENT_NODE && (this.name == null || node.getNodeName().equals( this.name))) { this.element = (Element) node; } } } public boolean hasNext() { return (this.element != null); } public Object next() { final Element el = this.element; if (el == null) { throw new NoSuchElementException(); } advance(); return el; } public void remove() { throw new UnsupportedOperationException(); } } }