Save This Page
Home » openjdk-7 » java » rmi » server » [javadoc | source]
    1   /*
    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   
   26   package java.rmi.server;
   27   
   28   import java.net.MalformedURLException;
   29   import java.net.URL;
   30   import java.security.AccessController;
   31   import java.security.PrivilegedAction;
   32   import java.util.Iterator;
   33   import 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    */
  110   public 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   }

Save This Page
Home » openjdk-7 » java » rmi » server » [javadoc | source]