KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mx > loading > HeirarchicalLoaderRepository3


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.mx.loading;
23
24 import java.net.URL JavaDoc;
25 import java.security.AccessController JavaDoc;
26 import java.security.PrivilegedAction JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Set JavaDoc;
30
31 import javax.management.AttributeNotFoundException JavaDoc;
32 import javax.management.InstanceNotFoundException JavaDoc;
33 import javax.management.MBeanException JavaDoc;
34 import javax.management.MBeanServer JavaDoc;
35 import javax.management.ObjectName JavaDoc;
36 import javax.management.ReflectionException JavaDoc;
37
38 import org.jboss.mx.loading.LoadMgr3.PkgClassLoader;
39 import org.jboss.mx.util.ObjectNameFactory;
40
41 /** A simple extension of UnifiedLoaderRepository3 that adds the notion of a
42  * parent UnifiedLoaderRepository. Classes and resources are loaded from child
43  * first and then the parent depending on the java2ParentDelegation flag.
44  *
45  * @author Scott.Stark@jboss.org
46  * @version $Revision: 43332 $
47  */

48 public class HeirarchicalLoaderRepository3 extends UnifiedLoaderRepository3
49 {
50    private static ObjectName JavaDoc DEFAULT_LOADER_OBJECT_NAME = ObjectNameFactory.create(DEFAULT_LOADER_NAME);
51
52    /** A ClassLoader override that prevents a child class loader from looking
53     * beyond its URLs for classes.
54     */

55    static class NoParentClassLoader extends ClassLoader JavaDoc
56    {
57       NoParentClassLoader()
58       {
59          super(HeirarchicalLoaderRepository3.class.getClassLoader());
60       }
61
62       /** Override to always return null to force the UCL to only load from
63        * its URLs.
64        * @param name
65        * @return
66        */

67       public URL JavaDoc getResource(String JavaDoc name)
68       {
69          return null;
70       }
71       /** Override to always throw a CNFE to force the UCL to only load from
72        * its URLs.
73        * @param name
74        * @param resolve
75        * @return nothing
76        * @throws ClassNotFoundException always
77        */

78       protected synchronized Class JavaDoc loadClass(String JavaDoc name, boolean resolve)
79             throws ClassNotFoundException JavaDoc
80       {
81          throw new ClassNotFoundException JavaDoc("NoParentClassLoader has no classes");
82       }
83       /** Override to always throw a CNFE to force the UCL to only load from
84        * its URLs.
85        * @param name
86        * @return
87        * @throws ClassNotFoundException
88        */

89       protected Class JavaDoc findClass(String JavaDoc name) throws ClassNotFoundException JavaDoc
90       {
91          throw new ClassNotFoundException JavaDoc("NoParentClassLoader has no classes");
92       }
93    }
94    static class CacheClassLoader extends UnifiedClassLoader3
95    {
96       Class JavaDoc cacheClass;
97       CacheClassLoader(Class JavaDoc cacheClass, LoaderRepository rep)
98       {
99          super(null, null, new NoParentClassLoader(), rep);
100          this.cacheClass = cacheClass;
101       }
102
103       protected Class JavaDoc findClass(String JavaDoc name) throws ClassNotFoundException JavaDoc
104       {
105          Class JavaDoc c = cacheClass;
106          if( name.equals(cacheClass.getName()) == false )
107             c = null;
108          return c;
109       }
110    }
111
112    /** The repository to which we delegate if requested classes or resources
113     are not available from this repository.
114     */

115    private UnifiedLoaderRepository3 parentRepository;
116    /** A flag indicating if the standard parent delegation loading where the
117     parent repository is used before this repository.
118     */

119    private boolean java2ParentDelegation;
120
121    /** The package classloader */
122    private PkgClassLoader packageClassLoader;
123
124    /** Create a HeirarchicalLoaderRepository3 with an explicit parent.
125     *
126     * @param parent
127     * @throws AttributeNotFoundException
128     * @throws InstanceNotFoundException
129     * @throws MBeanException
130     * @throws ReflectionException
131     */

132    public HeirarchicalLoaderRepository3(UnifiedLoaderRepository3 parent)
133       throws AttributeNotFoundException JavaDoc, InstanceNotFoundException JavaDoc, MBeanException JavaDoc, ReflectionException JavaDoc
134    {
135       this.parentRepository = parent;
136       init();
137    }
138    /** Create a HeirarchicalLoaderRepository3 with a parent obtained by querying
139     * the server for the ServerConstants.DEFAULT_LOADER_NAME mbean.
140     *
141     * @param server
142     * @throws AttributeNotFoundException
143     * @throws InstanceNotFoundException
144     * @throws MBeanException
145     * @throws ReflectionException
146     */

147    public HeirarchicalLoaderRepository3(MBeanServer JavaDoc server)
148       throws AttributeNotFoundException JavaDoc, InstanceNotFoundException JavaDoc, MBeanException JavaDoc, ReflectionException JavaDoc
149    {
150       this(server, DEFAULT_LOADER_OBJECT_NAME);
151    }
152    /** Create a HeirarchicalLoaderRepository3 with a parent obtained by querying
153     * the server for the parentName mbean.
154     *
155     * @param server
156     * @param parentName
157     * @throws AttributeNotFoundException
158     * @throws InstanceNotFoundException
159     * @throws MBeanException
160     * @throws ReflectionException
161     */

162    public HeirarchicalLoaderRepository3(MBeanServer JavaDoc server, ObjectName JavaDoc parentName)
163       throws AttributeNotFoundException JavaDoc, InstanceNotFoundException JavaDoc, MBeanException JavaDoc, ReflectionException JavaDoc
164    {
165       this.parentRepository = (UnifiedLoaderRepository3) server.getAttribute(parentName,
166                     "Instance");
167       init();
168    }
169
170    /**
171     * Initialisation
172     */

173    private void init()
174    {
175       // Include a class loader with a parent to the system class loader
176
ClassLoader JavaDoc loader = RepositoryClassLoader.class.getClassLoader();
177       RepositoryClassLoader ucl = null;
178       if( loader instanceof RepositoryClassLoader )
179          ucl = (RepositoryClassLoader) loader;
180       else
181          ucl = new UnifiedClassLoader3(null, null, HeirarchicalLoaderRepository3.this);
182       packageClassLoader = new PkgClassLoader(ucl, 3);
183    }
184
185    // Public --------------------------------------------------------
186

187    public RepositoryClassLoader newClassLoader(final URL JavaDoc url, boolean addToRepository)
188       throws Exception JavaDoc
189    {
190       UnifiedClassLoader3 ucl = null;
191       if( java2ParentDelegation == false )
192          ucl = new UnifiedClassLoader3(url, null, new NoParentClassLoader(), this);
193       else
194          ucl = new UnifiedClassLoader3(url, null, this);
195
196       if( addToRepository )
197       {
198          this.addClassLoader(ucl);
199       }
200       return ucl;
201    }
202    public RepositoryClassLoader newClassLoader(final URL JavaDoc url, final URL JavaDoc origURL, boolean addToRepository)
203       throws Exception JavaDoc
204    {
205       UnifiedClassLoader3 ucl = null;
206       if( java2ParentDelegation == false )
207          ucl = new UnifiedClassLoader3(url, origURL, new NoParentClassLoader(), this);
208       else
209          ucl = new UnifiedClassLoader3(url, origURL, this);
210
211       if( addToRepository )
212       {
213          this.addClassLoader(ucl);
214       }
215       return ucl;
216    }
217
218    /** Get the use parent first flag. This indicates whether the parent
219     * repository is consulted first for resource and class loading or if the
220     * HeirchicalLoaderRepository is consulted first.
221     *
222     * @return true if the parent repository is consulted first, false if the
223     * HeirchicalLoaderRepository is consulted first.
224     */

225    public boolean getUseParentFirst()
226    {
227       return java2ParentDelegation;
228    }
229    /** Set the use parent first flag. This indicates whether the parent
230     * repository is consulted first for resource and class loading or if the
231     * HeirchicalLoaderRepository is consulted first.
232     *
233     * @param flag true if the parent repository is consulted first, false if the
234     * HeirchicalLoaderRepository is consulted first.
235     */

236    public void setUseParentFirst(boolean flag)
237    {
238       java2ParentDelegation = flag;
239    }
240
241    /** Load a class using the repository class loaders.
242     *
243     * @param name The name of the class
244     * @param resolve an obsolete unused parameter from ClassLoader.loadClass
245     * @param scl The asking class loader
246     * @return The loaded class
247     * @throws ClassNotFoundException If the class could not be found.
248     */

249    public Class JavaDoc loadClass(String JavaDoc name, boolean resolve, ClassLoader JavaDoc scl)
250       throws ClassNotFoundException JavaDoc
251    {
252       Class JavaDoc foundClass = null;
253
254       if( java2ParentDelegation == true )
255       {
256          try
257          {
258             // Try the parent repository first
259
foundClass = parentRepository.loadClass(name, resolve, scl);
260          }
261          catch(ClassNotFoundException JavaDoc e)
262          {
263             // Next try our repository
264
if( foundClass == null )
265                foundClass = super.loadClass(name, resolve, scl);
266          }
267       }
268       else
269       {
270          try
271          {
272             // Try this repository first
273
foundClass = super.loadClass(name, resolve, scl);
274          }
275          catch(ClassNotFoundException JavaDoc e)
276          {
277             // Next try our parent repository
278
if( foundClass == null )
279                foundClass = parentRepository.loadClass(name, resolve, scl);
280          }
281       }
282
283       if( foundClass != null )
284          return foundClass;
285
286       /* If we reach here, all of the classloaders currently in the VM don't
287          know about the class
288       */

289       throw new ClassNotFoundException JavaDoc(name);
290    }
291
292    /** Override getCachedClass to return the parent repository cached class
293     * if java2ParentDelegation=true, followed by this repository's cached
294     * value. Else, if java2ParentDelegation=false, only check this repository's
295     * cache to attempt to load the class from the child repository before
296     * going to the parent cache.
297     *
298     * @param classname
299     * @return the cached class if found, null otherwise
300     */

301    public Class JavaDoc getCachedClass(String JavaDoc classname)
302    {
303       Class JavaDoc clazz = null;
304       if( java2ParentDelegation == true )
305       {
306          // Try the parent repository
307
clazz = parentRepository.getCachedClass(classname);
308          // Next try our parent repository
309
if( clazz == null )
310             clazz = super.getCachedClass(classname);
311       }
312       else
313       {
314          // Try this repository
315
clazz = super.getCachedClass(classname);
316       }
317       return clazz;
318    }
319
320    /** Find a resource from this repository. This first looks to this
321     * repository and then the parent repository.
322     * @param name The name of the resource
323     * @param scl The asking class loader
324     * @return An URL for reading the resource, or <code>null</code> if the
325     * resource could not be found.
326     */

327    public URL JavaDoc getResource(String JavaDoc name, ClassLoader JavaDoc scl)
328    {
329       URL JavaDoc resource = null;
330
331       if( java2ParentDelegation == true )
332       {
333          /* Try our parent repository. This cannot use the getResource method
334          because we do not want the parent repository to load the resource via
335          our scoped class loader
336          */

337          resource = getParentResource(name, scl);
338          // Next try this repository
339
if( resource == null )
340             resource = super.getResource(name, scl);
341       }
342       else
343       {
344          // Try this repository
345
resource = super.getResource(name, scl);
346          // Next try our parent repository
347
if( resource == null )
348          {
349             /* Try our parent repository. This cannot use the getResource method
350             because we do not want the parent repository to load the resource via
351             our scoped class loader
352             */

353             resource = getParentResource(name, scl);
354          }
355       }
356
357       return resource;
358    }
359
360    /** Find all resource URLs for the given name. This is entails an
361     * exhuastive search of this and the parent repository and is an expensive
362     * operation.
363     *
364     * @param name the resource name
365     * @param cl the requesting class loader
366     * @param urls a list into which the located resource URLs will be placed
367     */

368    public void getResources(String JavaDoc name, ClassLoader JavaDoc cl, List JavaDoc urls)
369    {
370       if( java2ParentDelegation == true )
371       {
372          // Get the parent repository resources
373
parentRepository.getResources(name, cl, urls);
374          // Next get this repositories resources
375
super.getResources(name, cl, urls);
376       }
377       else
378       {
379          // Get this repositories resources
380
super.getResources(name, cl, urls);
381          // Next get the parent repository resources
382
parentRepository.getResources(name, cl, urls);
383       }
384    }
385
386    /** Obtain a listing of the URLs for all UnifiedClassLoaders associated with
387     *the repository
388     */

389    public URL JavaDoc[] getURLs()
390    {
391       URL JavaDoc[] ourURLs = super.getURLs();
392       URL JavaDoc[] parentURLs = parentRepository.getURLs();
393       int size = ourURLs.length + parentURLs.length;
394       URL JavaDoc[] urls = new URL JavaDoc[size];
395       System.arraycopy(ourURLs, 0, urls, 0, ourURLs.length);
396       System.arraycopy(parentURLs, 0, urls, ourURLs.length, parentURLs.length);
397       return urls;
398    }
399
400    /** Called by LoadMgr to locate a previously loaded class. This looks
401     * first to this repository and then the parent repository.
402     *@return the cached class if found, null otherwise
403     */

404    public Class JavaDoc loadClassFromCache(String JavaDoc name)
405    {
406       Class JavaDoc foundClass = null;
407
408       if( java2ParentDelegation == true )
409       {
410          // Try this repository
411
foundClass = parentRepository.loadClassFromCache(name);
412          // Next try our parent repository
413
if( foundClass == null )
414             foundClass = super.loadClassFromCache(name);
415       }
416       else
417       {
418          // Try this repository
419
foundClass = super.loadClassFromCache(name);
420          /* We do not try the parent repository cache as this does not allow
421          the child repository to override classes in the parent
422          */

423       }
424       return foundClass;
425    }
426
427    /** Called by LoadMgr to obtain all class loaders. This returns a set of
428     * PkgClassLoader with the HeirarchicalLoaderRepository3 ordered ahead of
429     * the parent repository pkg class loaders
430     *@return Set<PkgClassLoader>
431     */

432    public Set JavaDoc getPackageClassLoaders(String JavaDoc name)
433    {
434       Set JavaDoc pkgSet = super.getPackageClassLoaders(name);
435       Set JavaDoc parentPkgSet = parentRepository.getPackageClassLoaders(name);
436       GetClassLoadersAction action = new GetClassLoadersAction(name, pkgSet,
437          parentPkgSet);
438       Set JavaDoc theSet = (Set JavaDoc) AccessController.doPrivileged(action);
439       return theSet;
440
441    }
442
443    public int compare(LoaderRepository lr)
444    {
445       if (lr == this)
446          return 0;
447       return reverseCompare(lr);
448    }
449    
450    protected int reverseCompare(LoaderRepository lr)
451    {
452       // If it is not our parent we don't care
453
if (lr != parentRepository)
454          return 0;
455       
456       // The order depends upon the delegation model
457
if (java2ParentDelegation)
458          return +1;
459       else
460          return -1;
461    }
462
463    /** A subset of the functionality found in getResource(String, ClassLoader),
464     * but this version queries the parentRepository and does not use the scl
465     * to avoid leaking class loaders across scoped.
466     *
467     * @param name - the resource name
468     * @param scl - the requesting class loader
469     * @return the resource URL if found, null otherwise
470     */

471    private URL JavaDoc getParentResource(String JavaDoc name, ClassLoader JavaDoc scl)
472    {
473       // Not found in classloader, ask the global cache
474
URL JavaDoc resource = parentRepository.getResourceFromGlobalCache(name);
475
476       // The cache has it, we are done
477
if( resource != null )
478          return resource;
479
480       // Not visible in global cache, iterate on all classloaders
481
resource = parentRepository.getResourceFromRepository(name, scl);
482
483       return resource;
484    }
485
486    private class GetClassLoadersAction implements PrivilegedAction JavaDoc
487    {
488       private String JavaDoc name;
489       Set JavaDoc pkgSet;
490       Set JavaDoc parentPkgSet;
491
492       GetClassLoadersAction(String JavaDoc name, Set JavaDoc pkgSet, Set JavaDoc parentPkgSet)
493       {
494          this.name = name;
495          this.pkgSet = pkgSet;
496          this.parentPkgSet = parentPkgSet;
497       }
498
499       public Object JavaDoc run()
500       {
501          // Build a set of PkgClassLoader
502
Set JavaDoc theSet = ClassLoaderUtils.newPackageSet();
503          if( pkgSet != null )
504          {
505             Iterator JavaDoc iter = pkgSet.iterator();
506             while( iter.hasNext() )
507             {
508                RepositoryClassLoader ucl = (RepositoryClassLoader) iter.next();
509                PkgClassLoader pkgUcl = new PkgClassLoader(ucl, 0);
510                theSet.add(pkgUcl);
511             }
512          }
513
514          if( java2ParentDelegation == false )
515          {
516             Class JavaDoc cacheClass = parentRepository.loadClassFromCache(name);
517             if( cacheClass != null )
518             {
519                RepositoryClassLoader ucl = new CacheClassLoader(cacheClass, HeirarchicalLoaderRepository3.this);
520                PkgClassLoader pkgUcl = new PkgClassLoader(ucl, 1);
521                theSet.add(pkgUcl);
522             }
523          }
524
525          if( parentPkgSet != null )
526          {
527             Iterator JavaDoc iter = parentPkgSet.iterator();
528             while( iter.hasNext() )
529             {
530                RepositoryClassLoader ucl = (RepositoryClassLoader) iter.next();
531                PkgClassLoader pkgUcl = new PkgClassLoader(ucl, 2);
532                theSet.add(pkgUcl);
533             }
534          }
535
536          if( java2ParentDelegation == false )
537          {
538             theSet.add(packageClassLoader);
539          }
540
541          return theSet;
542       }
543    }
544
545 }
546
Popular Tags