blob: f45ab6454b98ea0d93eb0f91968f3234547ef697 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.rmi.server;
27
28import java.net.MalformedURLException;
29import java.net.URL;
30import java.security.AccessController;
31import java.security.PrivilegedAction;
32import java.util.Iterator;
33import java.util.ServiceLoader;
34
35/**
36 * <code>RMIClassLoader</code> comprises static methods to support
37 * dynamic class loading with RMI. Included are methods for loading
38 * classes from a network location (one or more URLs) and obtaining
39 * the location from which an existing class should be loaded by
40 * remote parties. These methods are used by the RMI runtime when
41 * marshalling and unmarshalling classes contained in the arguments
42 * and return values of remote method calls, and they also may be
43 * invoked directly by applications in order to mimic RMI's dynamic
44 * class loading behavior.
45 *
46 * <p>The implementation of the following static methods
47 *
48 * <ul>
49 *
50 * <li>{@link #loadClass(URL,String)}
51 * <li>{@link #loadClass(String,String)}
52 * <li>{@link #loadClass(String,String,ClassLoader)}
53 * <li>{@link #loadProxyClass(String,String[],ClassLoader)}
54 * <li>{@link #getClassLoader(String)}
55 * <li>{@link #getClassAnnotation(Class)}
56 *
57 * </ul>
58 *
59 * is provided by an instance of {@link RMIClassLoaderSpi}, the
60 * service provider interface for those methods. When one of the
61 * methods is invoked, its behavior is to delegate to a corresponding
62 * method on the service provider instance. The details of how each
63 * method delegates to the provider instance is described in the
64 * documentation for each particular method.
65 *
66 * <p>The service provider instance is chosen as follows:
67 *
68 * <ul>
69 *
70 * <li>If the system property
71 * <code>java.rmi.server.RMIClassLoaderSpi</code> is defined, then if
72 * its value equals the string <code>"default"</code>, the provider
73 * instance will be the value returned by an invocation of the {@link
74 * #getDefaultProviderInstance()} method, and for any other value, if
75 * a class named with the value of the property can be loaded by the
76 * system class loader (see {@link ClassLoader#getSystemClassLoader})
77 * and that class is assignable to {@link RMIClassLoaderSpi} and has a
78 * public no-argument constructor, then that constructor will be
79 * invoked to create the provider instance. If the property is
80 * defined but any other of those conditions are not true, then an
81 * unspecified <code>Error</code> will be thrown to code that attempts
82 * to use <code>RMIClassLoader</code>, indicating the failure to
83 * obtain a provider instance.
84 *
85 * <li>If a resource named
86 * <code>META-INF/services/java.rmi.server.RMIClassLoaderSpi</code> is
87 * visible to the system class loader, then the contents of that
88 * resource are interpreted as a provider-configuration file, and the
89 * first class name specified in that file is used as the provider
90 * class name. If a class with that name can be loaded by the system
91 * class loader and that class is assignable to {@link
92 * RMIClassLoaderSpi} and has a public no-argument constructor, then
93 * that constructor will be invoked to create the provider instance.
94 * If the resource is found but a provider cannot be instantiated as
95 * described, then an unspecified <code>Error</code> will be thrown to
96 * code that attempts to use <code>RMIClassLoader</code>, indicating
97 * the failure to obtain a provider instance.
98 *
99 * <li>Otherwise, the provider instance will be the value returned by
100 * an invocation of the {@link #getDefaultProviderInstance()} method.
101 *
102 * </ul>
103 *
104 * @author Ann Wollrath
105 * @author Peter Jones
106 * @author Laird Dornin
107 * @see RMIClassLoaderSpi
108 * @since JDK1.1
109 */
110public class RMIClassLoader {
111
112 /** "default" provider instance */
113 private static final RMIClassLoaderSpi defaultProvider =
114 newDefaultProviderInstance();
115
116 /** provider instance */
117 private static final RMIClassLoaderSpi provider =
118 AccessController.doPrivileged(
119 new PrivilegedAction<RMIClassLoaderSpi>() {
120 public RMIClassLoaderSpi run() { return initializeProvider(); }
121 });
122
123 /*
124 * Disallow anyone from creating one of these.
125 */
126 private RMIClassLoader() {}
127
128 /**
129 * Loads the class with the specified <code>name</code>.
130 *
131 * <p>This method delegates to {@link #loadClass(String,String)},
132 * passing <code>null</code> as the first argument and
133 * <code>name</code> as the second argument.
134 *
135 * @param name the name of the class to load
136 *
137 * @return the <code>Class</code> object representing the loaded class
138 *
139 * @throws MalformedURLException if a provider-specific URL used
140 * to load classes is invalid
141 *
142 * @throws ClassNotFoundException if a definition for the class
143 * could not be found at the codebase location
144 *
145 * @deprecated replaced by <code>loadClass(String,String)</code> method
146 * @see #loadClass(String,String)
147 */
148 @Deprecated
149 public static Class<?> loadClass(String name)
150 throws MalformedURLException, ClassNotFoundException
151 {
152 return loadClass((String) null, name);
153 }
154
155 /**
156 * Loads a class from a codebase URL.
157 *
158 * If <code>codebase</code> is <code>null</code>, then this method
159 * will behave the same as {@link #loadClass(String,String)} with a
160 * <code>null</code> <code>codebase</code> and the given class name.
161 *
162 * <p>This method delegates to the
163 * {@link RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}
164 * method of the provider instance, passing the result of invoking
165 * {@link URL#toString} on the given URL (or <code>null</code> if
166 * <code>codebase</code> is null) as the first argument,
167 * <code>name</code> as the second argument,
168 * and <code>null</code> as the third argument.
169 *
170 * @param codebase the URL to load the class from, or <code>null</code>
171 *
172 * @param name the name of the class to load
173 *
174 * @return the <code>Class</code> object representing the loaded class
175 *
176 * @throws MalformedURLException if <code>codebase</code> is
177 * <code>null</code> and a provider-specific URL used
178 * to load classes is invalid
179 *
180 * @throws ClassNotFoundException if a definition for the class
181 * could not be found at the specified URL
182 */
183 public static Class<?> loadClass(URL codebase, String name)
184 throws MalformedURLException, ClassNotFoundException
185 {
186 return provider.loadClass(
187 codebase != null ? codebase.toString() : null, name, null);
188 }
189
190 /**
191 * Loads a class from a codebase URL path.
192 *
193 * <p>This method delegates to the
194 * {@link RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}
195 * method of the provider instance, passing <code>codebase</code>
196 * as the first argument, <code>name</code> as the second argument,
197 * and <code>null</code> as the third argument.
198 *
199 * @param codebase the list of URLs (separated by spaces) to load
200 * the class from, or <code>null</code>
201 *
202 * @param name the name of the class to load
203 *
204 * @return the <code>Class</code> object representing the loaded class
205 *
206 * @throws MalformedURLException if <code>codebase</code> is
207 * non-<code>null</code> and contains an invalid URL, or if
208 * <code>codebase</code> is <code>null</code> and a provider-specific
209 * URL used to load classes is invalid
210 *
211 * @throws ClassNotFoundException if a definition for the class
212 * could not be found at the specified location
213 *
214 * @since 1.2
215 */
216 public static Class<?> loadClass(String codebase, String name)
217 throws MalformedURLException, ClassNotFoundException
218 {
219 return provider.loadClass(codebase, name, null);
220 }
221
222 /**
223 * Loads a class from a codebase URL path, optionally using the
224 * supplied loader.
225 *
226 * This method should be used when the caller would like to make
227 * available to the provider implementation an additional contextual
228 * class loader to consider, such as the loader of a caller on the
229 * stack. Typically, a provider implementation will attempt to
230 * resolve the named class using the given <code>defaultLoader</code>,
231 * if specified, before attempting to resolve the class from the
232 * codebase URL path.
233 *
234 * <p>This method delegates to the
235 * {@link RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}
236 * method of the provider instance, passing <code>codebase</code>
237 * as the first argument, <code>name</code> as the second argument,
238 * and <code>defaultLoader</code> as the third argument.
239 *
240 * @param codebase the list of URLs (separated by spaces) to load
241 * the class from, or <code>null</code>
242 *
243 * @param name the name of the class to load
244 *
245 * @param defaultLoader additional contextual class loader
246 * to use, or <code>null</code>
247 *
248 * @return the <code>Class</code> object representing the loaded class
249 *
250 * @throws MalformedURLException if <code>codebase</code> is
251 * non-<code>null</code> and contains an invalid URL, or if
252 * <code>codebase</code> is <code>null</code> and a provider-specific
253 * URL used to load classes is invalid
254 *
255 * @throws ClassNotFoundException if a definition for the class
256 * could not be found at the specified location
257 *
258 * @since 1.4
259 */
260 public static Class<?> loadClass(String codebase, String name,
261 ClassLoader defaultLoader)
262 throws MalformedURLException, ClassNotFoundException
263 {
264 return provider.loadClass(codebase, name, defaultLoader);
265 }
266
267 /**
268 * Loads a dynamic proxy class (see {@link java.lang.reflect.Proxy})
269 * that implements a set of interfaces with the given names
270 * from a codebase URL path.
271 *
272 * <p>The interfaces will be resolved similar to classes loaded via
273 * the {@link #loadClass(String,String)} method using the given
274 * <code>codebase</code>.
275 *
276 * <p>This method delegates to the
277 * {@link RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)}
278 * method of the provider instance, passing <code>codebase</code>
279 * as the first argument, <code>interfaces</code> as the second argument,
280 * and <code>defaultLoader</code> as the third argument.
281 *
282 * @param codebase the list of URLs (space-separated) to load
283 * classes from, or <code>null</code>
284 *
285 * @param interfaces the names of the interfaces for the proxy class
286 * to implement
287 *
288 * @param defaultLoader additional contextual class loader
289 * to use, or <code>null</code>
290 *
291 * @return a dynamic proxy class that implements the named interfaces
292 *
293 * @throws MalformedURLException if <code>codebase</code> is
294 * non-<code>null</code> and contains an invalid URL, or
295 * if <code>codebase</code> is <code>null</code> and a provider-specific
296 * URL used to load classes is invalid
297 *
298 * @throws ClassNotFoundException if a definition for one of
299 * the named interfaces could not be found at the specified location,
300 * or if creation of the dynamic proxy class failed (such as if
301 * {@link java.lang.reflect.Proxy#getProxyClass(ClassLoader,Class[])}
302 * would throw an <code>IllegalArgumentException</code> for the given
303 * interface list)
304 *
305 * @since 1.4
306 */
307 public static Class<?> loadProxyClass(String codebase, String[] interfaces,
308 ClassLoader defaultLoader)
309 throws ClassNotFoundException, MalformedURLException
310 {
311 return provider.loadProxyClass(codebase, interfaces, defaultLoader);
312 }
313
314 /**
315 * Returns a class loader that loads classes from the given codebase
316 * URL path.
317 *
318 * <p>The class loader returned is the class loader that the
319 * {@link #loadClass(String,String)} method would use to load classes
320 * for the same <code>codebase</code> argument.
321 *
322 * <p>This method delegates to the
323 * {@link RMIClassLoaderSpi#getClassLoader(String)} method
324 * of the provider instance, passing <code>codebase</code> as the argument.
325 *
326 * <p>If there is a security manger, its <code>checkPermission</code>
327 * method will be invoked with a
328 * <code>RuntimePermission("getClassLoader")</code> permission;
329 * this could result in a <code>SecurityException</code>.
330 * The provider implementation of this method may also perform further
331 * security checks to verify that the calling context has permission to
332 * connect to all of the URLs in the codebase URL path.
333 *
334 * @param codebase the list of URLs (space-separated) from which
335 * the returned class loader will load classes from, or <code>null</code>
336 *
337 * @return a class loader that loads classes from the given codebase URL
338 * path
339 *
340 * @throws MalformedURLException if <code>codebase</code> is
341 * non-<code>null</code> and contains an invalid URL, or
342 * if <code>codebase</code> is <code>null</code> and a provider-specific
343 * URL used to identify the class loader is invalid
344 *
345 * @throws SecurityException if there is a security manager and the
346 * invocation of its <code>checkPermission</code> method fails, or
347 * if the caller does not have permission to connect to all of the
348 * URLs in the codebase URL path
349 *
350 * @since 1.3
351 */
352 public static ClassLoader getClassLoader(String codebase)
353 throws MalformedURLException, SecurityException
354 {
355 return provider.getClassLoader(codebase);
356 }
357
358 /**
359 * Returns the annotation string (representing a location for
360 * the class definition) that RMI will use to annotate the class
361 * descriptor when marshalling objects of the given class.
362 *
363 * <p>This method delegates to the
364 * {@link RMIClassLoaderSpi#getClassAnnotation(Class)} method
365 * of the provider instance, passing <code>cl</code> as the argument.
366 *
367 * @param cl the class to obtain the annotation for
368 *
369 * @return a string to be used to annotate the given class when
370 * it gets marshalled, or <code>null</code>
371 *
372 * @throws NullPointerException if <code>cl</code> is <code>null</code>
373 *
374 * @since 1.2
375 */
376 /*
377 * REMIND: Should we say that the returned class annotation will or
378 * should be a (space-separated) list of URLs?
379 */
380 public static String getClassAnnotation(Class<?> cl) {
381 return provider.getClassAnnotation(cl);
382 }
383
384 /**
385 * Returns the canonical instance of the default provider
386 * for the service provider interface {@link RMIClassLoaderSpi}.
387 * If the system property <code>java.rmi.server.RMIClassLoaderSpi</code>
388 * is not defined, then the <code>RMIClassLoader</code> static
389 * methods
390 *
391 * <ul>
392 *
393 * <li>{@link #loadClass(URL,String)}
394 * <li>{@link #loadClass(String,String)}
395 * <li>{@link #loadClass(String,String,ClassLoader)}
396 * <li>{@link #loadProxyClass(String,String[],ClassLoader)}
397 * <li>{@link #getClassLoader(String)}
398 * <li>{@link #getClassAnnotation(Class)}
399 *
400 * </ul>
401 *
402 * will use the canonical instance of the default provider
403 * as the service provider instance.
404 *
405 * <p>If there is a security manager, its
406 * <code>checkPermission</code> method will be invoked with a
407 * <code>RuntimePermission("setFactory")</code> permission; this
408 * could result in a <code>SecurityException</code>.
409 *
410 * <p>The default service provider instance implements
411 * {@link RMIClassLoaderSpi} as follows:
412 *
413 * <blockquote>
414 *
415 * <p>The <b>{@link RMIClassLoaderSpi#getClassAnnotation(Class)
416 * getClassAnnotation}</b> method returns a <code>String</code>
417 * representing the codebase URL path that a remote party should
418 * use to download the definition for the specified class. The
419 * format of the returned string is a path of URLs separated by
420 * spaces.
421 *
422 * The codebase string returned depends on the defining class
423 * loader of the specified class:
424 *
425 * <ul>
426 *
427 * <p><li>If the class loader is the system class loader (see
428 * {@link ClassLoader#getSystemClassLoader}), a parent of the
429 * system class loader such as the loader used for installed
430 * extensions, or the bootstrap class loader (which may be
431 * represented by <code>null</code>), then the value of the
432 * <code>java.rmi.server.codebase</code> property (or possibly an
433 * earlier cached value) is returned, or
434 * <code>null</code> is returned if that property is not set.
435 *
436 * <p><li>Otherwise, if the class loader is an instance of
437 * <code>URLClassLoader</code>, then the returned string is a
438 * space-separated list of the external forms of the URLs returned
439 * by invoking the <code>getURLs</code> methods of the loader. If
440 * the <code>URLClassLoader</code> was created by this provider to
441 * service an invocation of its <code>loadClass</code> or
442 * <code>loadProxyClass</code> methods, then no permissions are
443 * required to get the associated codebase string. If it is an
444 * arbitrary other <code>URLClassLoader</code> instance, then if
445 * there is a security manager, its <code>checkPermission</code>
446 * method will be invoked once for each URL returned by the
447 * <code>getURLs</code> method, with the permission returned by
448 * invoking <code>openConnection().getPermission()</code> on each
449 * URL; if any of those invocations throws a
450 * <code>SecurityException</code> or an <code>IOException</code>,
451 * then the value of the <code>java.rmi.server.codebase</code>
452 * property (or possibly an earlier cached value) is returned, or
453 * <code>null</code> is returned if that property is not set.
454 *
455 * <p><li>Finally, if the class loader is not an instance of
456 * <code>URLClassLoader</code>, then the value of the
457 * <code>java.rmi.server.codebase</code> property (or possibly an
458 * earlier cached value) is returned, or
459 * <code>null</code> is returned if that property is not set.
460 *
461 * </ul>
462 *
463 * <p>For the implementations of the methods described below,
464 * which all take a <code>String</code> parameter named
465 * <code>codebase</code> that is a space-separated list of URLs,
466 * each invocation has an associated <i>codebase loader</i> that
467 * is identified using the <code>codebase</code> argument in
468 * conjunction with the current thread's context class loader (see
469 * {@link Thread#getContextClassLoader()}). When there is a
470 * security manager, this provider maintains an internal table of
471 * class loader instances (which are at least instances of {@link
472 * java.net.URLClassLoader}) keyed by the pair of their parent
473 * class loader and their codebase URL path (an ordered list of
474 * URLs). If the <code>codebase</code> argument is <code>null</code>,
475 * the codebase URL path is the value of the system property
476 * <code>java.rmi.server.codebase</code> or possibly an
477 * earlier cached value. For a given codebase URL path passed as the
478 * <code>codebase</code> argument to an invocation of one of the
479 * below methods in a given context, the codebase loader is the
480 * loader in the table with the specified codebase URL path and
481 * the current thread's context class loader as its parent. If no
482 * such loader exists, then one is created and added to the table.
483 * The table does not maintain strong references to its contained
484 * loaders, in order to allow them and their defined classes to be
485 * garbage collected when not otherwise reachable. In order to
486 * prevent arbitrary untrusted code from being implicitly loaded
487 * into a virtual machine with no security manager, if there is no
488 * security manager set, the codebase loader is just the current
489 * thread's context class loader (the supplied codebase URL path
490 * is ignored, so remote class loading is disabled).
491 *
492 * <p>The <b>{@link RMIClassLoaderSpi#getClassLoader(String)
493 * getClassLoader}</b> method returns the codebase loader for the
494 * specified codebase URL path. If there is a security manager,
495 * then if the calling context does not have permission to connect
496 * to all of the URLs in the codebase URL path, a
497 * <code>SecurityException</code> will be thrown.
498 *
499 * <p>The <b>{@link
500 * RMIClassLoaderSpi#loadClass(String,String,ClassLoader)
501 * loadClass}</b> method attempts to load the class with the
502 * specified name as follows:
503 *
504 * <blockquote>
505 *
506 * If the <code>defaultLoader</code> argument is
507 * non-<code>null</code>, it first attempts to load the class with the
508 * specified <code>name</code> using the
509 * <code>defaultLoader</code>, such as by evaluating
510 *
511 * <pre>
512 * Class.forName(name, false, defaultLoader)
513 * </pre>
514 *
515 * If the class is successfully loaded from the
516 * <code>defaultLoader</code>, that class is returned. If an
517 * exception other than <code>ClassNotFoundException</code> is
518 * thrown, that exception is thrown to the caller.
519 *
520 * <p>Next, the <code>loadClass</code> method attempts to load the
521 * class with the specified <code>name</code> using the codebase
522 * loader for the specified codebase URL path.
523 * If there is a security manager, then the calling context
524 * must have permission to connect to all of the URLs in the
525 * codebase URL path; otherwise, the current thread's context
526 * class loader will be used instead of the codebase loader.
527 *
528 * </blockquote>
529 *
530 * <p>The <b>{@link
531 * RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)
532 * loadProxyClass}</b> method attempts to return a dynamic proxy
533 * class with the named interface as follows:
534 *
535 * <blockquote>
536 *
537 * <p>If the <code>defaultLoader</code> argument is
538 * non-<code>null</code> and all of the named interfaces can be
539 * resolved through that loader, then,
540 *
541 * <ul>
542 *
543 * <li>if all of the resolved interfaces are <code>public</code>,
544 * then it first attempts to obtain a dynamic proxy class (using
545 * {@link
546 * java.lang.reflect.Proxy#getProxyClass(ClassLoader,Class[])
547 * Proxy.getProxyClass}) for the resolved interfaces defined in
548 * the codebase loader; if that attempt throws an
549 * <code>IllegalArgumentException</code>, it then attempts to
550 * obtain a dynamic proxy class for the resolved interfaces
551 * defined in the <code>defaultLoader</code>. If both attempts
552 * throw <code>IllegalArgumentException</code>, then this method
553 * throws a <code>ClassNotFoundException</code>. If any other
554 * exception is thrown, that exception is thrown to the caller.
555 *
556 * <li>if all of the non-<code>public</code> resolved interfaces
557 * are defined in the same class loader, then it attempts to
558 * obtain a dynamic proxy class for the resolved interfaces
559 * defined in that loader.
560 *
561 * <li>otherwise, a <code>LinkageError</code> is thrown (because a
562 * class that implements all of the specified interfaces cannot be
563 * defined in any loader).
564 *
565 * </ul>
566 *
567 * <p>Otherwise, if all of the named interfaces can be resolved
568 * through the codebase loader, then,
569 *
570 * <ul>
571 *
572 * <li>if all of the resolved interfaces are <code>public</code>,
573 * then it attempts to obtain a dynamic proxy class for the
574 * resolved interfaces in the codebase loader. If the attempt
575 * throws an <code>IllegalArgumentException</code>, then this
576 * method throws a <code>ClassNotFoundException</code>.
577 *
578 * <li>if all of the non-<code>public</code> resolved interfaces
579 * are defined in the same class loader, then it attempts to
580 * obtain a dynamic proxy class for the resolved interfaces
581 * defined in that loader.
582 *
583 * <li>otherwise, a <code>LinkageError</code> is thrown (because a
584 * class that implements all of the specified interfaces cannot be
585 * defined in any loader).
586 *
587 * </ul>
588 *
589 * <p>Otherwise, a <code>ClassNotFoundException</code> is thrown
590 * for one of the named interfaces that could not be resolved.
591 *
592 * </blockquote>
593 *
594 * </blockquote>
595 *
596 * @return the canonical instance of the default service provider
597 *
598 * @throws SecurityException if there is a security manager and the
599 * invocation of its <code>checkPermission</code> method fails
600 *
601 * @since 1.4
602 */
603 public static RMIClassLoaderSpi getDefaultProviderInstance() {
604 SecurityManager sm = System.getSecurityManager();
605 if (sm != null) {
606 sm.checkPermission(new RuntimePermission("setFactory"));
607 }
608 return defaultProvider;
609 }
610
611 /**
612 * Returns the security context of the given class loader.
613 *
614 * @param loader a class loader from which to get the security context
615 *
616 * @return the security context
617 *
618 * @deprecated no replacement. As of the Java 2 platform v1.2, RMI no
619 * longer uses this method to obtain a class loader's security context.
620 * @see java.lang.SecurityManager#getSecurityContext()
621 */
622 @Deprecated
623 public static Object getSecurityContext(ClassLoader loader)
624 {
625 return sun.rmi.server.LoaderHandler.getSecurityContext(loader);
626 }
627
628 /**
629 * Creates an instance of the default provider class.
630 */
631 private static RMIClassLoaderSpi newDefaultProviderInstance() {
632 return new RMIClassLoaderSpi() {
633 public Class<?> loadClass(String codebase, String name,
634 ClassLoader defaultLoader)
635 throws MalformedURLException, ClassNotFoundException
636 {
637 return sun.rmi.server.LoaderHandler.loadClass(
638 codebase, name, defaultLoader);
639 }
640
641 public Class<?> loadProxyClass(String codebase,
642 String[] interfaces,
643 ClassLoader defaultLoader)
644 throws MalformedURLException, ClassNotFoundException
645 {
646 return sun.rmi.server.LoaderHandler.loadProxyClass(
647 codebase, interfaces, defaultLoader);
648 }
649
650 public ClassLoader getClassLoader(String codebase)
651 throws MalformedURLException
652 {
653 return sun.rmi.server.LoaderHandler.getClassLoader(codebase);
654 }
655
656 public String getClassAnnotation(Class<?> cl) {
657 return sun.rmi.server.LoaderHandler.getClassAnnotation(cl);
658 }
659 };
660 }
661
662 /**
663 * Chooses provider instance, following above documentation.
664 *
665 * This method assumes that it has been invoked in a privileged block.
666 */
667 private static RMIClassLoaderSpi initializeProvider() {
668 /*
669 * First check for the system property being set:
670 */
671 String providerClassName =
672 System.getProperty("java.rmi.server.RMIClassLoaderSpi");
673
674 if (providerClassName != null) {
675 if (providerClassName.equals("default")) {
676 return defaultProvider;
677 }
678
679 try {
680 Class<? extends RMIClassLoaderSpi> providerClass =
681 Class.forName(providerClassName, false,
682 ClassLoader.getSystemClassLoader())
683 .asSubclass(RMIClassLoaderSpi.class);
684 return providerClass.newInstance();
685
686 } catch (ClassNotFoundException e) {
687 throw new NoClassDefFoundError(e.getMessage());
688 } catch (IllegalAccessException e) {
689 throw new IllegalAccessError(e.getMessage());
690 } catch (InstantiationException e) {
691 throw new InstantiationError(e.getMessage());
692 } catch (ClassCastException e) {
693 Error error = new LinkageError(
694 "provider class not assignable to RMIClassLoaderSpi");
695 error.initCause(e);
696 throw error;
697 }
698 }
699
700 /*
701 * Next look for a provider configuration file installed:
702 */
703 Iterator<RMIClassLoaderSpi> iter =
704 ServiceLoader.load(RMIClassLoaderSpi.class,
705 ClassLoader.getSystemClassLoader()).iterator();
706 if (iter.hasNext()) {
707 try {
708 return iter.next();
709 } catch (ClassCastException e) {
710 Error error = new LinkageError(
711 "provider class not assignable to RMIClassLoaderSpi");
712 error.initCause(e);
713 throw error;
714 }
715 }
716
717 /*
718 * Finally, return the canonical instance of the default provider.
719 */
720 return defaultProvider;
721 }
722}