/*
 * Copyright 1996-2004 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package java.rmi.server;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Iterator;
import java.util.ServiceLoader;

/**
 * <code>RMIClassLoader</code> comprises static methods to support
 * dynamic class loading with RMI.  Included are methods for loading
 * classes from a network location (one or more URLs) and obtaining
 * the location from which an existing class should be loaded by
 * remote parties.  These methods are used by the RMI runtime when
 * marshalling and unmarshalling classes contained in the arguments
 * and return values of remote method calls, and they also may be
 * invoked directly by applications in order to mimic RMI's dynamic
 * class loading behavior.
 *
 * <p>The implementation of the following static methods
 *
 * <ul>
 *
 * <li>{@link #loadClass(URL,String)}
 * <li>{@link #loadClass(String,String)}
 * <li>{@link #loadClass(String,String,ClassLoader)}
 * <li>{@link #loadProxyClass(String,String[],ClassLoader)}
 * <li>{@link #getClassLoader(String)}
 * <li>{@link #getClassAnnotation(Class)}
 *
 * </ul>
 *
 * is provided by an instance of {@link RMIClassLoaderSpi}, the
 * service provider interface for those methods.  When one of the
 * methods is invoked, its behavior is to delegate to a corresponding
 * method on the service provider instance.  The details of how each
 * method delegates to the provider instance is described in the
 * documentation for each particular method.
 *
 * <p>The service provider instance is chosen as follows:
 *
 * <ul>
 *
 * <li>If the system property
 * <code>java.rmi.server.RMIClassLoaderSpi</code> is defined, then if
 * its value equals the string <code>"default"</code>, the provider
 * instance will be the value returned by an invocation of the {@link
 * #getDefaultProviderInstance()} method, and for any other value, if
 * a class named with the value of the property can be loaded by the
 * system class loader (see {@link ClassLoader#getSystemClassLoader})
 * and that class is assignable to {@link RMIClassLoaderSpi} and has a
 * public no-argument constructor, then that constructor will be
 * invoked to create the provider instance.  If the property is
 * defined but any other of those conditions are not true, then an
 * unspecified <code>Error</code> will be thrown to code that attempts
 * to use <code>RMIClassLoader</code>, indicating the failure to
 * obtain a provider instance.
 *
 * <li>If a resource named
 * <code>META-INF/services/java.rmi.server.RMIClassLoaderSpi</code> is
 * visible to the system class loader, then the contents of that
 * resource are interpreted as a provider-configuration file, and the
 * first class name specified in that file is used as the provider
 * class name.  If a class with that name can be loaded by the system
 * class loader and that class is assignable to {@link
 * RMIClassLoaderSpi} and has a public no-argument constructor, then
 * that constructor will be invoked to create the provider instance.
 * If the resource is found but a provider cannot be instantiated as
 * described, then an unspecified <code>Error</code> will be thrown to
 * code that attempts to use <code>RMIClassLoader</code>, indicating
 * the failure to obtain a provider instance.
 *
 * <li>Otherwise, the provider instance will be the value returned by
 * an invocation of the {@link #getDefaultProviderInstance()} method.
 *
 * </ul>
 *
 * @author      Ann Wollrath
 * @author      Peter Jones
 * @author      Laird Dornin
 * @see         RMIClassLoaderSpi
 * @since       JDK1.1
 */
public class RMIClassLoader {

    /** "default" provider instance */
    private static final RMIClassLoaderSpi defaultProvider =
        newDefaultProviderInstance();

    /** provider instance */
    private static final RMIClassLoaderSpi provider =
        AccessController.doPrivileged(
            new PrivilegedAction<RMIClassLoaderSpi>() {
                public RMIClassLoaderSpi run() { return initializeProvider(); }
            });

    /*
     * Disallow anyone from creating one of these.
     */
    private RMIClassLoader() {}

    /**
     * Loads the class with the specified <code>name</code>.
     *
     * <p>This method delegates to {@link #loadClass(String,String)},
     * passing <code>null</code> as the first argument and
     * <code>name</code> as the second argument.
     *
     * @param   name the name of the class to load
     *
     * @return  the <code>Class</code> object representing the loaded class
     *
     * @throws MalformedURLException if a provider-specific URL used
     * to load classes is invalid
     *
     * @throws  ClassNotFoundException if a definition for the class
     * could not be found at the codebase location
     *
     * @deprecated replaced by <code>loadClass(String,String)</code> method
     * @see #loadClass(String,String)
     */
    @Deprecated
    public static Class<?> loadClass(String name)
        throws MalformedURLException, ClassNotFoundException
    {
        return loadClass((String) null, name);
    }

    /**
     * Loads a class from a codebase URL.
     *
     * If <code>codebase</code> is <code>null</code>, then this method
     * will behave the same as {@link #loadClass(String,String)} with a
     * <code>null</code> <code>codebase</code> and the given class name.
     *
     * <p>This method delegates to the
     * {@link RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}
     * method of the provider instance, passing the result of invoking
     * {@link URL#toString} on the given URL (or <code>null</code> if
     * <code>codebase</code> is null) as the first argument,
     * <code>name</code> as the second argument,
     * and <code>null</code> as the third argument.
     *
     * @param   codebase the URL to load the class from, or <code>null</code>
     *
     * @param   name the name of the class to load
     *
     * @return  the <code>Class</code> object representing the loaded class
     *
     * @throws MalformedURLException if <code>codebase</code> is
     * <code>null</code> and a provider-specific URL used
     * to load classes is invalid
     *
     * @throws  ClassNotFoundException if a definition for the class
     * could not be found at the specified URL
     */
    public static Class<?> loadClass(URL codebase, String name)
        throws MalformedURLException, ClassNotFoundException
    {
        return provider.loadClass(
            codebase != null ? codebase.toString() : null, name, null);
    }

    /**
     * Loads a class from a codebase URL path.
     *
     * <p>This method delegates to the
     * {@link RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}
     * method of the provider instance, passing <code>codebase</code>
     * as the first argument, <code>name</code> as the second argument,
     * and <code>null</code> as the third argument.
     *
     * @param   codebase the list of URLs (separated by spaces) to load
     * the class from, or <code>null</code>
     *
     * @param   name the name of the class to load
     *
     * @return  the <code>Class</code> object representing the loaded class
     *
     * @throws MalformedURLException if <code>codebase</code> is
     * non-<code>null</code> and contains an invalid URL, or if
     * <code>codebase</code> is <code>null</code> and a provider-specific
     * URL used to load classes is invalid
     *
     * @throws  ClassNotFoundException if a definition for the class
     * could not be found at the specified location
     *
     * @since   1.2
     */
    public static Class<?> loadClass(String codebase, String name)
        throws MalformedURLException, ClassNotFoundException
    {
        return provider.loadClass(codebase, name, null);
    }

    /**
     * Loads a class from a codebase URL path, optionally using the
     * supplied loader.
     *
     * This method should be used when the caller would like to make
     * available to the provider implementation an additional contextual
     * class loader to consider, such as the loader of a caller on the
     * stack.  Typically, a provider implementation will attempt to
     * resolve the named class using the given <code>defaultLoader</code>,
     * if specified, before attempting to resolve the class from the
     * codebase URL path.
     *
     * <p>This method delegates to the
     * {@link RMIClassLoaderSpi#loadClass(String,String,ClassLoader)}
     * method of the provider instance, passing <code>codebase</code>
     * as the first argument, <code>name</code> as the second argument,
     * and <code>defaultLoader</code> as the third argument.
     *
     * @param   codebase the list of URLs (separated by spaces) to load
     * the class from, or <code>null</code>
     *
     * @param   name the name of the class to load
     *
     * @param   defaultLoader additional contextual class loader
     * to use, or <code>null</code>
     *
     * @return  the <code>Class</code> object representing the loaded class
     *
     * @throws MalformedURLException if <code>codebase</code> is
     * non-<code>null</code> and contains an invalid URL, or if
     * <code>codebase</code> is <code>null</code> and a provider-specific
     * URL used to load classes is invalid
     *
     * @throws  ClassNotFoundException if a definition for the class
     * could not be found at the specified location
     *
     * @since   1.4
     */
    public static Class<?> loadClass(String codebase, String name,
                                     ClassLoader defaultLoader)
        throws MalformedURLException, ClassNotFoundException
    {
        return provider.loadClass(codebase, name, defaultLoader);
    }

    /**
     * Loads a dynamic proxy class (see {@link java.lang.reflect.Proxy})
     * that implements a set of interfaces with the given names
     * from a codebase URL path.
     *
     * <p>The interfaces will be resolved similar to classes loaded via
     * the {@link #loadClass(String,String)} method using the given
     * <code>codebase</code>.
     *
     * <p>This method delegates to the
     * {@link RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)}
     * method of the provider instance, passing <code>codebase</code>
     * as the first argument, <code>interfaces</code> as the second argument,
     * and <code>defaultLoader</code> as the third argument.
     *
     * @param   codebase the list of URLs (space-separated) to load
     * classes from, or <code>null</code>
     *
     * @param   interfaces the names of the interfaces for the proxy class
     * to implement
     *
     * @param   defaultLoader additional contextual class loader
     * to use, or <code>null</code>
     *
     * @return  a dynamic proxy class that implements the named interfaces
     *
     * @throws  MalformedURLException if <code>codebase</code> is
     * non-<code>null</code> and contains an invalid URL, or
     * if <code>codebase</code> is <code>null</code> and a provider-specific
     * URL used to load classes is invalid
     *
     * @throws  ClassNotFoundException if a definition for one of
     * the named interfaces could not be found at the specified location,
     * or if creation of the dynamic proxy class failed (such as if
     * {@link java.lang.reflect.Proxy#getProxyClass(ClassLoader,Class[])}
     * would throw an <code>IllegalArgumentException</code> for the given
     * interface list)
     *
     * @since   1.4
     */
    public static Class<?> loadProxyClass(String codebase, String[] interfaces,
                                          ClassLoader defaultLoader)
        throws ClassNotFoundException, MalformedURLException
    {
        return provider.loadProxyClass(codebase, interfaces, defaultLoader);
    }

    /**
     * Returns a class loader that loads classes from the given codebase
     * URL path.
     *
     * <p>The class loader returned is the class loader that the
     * {@link #loadClass(String,String)} method would use to load classes
     * for the same <code>codebase</code> argument.
     *
     * <p>This method delegates to the
     * {@link RMIClassLoaderSpi#getClassLoader(String)} method
     * of the provider instance, passing <code>codebase</code> as the argument.
     *
     * <p>If there is a security manger, its <code>checkPermission</code>
     * method will be invoked with a
     * <code>RuntimePermission("getClassLoader")</code> permission;
     * this could result in a <code>SecurityException</code>.
     * The provider implementation of this method may also perform further
     * security checks to verify that the calling context has permission to
     * connect to all of the URLs in the codebase URL path.
     *
     * @param   codebase the list of URLs (space-separated) from which
     * the returned class loader will load classes from, or <code>null</code>
     *
     * @return a class loader that loads classes from the given codebase URL
     * path
     *
     * @throws  MalformedURLException if <code>codebase</code> is
     * non-<code>null</code> and contains an invalid URL, or
     * if <code>codebase</code> is <code>null</code> and a provider-specific
     * URL used to identify the class loader is invalid
     *
     * @throws  SecurityException if there is a security manager and the
     * invocation of its <code>checkPermission</code> method fails, or
     * if the caller does not have permission to connect to all of the
     * URLs in the codebase URL path
     *
     * @since   1.3
     */
    public static ClassLoader getClassLoader(String codebase)
        throws MalformedURLException, SecurityException
    {
        return provider.getClassLoader(codebase);
    }

    /**
     * Returns the annotation string (representing a location for
     * the class definition) that RMI will use to annotate the class
     * descriptor when marshalling objects of the given class.
     *
     * <p>This method delegates to the
     * {@link RMIClassLoaderSpi#getClassAnnotation(Class)} method
     * of the provider instance, passing <code>cl</code> as the argument.
     *
     * @param   cl the class to obtain the annotation for
     *
     * @return  a string to be used to annotate the given class when
     * it gets marshalled, or <code>null</code>
     *
     * @throws  NullPointerException if <code>cl</code> is <code>null</code>
     *
     * @since   1.2
     */
    /*
     * REMIND: Should we say that the returned class annotation will or
     * should be a (space-separated) list of URLs?
     */
    public static String getClassAnnotation(Class<?> cl) {
        return provider.getClassAnnotation(cl);
    }

    /**
     * Returns the canonical instance of the default provider
     * for the service provider interface {@link RMIClassLoaderSpi}.
     * If the system property <code>java.rmi.server.RMIClassLoaderSpi</code>
     * is not defined, then the <code>RMIClassLoader</code> static
     * methods
     *
     * <ul>
     *
     * <li>{@link #loadClass(URL,String)}
     * <li>{@link #loadClass(String,String)}
     * <li>{@link #loadClass(String,String,ClassLoader)}
     * <li>{@link #loadProxyClass(String,String[],ClassLoader)}
     * <li>{@link #getClassLoader(String)}
     * <li>{@link #getClassAnnotation(Class)}
     *
     * </ul>
     *
     * will use the canonical instance of the default provider
     * as the service provider instance.
     *
     * <p>If there is a security manager, its
     * <code>checkPermission</code> method will be invoked with a
     * <code>RuntimePermission("setFactory")</code> permission; this
     * could result in a <code>SecurityException</code>.
     *
     * <p>The default service provider instance implements
     * {@link RMIClassLoaderSpi} as follows:
     *
     * <blockquote>
     *
     * <p>The <b>{@link RMIClassLoaderSpi#getClassAnnotation(Class)
     * getClassAnnotation}</b> method returns a <code>String</code>
     * representing the codebase URL path that a remote party should
     * use to download the definition for the specified class.  The
     * format of the returned string is a path of URLs separated by
     * spaces.
     *
     * The codebase string returned depends on the defining class
     * loader of the specified class:
     *
     * <ul>
     *
     * <p><li>If the class loader is the system class loader (see
     * {@link ClassLoader#getSystemClassLoader}), a parent of the
     * system class loader such as the loader used for installed
     * extensions, or the bootstrap class loader (which may be
     * represented by <code>null</code>), then the value of the
     * <code>java.rmi.server.codebase</code> property (or possibly an
     * earlier cached value) is returned, or
     * <code>null</code> is returned if that property is not set.
     *
     * <p><li>Otherwise, if the class loader is an instance of
     * <code>URLClassLoader</code>, then the returned string is a
     * space-separated list of the external forms of the URLs returned
     * by invoking the <code>getURLs</code> methods of the loader.  If
     * the <code>URLClassLoader</code> was created by this provider to
     * service an invocation of its <code>loadClass</code> or
     * <code>loadProxyClass</code> methods, then no permissions are
     * required to get the associated codebase string.  If it is an
     * arbitrary other <code>URLClassLoader</code> instance, then if
     * there is a security manager, its <code>checkPermission</code>
     * method will be invoked once for each URL returned by the
     * <code>getURLs</code> method, with the permission returned by
     * invoking <code>openConnection().getPermission()</code> on each
     * URL; if any of those invocations throws a
     * <code>SecurityException</code> or an <code>IOException</code>,
     * then the value of the <code>java.rmi.server.codebase</code>
     * property (or possibly an earlier cached value) is returned, or
     * <code>null</code> is returned if that property is not set.
     *
     * <p><li>Finally, if the class loader is not an instance of
     * <code>URLClassLoader</code>, then the value of the
     * <code>java.rmi.server.codebase</code> property (or possibly an
     * earlier cached value) is returned, or
     * <code>null</code> is returned if that property is not set.
     *
     * </ul>
     *
     * <p>For the implementations of the methods described below,
     * which all take a <code>String</code> parameter named
     * <code>codebase</code> that is a space-separated list of URLs,
     * each invocation has an associated <i>codebase loader</i> that
     * is identified using the <code>codebase</code> argument in
     * conjunction with the current thread's context class loader (see
     * {@link Thread#getContextClassLoader()}).  When there is a
     * security manager, this provider maintains an internal table of
     * class loader instances (which are at least instances of {@link
     * java.net.URLClassLoader}) keyed by the pair of their parent
     * class loader and their codebase URL path (an ordered list of
     * URLs).  If the <code>codebase</code> argument is <code>null</code>,
     * the codebase URL path is the value of the system property
     * <code>java.rmi.server.codebase</code> or possibly an
     * earlier cached value.  For a given codebase URL path passed as the
     * <code>codebase</code> argument to an invocation of one of the
     * below methods in a given context, the codebase loader is the
     * loader in the table with the specified codebase URL path and
     * the current thread's context class loader as its parent.  If no
     * such loader exists, then one is created and added to the table.
     * The table does not maintain strong references to its contained
     * loaders, in order to allow them and their defined classes to be
     * garbage collected when not otherwise reachable.  In order to
     * prevent arbitrary untrusted code from being implicitly loaded
     * into a virtual machine with no security manager, if there is no
     * security manager set, the codebase loader is just the current
     * thread's context class loader (the supplied codebase URL path
     * is ignored, so remote class loading is disabled).
     *
     * <p>The <b>{@link RMIClassLoaderSpi#getClassLoader(String)
     * getClassLoader}</b> method returns the codebase loader for the
     * specified codebase URL path.  If there is a security manager,
     * then if the calling context does not have permission to connect
     * to all of the URLs in the codebase URL path, a
     * <code>SecurityException</code> will be thrown.
     *
     * <p>The <b>{@link
     * RMIClassLoaderSpi#loadClass(String,String,ClassLoader)
     * loadClass}</b> method attempts to load the class with the
     * specified name as follows:
     *
     * <blockquote>
     *
     * If the <code>defaultLoader</code> argument is
     * non-<code>null</code>, it first attempts to load the class with the
     * specified <code>name</code> using the
     * <code>defaultLoader</code>, such as by evaluating
     *
     * <pre>
     *     Class.forName(name, false, defaultLoader)
     * </pre>
     *
     * If the class is successfully loaded from the
     * <code>defaultLoader</code>, that class is returned.  If an
     * exception other than <code>ClassNotFoundException</code> is
     * thrown, that exception is thrown to the caller.
     *
     * <p>Next, the <code>loadClass</code> method attempts to load the
     * class with the specified <code>name</code> using the codebase
     * loader for the specified codebase URL path.
     * If there is a security manager, then the calling context
     * must have permission to connect to all of the URLs in the
     * codebase URL path; otherwise, the current thread's context
     * class loader will be used instead of the codebase loader.
     *
     * </blockquote>
     *
     * <p>The <b>{@link
     * RMIClassLoaderSpi#loadProxyClass(String,String[],ClassLoader)
     * loadProxyClass}</b> method attempts to return a dynamic proxy
     * class with the named interface as follows:
     *
     * <blockquote>
     *
     * <p>If the <code>defaultLoader</code> argument is
     * non-<code>null</code> and all of the named interfaces can be
     * resolved through that loader, then,
     *
     * <ul>
     *
     * <li>if all of the resolved interfaces are <code>public</code>,
     * then it first attempts to obtain a dynamic proxy class (using
     * {@link
     * java.lang.reflect.Proxy#getProxyClass(ClassLoader,Class[])
     * Proxy.getProxyClass}) for the resolved interfaces defined in
     * the codebase loader; if that attempt throws an
     * <code>IllegalArgumentException</code>, it then attempts to
     * obtain a dynamic proxy class for the resolved interfaces
     * defined in the <code>defaultLoader</code>.  If both attempts
     * throw <code>IllegalArgumentException</code>, then this method
     * throws a <code>ClassNotFoundException</code>.  If any other
     * exception is thrown, that exception is thrown to the caller.
     *
     * <li>if all of the non-<code>public</code> resolved interfaces
     * are defined in the same class loader, then it attempts to
     * obtain a dynamic proxy class for the resolved interfaces
     * defined in that loader.
     *
     * <li>otherwise, a <code>LinkageError</code> is thrown (because a
     * class that implements all of the specified interfaces cannot be
     * defined in any loader).
     *
     * </ul>
     *
     * <p>Otherwise, if all of the named interfaces can be resolved
     * through the codebase loader, then,
     *
     * <ul>
     *
     * <li>if all of the resolved interfaces are <code>public</code>,
     * then it attempts to obtain a dynamic proxy class for the
     * resolved interfaces in the codebase loader.  If the attempt
     * throws an <code>IllegalArgumentException</code>, then this
     * method throws a <code>ClassNotFoundException</code>.
     *
     * <li>if all of the non-<code>public</code> resolved interfaces
     * are defined in the same class loader, then it attempts to
     * obtain a dynamic proxy class for the resolved interfaces
     * defined in that loader.
     *
     * <li>otherwise, a <code>LinkageError</code> is thrown (because a
     * class that implements all of the specified interfaces cannot be
     * defined in any loader).
     *
     * </ul>
     *
     * <p>Otherwise, a <code>ClassNotFoundException</code> is thrown
     * for one of the named interfaces that could not be resolved.
     *
     * </blockquote>
     *
     * </blockquote>
     *
     * @return  the canonical instance of the default service provider
     *
     * @throws  SecurityException if there is a security manager and the
     * invocation of its <code>checkPermission</code> method fails
     *
     * @since   1.4
     */
    public static RMIClassLoaderSpi getDefaultProviderInstance() {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("setFactory"));
        }
        return defaultProvider;
    }

    /**
     * Returns the security context of the given class loader.
     *
     * @param   loader a class loader from which to get the security context
     *
     * @return  the security context
     *
     * @deprecated no replacement.  As of the Java 2 platform v1.2, RMI no
     * longer uses this method to obtain a class loader's security context.
     * @see java.lang.SecurityManager#getSecurityContext()
     */
    @Deprecated
    public static Object getSecurityContext(ClassLoader loader)
    {
        return sun.rmi.server.LoaderHandler.getSecurityContext(loader);
    }

    /**
     * Creates an instance of the default provider class.
     */
    private static RMIClassLoaderSpi newDefaultProviderInstance() {
        return new RMIClassLoaderSpi() {
            public Class<?> loadClass(String codebase, String name,
                                      ClassLoader defaultLoader)
                throws MalformedURLException, ClassNotFoundException
            {
                return sun.rmi.server.LoaderHandler.loadClass(
                    codebase, name, defaultLoader);
            }

            public Class<?> loadProxyClass(String codebase,
                                           String[] interfaces,
                                           ClassLoader defaultLoader)
                throws MalformedURLException, ClassNotFoundException
            {
                return sun.rmi.server.LoaderHandler.loadProxyClass(
                    codebase, interfaces, defaultLoader);
            }

            public ClassLoader getClassLoader(String codebase)
                throws MalformedURLException
            {
                return sun.rmi.server.LoaderHandler.getClassLoader(codebase);
            }

            public String getClassAnnotation(Class<?> cl) {
                return sun.rmi.server.LoaderHandler.getClassAnnotation(cl);
            }
        };
    }

    /**
     * Chooses provider instance, following above documentation.
     *
     * This method assumes that it has been invoked in a privileged block.
     */
    private static RMIClassLoaderSpi initializeProvider() {
        /*
         * First check for the system property being set:
         */
        String providerClassName =
            System.getProperty("java.rmi.server.RMIClassLoaderSpi");

        if (providerClassName != null) {
            if (providerClassName.equals("default")) {
                return defaultProvider;
            }

            try {
                Class<? extends RMIClassLoaderSpi> providerClass =
                    Class.forName(providerClassName, false,
                                  ClassLoader.getSystemClassLoader())
                    .asSubclass(RMIClassLoaderSpi.class);
                return providerClass.newInstance();

            } catch (ClassNotFoundException e) {
                throw new NoClassDefFoundError(e.getMessage());
            } catch (IllegalAccessException e) {
                throw new IllegalAccessError(e.getMessage());
            } catch (InstantiationException e) {
                throw new InstantiationError(e.getMessage());
            } catch (ClassCastException e) {
                Error error = new LinkageError(
                    "provider class not assignable to RMIClassLoaderSpi");
                error.initCause(e);
                throw error;
            }
        }

        /*
         * Next look for a provider configuration file installed:
         */
        Iterator<RMIClassLoaderSpi> iter =
            ServiceLoader.load(RMIClassLoaderSpi.class,
                               ClassLoader.getSystemClassLoader()).iterator();
        if (iter.hasNext()) {
            try {
                return iter.next();
            } catch (ClassCastException e) {
                Error error = new LinkageError(
                    "provider class not assignable to RMIClassLoaderSpi");
                error.initCause(e);
                throw error;
            }
        }

        /*
         * Finally, return the canonical instance of the default provider.
         */
        return defaultProvider;
    }
}
