1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49:
50:
55: public class RMIClassLoaderImpl extends RMIClassLoaderSpi
56: {
57: private static class MyClassLoader extends URLClassLoader
58: {
59:
60: MyClassLoader (URL[] urls, ClassLoader parent, String annotation)
61: {
62: super (urls, parent);
63: this.annotation = annotation;
64: }
65:
66: private MyClassLoader (URL[] urls, ClassLoader parent)
67: {
68: super (urls, parent);
69: this.annotation = urlToAnnotation (urls);
70: }
71:
72: public static String urlToAnnotation (URL[] urls)
73: {
74: if (urls.length == 0)
75: return null;
76:
77: StringBuffer annotation = new StringBuffer (64 * urls.length);
78:
79: for (int i = 0; i < urls.length; i++)
80: {
81: annotation.append (urls [i].toExternalForm());
82: annotation.append (' ');
83: }
84:
85: return annotation.toString();
86: }
87:
88: public final String getClassAnnotation()
89: {
90: return annotation;
91: }
92:
93: private final String annotation;
94: }
95:
96:
100: private static class CacheKey
101: {
102: private String mCodeBase;
103: private ClassLoader mContextClassLoader;
104:
105: public CacheKey (String theCodebase, ClassLoader theContextClassLoader)
106: {
107: mCodeBase = theCodebase;
108: mContextClassLoader = theContextClassLoader;
109: }
110:
111:
114: public boolean equals (Object theOther)
115: {
116: if (theOther instanceof CacheKey)
117: {
118: CacheKey key = (CacheKey) theOther;
119:
120: return (equals (this.mCodeBase,key.mCodeBase)
121: && equals (this.mContextClassLoader, key.mContextClassLoader));
122: }
123: return false;
124: }
125:
126:
132: private boolean equals (Object theOne, Object theOther)
133: {
134: return theOne != null ? theOne.equals (theOther) : theOther == null;
135: }
136:
137:
140: public int hashCode()
141: {
142: return ((mCodeBase != null ? mCodeBase.hashCode() : 0)
143: ^(mContextClassLoader != null ? mContextClassLoader.hashCode() : -1));
144: }
145:
146: public String toString()
147: {
148: return "[" + mCodeBase + "," + mContextClassLoader + "]";
149: }
150:
151: }
152:
153: private static RMIClassLoaderImpl instance = null;
154:
155: private static Map cacheLoaders;
156: private static Map cacheAnnotations;
157:
158: private static MyClassLoader defaultClassLoader;
159:
160:
161:
162: private static String defaultAnnotation;
163:
164:
165: private static URL defaultCodebase;
166:
167: static
168: {
169:
170: cacheLoaders = new Hashtable (89);
171: cacheAnnotations = new Hashtable (89);
172:
173: defaultAnnotation = System.getProperty ("java.rmi.server.defaultAnnotation");
174:
175: try
176: {
177: if (defaultAnnotation != null)
178: defaultCodebase = new URL (defaultAnnotation);
179: }
180: catch (Exception _)
181: {
182: defaultCodebase = null;
183: }
184:
185: if (defaultCodebase != null)
186: {
187: defaultClassLoader = new MyClassLoader (new URL[] { defaultCodebase }, null,
188: defaultAnnotation);
189: cacheLoaders.put (new CacheKey (defaultAnnotation,
190: Thread.currentThread().getContextClassLoader()),
191: defaultClassLoader);
192: }
193: }
194:
195:
199: private RMIClassLoaderImpl()
200: {
201: }
202:
203:
208: public static RMIClassLoaderSpi getInstance()
209: {
210: if (instance == null)
211: instance = new RMIClassLoaderImpl();
212: return instance;
213: }
214:
215: public Class loadClass(String codeBase, String name,
216: ClassLoader defaultLoader)
217: throws MalformedURLException, ClassNotFoundException
218: {
219: ClassLoader loader;
220: if (defaultLoader == null)
221: loader = Thread.currentThread().getContextClassLoader();
222: else
223: loader = defaultLoader;
224:
225:
226: try
227: {
228: return Class.forName(name, false, loader);
229: }
230: catch (ClassNotFoundException e)
231: {
232:
233: }
234:
235: if (codeBase.length() == 0)
236: {
237: loader = defaultClassLoader;
238: }
239: else
240: {
241: loader = getClassLoader(codeBase);
242: }
243:
244: if (loader == null)
245: {
246:
247: throw new ClassNotFoundException ("Could not find class (" + name +
248: ") at codebase (" + codeBase + ")");
249: }
250:
251: return Class.forName(name, false, loader);
252: }
253:
254: public Class loadProxyClass(String codeBase, String[] interfaces,
255: ClassLoader defaultLoader)
256: throws MalformedURLException, ClassNotFoundException
257: {
258:
259: return null;
260: }
261:
262:
272: public ClassLoader getClassLoader(String codebase)
273: throws MalformedURLException
274: {
275: ClassLoader loader;
276: CacheKey loaderKey = new CacheKey
277: (codebase, Thread.currentThread().getContextClassLoader());
278: loader = (ClassLoader) cacheLoaders.get (loaderKey);
279:
280: if (loader == null)
281: {
282:
283:
284: StringTokenizer tok = new StringTokenizer (codebase, " ");
285: ArrayList urls = new ArrayList();
286:
287: while (tok.hasMoreTokens())
288: urls.add (new URL(tok.nextToken()));
289:
290: loader = new MyClassLoader((URL[]) urls.toArray(new URL [urls.size()]),
291: Thread.currentThread().getContextClassLoader(),
292: codebase);
293: cacheLoaders.put (loaderKey, loader);
294: }
295:
296: return loader;
297: }
298:
299:
308: public String getClassAnnotation(Class cl)
309: {
310: ClassLoader loader = cl.getClassLoader();
311:
312: if (loader == null
313: || loader == ClassLoader.getSystemClassLoader())
314: {
315: return System.getProperty ("java.rmi.server.codebase");
316: }
317:
318: if (loader instanceof MyClassLoader)
319: {
320: return ((MyClassLoader) loader).getClassAnnotation();
321: }
322:
323: String s = (String) cacheAnnotations.get (loader);
324:
325: if (s != null)
326: return s;
327:
328: if (loader instanceof URLClassLoader)
329: {
330: URL[] urls = ((URLClassLoader) loader).getURLs();
331:
332: if (urls.length == 0)
333: return null;
334:
335: StringBuffer annotation = new StringBuffer (64 * urls.length);
336:
337: for (int i = 0; i < urls.length; i++)
338: {
339: annotation.append (urls [i].toExternalForm());
340: annotation.append (' ');
341: }
342:
343: s = annotation.toString();
344: cacheAnnotations.put (loader, s);
345: return s;
346: }
347:
348: return System.getProperty ("java.rmi.server.codebase");
349: }
350: }