KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > corba > se > impl > util > JDKClassLoader


1 /*
2  * @(#)JDKClassLoader.java 1.23 04/04/07
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 /*
8  * Licensed Materials - Property of IBM
9  * RMI-IIOP v1.0
10  * Copyright IBM Corp. 1998 1999 All Rights Reserved
11  *
12  * US Government Users Restricted Rights - Use, duplication or
13  * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
14  */

15
16 package com.sun.corba.se.impl.util;
17
18 import sun.corba.Bridge ;
19
20 import java.util.Map JavaDoc ;
21 import java.util.WeakHashMap JavaDoc ;
22 import java.util.Collections JavaDoc ;
23
24 import java.security.AccessController JavaDoc ;
25 import java.security.PrivilegedAction JavaDoc ;
26
27 /**
28  * Utility method for crawling call stack to load class
29  */

30 class JDKClassLoader {
31
32     private static final JDKClassLoaderCache classCache
33         = new JDKClassLoaderCache();
34
35     private static final Bridge bridge =
36     (Bridge)AccessController.doPrivileged(
37         new PrivilegedAction JavaDoc() {
38         public Object JavaDoc run() {
39             return Bridge.get() ;
40         }
41         }
42     ) ;
43
44     static Class JavaDoc loadClass(Class JavaDoc aClass, String JavaDoc className)
45     throws ClassNotFoundException JavaDoc {
46
47         // Maintain the same error semantics as Class.forName()
48
if (className == null) {
49             throw new NullPointerException JavaDoc();
50         }
51         if (className.length() == 0) {
52             throw new ClassNotFoundException JavaDoc();
53         }
54
55         // It would be nice to bypass JDKClassLoader's attempts completely
56
// if it's known that the latest user defined ClassLoader will
57
// fail.
58
//
59
// Otherwise, we end up calling Class.forName here as well as in
60
// the next step in JDKBridge. That can take a long time depending
61
// on the length of the classpath.
62

63         // Note: Looking at the only place in JDKBridge where this code
64
// is invoked, it is clear that aClass will always be null.
65
ClassLoader JavaDoc loader;
66         if (aClass != null) {
67             loader = aClass.getClassLoader();
68         } else {
69             loader = bridge.getLatestUserDefinedLoader();
70         }
71         // See createKey for a description of what's involved
72
Object JavaDoc key = classCache.createKey(className, loader);
73
74         if (classCache.knownToFail(key)) {
75             throw new ClassNotFoundException JavaDoc(className);
76         } else {
77             try {
78                 // Loading this class with the call stack
79
// loader isn't known to fail, so try
80
// to load it.
81
return Class.forName(className, false, loader);
82             } catch(ClassNotFoundException JavaDoc cnfe) {
83                 // Record that we failed to find the class
84
// with this particular loader. This way, we won't
85
// waste time looking with this loader, again.
86
classCache.recordFailure(key);
87                 throw cnfe;
88             }
89         }
90     }
91     
92     /**
93      * Private cache implementation specific to JDKClassLoader.
94      */

95     private static class JDKClassLoaderCache
96     {
97         // JDKClassLoader couldn't find the class with the located
98
// ClassLoader. Note this in our cache so JDKClassLoader
99
// can abort early next time.
100
public final void recordFailure(Object JavaDoc key) {
101             cache.put(key, JDKClassLoaderCache.KNOWN_TO_FAIL);
102         }
103
104         // Factory for a key (CacheKey is an implementation detail
105
// of JDKClassLoaderCache).
106
//
107
// A key currently consists of the class name as well as
108
// the latest user defined class loader, so it's fairly
109
// expensive to create.
110
public final Object JavaDoc createKey(String JavaDoc className, ClassLoader JavaDoc latestLoader) {
111             return new CacheKey(className, latestLoader);
112         }
113
114         // Determine whether or not this combination of class name
115
// and ClassLoader is known to fail.
116
public final boolean knownToFail(Object JavaDoc key) {
117             return cache.get(key) == JDKClassLoaderCache.KNOWN_TO_FAIL;
118         }
119
120         // Synchronized WeakHashMap
121
private final Map JavaDoc cache
122             = Collections.synchronizedMap(new WeakHashMap JavaDoc());
123
124         // Cache result used to mark the caches when there is
125
// no way JDKClassLoader could succeed with the given
126
// key
127
private static final Object JavaDoc KNOWN_TO_FAIL = new Object JavaDoc();
128
129         // Key consisting of the class name and the latest
130
// user defined class loader
131
private static class CacheKey
132         {
133             String JavaDoc className;
134             ClassLoader JavaDoc loader;
135         
136             public CacheKey(String JavaDoc className, ClassLoader JavaDoc loader) {
137                 this.className = className;
138                 this.loader = loader;
139             }
140
141             // Try to incorporate both class name and loader
142
// into the hashcode
143
public int hashCode() {
144                 if (loader == null)
145                     return className.hashCode();
146                 else
147                     return className.hashCode() ^ loader.hashCode();
148             }
149
150             public boolean equals(Object JavaDoc obj) {
151                 try {
152
153                     // WeakHashMap may compare null keys
154
if (obj == null)
155                         return false;
156
157                     CacheKey other = (CacheKey)obj;
158
159                     // I've made a decision to actually compare the
160
// loader references. I don't want a case when
161
// two loader instances override their equals
162
// methods and only compare code base.
163
//
164
// This way, at worst, our performance will
165
// be slower, but we know we'll do the correct
166
// loading.
167
return (className.equals(other.className) &&
168                             loader == other.loader);
169                     
170                 } catch (ClassCastException JavaDoc cce) {
171                     return false;
172                 }
173             }
174         }
175     }
176 }
177
Popular Tags