/****************************************************************************** * 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.eclipse.jst.common.jdt.internal.classpath; import java.io.BufferedReader; import java.io.BufferedWriter; 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.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.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IClasspathAttribute; import org.eclipse.jst.common.frameworks.CommonFrameworksPlugin; 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 final File f; private final HashMap decorations; public ClasspathDecorationsManager( final String plugin ) { final IWorkspace ws = ResourcesPlugin.getWorkspace(); final File wsdir = ws.getRoot().getLocation().toFile(); final File wsmdroot = new File( wsdir, ".metadata/.plugins" ); //$NON-NLS-1$ final File pmdroot = new File( wsmdroot, plugin ); this.f = new File( pmdroot, "classpath.decorations.xml" ); //$NON-NLS-1$ this.decorations = read(); } 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() { final File folder = this.f.getParentFile(); if( ! folder.exists() && ! folder.mkdirs() ) { return; } PrintWriter w = null; try { w = new PrintWriter( new BufferedWriter( new OutputStreamWriter( new FileOutputStream( this.f ), "UTF-8" ) ) ); //$NON-NLS-1$ w.println( "<classpath>" ); //$NON-NLS-1$ for( Iterator itr1 = decorations.entrySet().iterator(); itr1.hasNext(); ) { final Map.Entry entry1 = (Map.Entry) itr1.next(); final Map submap = (Map) entry1.getValue(); w.print( " <container id=\"" ); //$NON-NLS-1$ w.print( (String) entry1.getKey() ); w.println( "\">" ); //$NON-NLS-1$ for( Iterator itr2 = submap.entrySet().iterator(); itr2.hasNext(); ) { final Map.Entry entry2 = (Map.Entry) itr2.next(); final ClasspathDecorations dec = (ClasspathDecorations) entry2.getValue(); w.print( " <entry id=\"" ); //$NON-NLS-1$ w.print( (String) entry2.getKey() ); w.println( "\">" ); //$NON-NLS-1$ if( dec.getSourceAttachmentPath() != null ) { w.print( " <source-attachment-path>" ); //$NON-NLS-1$ w.print( dec.getSourceAttachmentPath().toString() ); w.println( "</source-attachment-path>" ); //$NON-NLS-1$ } if( dec.getSourceAttachmentRootPath() != null ) { w.print( " <source-attachment-root-path>" ); //$NON-NLS-1$ w.print( dec.getSourceAttachmentRootPath().toString() ); w.println( "</source-attachment-root-path>" ); //$NON-NLS-1$ } final IClasspathAttribute[] attrs = dec.getExtraAttributes(); for( int i = 0; i < attrs.length; i++ ) { final IClasspathAttribute attr = attrs[ i ]; w.print( " <attribute name=\"" ); //$NON-NLS-1$ w.print( attr.getName() ); w.print( "\">" ); //$NON-NLS-1$ w.print( attr.getValue() ); w.println( "</attribute>" ); //$NON-NLS-1$ } w.println( " </entry>" ); //$NON-NLS-1$ } w.println( " </container>" ); //$NON-NLS-1$ } w.println( "</classpath>" ); //$NON-NLS-1$ } catch( IOException e ) { CommonFrameworksPlugin.log( e ); } finally { if(null != w){ w.close(); } } } private HashMap read() { final HashMap map = new HashMap(); if( ! this.f.exists() ) return map; BufferedReader in = null; Element root = null; try { final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); final DocumentBuilder docbuilder = factory.newDocumentBuilder(); in = new BufferedReader(new InputStreamReader( new FileInputStream( f.getPath()),"UTF-8")); //$NON-NLS-1$ root = docbuilder.parse( new InputSource(in)).getDocumentElement(); } catch( Exception e ) { CommonFrameworksPlugin.log( e ); return map; } finally { if( in != null ) { try { in.close(); } catch( IOException e ) {} } } 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(); 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 ) ) ); } else 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(); } } }