1:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48:
49:
50:
56: public class RMIClassLoader
57: {
58:
61: private RMIClassLoader() {}
62:
63: private static class MyClassLoader extends URLClassLoader
64: {
65:
66: MyClassLoader (URL[] urls, ClassLoader parent, String annotation)
67: {
68: super (urls, parent);
69: this.annotation = annotation;
70: }
71:
72: private MyClassLoader (URL[] urls, ClassLoader parent)
73: {
74: super (urls, parent);
75: this.annotation = urlToAnnotation (urls);
76: }
77:
78: public static String urlToAnnotation (URL[] urls)
79: {
80: if (urls.length == 0)
81: return null;
82:
83: StringBuffer annotation = new StringBuffer (64 * urls.length);
84:
85: for (int i = 0; i < urls.length; i++)
86: {
87: annotation.append (urls [i].toExternalForm());
88: annotation.append (' ');
89: }
90:
91: return annotation.toString();
92: }
93:
94: public final String getClassAnnotation()
95: {
96: return annotation;
97: }
98:
99: private final String annotation;
100: }
101:
102:
106: private static class CacheKey
107: {
108: private String mCodeBase;
109: private ClassLoader mContextClassLoader;
110:
111: public CacheKey (String theCodebase, ClassLoader theContextClassLoader)
112: {
113: mCodeBase = theCodebase;
114: mContextClassLoader = theContextClassLoader;
115: }
116:
117:
120: public boolean equals (Object theOther)
121: {
122: if (theOther instanceof CacheKey)
123: {
124: CacheKey key = (CacheKey) theOther;
125:
126: return (equals (this.mCodeBase,key.mCodeBase)
127: && equals (this.mContextClassLoader, key.mContextClassLoader));
128: }
129: return false;
130: }
131:
132:
138: private boolean equals (Object theOne, Object theOther)
139: {
140: return theOne != null ? theOne.equals (theOther) : theOther == null;
141: }
142:
143:
146: public int hashCode()
147: {
148: return ((mCodeBase != null ? mCodeBase.hashCode() : 0)
149: ^(mContextClassLoader != null ? mContextClassLoader.hashCode() : -1));
150: }
151:
152: public String toString()
153: {
154: return "[" + mCodeBase + "," + mContextClassLoader + "]";
155: }
156:
157: }
158:
159: private static Map cacheLoaders;
160: private static Map cacheAnnotations;
161:
162:
163:
164: private static String defaultAnnotation;
165:
166:
167: private static URL defaultCodebase;
168:
169:
170: private static MyClassLoader defaultLoader;
171:
172: static
173: {
174:
175: cacheLoaders = new Hashtable (89);
176: cacheAnnotations = new Hashtable (89);
177:
178: defaultAnnotation = System.getProperty ("java.rmi.server.defaultAnnotation");
179:
180: try
181: {
182: if (defaultAnnotation != null)
183: defaultCodebase = new URL (defaultAnnotation);
184: }
185: catch (Exception _)
186: {
187: defaultCodebase = null;
188: }
189:
190: if (defaultCodebase != null)
191: {
192: defaultLoader = new MyClassLoader (new URL[] { defaultCodebase }, null,
193: defaultAnnotation);
194: cacheLoaders.put (new CacheKey (defaultAnnotation,
195: Thread.currentThread().getContextClassLoader()),
196: defaultLoader);
197: }
198: }
199:
200:
203: public static Class loadClass (String name)
204: throws MalformedURLException, ClassNotFoundException
205: {
206: return loadClass ("", name);
207: }
208:
209: public static Class loadClass (String codebases, String name)
210: throws MalformedURLException, ClassNotFoundException
211: {
212: ClassLoader loader = Thread.currentThread().getContextClassLoader();
213:
214:
215: try
216: {
217: return loader.loadClass (name);
218: }
219: catch (ClassNotFoundException e)
220: {
221:
222: }
223:
224: if (codebases.length() == 0)
225: {
226: loader = defaultLoader;
227: }
228: else
229: {
230: loader = getClassLoader(codebases);
231: }
232:
233: if (loader == null)
234: {
235:
236: throw new ClassNotFoundException ("Could not find class (" + name +
237: ") at codebase (" + codebases + ")");
238: }
239:
240: return loader.loadClass (name);
241: }
242:
243:
253: public static ClassLoader getClassLoader (String codebases)
254: throws MalformedURLException
255: {
256: ClassLoader loader;
257: CacheKey loaderKey = new CacheKey
258: (codebases, Thread.currentThread().getContextClassLoader());
259: loader = (ClassLoader) cacheLoaders.get (loaderKey);
260:
261: if (loader == null)
262: {
263:
264:
265: StringTokenizer tok = new StringTokenizer (codebases, " ");
266: ArrayList urls = new ArrayList();
267:
268: while (tok.hasMoreTokens())
269: urls.add (new URL (tok.nextToken()));
270:
271: loader = new MyClassLoader ((URL[]) urls.toArray (new URL [urls.size()]),
272: Thread.currentThread().getContextClassLoader(),
273: codebases);
274: cacheLoaders.put (loaderKey, loader);
275: }
276:
277: return loader;
278: }
279:
280:
289: public static String getClassAnnotation (Class cl)
290: {
291: ClassLoader loader = cl.getClassLoader();
292:
293: if (loader == null
294: || loader == ClassLoader.getSystemClassLoader())
295: {
296: return System.getProperty ("java.rmi.server.codebase");
297: }
298:
299: if (loader instanceof MyClassLoader)
300: {
301: return ((MyClassLoader) loader).getClassAnnotation();
302: }
303:
304: String s = (String) cacheAnnotations.get (loader);
305:
306: if (s != null)
307: return s;
308:
309: if (loader instanceof URLClassLoader)
310: {
311: URL[] urls = ((URLClassLoader) loader).getURLs();
312:
313: if (urls.length == 0)
314: return null;
315:
316: StringBuffer annotation = new StringBuffer (64 * urls.length);
317:
318: for (int i = 0; i < urls.length; i++)
319: {
320: annotation.append (urls [i].toExternalForm());
321: annotation.append (' ');
322: }
323:
324: s = annotation.toString();
325: cacheAnnotations.put (loader, s);
326: return s;
327: }
328:
329: return System.getProperty ("java.rmi.server.codebase");
330: }
331:
332:
335: public static Object getSecurityContext (ClassLoader loader)
336: {
337: throw new Error ("Not implemented");
338: }
339: }