1 |
/* RMIClassLoader.java |
/* RMIClassLoader.java |
2 |
Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc. |
Copyright (c) 1996, 1997, 1998, 1999, 2002, 2003 |
3 |
|
Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
6 |
|
|
53 |
* RMI parameters and return values. |
* RMI parameters and return values. |
54 |
*/ |
*/ |
55 |
public class RMIClassLoader |
public class RMIClassLoader |
56 |
{ |
{ |
57 |
static private class MyClassLoader extends URLClassLoader |
static private class MyClassLoader extends URLClassLoader |
58 |
|
{ |
59 |
|
private MyClassLoader (URL[] urls, ClassLoader parent, String annotation) |
60 |
{ |
{ |
61 |
private MyClassLoader(URL[] urls, ClassLoader parent, String annotation) |
super (urls, parent); |
|
{ |
|
|
super(urls, parent); |
|
62 |
this.annotation = annotation; |
this.annotation = annotation; |
63 |
} |
} |
64 |
|
|
65 |
private MyClassLoader(URL[] urls, ClassLoader parent) |
private MyClassLoader (URL[] urls, ClassLoader parent) |
66 |
{ |
{ |
67 |
super(urls, parent); |
super (urls, parent); |
68 |
this.annotation = urlToAnnotation(urls); |
this.annotation = urlToAnnotation (urls); |
69 |
} |
} |
70 |
|
|
71 |
public static String urlToAnnotation(URL[] urls) |
public static String urlToAnnotation (URL[] urls) |
72 |
{ |
{ |
73 |
if (urls.length == 0) |
if (urls.length == 0) |
|
{ |
|
74 |
return null; |
return null; |
|
} |
|
75 |
|
|
76 |
StringBuffer annotation = new StringBuffer(64 * urls.length); |
StringBuffer annotation = new StringBuffer (64 * urls.length); |
77 |
|
|
78 |
for (int i = 0; i < urls.length; i++) |
for (int i = 0; i < urls.length; i++) |
79 |
{ |
{ |
80 |
annotation.append(urls[i].toExternalForm()); |
annotation.append (urls [i].toExternalForm()); |
81 |
annotation.append(' '); |
annotation.append (' '); |
82 |
} |
} |
83 |
|
|
84 |
return annotation.toString(); |
return annotation.toString(); |
85 |
} |
} |
86 |
|
|
87 |
public final String getClassAnnotation() |
public final String getClassAnnotation() |
88 |
{ |
{ |
89 |
return annotation; |
return annotation; |
90 |
} |
} |
91 |
|
|
92 |
private final String annotation; |
private final String annotation; |
93 |
|
} |
|
} |
|
94 |
|
|
95 |
/** |
/** |
96 |
* This class is used to identify a cached classloader by its codebase and |
* This class is used to identify a cached classloader by its codebase and |
98 |
*/ |
*/ |
99 |
private static class CacheKey |
private static class CacheKey |
100 |
{ |
{ |
101 |
|
private String mCodeBase; |
102 |
|
private ClassLoader mContextClassLoader; |
103 |
|
|
104 |
private String mCodeBase; |
public CacheKey (String theCodebase, ClassLoader theContextClassLoader) |
105 |
private ClassLoader mContextClassLoader; |
{ |
106 |
|
mCodeBase = theCodebase; |
107 |
public CacheKey(String theCodebase, ClassLoader theContextClassLoader) |
mContextClassLoader = theContextClassLoader; |
108 |
{ |
} |
|
mCodeBase = theCodebase; |
|
|
mContextClassLoader = theContextClassLoader; |
|
|
} |
|
|
|
|
|
|
|
109 |
|
|
110 |
/** |
/** |
111 |
* @return true if the codebase and the context classloader are equal |
* @return true if the codebase and the context classloader are equal |
112 |
*/ |
*/ |
113 |
public boolean equals(Object theOther) |
public boolean equals (Object theOther) |
114 |
{ |
{ |
115 |
if(theOther != null && theOther instanceof CacheKey) |
if (theOther != null |
116 |
{ |
&& theOther instanceof CacheKey) |
117 |
|
{ |
118 |
CacheKey key = (CacheKey) theOther; |
CacheKey key = (CacheKey) theOther; |
119 |
return ( equals(this.mCodeBase,key.mCodeBase) |
|
120 |
&& equals(this.mContextClassLoader,key.mContextClassLoader) ); |
return (equals (this.mCodeBase,key.mCodeBase) |
121 |
|
&& equals (this.mContextClassLoader, key.mContextClassLoader)); |
122 |
} |
} |
123 |
return false; |
return false; |
124 |
} |
} |
129 |
* @param theOther |
* @param theOther |
130 |
* @return |
* @return |
131 |
*/ |
*/ |
132 |
private boolean equals(Object theOne, Object theOther) |
private boolean equals (Object theOne, Object theOther) |
133 |
{ |
{ |
134 |
return (theOne != null ? theOne.equals(theOther): theOther == null); |
return theOne != null ? theOne.equals (theOther) : theOther == null; |
135 |
} |
} |
136 |
|
|
137 |
/** |
/** |
140 |
public int hashCode() |
public int hashCode() |
141 |
{ |
{ |
142 |
return ((mCodeBase != null ? mCodeBase.hashCode() : 0) |
return ((mCodeBase != null ? mCodeBase.hashCode() : 0) |
143 |
^(mContextClassLoader != null ? mContextClassLoader.hashCode() : -1)); |
^(mContextClassLoader != null ? mContextClassLoader.hashCode() : -1)); |
144 |
} |
} |
145 |
|
|
|
|
|
146 |
public String toString() |
public String toString() |
147 |
{ |
{ |
148 |
return "["+mCodeBase+","+mContextClassLoader+"]"; |
return "[" + mCodeBase + "," + mContextClassLoader + "]"; |
149 |
} |
} |
150 |
|
|
151 |
} |
} |
161 |
private static MyClassLoader defaultLoader; |
private static MyClassLoader defaultLoader; |
162 |
|
|
163 |
static |
static |
164 |
{ |
{ |
165 |
// 89 is a nice prime number for Hashtable initial capacity |
// 89 is a nice prime number for Hashtable initial capacity |
166 |
cacheLoaders = new Hashtable(89); |
cacheLoaders = new Hashtable (89); |
167 |
cacheAnnotations = new Hashtable(89); |
cacheAnnotations = new Hashtable (89); |
168 |
|
|
169 |
defaultAnnotation = System.getProperty("java.rmi.server.defaultAnnotation"); |
defaultAnnotation = System.getProperty ("java.rmi.server.defaultAnnotation"); |
170 |
|
|
171 |
try |
try |
172 |
{ |
{ |
173 |
if (defaultAnnotation != null) |
if (defaultAnnotation != null) |
174 |
{ |
defaultCodebase = new URL (defaultAnnotation); |
175 |
defaultCodebase = new URL(defaultAnnotation); |
} |
|
} |
|
|
} |
|
176 |
catch (Exception _) |
catch (Exception _) |
177 |
{ |
{ |
178 |
defaultCodebase = null; |
defaultCodebase = null; |
179 |
} |
} |
180 |
|
|
181 |
if (defaultCodebase != null) |
if (defaultCodebase != null) |
182 |
{ |
{ |
183 |
defaultLoader = new MyClassLoader(new URL[] { defaultCodebase }, null, |
defaultLoader = new MyClassLoader (new URL[] { defaultCodebase }, null, |
184 |
defaultAnnotation); |
defaultAnnotation); |
185 |
cacheLoaders.put(new CacheKey(defaultAnnotation,Thread.currentThread().getContextClassLoader()), defaultLoader); |
cacheLoaders.put (new CacheKey (defaultAnnotation, |
186 |
|
Thread.currentThread().getContextClassLoader()), |
187 |
|
defaultLoader); |
188 |
} |
} |
189 |
} |
} |
190 |
|
|
191 |
/** |
/** |
192 |
* @deprecated |
* @deprecated |
193 |
*/ |
*/ |
194 |
public static Class loadClass(String name) |
public static Class loadClass (String name) |
195 |
throws MalformedURLException, ClassNotFoundException |
throws MalformedURLException, ClassNotFoundException |
196 |
{ |
{ |
197 |
return (loadClass("", name)); |
return loadClass ("", name); |
198 |
} |
} |
199 |
|
|
200 |
public static Class loadClass(String codebases, String name) |
public static Class loadClass (String codebases, String name) |
201 |
throws MalformedURLException, ClassNotFoundException |
throws MalformedURLException, ClassNotFoundException |
202 |
{ |
{ |
|
Class c = null; |
|
203 |
ClassLoader loader = Thread.currentThread().getContextClassLoader(); |
ClassLoader loader = Thread.currentThread().getContextClassLoader(); |
204 |
|
|
205 |
//try context class loader first |
//try context class loader first |
206 |
try |
try |
207 |
{ |
{ |
208 |
c = loader.loadClass(name); |
return loader.loadClass (name); |
209 |
|
} |
|
return c; |
|
|
} |
|
210 |
catch (ClassNotFoundException e) |
catch (ClassNotFoundException e) |
211 |
{ |
{ |
212 |
// class not found in the local classpath |
// class not found in the local classpath |
213 |
} |
} |
214 |
|
|
215 |
if (codebases.length() == 0) //=="" |
if (codebases.length() == 0) //=="" |
216 |
{ |
{ |
217 |
loader = defaultLoader; |
loader = defaultLoader; |
218 |
} |
} |
219 |
else |
else |
220 |
{ |
{ |
221 |
loader = getClassLoader(codebases); |
loader = getClassLoader(codebases); |
222 |
} |
} |
223 |
|
|
224 |
if (loader == null) |
if (loader == null) |
225 |
{ |
{ |
226 |
//do not throw NullPointerException |
//do not throw NullPointerException |
227 |
throw new ClassNotFoundException("Could not find class (" + name + |
throw new ClassNotFoundException ("Could not find class (" + name + |
228 |
") at codebase (" + codebases + ")"); |
") at codebase (" + codebases + ")"); |
229 |
} |
} |
230 |
|
|
231 |
return loader.loadClass(name); |
return loader.loadClass (name); |
232 |
} |
} |
233 |
|
|
234 |
/** |
/** |
235 |
* Gets a classloader for the given codebase and with the current context classloader |
* Gets a classloader for the given codebase and with the current |
236 |
* as parent. |
* context classloader as parent. |
237 |
* @param codebases |
* |
238 |
* @return a classloader for the given codebase |
* @param codebases |
239 |
* @throws MalformedURLException if the codebase contains a malformed URL |
* |
240 |
*/ |
* @return a classloader for the given codebase |
241 |
private static ClassLoader getClassLoader(String codebases) throws MalformedURLException |
* |
242 |
{ |
* @throws MalformedURLException if the codebase contains a malformed URL |
243 |
ClassLoader loader; |
*/ |
244 |
CacheKey loaderKey = new CacheKey(codebases, Thread.currentThread().getContextClassLoader()); |
private static ClassLoader getClassLoader (String codebases) |
245 |
loader = (ClassLoader) cacheLoaders.get(loaderKey); |
throws MalformedURLException |
246 |
|
{ |
247 |
|
ClassLoader loader; |
248 |
|
CacheKey loaderKey = new CacheKey |
249 |
|
(codebases, Thread.currentThread().getContextClassLoader()); |
250 |
|
loader = (ClassLoader) cacheLoaders.get (loaderKey); |
251 |
|
|
252 |
if (loader == null) |
if (loader == null) |
253 |
{ |
{ |
254 |
//create an entry in cacheLoaders mapping a loader to codebases. |
//create an entry in cacheLoaders mapping a loader to codebases. |
255 |
// codebases are separated by " " |
// codebases are separated by " " |
256 |
StringTokenizer tok = new StringTokenizer(codebases, " "); |
StringTokenizer tok = new StringTokenizer (codebases, " "); |
257 |
ArrayList urls = new ArrayList(); |
ArrayList urls = new ArrayList(); |
258 |
|
|
259 |
while (tok.hasMoreTokens()) |
while (tok.hasMoreTokens()) |
260 |
urls.add(new URL(tok.nextToken())); |
urls.add (new URL (tok.nextToken())); |
261 |
|
|
262 |
loader = new MyClassLoader( (URL[]) urls.toArray(new URL[urls.size()]), |
loader = new MyClassLoader ((URL[]) urls.toArray (new URL [urls.size()]), |
263 |
Thread.currentThread().getContextClassLoader(), |
Thread.currentThread().getContextClassLoader(), |
264 |
codebases); |
codebases); |
265 |
cacheLoaders.put(loaderKey, loader); |
cacheLoaders.put (loaderKey, loader); |
266 |
} |
} |
267 |
|
|
268 |
return loader; |
return loader; |
269 |
} |
} |
270 |
|
|
271 |
/** |
/** |
272 |
* Returns a string representation of the network location where a remote |
* Returns a string representation of the network location where a remote |
273 |
* endpoint can get the class-definition of the given class. |
* endpoint can get the class-definition of the given class. |
274 |
|
* |
275 |
* @param cl |
* @param cl |
276 |
* @return a space seperated list of URLs where the class-definition of cl may be found |
* |
277 |
|
* @return a space seperated list of URLs where the class-definition |
278 |
|
* of cl may be found |
279 |
*/ |
*/ |
280 |
public static String getClassAnnotation(Class cl) |
public static String getClassAnnotation (Class cl) |
281 |
{ |
{ |
282 |
ClassLoader loader = cl.getClassLoader(); |
ClassLoader loader = cl.getClassLoader(); |
283 |
|
|
284 |
if ((loader == null) || (loader == ClassLoader.getSystemClassLoader())) |
if ((loader == null) |
285 |
|
|| (loader == ClassLoader.getSystemClassLoader())) |
286 |
{ |
{ |
287 |
return System.getProperty("java.rmi.server.codebase"); |
return System.getProperty ("java.rmi.server.codebase"); |
288 |
} |
} |
289 |
|
|
290 |
if (loader instanceof MyClassLoader) |
if (loader instanceof MyClassLoader) |
291 |
{ |
{ |
292 |
return ((MyClassLoader) loader).getClassAnnotation(); |
return ((MyClassLoader) loader).getClassAnnotation(); |
293 |
} |
} |
294 |
|
|
295 |
String s = (String) cacheAnnotations.get(loader); |
String s = (String) cacheAnnotations.get (loader); |
296 |
|
|
297 |
if (s != null) |
if (s != null) |
298 |
{ |
{ |
299 |
return s; |
return s; |
300 |
} |
} |
301 |
|
|
302 |
if (loader instanceof URLClassLoader) |
if (loader instanceof URLClassLoader) |
303 |
{ |
{ |
304 |
URL[] urls = ((URLClassLoader) loader).getURLs(); |
URL[] urls = ((URLClassLoader) loader).getURLs(); |
305 |
|
|
306 |
if (urls.length == 0) |
if (urls.length == 0) |
307 |
{ |
{ |
308 |
return null; |
return null; |
309 |
} |
} |
|
|
|
|
StringBuffer annotation = new StringBuffer(64 * urls.length); |
|
310 |
|
|
311 |
for (int i = 0; i < urls.length; i++) |
StringBuffer annotation = new StringBuffer (64 * urls.length); |
|
{ |
|
|
annotation.append(urls[i].toExternalForm()); |
|
|
annotation.append(' '); |
|
|
} |
|
312 |
|
|
313 |
s = annotation.toString(); |
for (int i = 0; i < urls.length; i++) |
314 |
cacheAnnotations.put(loader, s); |
{ |
315 |
|
annotation.append (urls [i].toExternalForm()); |
316 |
|
annotation.append (' '); |
317 |
|
} |
318 |
|
|
319 |
return s; |
s = annotation.toString(); |
320 |
|
cacheAnnotations.put (loader, s); |
321 |
|
return s; |
322 |
} |
} |
323 |
|
|
324 |
return System.getProperty("java.rmi.server.codebase"); |
return System.getProperty ("java.rmi.server.codebase"); |
325 |
} |
} |
326 |
|
|
327 |
/** |
/** |
328 |
* @deprecated |
* @deprecated |
329 |
*/ |
*/ |
330 |
public static Object getSecurityContext(ClassLoader loader) |
public static Object getSecurityContext (ClassLoader loader) |
331 |
{ |
{ |
332 |
throw new Error("Not implemented"); |
throw new Error ("Not implemented"); |
|
} |
|
333 |
} |
} |
334 |
|
} |