Source Code Cross Referenced for MultiParentClassLoader.java in  » EJB-Server-geronimo » kernel » org » apache » geronimo » kernel » config » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server geronimo » kernel » org.apache.geronimo.kernel.config 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
003:         *  contributor license agreements.  See the NOTICE file distributed with
004:         *  this work for additional information regarding copyright ownership.
005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
006:         *  (the "License"); you may not use this file except in compliance with
007:         *  the License.  You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         *  Unless required by applicable law or agreed to in writing, software
012:         *  distributed under the License is distributed on an "AS IS" BASIS,
013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         *  See the License for the specific language governing permissions and
015:         *  limitations under the License.
016:         */package org.apache.geronimo.kernel.config;
017:
018:        import java.beans.Introspector;
019:        import java.io.IOException;
020:        import java.io.ObjectInputStream;
021:        import java.io.ObjectOutputStream;
022:        import java.io.ObjectStreamClass;
023:        import java.lang.reflect.Field;
024:        import java.net.URL;
025:        import java.net.URLClassLoader;
026:        import java.net.URLStreamHandlerFactory;
027:        import java.util.ArrayList;
028:        import java.util.Collection;
029:        import java.util.Collections;
030:        import java.util.Enumeration;
031:        import java.util.HashSet;
032:        import java.util.LinkedList;
033:        import java.util.List;
034:        import java.util.Map;
035:        import java.util.Set;
036:
037:        import org.apache.commons.logging.Log;
038:        import org.apache.commons.logging.LogFactory;
039:        import org.apache.geronimo.kernel.classloader.UnionEnumeration;
040:        import org.apache.geronimo.kernel.repository.Artifact;
041:        import org.apache.geronimo.kernel.util.ClassLoaderRegistry;
042:
043:        /**
044:         * A MultiParentClassLoader is a simple extension of the URLClassLoader that simply changes the single parent class
045:         * loader model to support a list of parent class loaders.  Each operation that accesses a parent, has been replaced
046:         * with a operation that checks each parent in order.  This getParent method of this class will always return null,
047:         * which may be interpreted by the calling code to mean that this class loader is a direct child of the system class
048:         * loader.
049:         *
050:         * @version $Rev: 562116 $ $Date: 2007-08-02 07:14:55 -0700 (Thu, 02 Aug 2007) $
051:         */
052:        public class MultiParentClassLoader extends URLClassLoader {
053:            private static final Log log = LogFactory
054:                    .getLog(MultiParentClassLoader.class);
055:            private final Artifact id;
056:            private final ClassLoader[] parents;
057:            private final boolean inverseClassLoading;
058:            private final String[] hiddenClasses;
059:            private final String[] nonOverridableClasses;
060:            private final String[] hiddenResources;
061:            private final String[] nonOverridableResources;
062:            private boolean destroyed = false;
063:
064:            // I used this pattern as its temporary and with the static final we get compile time 
065:            // optimizations.
066:            private final static int classLoaderSearchMode;
067:            private final static int ORIGINAL_SEARCH = 1;
068:            private final static int OPTIMIZED_SEARCH = 2;
069:
070:            static {
071:                // Extract the classLoaderSearchMode if specified.  If not, default to "safe".
072:                String mode = System
073:                        .getProperty("Xorg.apache.geronimo.kernel.config.MPCLSearchOption");
074:                int runtimeMode = OPTIMIZED_SEARCH; // Default to optimized
075:                String runtimeModeMessage = "Original Classloading";
076:                if (mode != null) {
077:                    if (mode.equals("safe")) {
078:                        runtimeMode = ORIGINAL_SEARCH;
079:                        runtimeModeMessage = "Safe ClassLoading";
080:                    } else if (mode.equals("optimized"))
081:                        runtimeMode = OPTIMIZED_SEARCH;
082:                }
083:
084:                classLoaderSearchMode = runtimeMode;
085:                log
086:                        .info("ClassLoading behaviour has changed.  The "
087:                                + runtimeModeMessage
088:                                + " mode is in effect.  If you are experiencing a problem\n"
089:                                + "you can change the behaviour by specifying -DXorg.apache.geronimo.kernel.config.MPCLSearchOption= property.  Specify \n"
090:                                + "=\"safe\" to revert to the original behaviour.  This is a temporary change until we decide whether or not to make it\n"
091:                                + "permanent for the 2.0 release");
092:            }
093:
094:            /**
095:             * Creates a named class loader with no parents.
096:             *
097:             * @param id   the id of this class loader
098:             * @param urls the urls from which this class loader will classes and resources
099:             */
100:            public MultiParentClassLoader(Artifact id, URL[] urls) {
101:                super (urls);
102:                this .id = id;
103:                parents = new ClassLoader[] { ClassLoader
104:                        .getSystemClassLoader() };
105:                inverseClassLoading = false;
106:                hiddenClasses = new String[0];
107:                nonOverridableClasses = new String[0];
108:                hiddenResources = new String[0];
109:                nonOverridableResources = new String[0];
110:                ClassLoaderRegistry.add(this );
111:            }
112:
113:            /**
114:             * Creates a named class loader as a child of the specified parent.
115:             *
116:             * @param id     the id of this class loader
117:             * @param urls   the urls from which this class loader will classes and resources
118:             * @param parent the parent of this class loader
119:             */
120:            public MultiParentClassLoader(Artifact id, URL[] urls,
121:                    ClassLoader parent) {
122:                this (id, urls, new ClassLoader[] { parent });
123:            }
124:
125:            public MultiParentClassLoader(Artifact id, URL[] urls,
126:                    ClassLoader parent, boolean inverseClassLoading,
127:                    String[] hiddenClasses, String[] nonOverridableClasses) {
128:                this (id, urls, new ClassLoader[] { parent },
129:                        inverseClassLoading, hiddenClasses,
130:                        nonOverridableClasses);
131:            }
132:
133:            /**
134:             * Creates a named class loader as a child of the specified parent and using the specified URLStreamHandlerFactory
135:             * for accessing the urls..
136:             *
137:             * @param id      the id of this class loader
138:             * @param urls    the urls from which this class loader will classes and resources
139:             * @param parent  the parent of this class loader
140:             * @param factory the URLStreamHandlerFactory used to access the urls
141:             */
142:            public MultiParentClassLoader(Artifact id, URL[] urls,
143:                    ClassLoader parent, URLStreamHandlerFactory factory) {
144:                this (id, urls, new ClassLoader[] { parent }, factory);
145:            }
146:
147:            /**
148:             * Creates a named class loader as a child of the specified parents.
149:             *
150:             * @param id      the id of this class loader
151:             * @param urls    the urls from which this class loader will classes and resources
152:             * @param parents the parents of this class loader
153:             */
154:            public MultiParentClassLoader(Artifact id, URL[] urls,
155:                    ClassLoader[] parents) {
156:                super (urls);
157:                this .id = id;
158:                this .parents = copyParents(parents);
159:                inverseClassLoading = false;
160:                hiddenClasses = new String[0];
161:                nonOverridableClasses = new String[0];
162:                hiddenResources = new String[0];
163:                nonOverridableResources = new String[0];
164:                ClassLoaderRegistry.add(this );
165:            }
166:
167:            public MultiParentClassLoader(Artifact id, URL[] urls,
168:                    ClassLoader[] parents, boolean inverseClassLoading,
169:                    Collection hiddenClasses, Collection nonOverridableClasses) {
170:                this (id, urls, parents, inverseClassLoading,
171:                        (String[]) hiddenClasses
172:                                .toArray(new String[hiddenClasses.size()]),
173:                        (String[]) nonOverridableClasses
174:                                .toArray(new String[nonOverridableClasses
175:                                        .size()]));
176:            }
177:
178:            public MultiParentClassLoader(Artifact id, URL[] urls,
179:                    ClassLoader[] parents, boolean inverseClassLoading,
180:                    String[] hiddenClasses, String[] nonOverridableClasses) {
181:                super (urls);
182:                this .id = id;
183:                this .parents = copyParents(parents);
184:                this .inverseClassLoading = inverseClassLoading;
185:                this .hiddenClasses = hiddenClasses;
186:                this .nonOverridableClasses = nonOverridableClasses;
187:                hiddenResources = toResources(hiddenClasses);
188:                nonOverridableResources = toResources(nonOverridableClasses);
189:                ClassLoaderRegistry.add(this );
190:            }
191:
192:            public MultiParentClassLoader(MultiParentClassLoader source) {
193:                this (source.id, source.getURLs(),
194:                        deepCopyParents(source.parents),
195:                        source.inverseClassLoading, source.hiddenClasses,
196:                        source.nonOverridableClasses);
197:            }
198:
199:            static ClassLoader copy(ClassLoader source) {
200:                if (source instanceof  MultiParentClassLoader) {
201:                    return new MultiParentClassLoader(
202:                            (MultiParentClassLoader) source);
203:                } else if (source instanceof  URLClassLoader) {
204:                    return new URLClassLoader(((URLClassLoader) source)
205:                            .getURLs(), source.getParent());
206:                } else {
207:                    return new URLClassLoader(new URL[0], source);
208:                }
209:            }
210:
211:            ClassLoader copy() {
212:                return MultiParentClassLoader.copy(this );
213:            }
214:
215:            private String[] toResources(String[] classes) {
216:                String[] resources = new String[classes.length];
217:                for (int i = 0; i < classes.length; i++) {
218:                    String className = classes[i];
219:                    resources[i] = className.replace('.', '/');
220:                }
221:                return resources;
222:            }
223:
224:            /**
225:             * Creates a named class loader as a child of the specified parents and using the specified URLStreamHandlerFactory
226:             * for accessing the urls..
227:             *
228:             * @param id      the id of this class loader
229:             * @param urls    the urls from which this class loader will classes and resources
230:             * @param parents the parents of this class loader
231:             * @param factory the URLStreamHandlerFactory used to access the urls
232:             */
233:            public MultiParentClassLoader(Artifact id, URL[] urls,
234:                    ClassLoader[] parents, URLStreamHandlerFactory factory) {
235:                super (urls, null, factory);
236:                this .id = id;
237:                this .parents = copyParents(parents);
238:                inverseClassLoading = false;
239:                hiddenClasses = new String[0];
240:                nonOverridableClasses = new String[0];
241:                hiddenResources = new String[0];
242:                nonOverridableResources = new String[0];
243:                ClassLoaderRegistry.add(this );
244:            }
245:
246:            private static ClassLoader[] copyParents(ClassLoader[] parents) {
247:                ClassLoader[] newParentsArray = new ClassLoader[parents.length];
248:                for (int i = 0; i < parents.length; i++) {
249:                    ClassLoader parent = parents[i];
250:                    if (parent == null) {
251:                        throw new NullPointerException("parent[" + i
252:                                + "] is null");
253:                    }
254:                    newParentsArray[i] = parent;
255:                }
256:                return newParentsArray;
257:            }
258:
259:            private static ClassLoader[] deepCopyParents(ClassLoader[] parents) {
260:                ClassLoader[] newParentsArray = new ClassLoader[parents.length];
261:                for (int i = 0; i < parents.length; i++) {
262:                    ClassLoader parent = parents[i];
263:                    if (parent == null) {
264:                        throw new NullPointerException("parent[" + i
265:                                + "] is null");
266:                    }
267:                    if (parent instanceof  MultiParentClassLoader) {
268:                        parent = ((MultiParentClassLoader) parent).copy();
269:                    }
270:                    newParentsArray[i] = parent;
271:                }
272:                return newParentsArray;
273:            }
274:
275:            /**
276:             * Gets the id of this class loader.
277:             *
278:             * @return the id of this class loader
279:             */
280:            public Artifact getId() {
281:                return id;
282:            }
283:
284:            /**
285:             * Gets the parents of this class loader.
286:             *
287:             * @return the parents of this class loader
288:             */
289:            public ClassLoader[] getParents() {
290:                return parents;
291:            }
292:
293:            public void addURL(URL url) {
294:                // todo this needs a security check
295:                super .addURL(url);
296:            }
297:
298:            /**
299:             * TODO This method should be removed and replaced with the best classLoading option.  Its intent is to 
300:             * provide a way for folks to switch back to the old classLoader if this fix breaks something.
301:             */
302:            protected synchronized Class<?> loadClass(String name,
303:                    boolean resolve) throws ClassNotFoundException {
304:                if (classLoaderSearchMode == ORIGINAL_SEARCH)
305:                    return loadSafeClass(name, resolve);
306:                else
307:                    return loadOptimizedClass(name, resolve);
308:            }
309:
310:            /**
311:             * This method executes the old class loading behaviour before optimization.
312:             * 
313:             * @param name
314:             * @param resolve
315:             * @return
316:             * @throws ClassNotFoundException
317:             */
318:            protected synchronized Class<?> loadSafeClass(String name,
319:                    boolean resolve) throws ClassNotFoundException {
320:                //
321:                // Check if class is in the loaded classes cache
322:                //
323:                Class cachedClass = findLoadedClass(name);
324:                if (cachedClass != null) {
325:                    return resolveClass(cachedClass, resolve);
326:                }
327:
328:                // This is a reasonable hack.  We can add some classes to the list below.
329:                // Since we know these classes are in the system class loader let's not waste our
330:                // time going through the hierarchy.
331:                //
332:                // The order is based on profiling the server.  It may not be optimal for all
333:                // workloads.
334:
335:                if (name.startsWith("java.") || name.equals("boolean")
336:                        || name.equals("int") || name.equals("double")
337:                        || name.equals("long")) {
338:                    Class clazz = ClassLoader.getSystemClassLoader().loadClass(
339:                            name);
340:                    return resolveClass(clazz, resolve);
341:                }
342:
343:                //
344:                // if we are using inverse class loading, check local urls first
345:                //
346:                if (inverseClassLoading && !isDestroyed()
347:                        && !isNonOverridableClass(name)) {
348:                    try {
349:                        Class clazz = findClass(name);
350:                        return resolveClass(clazz, resolve);
351:                    } catch (ClassNotFoundException ignored) {
352:                    }
353:                }
354:
355:                //
356:                // Check parent class loaders
357:                //
358:                if (!isHiddenClass(name)) {
359:                    for (ClassLoader parent : parents) {
360:                        try {
361:                            Class clazz = parent.loadClass(name);
362:                            return resolveClass(clazz, resolve);
363:                        } catch (ClassNotFoundException ignored) {
364:                            // this parent didn't have the class; try the next one
365:                        }
366:                    }
367:                }
368:
369:                //
370:                // if we are not using inverse class loading, check local urls now
371:                //
372:                // don't worry about excluding non-overridable classes here... we
373:                // have alredy checked he parent and the parent didn't have the
374:                // class, so we can override now
375:                if (!isDestroyed()) {
376:                    try {
377:                        Class clazz = findClass(name);
378:                        return resolveClass(clazz, resolve);
379:                    } catch (ClassNotFoundException ignored) {
380:                    }
381:                }
382:
383:                throw new ClassNotFoundException(name + " in classloader " + id);
384:            }
385:
386:            /**
387:             * 
388:             * Optimized classloading.
389:             * 
390:             * This method is the normal way to resolve class loads.  This method recursively calls its parents to resolve 
391:             * classloading requests.  Here is the sequence of operations:
392:             * 
393:             *   1. Call findClass to see if we already have this class loaded.
394:             *   2. If not, call the SystemClassLoader which needs to be called anyway.
395:             *   3. Check if inverse loading, if so look in our class loader.
396:             *   4. Search our parents, recursively.  Keeping track of which parents have already been called.
397:             *      Since MultiParentClassLoaders can appear more than once we do not search an already searched classloader.
398:             *   5. Search our classloader.  
399:             * 
400:             */
401:            protected synchronized Class<?> loadOptimizedClass(String name,
402:                    boolean resolve) throws ClassNotFoundException {
403:                // System.err.println("Started load for class "+name+" in classloader "+this);
404:                //
405:                // Check if class is in the loaded classes cache
406:                //
407:                Class cachedClass = findLoadedClass(name);
408:                if (cachedClass != null) {
409:                    return resolveClass(cachedClass, resolve);
410:                }
411:
412:                //
413:                // No dice, let's offer the primordial loader a shot...
414:                //
415:                try {
416:                    return resolveClass(findSystemClass(name), resolve);
417:                } catch (ClassNotFoundException cnfe) {
418:                    // ignore...just being a good citizen.
419:                }
420:
421:                //
422:                // if we are using inverse class loading, check local urls first
423:                //
424:                if (inverseClassLoading && !isDestroyed()
425:                        && !isNonOverridableClass(name)) {
426:                    try {
427:                        Class clazz = findClass(name);
428:                        return resolveClass(clazz, resolve);
429:                    } catch (ClassNotFoundException ignored) {
430:                    }
431:                }
432:
433:                //
434:                // Check parent class loaders
435:                //
436:                if (!isHiddenClass(name)) {
437:                    try {
438:                        LinkedList<ClassLoader> visitedClassLoaders = new LinkedList<ClassLoader>();
439:                        Class clazz = checkParents(name, resolve,
440:                                visitedClassLoaders);
441:                        if (clazz != null)
442:                            return resolveClass(clazz, resolve);
443:                    } catch (ClassNotFoundException cnfe) {
444:                        // ignore
445:                    }
446:                }
447:
448:                //
449:                // if we are not using inverse class loading, check local urls now
450:                //
451:                // don't worry about excluding non-overridable classes here... we
452:                // have alredy checked he parent and the parent didn't have the
453:                // class, so we can override now
454:                if (!isDestroyed()) {
455:                    try {
456:                        Class clazz = findClass(name);
457:                        return resolveClass(clazz, resolve);
458:                    } catch (ClassNotFoundException ignored) {
459:                    }
460:                }
461:
462:                throw new ClassNotFoundException(name + " in classloader " + id);
463:            }
464:
465:            /**
466:             * This method is an internal hook that allows us to be performant on Class lookups when multiparent
467:             * classloaders are involved.  We can bypass certain lookups that have already occurred in the initiating
468:             * classloader.  Also, we track the classLoaders that are visited by adding them to an already vistied list.
469:             * In this way, we can bypass redundant checks for the same class.
470:             * 
471:             * @param name
472:             * @param visitedClassLoaders
473:             * @return
474:             * @throws ClassNotFoundException
475:             */
476:            protected synchronized Class<?> loadClassInternal(String name,
477:                    boolean resolve, LinkedList<ClassLoader> visitedClassLoaders)
478:                    throws ClassNotFoundException {
479:                //
480:                // Check if class is in the loaded classes cache
481:                //
482:                Class cachedClass = findLoadedClass(name);
483:                if (cachedClass != null) {
484:                    return resolveClass(cachedClass, resolve);
485:                }
486:
487:                //
488:                // Check parent class loaders
489:                //
490:                if (!isHiddenClass(name)) {
491:                    try {
492:                        Class clazz = checkParents(name, resolve,
493:                                visitedClassLoaders);
494:                        if (clazz != null)
495:                            return resolveClass(clazz, resolve);
496:                    } catch (ClassNotFoundException cnfe) {
497:                        // ignore
498:                    }
499:                }
500:
501:                //
502:                // if we are not using inverse class loading, check local urls now
503:                //
504:                // don't worry about excluding non-overridable classes here... we
505:                // have alredy checked he parent and the parent didn't have the
506:                // class, so we can override now
507:                if (!isDestroyed()) {
508:                    Class clazz = findClass(name);
509:                    return resolveClass(clazz, resolve);
510:                }
511:
512:                return null; // Caler is expecting a class.  Null indicates CNFE and will save some time.
513:            }
514:
515:            /**
516:             * In order to optimize the classLoading process and visit a directed set of 
517:             * classloaders this internal method for Geronimo MultiParentClassLoaders 
518:             * is used.  Effectively, as each classloader is visited it is passed a linked
519:             * list of classloaders that have already been visited and can safely be skipped.
520:             * This method assumes the context of an MPCL and is not for use external to this class.
521:             * 
522:             * @param name
523:             * @param visitedClassLoaders
524:             * @return
525:             * @throws ClassNotFoundException
526:             */
527:            private synchronized Class<?> checkParents(String name,
528:                    boolean resolve, LinkedList<ClassLoader> visitedClassLoaders)
529:                    throws ClassNotFoundException {
530:                for (ClassLoader parent : parents) {
531:                    //  When we've encountered the primordial loader we are done.  Since we've already looked there we do not need
532:                    // to repeat the check.  Simply return null and all things will be handled nicely.
533:                    if (parent == ClassLoader.getSystemClassLoader())
534:                        return null;
535:                    if (!visitedClassLoaders.contains(parent)) {
536:                        visitedClassLoaders.add(parent); // Track that we've been here before
537:                        try {
538:                            if (parent instanceof  MultiParentClassLoader) {
539:                                Class clazz = ((MultiParentClassLoader) parent)
540:                                        .loadClassInternal(name, resolve,
541:                                                visitedClassLoaders);
542:                                if (clazz != null)
543:                                    return resolveClass(clazz, resolve);
544:                            } else {
545:                                return parent.loadClass(name);
546:                            }
547:                        } catch (ClassNotFoundException cnfe) {
548:                            // ignore
549:                        }
550:                    }
551:                }
552:                // To avoid yet another CNFE we'll simply return null and let the caller handle appropriately.
553:                return null;
554:            }
555:
556:            private boolean isNonOverridableClass(String name) {
557:                for (String nonOverridableClass : nonOverridableClasses) {
558:                    if (name.startsWith(nonOverridableClass)) {
559:                        return true;
560:                    }
561:                }
562:                return false;
563:            }
564:
565:            private boolean isHiddenClass(String name) {
566:                for (String hiddenClass : hiddenClasses) {
567:                    if (name.startsWith(hiddenClass)) {
568:                        return true;
569:                    }
570:                }
571:                return false;
572:            }
573:
574:            private Class resolveClass(Class clazz, boolean resolve) {
575:                if (resolve) {
576:                    resolveClass(clazz);
577:                }
578:                return clazz;
579:            }
580:
581:            public URL getResource(String name) {
582:                if (isDestroyed()) {
583:                    return null;
584:                }
585:
586:                //
587:                // if we are using inverse class loading, check local urls first
588:                //
589:                if (inverseClassLoading && !isDestroyed()
590:                        && !isNonOverridableResource(name)) {
591:                    URL url = findResource(name);
592:                    if (url != null) {
593:                        return url;
594:                    }
595:                }
596:
597:                //
598:                // Check parent class loaders
599:                //
600:                if (!isHiddenResource(name)) {
601:                    for (ClassLoader parent : parents) {
602:                        URL url = parent.getResource(name);
603:                        if (url != null) {
604:                            return url;
605:                        }
606:                    }
607:                }
608:
609:                //
610:                // if we are not using inverse class loading, check local urls now
611:                //
612:                // don't worry about excluding non-overridable resources here... we
613:                // have alredy checked he parent and the parent didn't have the
614:                // resource, so we can override now
615:                if (!isDestroyed()) {
616:                    // parents didn't have the resource; attempt to load it from my urls
617:                    return findResource(name);
618:                }
619:
620:                return null;
621:            }
622:
623:            public Enumeration<URL> findResources(String name)
624:                    throws IOException {
625:                if (isDestroyed()) {
626:                    return Collections.enumeration(Collections.EMPTY_SET);
627:                }
628:
629:                Set<ClassLoader> knownClassloaders = new HashSet<ClassLoader>();
630:                List<Enumeration<URL>> enumerations = new ArrayList<Enumeration<URL>>();
631:
632:                recursiveFind(knownClassloaders, enumerations, name);
633:
634:                return new UnionEnumeration<URL>(enumerations);
635:            }
636:
637:            protected void recursiveFind(Set<ClassLoader> knownClassloaders,
638:                    List<Enumeration<URL>> enumerations, String name)
639:                    throws IOException {
640:                if (isDestroyed() || knownClassloaders.contains(this )) {
641:                    return;
642:                }
643:                knownClassloaders.add(this );
644:                if (inverseClassLoading && !isNonOverridableResource(name)) {
645:                    enumerations.add(internalfindResources(name));
646:                }
647:                if (!isHiddenResource(name)) {
648:                    for (ClassLoader parent : parents) {
649:                        if (parent instanceof  MultiParentClassLoader) {
650:                            ((MultiParentClassLoader) parent).recursiveFind(
651:                                    knownClassloaders, enumerations, name);
652:                        } else {
653:                            if (!knownClassloaders.contains(parent)) {
654:                                enumerations.add(parent.getResources(name));
655:                                knownClassloaders.add(parent);
656:                            }
657:                        }
658:                    }
659:                }
660:                if (!inverseClassLoading) {
661:                    enumerations.add(internalfindResources(name));
662:                }
663:            }
664:
665:            protected Enumeration<URL> internalfindResources(String name)
666:                    throws IOException {
667:                return super .findResources(name);
668:            }
669:
670:            private boolean isNonOverridableResource(String name) {
671:                for (String nonOverridableResource : nonOverridableResources) {
672:                    if (name.startsWith(nonOverridableResource)) {
673:                        return true;
674:                    }
675:                }
676:                return false;
677:            }
678:
679:            private boolean isHiddenResource(String name) {
680:                for (String hiddenResource : hiddenResources) {
681:                    if (name.startsWith(hiddenResource)) {
682:                        return true;
683:                    }
684:                }
685:                return false;
686:            }
687:
688:            public String toString() {
689:                return "[" + getClass().getName() + " id=" + id + "]";
690:            }
691:
692:            public synchronized boolean isDestroyed() {
693:                return destroyed;
694:            }
695:
696:            public void destroy() {
697:                synchronized (this ) {
698:                    if (destroyed)
699:                        return;
700:                    destroyed = true;
701:                }
702:
703:                LogFactory.release(this );
704:                clearSoftCache(ObjectInputStream.class, "subclassAudits");
705:                clearSoftCache(ObjectOutputStream.class, "subclassAudits");
706:                clearSoftCache(ObjectStreamClass.class, "localDescs");
707:                clearSoftCache(ObjectStreamClass.class, "reflectors");
708:
709:                // The beanInfoCache in java.beans.Introspector will hold on to Classes which
710:                // it has introspected. If we don't flush the cache, we may run out of
711:                // Permanent Generation space.
712:                Introspector.flushCaches();
713:
714:                ClassLoaderRegistry.remove(this );
715:            }
716:
717:            private static final Object lock = new Object();
718:            private static boolean clearSoftCacheFailed = false;
719:
720:            private static void clearSoftCache(Class clazz, String fieldName) {
721:                Map cache = null;
722:                try {
723:                    Field f = clazz.getDeclaredField(fieldName);
724:                    f.setAccessible(true);
725:                    cache = (Map) f.get(null);
726:                } catch (Throwable e) {
727:                    synchronized (lock) {
728:                        if (!clearSoftCacheFailed) {
729:                            clearSoftCacheFailed = true;
730:                            LogFactory.getLog(MultiParentClassLoader.class)
731:                                    .debug(
732:                                            "Unable to clear SoftCache field "
733:                                                    + fieldName + " in class "
734:                                                    + clazz);
735:                        }
736:                    }
737:                }
738:
739:                if (cache != null) {
740:                    synchronized (cache) {
741:                        cache.clear();
742:                    }
743:                }
744:            }
745:
746:            protected void finalize() throws Throwable {
747:                ClassLoaderRegistry.remove(this);
748:                super.finalize();
749:            }
750:
751:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.