KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > rmi > server > RMIClassLoader


1 /*
2  * @(#)RMIClassLoader.java 1.40 04/05/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.rmi.server;
9
10 import java.net.MalformedURLException JavaDoc;
11 import java.net.URL JavaDoc;
12
13 import java.util.Iterator JavaDoc;
14
15 import sun.misc.Service;
16
17 /**
18  * <code>RMIClassLoader</code> comprises static methods to support
19  * dynamic class loading with RMI. Included are methods for loading
20  * classes from a network location (one or more URLs) and obtaining
21  * the location from which an existing class should be loaded by
22  * remote parties. These methods are used by the RMI runtime when
23  * marshalling and unmarshalling classes contained in the arguments
24  * and return values of remote method calls, and they also may be
25  * invoked directly by applications in order to mimic RMI's dynamic
26  * class loading behavior.
27  *
28  * <p>The implementation of the following static methods
29  *
30  * <ul>
31  *
32  * <li>{@link #loadClass(URL,String)}
33  * <li>{@link #loadClass(String,String)}
34  * <li>{@link #loadClass(String,String,ClassLoader)}
35  * <li>{@link #loadProxyClass(String,String[],ClassLoader)}
36  * <li>{@link #getClassLoader(String)}
37  * <li>{@link #getClassAnnotation(Class)}
38  *
39  * </ul>
40  *
41  * is provided by an instance of {@link RMIClassLoaderSpi}, the
42  * service provider interface for those methods. When one of the
43  * methods is invoked, its behavior is to delegate to a corresponding
44  * method on the service provider instance. The details of how each
45  * method delegates to the provider instance is described in the
46  * documentation for each particular method.
47  *
48  * <p>The service provider instance is chosen as follows:
49  *
50  * <ul>
51  *
52  * <li>If the system property
53  * <code>java.rmi.server.RMIClassLoaderSpi</code> is defined, then if
54  * its value equals the string <code>"default"</code>, the provider
55  * instance will be the value returned by an invocation of the {@link
56  * #getDefaultProviderInstance()} method, and for any other value, if
57  * a class named with the value of the property can be loaded by the
58  * system class loader (see {@link ClassLoader#getSystemClassLoader})
59  * and that class is assignable to {@link RMIClassLoaderSpi} and has a
60  * public no-argument constructor, then that constructor will be
61  * invoked to create the provider instance. If the property is
62  * defined but any other of those conditions are not true, then an
63  * unspecified <code>Error</code> will be thrown to code that attempts
64  * to use <code>RMIClassLoader</code>, indicating the failure to
65  * obtain a provider instance.
66  *
67  * <li>If a resource named
68  * <code>META-INF/services/java.rmi.server.RMIClassLoaderSpi</code> is
69  * visible to the system class loader, then the contents of that
70  * resource are interpreted as a provider-configuration file, and the
71  * first class name specified in that file is used as the provider
72  * class name. If a class with that name can be loaded by the system
73  * class loader and that class is assignable to {@link
74  * RMIClassLoaderSpi} and has a public no-argument constructor, then
75  * that constructor will be invoked to create the provider instance.
76  * If the resource is found but a provider cannot be instantiated as
77  * described, then an unspecified <code>Error</code> will be thrown to
78  * code that attempts to use <code>RMIClassLoader</code>, indicating
79  * the failure to obtain a provider instance.
80  *
81  * <li>Otherwise, the provider instance will be the value returned by
82  * an invocation of the {@link #getDefaultProviderInstance()} method.
83  *
84  * </ul>
85  *
86  * @version 1.40, 04/05/18
87  * @author Ann Wollrath
88  * @author Peter Jones
89  * @author Laird Dornin
90  * @see RMIClassLoaderSpi
91  * @since JDK1.1
92  */

93 public class RMIClassLoader {
94
95     /** "default" provider instance */
96     private static final RMIClassLoaderSpi JavaDoc defaultProvider =
97     newDefaultProviderInstance();
98
99     /** provider instance */
100     private static final RMIClassLoaderSpi JavaDoc provider =
101     (RMIClassLoaderSpi JavaDoc) java.security.AccessController.doPrivileged(
102     new java.security.PrivilegedAction JavaDoc() {
103         public Object JavaDoc run() { return initializeProvider(); }
104     });
105
106     /*
107      * Disallow anyone from creating one of these.
108      */

109     private RMIClassLoader() {}
110
111     /**
112      * Loads the class with the specified <code>name</code>.
113      *
114      * <p>This method delegates to {@link #loadClass(String,String)},
115      * passing <code>null</code> as the first argument and
116      * <code>name</code> as the second argument.
117      *
118      * @param name the name of the class to load
119      *
120      * @return the <code>Class</code> object representing the loaded class
121      *
122      * @throws MalformedURLException if a provider-specific URL used
123      * to load classes is invalid
124      *
125      * @throws ClassNotFoundException if a definition for the class
126      * could not be found at the codebase location
127      *
128      * @deprecated replaced by <code>loadClass(String,String)</code> method
129      * @see #loadClass(String,String)
130      */

131     @Deprecated JavaDoc
132     public static Class JavaDoc<?> loadClass(String JavaDoc name)
133     throws MalformedURLException JavaDoc, ClassNotFoundException JavaDoc
134     {
135     return loadClass((String JavaDoc) null, name);
136     }
137
138     /**
139      * Loads a class from a codebase URL.
140      *
141      * If <code>codebase</code> is <code>null</code>, then this method
142      * will behave the same as {@link #loadClass(String,String)} with a
143      * <code>null</code> <code>codebase</code> and the given class name.
144      *
145      * <p>This method delegates to the
146      * {@link RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}
147      * method of the provider instance, passing the result of invoking
148      * {@link URL#toString} on the given URL (or <code>null</code> if
149      * <code>codebase</code> is null) as the first argument,
150      * <code>name</code> as the second argument,
151      * and <code>null</code> as the third argument.
152      *
153      * @param codebase the URL to load the class from, or <code>null</code>
154      *
155      * @param name the name of the class to load
156      *
157      * @return the <code>Class</code> object representing the loaded class
158      *
159      * @throws MalformedURLException if <code>codebase</code> is
160      * <code>null</code> and a provider-specific URL used
161      * to load classes is invalid
162      *
163      * @throws ClassNotFoundException if a definition for the class
164      * could not be found at the specified URL
165      */

166     public static Class JavaDoc<?> loadClass(URL JavaDoc codebase, String JavaDoc name)
167     throws MalformedURLException JavaDoc, ClassNotFoundException JavaDoc
168     {
169     return provider.loadClass(
170         codebase != null ? codebase.toString() : null, name, null);
171     }
172
173     /**
174      * Loads a class from a codebase URL path.
175      *
176      * <p>This method delegates to the
177      * {@link RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}
178      * method of the provider instance, passing <code>codebase</code>
179      * as the first argument, <code>name</code> as the second argument,
180      * and <code>null</code> as the third argument.
181      *
182      * @param codebase the list of URLs (separated by spaces) to load
183      * the class from, or <code>null</code>
184      *
185      * @param name the name of the class to load
186      *
187      * @return the <code>Class</code> object representing the loaded class
188      *
189      * @throws MalformedURLException if <code>codebase</code> is
190      * non-<code>null</code> and contains an invalid URL, or if
191      * <code>codebase</code> is <code>null</code> and a provider-specific
192      * URL used to load classes is invalid
193      *
194      * @throws ClassNotFoundException if a definition for the class
195      * could not be found at the specified location
196      *
197      * @since 1.2
198      */

199     public static Class JavaDoc<?> loadClass(String JavaDoc codebase, String JavaDoc name)
200     throws MalformedURLException JavaDoc, ClassNotFoundException JavaDoc
201     {
202     return provider.loadClass(codebase, name, null);
203     }
204
205     /**
206      * Loads a class from a codebase URL path, optionally using the
207      * supplied loader.
208      *
209      * This method should be used when the caller would like to make
210      * available to the provider implementation an additional contextual
211      * class loader to consider, such as the loader of a caller on the
212      * stack. Typically, a provider implementation will attempt to
213      * resolve the named class using the given <code>defaultLoader</code>,
214      * if specified, before attempting to resolve the class from the
215      * codebase URL path.
216      *
217      * <p>This method delegates to the
218      * {@link RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}
219      * method of the provider instance, passing <code>codebase</code>
220      * as the first argument, <code>name</code> as the second argument,
221      * and <code>defaultLoader</code> as the third argument.
222      *
223      * @param codebase the list of URLs (separated by spaces) to load
224      * the class from, or <code>null</code>
225      *
226      * @param name the name of the class to load
227      *
228      * @param defaultLoader additional contextual class loader
229      * to use, or <code>null</code>
230      *
231      * @return the <code>Class</code> object representing the loaded class
232      *
233      * @throws MalformedURLException if <code>codebase</code> is
234      * non-<code>null</code> and contains an invalid URL, or if
235      * <code>codebase</code> is <code>null</code> and a provider-specific
236      * URL used to load classes is invalid
237      *
238      * @throws ClassNotFoundException if a definition for the class
239      * could not be found at the specified location
240      *
241      * @since 1.4
242      */

243     public static Class JavaDoc<?> loadClass(String JavaDoc codebase, String JavaDoc name,
244                      ClassLoader JavaDoc defaultLoader)
245     throws MalformedURLException JavaDoc, ClassNotFoundException JavaDoc
246     {
247     return provider.loadClass(codebase, name, defaultLoader);
248     }
249
250     /**
251      * Loads a dynamic proxy class (see {@link java.lang.reflect.Proxy})
252      * that implements a set of interfaces with the given names
253      * from a codebase URL path.
254      *
255      * <p>The interfaces will be resolved similar to classes loaded via
256      * the {@link #loadClass(String,String)} method using the given
257      * <code>codebase</code>.
258      *
259      * <p>This method delegates to the
260      * {@link RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)}
261      * method of the provider instance, passing <code>codebase</code>
262      * as the first argument, <code>interfaces</code> as the second argument,
263      * and <code>defaultLoader</code> as the third argument.
264      *
265      * @param codebase the list of URLs (space-separated) to load
266      * classes from, or <code>null</code>
267      *
268      * @param interfaces the names of the interfaces for the proxy class
269      * to implement
270      *
271      * @param defaultLoader additional contextual class loader
272      * to use, or <code>null</code>
273      *
274      * @return a dynamic proxy class that implements the named interfaces
275      *
276      * @throws MalformedURLException if <code>codebase</code> is
277      * non-<code>null</code> and contains an invalid URL, or
278      * if <code>codebase</code> is <code>null</code> and a provider-specific
279      * URL used to load classes is invalid
280      *
281      * @throws ClassNotFoundException if a definition for one of
282      * the named interfaces could not be found at the specified location,
283      * or if creation of the dynamic proxy class failed (such as if
284      * {@link java.lang.reflect.Proxy#getProxyClass(ClassLoader,Class[])}
285      * would throw an <code>IllegalArgumentException</code> for the given
286      * interface list)
287      *
288      * @since 1.4
289      */

290     public static Class JavaDoc<?> loadProxyClass(String JavaDoc codebase, String JavaDoc[] interfaces,
291                       ClassLoader JavaDoc defaultLoader)
292     throws ClassNotFoundException JavaDoc, MalformedURLException JavaDoc
293     {
294     return provider.loadProxyClass(codebase, interfaces, defaultLoader);
295     }
296   
297     /**
298      * Returns a class loader that loads classes from the given codebase
299      * URL path.
300      *
301      * <p>The class loader returned is the class loader that the
302      * {@link #loadClass(String,String)} method would use to load classes
303      * for the same <code>codebase</code> argument.
304      *
305      * <p>This method delegates to the
306      * {@link RMIClassLoaderSpi#getClassLoader(String)} method
307      * of the provider instance, passing <code>codebase</code> as the argument.
308      *
309      * <p>If there is a security manger, its <code>checkPermission</code>
310      * method will be invoked with a
311      * <code>RuntimePermission("getClassLoader")</code> permission;
312      * this could result in a <code>SecurityException</code>.
313      * The provider implementation of this method may also perform further
314      * security checks to verify that the calling context has permission to
315      * connect to all of the URLs in the codebase URL path.
316      *
317      * @param codebase the list of URLs (space-separated) from which
318      * the returned class loader will load classes from, or <code>null</code>
319      *
320      * @return a class loader that loads classes from the given codebase URL
321      * path
322      *
323      * @throws MalformedURLException if <code>codebase</code> is
324      * non-<code>null</code> and contains an invalid URL, or
325      * if <code>codebase</code> is <code>null</code> and a provider-specific
326      * URL used to identify the class loader is invalid
327      *
328      * @throws SecurityException if there is a security manager and the
329      * invocation of its <code>checkPermission</code> method fails, or
330      * if the caller does not have permission to connect to all of the
331      * URLs in the codebase URL path
332      *
333      * @since 1.3
334      */

335     public static ClassLoader JavaDoc getClassLoader(String JavaDoc codebase)
336     throws MalformedURLException JavaDoc, SecurityException JavaDoc
337     {
338     return provider.getClassLoader(codebase);
339     }
340
341     /**
342      * Returns the annotation string (representing a location for
343      * the class definition) that RMI will use to annotate the class
344      * descriptor when marshalling objects of the given class.
345      *
346      * <p>This method delegates to the
347      * {@link RMIClassLoaderSpi#getClassAnnotation(Class)} method
348      * of the provider instance, passing <code>cl</code> as the argument.
349      *
350      * @param cl the class to obtain the annotation for
351      *
352      * @return a string to be used to annotate the given class when
353      * it gets marshalled, or <code>null</code>
354      *
355      * @throws NullPointerException if <code>cl</code> is <code>null</code>
356      *
357      * @since 1.2
358      */

359     /*
360      * REMIND: Should we say that the returned class annotation will or
361      * should be a (space-separated) list of URLs?
362      */

363     public static String JavaDoc getClassAnnotation(Class JavaDoc<?> cl) {
364     return provider.getClassAnnotation(cl);
365     }
366
367     /**
368      * Returns the canonical instance of the default provider
369      * for the service provider interface {@link RMIClassLoaderSpi}.
370      * If the system property <code>java.rmi.server.RMIClassLoaderSpi</code>
371      * is not defined, then the <code>RMIClassLoader</code> static
372      * methods
373      *
374      * <ul>
375      *
376      * <li>{@link #loadClass(URL,String)}
377      * <li>{@link #loadClass(String,String)}
378      * <li>{@link #loadClass(String,String,ClassLoader)}
379      * <li>{@link #loadProxyClass(String,String[],ClassLoader)}
380      * <li>{@link #getClassLoader(String)}
381      * <li>{@link #getClassAnnotation(Class)}
382      *
383      * </ul>
384      *
385      * will use the canonical instance of the default provider
386      * as the service provider instance.
387      *
388      * <p>If there is a security manager, its
389      * <code>checkPermission</code> method will be invoked with a
390      * <code>RuntimePermission("setFactory")</code> permission; this
391      * could result in a <code>SecurityException</code>.
392      *
393      * <p>The default service provider instance implements
394      * {@link RMIClassLoaderSpi} as follows:
395      *
396      * <blockquote>
397      *
398      * <p>The <b>{@link RMIClassLoaderSpi#getClassAnnotation(Class)
399      * getClassAnnotation}</b> method returns a <code>String</code>
400      * representing the codebase URL path that a remote party should
401      * use to download the definition for the specified class. The
402      * format of the returned string is a path of URLs separated by
403      * spaces.
404      *
405      * The codebase string returned depends on the defining class
406      * loader of the specified class:
407      *
408      * <ul>
409      *
410      * <p><li>If the class loader is the system class loader (see
411      * {@link ClassLoader#getSystemClassLoader}), a parent of the
412      * system class loader such as the loader used for installed
413      * extensions, or the bootstrap class loader (which may be
414      * represented by <code>null</code>), then the value of the
415      * <code>java.rmi.server.codebase</code> property (or possibly an
416      * earlier cached value) is returned, or
417      * <code>null</code> is returned if that property is not set.
418      *
419      * <p><li>Otherwise, if the class loader is an instance of
420      * <code>URLClassLoader</code>, then the returned string is a
421      * space-separated list of the external forms of the URLs returned
422      * by invoking the <code>getURLs</code> methods of the loader. If
423      * the <code>URLClassLoader</code> was created by this provider to
424      * service an invocation of its <code>loadClass</code> or
425      * <code>loadProxyClass</code> methods, then no permissions are
426      * required to get the associated codebase string. If it is an
427      * arbitrary other <code>URLClassLoader</code> instance, then if
428      * there is a security manager, its <code>checkPermission</code>
429      * method will be invoked once for each URL returned by the
430      * <code>getURLs</code> method, with the permission returned by
431      * invoking <code>openConnection().getPermission()</code> on each
432      * URL; if any of those invocations throws a
433      * <code>SecurityException</code> or an <code>IOException</code>,
434      * then the value of the <code>java.rmi.server.codebase</code>
435      * property (or possibly an earlier cached value) is returned, or
436      * <code>null</code> is returned if that property is not set.
437      *
438      * <p><li>Finally, if the class loader is not an instance of
439      * <code>URLClassLoader</code>, then the value of the
440      * <code>java.rmi.server.codebase</code> property (or possibly an
441      * earlier cached value) is returned, or
442      * <code>null</code> is returned if that property is not set.
443      *
444      * </ul>
445      *
446      * <p>For the implementations of the methods described below,
447      * which all take a <code>String</code> parameter named
448      * <code>codebase</code> that is a space-separated list of URLs,
449      * each invocation has an associated <i>codebase loader</i> that
450      * is identified using the <code>codebase</code> argument in
451      * conjunction with the current thread's context class loader (see
452      * {@link Thread#getContextClassLoader()}). When there is a
453      * security manager, this provider maintains an internal table of
454      * class loader instances (which are at least instances of {@link
455      * java.net.URLClassLoader}) keyed by the pair of their parent
456      * class loader and their codebase URL path (an ordered list of
457      * URLs). If the <code>codebase</code> argument is <code>null</code>,
458      * the codebase URL path is the value of the system property
459      * <code>java.rmi.server.codebase</code> or possibly an
460      * earlier cached value. For a given codebase URL path passed as the
461      * <code>codebase</code> argument to an invocation of one of the
462      * below methods in a given context, the codebase loader is the
463      * loader in the table with the specified codebase URL path and
464      * the current thread's context class loader as its parent. If no
465      * such loader exists, then one is created and added to the table.
466      * The table does not maintain strong references to its contained
467      * loaders, in order to allow them and their defined classes to be
468      * garbage collected when not otherwise reachable. In order to
469      * prevent arbitrary untrusted code from being implicitly loaded
470      * into a virtual machine with no security manager, if there is no
471      * security manager set, the codebase loader is just the current
472      * thread's context class loader (the supplied codebase URL path
473      * is ignored, so remote class loading is disabled).
474      *
475      * <p>The <b>{@link RMIClassLoaderSpi#getClassLoader(String)
476      * getClassLoader}</b> method returns the codebase loader for the
477      * specified codebase URL path. If there is a security manager,
478      * then if the calling context does not have permission to connect
479      * to all of the URLs in the codebase URL path, a
480      * <code>SecurityException</code> will be thrown.
481      *
482      * <p>The <b>{@link
483      * RMIClassLoaderSpi#loadClass(String,String,ClassLoader)
484      * loadClass}</b> method attempts to load the class with the
485      * specified name as follows:
486      *
487      * <blockquote>
488      *
489      * If the <code>defaultLoader</code> argument is
490      * non-<code>null</code>, it first attempts to load the class with the
491      * specified <code>name</code> using the
492      * <code>defaultLoader</code>, such as by evaluating
493      *
494      * <pre>
495      * Class.forName(name, false, defaultLoader)
496      * </pre>
497      *
498      * If the class is successfully loaded from the
499      * <code>defaultLoader</code>, that class is returned. If an
500      * exception other than <code>ClassNotFoundException</code> is
501      * thrown, that exception is thrown to the caller.
502      *
503      * <p>Next, the <code>loadClass</code> method attempts to load the
504      * class with the specified <code>name</code> using the codebase
505      * loader for the specified codebase URL path.
506      * If there is a security manager, then the calling context
507      * must have permission to connect to all of the URLs in the
508      * codebase URL path; otherwise, the current thread's context
509      * class loader will be used instead of the codebase loader.
510      *
511      * </blockquote>
512      *
513      * <p>The <b>{@link
514      * RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)
515      * loadProxyClass}</b> method attempts to return a dynamic proxy
516      * class with the named interface as follows:
517      *
518      * <blockquote>
519      *
520      * <p>If the <code>defaultLoader</code> argument is
521      * non-<code>null</code> and all of the named interfaces can be
522      * resolved through that loader, then,
523      *
524      * <ul>
525      *
526      * <li>if all of the resolved interfaces are <code>public</code>,
527      * then it first attempts to obtain a dynamic proxy class (using
528      * {@link
529      * java.lang.reflect.Proxy#getProxyClass(ClassLoader,Class[])
530      * Proxy.getProxyClass}) for the resolved interfaces defined in
531      * the codebase loader; if that attempt throws an
532      * <code>IllegalArgumentException</code>, it then attempts to
533      * obtain a dynamic proxy class for the resolved interfaces
534      * defined in the <code>defaultLoader</code>. If both attempts
535      * throw <code>IllegalArgumentException</code>, then this method
536      * throws a <code>ClassNotFoundException</code>. If any other
537      * exception is thrown, that exception is thrown to the caller.
538      *
539      * <li>if all of the non-<code>public</code> resolved interfaces
540      * are defined in the same class loader, then it attempts to
541      * obtain a dynamic proxy class for the resolved interfaces
542      * defined in that loader.
543      *
544      * <li>otherwise, a <code>LinkageError</code> is thrown (because a
545      * class that implements all of the specified interfaces cannot be
546      * defined in any loader).
547      *
548      * </ul>
549      *
550      * <p>Otherwise, if all of the named interfaces can be resolved
551      * through the codebase loader, then,
552      *
553      * <ul>
554      *
555      * <li>if all of the resolved interfaces are <code>public</code>,
556      * then it attempts to obtain a dynamic proxy class for the
557      * resolved interfaces in the codebase loader. If the attempt
558      * throws an <code>IllegalArgumentException</code>, then this
559      * method throws a <code>ClassNotFoundException</code>.
560      *
561      * <li>if all of the non-<code>public</code> resolved interfaces
562      * are defined in the same class loader, then it attempts to
563      * obtain a dynamic proxy class for the resolved interfaces
564      * defined in that loader.
565      *
566      * <li>otherwise, a <code>LinkageError</code> is thrown (because a
567      * class that implements all of the specified interfaces cannot be
568      * defined in any loader).
569      *
570      * </ul>
571      *
572      * <p>Otherwise, a <code>ClassNotFoundException</code> is thrown
573      * for one of the named interfaces that could not be resolved.
574      *
575      * </blockquote>
576      *
577      * </blockquote>
578      *
579      * @return the canonical instance of the default service provider
580      *
581      * @throws SecurityException if there is a security manager and the
582      * invocation of its <code>checkPermission</code> method fails
583      *
584      * @since 1.4
585      */

586     public static RMIClassLoaderSpi JavaDoc getDefaultProviderInstance() {
587     SecurityManager JavaDoc sm = System.getSecurityManager();
588     if (sm != null) {
589         sm.checkPermission(new RuntimePermission JavaDoc("setFactory"));
590     }
591     return defaultProvider;
592     }
593
594     /**
595      * Returns the security context of the given class loader.
596      *
597      * @param loader a class loader from which to get the security context
598      *
599      * @return the security context
600      *
601      * @deprecated no replacement. As of the Java 2 platform v1.2, RMI no
602      * longer uses this method to obtain a class loader's security context.
603      * @see java.lang.SecurityManager#getSecurityContext()
604      */

605     @Deprecated JavaDoc
606     public static Object JavaDoc getSecurityContext(ClassLoader JavaDoc loader)
607     {
608     return sun.rmi.server.LoaderHandler.getSecurityContext(loader);
609     }
610
611     /**
612      * Creates an instance of the default provider class.
613      */

614     private static RMIClassLoaderSpi JavaDoc newDefaultProviderInstance() {
615     return new RMIClassLoaderSpi JavaDoc() {
616         public Class JavaDoc loadClass(String JavaDoc codebase, String JavaDoc name,
617                    ClassLoader JavaDoc defaultLoader)
618         throws MalformedURLException JavaDoc, ClassNotFoundException JavaDoc
619         {
620         return sun.rmi.server.LoaderHandler.loadClass(
621             codebase, name, defaultLoader);
622         }
623     
624         public Class JavaDoc loadProxyClass(String JavaDoc codebase, String JavaDoc[] interfaces,
625                     ClassLoader JavaDoc defaultLoader)
626         throws MalformedURLException JavaDoc, ClassNotFoundException JavaDoc
627         {
628         return sun.rmi.server.LoaderHandler.loadProxyClass(
629             codebase, interfaces, defaultLoader);
630         }
631
632         public ClassLoader JavaDoc getClassLoader(String JavaDoc codebase)
633         throws MalformedURLException JavaDoc
634         {
635         return sun.rmi.server.LoaderHandler.getClassLoader(codebase);
636         }
637
638         public String JavaDoc getClassAnnotation(Class JavaDoc<?> cl) {
639         return sun.rmi.server.LoaderHandler.getClassAnnotation(cl);
640         }
641     };
642     }
643
644     /**
645      * Chooses provider instance, following above documentation.
646      *
647      * This method assumes that it has been invoked in a privileged block.
648      */

649     private static RMIClassLoaderSpi JavaDoc initializeProvider() {
650     /*
651      * First check for the system property being set:
652      */

653     String JavaDoc providerClassName =
654         System.getProperty("java.rmi.server.RMIClassLoaderSpi");
655
656     if (providerClassName != null) {
657         if (providerClassName.equals("default")) {
658         return defaultProvider;
659         }
660
661         try {
662         Class JavaDoc providerClass =
663             Class.forName(providerClassName, false,
664                   ClassLoader.getSystemClassLoader());
665         return (RMIClassLoaderSpi JavaDoc) providerClass.newInstance();
666
667         } catch (ClassNotFoundException JavaDoc e) {
668         throw new NoClassDefFoundError JavaDoc(e.getMessage());
669         } catch (IllegalAccessException JavaDoc e) {
670         throw new IllegalAccessError JavaDoc(e.getMessage());
671         } catch (InstantiationException JavaDoc e) {
672         throw new InstantiationError JavaDoc(e.getMessage());
673         } catch (ClassCastException JavaDoc e) {
674         Error JavaDoc error = new LinkageError JavaDoc(
675             "provider class not assignable to RMIClassLoaderSpi");
676         error.initCause(e);
677         throw error;
678         }
679     }
680
681     /*
682      * Next look for a provider configuration file intalled:
683      */

684     Iterator JavaDoc iter = Service.providers(RMIClassLoaderSpi JavaDoc.class,
685                       ClassLoader.getSystemClassLoader());
686     if (iter.hasNext()) {
687         try {
688         return (RMIClassLoaderSpi JavaDoc) iter.next();
689         } catch (ClassCastException JavaDoc e) {
690         Error JavaDoc error = new LinkageError JavaDoc(
691             "provider class not assignable to RMIClassLoaderSpi");
692         error.initCause(e);
693         throw error;
694         }
695     }
696
697     /*
698      * Finally, return the canonical instance of the default provider.
699      */

700     return defaultProvider;
701     }
702 }
703
Popular Tags