Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: javax/ide/extension/spi/ExtensionVisitor.java


1   package javax.ide.extension.spi;
2   
3   import java.net.URI;
4   
5   import java.util.ArrayList;
6   import java.util.Collection;
7   import java.util.StringTokenizer;
8   import java.util.logging.Level;
9   
10  import javax.ide.extension.ElementContext;
11  import javax.ide.extension.ElementEndContext;
12  import javax.ide.extension.ElementName;
13  import javax.ide.extension.ElementStartContext;
14  import javax.ide.extension.ElementVisitor;
15  import javax.ide.extension.ElementVisitorFactory;
16  import javax.ide.extension.Extension;
17  import javax.ide.extension.ExtensionHook;
18  import javax.ide.extension.I18NStringVisitor;
19  
20  /**
21   * Visitor for the root JSR-198 extension element. This is the "entry point"
22   * for all manifest processing.
23   */
24  public abstract class ExtensionVisitor extends BaseExtensionVisitor
25  {
26  
27    private static final ElementName NAME = 
28      new ElementName( ExtensionHook.MANIFEST_XMLNS, "name" );
29    private static final ElementName OWNER =
30      new ElementName( ExtensionHook.MANIFEST_XMLNS, "owner" );
31    private static final ElementName HOOKS =
32      new ElementName( ExtensionHook.MANIFEST_XMLNS, "hooks" );
33    private static final ElementName CLASSPATHS = 
34      new ElementName( ExtensionHook.MANIFEST_XMLNS, "classpaths" );
35    private static final ElementName  CLASSPATH =
36      new ElementName( ExtensionHook.MANIFEST_XMLNS, "classpath" );
37  
38    private ElementVisitor _nameVisitor = createNameVisitor();
39    private ElementVisitor _ownerVisitor = createOwnerVisitor();
40    private ElementVisitor _hooksVisitor = createHooksVisitor();
41    private ElementVisitor _classpathsVisitor = createClasspathsVisitor();
42    private ElementVisitor _classpathVisitor = createClasspathVisitor();
43    private ElementVisitor _dependenciesVisitor = createDependenciesVisitor();
44   
45    /**
46     * The key for the current <tt>ExtensionSource</tt> instance in the scope
47     * data map.
48     */
49    public static final String KEY_EXTENSION_SOURCE = "extSource";
50    
51    /**
52     * The key for the <tt>ClassLoader</tt> to be used to when looking up classes
53     * for the current extension. This is used by I18NStringVisitor / 
54     * I18NCharVisitor. If no classloader is in the scope map, the context
55     * classloader of the current thread is used.
56     */
57    public static final String KEY_CLASSLOADER = "classLoader";
58    
59    private Collection _extensions = new ArrayList();
60    
61    private final ElementVisitorFactory _hookVisitorFactory;
62    
63    protected ExtensionVisitor( ElementVisitorFactory hookFactory )
64    {
65      _hookVisitorFactory = hookFactory;
66    }
67    
68    public final Collection getExtensions()
69    {
70      return _extensions;
71    }
72      
73    public final void start( ElementStartContext context )
74    {
75      Extension ext = processExtension( context );
76      if ( ext == null )
77      {
78        return;
79      }
80      
81      context.getScopeData().put( ExtensionVisitor.KEY_CLASSLOADER, 
82        getClassLoader( ext ) );
83      
84      String rsbundleClass = context.getAttributeValue( "rsbundle-class" );
85      if ( rsbundleClass != null && 
86        ( rsbundleClass = rsbundleClass.trim()) != "" )
87      {
88        context.getScopeData().put( ExtensionHook.KEY_RSBUNDLE_CLASS, 
89          rsbundleClass );
90      }
91      
92      context.registerChildVisitor( NAME, _nameVisitor );
93      context.registerChildVisitor( OWNER, _ownerVisitor );
94      context.registerChildVisitor( HOOKS, _hooksVisitor );
95      context.registerChildVisitor( CLASSPATHS, _classpathsVisitor );
96      context.registerChildVisitor( DependenciesVisitor.ELEMENT, 
97        _dependenciesVisitor );
98    }
99    
100   public final void end( ElementEndContext end )
101   {
102     _extensions.add( (Extension) end.getScopeData().get( ExtensionHook.KEY_EXTENSION ));
103   }
104   
105   
106   protected final DefaultExtension getExtension( ElementContext context )
107   {
108     return (DefaultExtension) context.getScopeData().get( 
109       ExtensionHook.KEY_EXTENSION );
110   }
111   
112   protected final ExtensionSource getSource( ElementContext context )
113   {
114     return (ExtensionSource) context.getScopeData().get(
115       KEY_EXTENSION_SOURCE );
116   }
117   
118   protected ElementVisitor createNameVisitor()
119   {
120     return new I18NStringVisitor() 
121     {
122       public void string( ElementContext context, String value )
123       {
124         getExtension( context ).setName( value );
125       }
126     };
127   }
128   
129   protected ElementVisitor createOwnerVisitor()
130   {
131     return new I18NStringVisitor()
132     {
133       public void string( ElementContext context, String value )
134       {
135         getExtension( context ).setOwner( value );
136       }
137     };
138   }
139 
140   protected ElementVisitor createClasspathsVisitor()
141   {
142     return new ClasspathsVisitor();
143   }
144   
145   protected ElementVisitor createClasspathVisitor()
146   {
147     return new ClasspathVisitor();
148   }
149   
150   protected ElementVisitor createHooksVisitor()
151   {
152     return new HooksVisitor();
153   }
154   
155   protected ElementVisitor createDependenciesVisitor()
156   {
157     return new DependenciesVisitor();
158   }
159   
160   private final class ClasspathsVisitor extends ElementVisitor
161   {
162     public void start( ElementStartContext context )
163     {
164       context.registerChildVisitor( CLASSPATH, _classpathVisitor );
165     }
166   }
167   
168   private final class ClasspathVisitor extends ElementVisitor
169   {
170     public void end( ElementEndContext context )
171     {
172       String text = context.getText().trim();
173       if ( text.length() == 0 )
174       {
175         log( context, Level.WARNING,
176           "Empty classpath definition"
177         );
178       }
179 
180       Extension ext = getExtension( context );
181       
182       // Check for path separators ( ';', ':', or the system path separator
183       // in case it is neither : nor ; )
184       char[] seps = new char[] { ':', ';', 
185         System.getProperty( "path.separator").charAt( 0 ) };
186       for ( int i=0; i < seps.length; i++ )
187       {
188         char sep = seps[ i ];
189         int sepIdx = text.indexOf( sep );
190         if ( sepIdx > 0 )
191         {
192           StringTokenizer tok = new StringTokenizer( text,  
193             String.valueOf( sep ) );
194           while ( tok.hasMoreTokens() )
195           {
196             String token = tok.nextToken();
197             URI abs = getSource( context ).resolvePath( ext, token );
198             addToClasspath( ext, abs );
199           }
200           // If we found a path separator, we're done.
201           return;
202         }
203       }
204       
205       // OK, this seems to be a single entry.
206       addToClasspath( ext, 
207         getSource( context ).resolvePath( ext, text ) );
208     }
209   }
210   
211   private final class HooksVisitor extends ElementVisitor
212   {
213     public void start( ElementStartContext context )
214     {
215       context.registerVisitorFactory( _hookVisitorFactory );
216     }
217   }
218   
219   /**
220    * Get the class loader that should be used by default to load an 
221    * extension.<p>
222    * 
223    * This implementation returns Thread.currentThread().getContextClassLoader().
224    * 
225    * @param extension the extension being processed.
226    * @return the classloader to use to load resources for the specified 
227    *    extension.
228    */
229   protected ClassLoader getClassLoader( Extension extension )
230   {
231     return Thread.currentThread().getContextClassLoader();
232   }
233   
234   /**
235    * Add the specified entry to the classpath of the class loader which is
236    * loading this extension and its dependent classes.
237    * 
238    * @param ext the extension being processed. This may be in a partially
239    *    initialized state.
240    * @param entry a classpath entry used by the current extension.
241    */
242   protected abstract void addToClasspath( Extension ext, URI entry );
243 }