KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > petals > classloader > PetalsClassLoader


1 /**
2  * PETALS - PETALS Services Platform.
3  * Copyright (c) 2005 EBM Websourcing, http://www.ebmwebsourcing.com/
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * -------------------------------------------------------------------------
19  * $Id: PetalsClassLoader.java 296 2006-05-02 12:58:27Z ddesjardins $
20  * -------------------------------------------------------------------------
21  */

22 package org.objectweb.petals.classloader;
23
24 import java.io.File JavaDoc;
25 import java.io.FileInputStream JavaDoc;
26 import java.io.FileNotFoundException JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.InputStream JavaDoc;
29 import java.net.URL JavaDoc;
30 import java.net.URLClassLoader JavaDoc;
31 import java.net.URLStreamHandlerFactory JavaDoc;
32 import java.util.Enumeration JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Set JavaDoc;
36 import java.util.jar.JarFile JavaDoc;
37
38 import org.objectweb.petals.classloader.factory.URLFactory;
39 import org.objectweb.petals.classloader.locator.Locator;
40
41 /**
42  * Petals class loader Do not implement loadClass(String) it causes a conflict
43  * with the SharedLibrariesClassLoader
44  *
45  * @version $Rev: 296 $ $Date: 2006-05-02 12:58:27Z $
46  * @since Petals 1.0
47  * @author Rafael Marins, Olivier Fabre
48  * @author ddesjardins - eBMWebsourcing
49  */

50 public class PetalsClassLoader extends URLClassLoader JavaDoc {
51
52     /**
53      * Standard Java package binary name.
54      */

55     private static final String JavaDoc JAVA_PACKAGE = "java.";
56
57     /**
58      * Standard Java extensions package binary name.
59      */

60     private static final String JavaDoc JAVAX_PACKAGE = "javax.";
61
62     /**
63      * To use or not the parent first class loading delegation model.
64      */

65     private boolean parentFirst;
66
67     /**
68      * Isolate Class Loading from parent.
69      */

70     private boolean ignoreParent;
71
72     /**
73      * To use or not the package intelligence self-first mechanism.
74      */

75     private boolean usePackageIntelligence;
76
77     /**
78      * List of known packages loaded from this class loader.
79      */

80     private Set JavaDoc<String JavaDoc> localKnownPackages;
81
82     /**
83      * Parent Class Loader.
84      */

85     protected ClassLoader JavaDoc parent;
86
87     /**
88      * Factories used to create URLs for URLClassLoader
89      */

90     private URLFactory[] factories;
91
92     /**
93      * Locators used to search jar/dir for files, directories, ...
94      */

95     private Locator[] locators;
96
97     /**
98      * Bases URLs
99      */

100     private URL JavaDoc[] bases;
101
102     /**
103      * Create a class loader for petals
104      *
105      * @param baseUrls installation root path in petals
106      * @param classpathLocations jar defined in the classpath part of the jbi
107      * descriptor
108      * @param parent
109      * @throws IOException
110      */

111     public PetalsClassLoader(URL JavaDoc[] baseUrls, List JavaDoc<String JavaDoc> classpathLocations, ClassLoader JavaDoc parent) throws IOException JavaDoc {
112         super(baseUrls, parent);
113         this.parent = parent;
114         this.bases = baseUrls;
115         initialize(classpathLocations);
116     }
117
118     /**
119      * Create a class loader for petals
120      *
121      * @param baseUrls installation root path in petals
122      * @param classpathLocations jar defined in the classpath part of the jbi
123      * descriptor
124      * @throws IOException
125      */

126     public PetalsClassLoader(URL JavaDoc[] baseUrls, List JavaDoc<String JavaDoc> classpathLocations) throws IOException JavaDoc {
127         super(baseUrls);
128         this.bases = baseUrls;
129         initialize(classpathLocations);
130     }
131
132     /**
133      * Create a class loader for petals
134      *
135      * @param baseUrls installation root path in petals
136      * @param classpathLocations jar defined in the classpath part of the jbi
137      * descriptor
138      * @param parent parent class loader
139      * @param factory url factory
140      * @throws IOException
141      */

142     public PetalsClassLoader(URL JavaDoc[] baseUrls, List JavaDoc<String JavaDoc> classpathLocations, ClassLoader JavaDoc parent, URLStreamHandlerFactory JavaDoc factory) throws IOException JavaDoc {
143         super(baseUrls, parent, factory);
144         this.parent = parent;
145         this.bases = baseUrls;
146         initialize(classpathLocations);
147     }
148
149     // ----------------------------------------------------------------------
150
// Getters and Setters
151
// ----------------------------------------------------------------------
152

153     /**
154      * @return Returns the useParentFirst.
155      */

156     public boolean isParentFirst() {
157         return parentFirst;
158     }
159
160     /**
161      * @param use The useParentFirst to set.
162      */

163     public void setParentFirst(boolean use) {
164         this.parentFirst = use;
165     }
166
167     /**
168      * @return Returns the isolated.
169      */

170     public boolean isIsolated() {
171         return ignoreParent;
172     }
173
174     /**
175      * @param isolated The ignoreParent to set.
176      */

177     public void setIsolated(boolean isolated) {
178         this.ignoreParent = isolated;
179     }
180
181     /**
182      * @return Returns the usePackageIntelligence.
183      */

184     public boolean isUsingPackageIntelligence() {
185         localKnownPackages = null;
186         return usePackageIntelligence;
187     }
188
189     /**
190      * @param use The usePackageIntelligence to set.
191      */

192     public void setUsingPackageIntelligence(boolean use) {
193         localKnownPackages = new HashSet JavaDoc<String JavaDoc>();
194         this.usePackageIntelligence = use;
195     }
196
197     /**
198      * @return Returns the bases.
199      */

200     public URL JavaDoc[] getBases() {
201         return bases;
202     }
203
204     /**
205      * @return Returns a String representation of the classpath used by this
206      * classloader
207      */

208     public String JavaDoc getClasspath() {
209         URL JavaDoc[] urls = getURLs();
210         StringBuffer JavaDoc cp = new StringBuffer JavaDoc();
211         for (int i = 0; i < urls.length; i++) {
212             String JavaDoc url = urls[i].getFile();
213             // do not add URL with !/ inside
214
if (url.indexOf("!/") == -1) {
215                 cp.append(File.pathSeparator + url);
216             }
217         }
218         return cp.toString();
219     }
220
221     // ----------------------------------------------------------------------
222
// overriding methods
223
// ----------------------------------------------------------------------
224

225     /**
226      * Load a class Use the parent classloader if parentFirst is set to true
227      * else use its own url classloader to load the class
228      *
229      * @param className name of the class to load
230      * @param resolve boolean to resolve or not the class
231      */

232     @Override JavaDoc
233     protected synchronized Class JavaDoc<?> loadClass(String JavaDoc className, boolean resolve) throws ClassNotFoundException JavaDoc {
234         Class JavaDoc<?> clazz = null;
235         clazz = findLoadedClass(className);
236         if (clazz == null) {
237             // parent first
238
if (useParentFirst(className, true)) {
239                 try {
240                     clazz = parent.loadClass(className);
241                 }
242                 catch (ClassNotFoundException JavaDoc cnfe) {
243                     clazz = findClass(className);
244                 }
245             }
246             // self first
247
else {
248                 try {
249                     clazz = findClass(className);
250                 }
251                 catch (Exception JavaDoc cnfe) {
252                     try {
253                         clazz = parent.loadClass(className);
254                     }
255                     catch (Exception JavaDoc e) {
256                         throw new ClassNotFoundException JavaDoc(className);
257                     }
258                     if (clazz == null) {
259                         throw new ClassNotFoundException JavaDoc(className);
260                     }
261                 }
262             }
263         }
264         if (resolve) {
265             resolveClass(clazz);
266         }
267         return clazz;
268     }
269
270     /**
271      * Find a class in the class path of the petals class loader
272      *
273      * @param className name of the class to find
274      * @throws ClassNotFoundException when fails (when the class is not found or
275      * when the class is a java.lang.object)
276      */

277     @Override JavaDoc
278     protected Class JavaDoc<?> findClass(String JavaDoc className) throws ClassNotFoundException JavaDoc {
279         return super.findClass(className);
280     }
281
282     /**
283      * Return a URL of the resource
284      *
285      * @param resourceName
286      * @return url of the resource (null if the resource is not found)
287      */

288     @Override JavaDoc
289     public URL JavaDoc getResource(String JavaDoc resourceName) {
290         URL JavaDoc resource = null;
291         // parent first
292
if (useParentFirst(resourceName, false)) {
293             resource = parent.getResource(resourceName);
294             if (resource == null) {
295                 resource = findResource(resourceName);
296             }
297         }
298         // self first
299
else {
300             resource = findResource(resourceName);
301             if (resource == null && !isIsolated()) {
302                 resource = parent.getResource(resourceName);
303             }
304         }
305         return resource;
306     }
307
308     /**
309      * Get a stream from a resource in the classpath
310      *
311      * @param resourceName name of the resource
312      * @return stream of the resource (null if the resource is not found)
313      */

314     @Override JavaDoc
315     public InputStream JavaDoc getResourceAsStream(String JavaDoc resourceName) {
316         InputStream JavaDoc inputStream = null;
317         // parent first
318
if (useParentFirst(resourceName, false)) {
319             inputStream = parent.getResourceAsStream(resourceName);
320             if (inputStream == null) {
321                 URL JavaDoc url = findResource(resourceName);
322                 if (url != null) {
323                     try {
324                         if (url.getProtocol().equals("file")) {
325                             // The resource is a file
326
inputStream = new FileInputStream JavaDoc(url.getPath());
327                         }
328                         else if (url.getProtocol().equals("jar")) {
329                             // The resource is contain into a Jar
330
try {
331                                 String JavaDoc fileName = url.getPath().substring(0, url.getPath().indexOf("!"));
332                                 fileName = fileName.substring(5);
333                                 JarFile JavaDoc jarFile = new JarFile JavaDoc(fileName);
334                                 inputStream = jarFile.getInputStream(jarFile.getEntry(url.getPath().substring(url.getPath().indexOf("!") + 2)));
335                             }
336                             catch (IOException JavaDoc e) {
337                                 inputStream = null;
338                             }
339                         }
340                     }
341                     catch (FileNotFoundException JavaDoc e) {
342                         inputStream = null;
343                     }
344                 }
345             }
346         }
347         // self first
348
else {
349             URL JavaDoc url = findResource(resourceName);
350             if (url == null && !isIsolated()) {
351                 url = parent.getResource(resourceName);
352             }
353             if (url != null) {
354                 try {
355                     if (url.getProtocol().equals("file")) {
356                         // The resource is a file
357
inputStream = new FileInputStream JavaDoc(url.getPath());
358                     }
359                     else if (url.getProtocol().equals("jar")) {
360                         // The resource is contain into a Jar
361
try {
362                             String JavaDoc fileName = url.getPath().substring(0, url.getPath().indexOf("!"));
363                             fileName = fileName.substring(5);
364                             JarFile JavaDoc jarFile = new JarFile JavaDoc(fileName);
365                             inputStream = jarFile.getInputStream(jarFile.getEntry(url.getPath().substring(url.getPath().indexOf("!") + 2)));
366                         }
367                         catch (IOException JavaDoc e) {
368                             inputStream = null;
369                         }
370                     }
371                 }
372                 catch (FileNotFoundException JavaDoc e) {
373                     inputStream = null;
374                 }
375             }
376         }
377         return inputStream;
378     }
379
380     /**
381      * Return a enumeration of resources
382      *
383      * @see java.lang.ClassLoader#getResources(java.lang.String)
384      */

385     @Override JavaDoc
386     public Enumeration JavaDoc<URL JavaDoc> getResources(String JavaDoc resourceName) throws IOException JavaDoc {
387         Enumeration JavaDoc<URL JavaDoc> resources = null;
388         // parent first
389
if (useParentFirst(resourceName, false)) {
390             resources = parent.getResources(resourceName);
391             if (resources == null) {
392                 resources = findResources(resourceName);
393             }
394         }
395         // self first
396
else {
397             resources = findResources(resourceName);
398             if (!resources.hasMoreElements() && !isIsolated()) {
399                 resources = parent.getResources(resourceName);
400             }
401         }
402         return resources;
403     }
404
405     // ----------------------------------------------------------------------
406
// implementation specific methods
407
// ----------------------------------------------------------------------
408

409     /**
410      * Initialize the petals class loader
411      *
412      * @param classpathLocations elements of the classpath
413      */

414     protected void initialize(List JavaDoc<String JavaDoc> classpathLocations) throws IOException JavaDoc {
415         this.parentFirst = true;
416         this.ignoreParent = false;
417         this.usePackageIntelligence = false;
418         if (parent == null) {
419             parent = getSystemClassLoader();
420         }
421         factories = new URLFactory[bases.length];
422         locators = new Locator[bases.length];
423         // Create factories and locator for each base URL
424
for (int i = 0; i < bases.length; i++) {
425             factories[i] = URLFactory.getFactory(bases[i]);
426             locators[i] = Locator.getLocator(bases[i]);
427         }
428         // Add all classpathLocations into the repository
429
for (String JavaDoc location : classpathLocations) {
430             addInRepository(location);
431         }
432     }
433
434     /**
435      * Method to know if we choose to use the parent class loader first
436      *
437      * @param resourceName resource name
438      * @param usingForClass resource as a class
439      * @return boolean
440      */

441     protected boolean useParentFirst(String JavaDoc resourceName, boolean usingForClass) {
442         // begin with the chosen delegation model
443
boolean useParentFirst = isParentFirst() && !isIsolated();
444         // try self-first based on intelligent mechanism of known packages
445
if (useParentFirst) {
446             if (isUsingPackageIntelligence() && usingForClass) {
447                 String JavaDoc packageName = getPackageName(resourceName);
448                 // self-first <-- when parent first is set to false
449
useParentFirst = !knowLocalPackage(packageName);
450             }
451         }
452         // always use parent class loader when loading java packages
453
else {
454             useParentFirst = (JAVA_PACKAGE.startsWith(resourceName) || JAVAX_PACKAGE.startsWith(resourceName));
455         }
456         return useParentFirst;
457     }
458
459     /**
460      * Add a package name to the known package
461      *
462      * @param packageName package name
463      */

464     protected void addLocalKnownPackage(String JavaDoc packageName) {
465         if (localKnownPackages != null) {
466             localKnownPackages.add(packageName);
467         }
468     }
469
470     /**
471      * Check if a package is in the known package list
472      *
473      * @param packageName package name
474      * @return true if the package is already known
475      */

476     protected boolean knowLocalPackage(String JavaDoc packageName) {
477         boolean known = false;
478         if (localKnownPackages != null) {
479             known = localKnownPackages.contains(packageName);
480         }
481         return known;
482     }
483
484     /**
485      * Return the package name of a class
486      *
487      * @param className complete name of a class
488      * @return package name
489      */

490     protected String JavaDoc getPackageName(String JavaDoc className) {
491         int lastSeparator = className.lastIndexOf('.');
492         String JavaDoc packageName = className.substring(0, lastSeparator);
493         return packageName;
494     }
495
496     /**
497      * Add specified location into the repository. If location is found in
498      * multiple URLs of the bases, new URLs will be added multiple times.
499      *
500      * @param location an entry name (for a jar) or a path name (for a
501      * directory)
502      * @throws IOException when constructed URL is malformed
503      */

504     protected void addInRepository(String JavaDoc location) throws IOException JavaDoc {
505         // test existence in each base URL
506
for (int i = 0; i < bases.length; i++) {
507             if (locators[i].hasDirectory(location) || locators[i].hasFile(location)) {
508                 addURL(factories[i].getURL(location));
509             }
510         }
511     }
512
513     /**
514      * @return Returns a String representation of the PetalsClassLoader
515      */

516     public String JavaDoc toString() {
517         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
518
519         sb.append("classloader : " + getClass().getName() + "\n");
520         sb.append("\tmodules bases (not in loader!) : \n");
521         for (int i = 0; i < bases.length; i++) {
522             sb.append("\t\t -" + bases[i] + "\n");
523         }
524         sb.append("\trepositories :\n");
525         URL JavaDoc[] rep = getURLs();
526         for (int i = 0; i < rep.length; i++) {
527             sb.append("\t\t -" + rep[i] + "\n");
528         }
529         sb.append("\tparent : " + getParent() + "\n");
530
531         return sb.toString();
532     }
533
534     /**
535      * Expose the protected <code>findLoadedClass</code> method. Used by the
536      * ShareLibraries class loader
537      *
538      * @param className
539      * @return
540      * @throws ClassNotFoundException
541      */

542     Class JavaDoc<?> findLoadedClazz(String JavaDoc className) throws ClassNotFoundException JavaDoc {
543         return super.findLoadedClass(className);
544     }
545 }
546
Popular Tags