/*
 * Copyright (c) 1996, 2004, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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;
    }
}
