Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / java / rmi / server / RMIClassLoader.java
blob6add274ef3e1c8fdee47ce023cc9f2f529e61c43
1 /* RMIClassLoader.java --
2 Copyright (c) 1996, 1997, 1998, 1999, 2002, 2003, 2004
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA.
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
39 package java.rmi.server;
41 import java.net.MalformedURLException;
42 import java.net.URL;
43 import java.net.URLClassLoader;
44 import java.util.ArrayList;
45 import java.util.Hashtable;
46 import java.util.Map;
47 import java.util.StringTokenizer;
50 /**
51 * This class provides a set of public static utility methods for supporting
52 * network-based class loading in RMI. These methods are called by RMI's
53 * internal marshal streams to implement the dynamic class loading of types for
54 * RMI parameters and return values.
56 public class RMIClassLoader
58 /**
59 * This class isn't intended to be instantiated.
61 private RMIClassLoader() {}
63 private static class MyClassLoader extends URLClassLoader
65 // Package-private to avoid a trampoline constructor.
66 MyClassLoader (URL[] urls, ClassLoader parent, String annotation)
68 super (urls, parent);
69 this.annotation = annotation;
72 private MyClassLoader (URL[] urls, ClassLoader parent)
74 super (urls, parent);
75 this.annotation = urlToAnnotation (urls);
78 public static String urlToAnnotation (URL[] urls)
80 if (urls.length == 0)
81 return null;
83 StringBuffer annotation = new StringBuffer (64 * urls.length);
85 for (int i = 0; i < urls.length; i++)
87 annotation.append (urls [i].toExternalForm());
88 annotation.append (' ');
91 return annotation.toString();
94 public final String getClassAnnotation()
96 return annotation;
99 private final String annotation;
102 /**
103 * This class is used to identify a cached classloader by its codebase and
104 * the context classloader that is its parent.
106 private static class CacheKey
108 private String mCodeBase;
109 private ClassLoader mContextClassLoader;
111 public CacheKey (String theCodebase, ClassLoader theContextClassLoader)
113 mCodeBase = theCodebase;
114 mContextClassLoader = theContextClassLoader;
118 * @return true if the codebase and the context classloader are equal
120 public boolean equals (Object theOther)
122 if (theOther instanceof CacheKey)
124 CacheKey key = (CacheKey) theOther;
126 return (equals (this.mCodeBase,key.mCodeBase)
127 && equals (this.mContextClassLoader, key.mContextClassLoader));
129 return false;
133 * Test if the two objects are equal or both null.
134 * @param theOne
135 * @param theOther
136 * @return
138 private boolean equals (Object theOne, Object theOther)
140 return theOne != null ? theOne.equals (theOther) : theOther == null;
144 * @return hashCode
146 public int hashCode()
148 return ((mCodeBase != null ? mCodeBase.hashCode() : 0)
149 ^(mContextClassLoader != null ? mContextClassLoader.hashCode() : -1));
152 public String toString()
154 return "[" + mCodeBase + "," + mContextClassLoader + "]";
159 private static Map cacheLoaders; //map annotations to loaders
160 private static Map cacheAnnotations; //map loaders to annotations
162 //defaultAnnotation is got from system property
163 // "java.rmi.server.defaultAnnotation"
164 private static String defaultAnnotation;
166 //URL object for defaultAnnotation
167 private static URL defaultCodebase;
169 //class loader for defaultAnnotation
170 private static MyClassLoader defaultLoader;
172 static
174 // 89 is a nice prime number for Hashtable initial capacity
175 cacheLoaders = new Hashtable (89);
176 cacheAnnotations = new Hashtable (89);
178 defaultAnnotation = System.getProperty ("java.rmi.server.defaultAnnotation");
182 if (defaultAnnotation != null)
183 defaultCodebase = new URL (defaultAnnotation);
185 catch (Exception _)
187 defaultCodebase = null;
190 if (defaultCodebase != null)
192 defaultLoader = new MyClassLoader (new URL[] { defaultCodebase }, null,
193 defaultAnnotation);
194 cacheLoaders.put (new CacheKey (defaultAnnotation,
195 Thread.currentThread().getContextClassLoader()),
196 defaultLoader);
201 * @deprecated
203 public static Class loadClass (String name)
204 throws MalformedURLException, ClassNotFoundException
206 return loadClass ("", name);
209 public static Class loadClass (String codebases, String name)
210 throws MalformedURLException, ClassNotFoundException
212 ClassLoader loader = Thread.currentThread().getContextClassLoader();
214 //try context class loader first
215 try
217 return loader.loadClass (name);
219 catch (ClassNotFoundException e)
221 // class not found in the local classpath
224 if (codebases.length() == 0) //==""
226 loader = defaultLoader;
228 else
230 loader = getClassLoader(codebases);
233 if (loader == null)
235 //do not throw NullPointerException
236 throw new ClassNotFoundException ("Could not find class (" + name +
237 ") at codebase (" + codebases + ")");
240 return loader.loadClass (name);
244 * Gets a classloader for the given codebase and with the current
245 * context classloader as parent.
247 * @param codebases
249 * @return a classloader for the given codebase
251 * @throws MalformedURLException if the codebase contains a malformed URL
253 private static ClassLoader getClassLoader (String codebases)
254 throws MalformedURLException
256 ClassLoader loader;
257 CacheKey loaderKey = new CacheKey
258 (codebases, Thread.currentThread().getContextClassLoader());
259 loader = (ClassLoader) cacheLoaders.get (loaderKey);
261 if (loader == null)
263 //create an entry in cacheLoaders mapping a loader to codebases.
264 // codebases are separated by " "
265 StringTokenizer tok = new StringTokenizer (codebases, " ");
266 ArrayList urls = new ArrayList();
268 while (tok.hasMoreTokens())
269 urls.add (new URL (tok.nextToken()));
271 loader = new MyClassLoader ((URL[]) urls.toArray (new URL [urls.size()]),
272 Thread.currentThread().getContextClassLoader(),
273 codebases);
274 cacheLoaders.put (loaderKey, loader);
277 return loader;
281 * Returns a string representation of the network location where a remote
282 * endpoint can get the class-definition of the given class.
284 * @param cl
286 * @return a space seperated list of URLs where the class-definition
287 * of cl may be found
289 public static String getClassAnnotation (Class cl)
291 ClassLoader loader = cl.getClassLoader();
293 if (loader == null
294 || loader == ClassLoader.getSystemClassLoader())
296 return System.getProperty ("java.rmi.server.codebase");
299 if (loader instanceof MyClassLoader)
301 return ((MyClassLoader) loader).getClassAnnotation();
304 String s = (String) cacheAnnotations.get (loader);
306 if (s != null)
307 return s;
309 if (loader instanceof URLClassLoader)
311 URL[] urls = ((URLClassLoader) loader).getURLs();
313 if (urls.length == 0)
314 return null;
316 StringBuffer annotation = new StringBuffer (64 * urls.length);
318 for (int i = 0; i < urls.length; i++)
320 annotation.append (urls [i].toExternalForm());
321 annotation.append (' ');
324 s = annotation.toString();
325 cacheAnnotations.put (loader, s);
326 return s;
329 return System.getProperty ("java.rmi.server.codebase");
333 * @deprecated
335 public static Object getSecurityContext (ClassLoader loader)
337 throw new Error ("Not implemented");