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