- /*
 - * @(#)ClassLoader.java 1.143 00/04/06
 - *
 - * Copyright 1994-2000 Sun Microsystems, Inc. All Rights Reserved.
 - *
 - * This software is the proprietary information of Sun Microsystems, Inc.
 - * Use is subject to license terms.
 - *
 - */
 - package java.lang;
 - import java.io.InputStream;
 - import java.io.IOException;
 - import java.io.StringWriter;
 - import java.io.PrintWriter;
 - import java.io.File;
 - import java.util.Hashtable;
 - import java.util.Enumeration;
 - import java.util.Vector;
 - import java.util.Stack;
 - import java.util.HashMap;
 - import java.util.HashSet;
 - import java.util.Map;
 - import java.util.NoSuchElementException;
 - import java.util.Set;
 - import java.util.jar.Manifest;
 - import java.net.URL;
 - import java.net.MalformedURLException;
 - import java.security.AccessController;
 - import java.security.AccessControlContext;
 - import java.security.PrivilegedAction;
 - import java.security.ProtectionDomain;
 - import java.security.PermissionCollection;
 - import java.security.CodeSource;
 - import java.security.Policy;
 - import sun.misc.URLClassPath;
 - import sun.misc.Resource;
 - import sun.misc.CompoundEnumeration;
 - //import sun.misc.Launcher;
 - /**
 - * The class <code>ClassLoader</code> is an abstract class.
 - * A class loader is an object that is responsible for loading
 - * classes. Given the name of a class, it should attempt to locate
 - * or generate data that constitutes a definition for the class. A
 - * typical strategy is to transform the name into a file
 - * name and then read a "class file" of that name from a file system.
 - * <p>
 - * Every <code>Class</code> object contains a
 - * {@link Class#getClassLoader() reference} to the
 - * <code>ClassLoader</code> that defined it.
 - * <p>
 - * Class objects for array classes are not created by class loaders, but
 - * are created automatically as required by the Java runtime. The class
 - * loader for an array class, as returned by {@link Class#getClassLoader()}
 - * is the same as the class loader for its element type; if the element
 - * type is a primitive type, then the array class has no class loader.
 - * <p>
 - * Applications implement subclasses of <code>ClassLoader</code> in
 - * order to extend the manner in which the Java virtual machine
 - * dynamically loads classes.
 - * <p>
 - * Class loaders may typically be used by security managers to
 - * indicate security domains.
 - * <p>
 - * The <code>ClassLoader</code> class uses a delegation model to
 - * search for classes and resources. Each instance of
 - * <code>ClassLoader</code> has an associated parent class loader.
 - * When called upon to find a class or resource, a
 - * <code>ClassLoader</code> instance will delegate the search for
 - * the class or resource to its parent class loader before
 - * attempting to find the class or resource itself. The virtual
 - * machine's built-in class loader, called the bootstrap class loader,
 - * does not itself have a parent but may serve as the parent of a
 - * <code>ClassLoader</code> instance.
 - * <p>
 - * Normally, the Java virtual machine loads classes from the local
 - * file system in a platform-dependent manner. For example, on UNIX
 - * systems, the virtual machine loads classes from the directory
 - * defined by the <code>CLASSPATH</code> environment variable.
 - * <p>
 - * However, some classes may not originate from a file; they may
 - * originate from other sources, such as the network, or they could
 - * be constructed by an application. The method
 - * <code>defineClass</code> converts an array of bytes into an
 - * instance of class <code>Class</code>. Instances of this newly
 - * defined class can be created using the <code>newInstance</code>
 - * method in class <code>Class</code>.
 - * <p>
 - * The methods and constructors of objects created by a class loader
 - * may reference other classes. To determine the class(es) referred
 - * to, the Java virtual machine calls the <code>loadClass</code>
 - * method of the class loader that originally created the class.
 - * <p>
 - * For example, an application could create a network class loader
 - * to download class files from a server. Sample code might look like:
 - * <blockquote><pre>
 - * ClassLoader loader = new NetworkClassLoader(host, port);
 - * Object main = loader.loadClass("Main", true).newInstance();
 - * . . .
 - * </pre></blockquote>
 - * <p>
 - * The network class loader subclass must define the methods
 - * <code>findClass</code> and <code>loadClassData</code>
 - * to load a class from the network. Once it
 - * has downloaded the bytes that make up the class, it should use the
 - * method <code>defineClass</code> to create a class instance. A
 - * sample implementation is:
 - * <p><hr><blockquote><pre>
 - * class NetworkClassLoader extends ClassLoader {
 - * String host;
 - * int port;
 - *
 - * public Class findClass(String name) {
 - * byte[] b = loadClassData(name);
 - * return defineClass(name, b, 0, b.length);
 - * }
 - *
 - * private byte[] loadClassData(String name) {
 - * // load the class data from the connection
 - * . . .
 - * }
 - * }
 - * </pre></blockquote><hr>
 - *
 - * @version 1.143, 04/06/00
 - * @see java.lang.Class
 - * @see java.lang.Class#newInstance()
 - * @see java.lang.ClassLoader#defineClass(byte[], int, int)
 - * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
 - * @see java.lang.ClassLoader#resolveClass(java.lang.Class)
 - * @since JDK1.0
 - */
 - public abstract class ClassLoader {
 - /*
 - * If initialization succeed this is set to true and security checks will
 - * succeed. Otherwise the object is not initialized and the object is
 - * useless.
 - */
 - private boolean initialized = false;
 - /*
 - * The parent class loader for delegation.
 - */
 - private ClassLoader parent;
 - /*
 - * Hashtable that maps packages to certs
 - */
 - private Hashtable package2certs = new Hashtable(11);
 - /*
 - * shared among all packages with unsigned classes
 - */
 - java.security.cert.Certificate[] nocerts;
 - /*
 - * The classes loaded by this class loader. The only purpose of this
 - * table is to keep the classes from being GC'ed until the loader
 - * is GC'ed.
 - */
 - private Vector classes = new Vector();
 - /*
 - * The initiating protection domains for all classes
 - * loaded by this loader.
 - */
 - private Set domains = new HashSet();
 - /*
 - * Called by the VM to record every loaded class with this loader.
 - */
 - void addClass(Class c) {
 - classes.addElement(c);
 - }
 - /*
 - * The packages defined in this class loader. Each package name is
 - * mapped to its corresponding Package object.
 - */
 - private HashMap packages = new HashMap();
 - /**
 - * Creates a new class loader using the specified parent class loader
 - * for delegation.
 - * <p>
 - * If there is a security manager, its <code>checkCreateClassLoader</code>
 - * method is called. This may result in a security exception.
 - *
 - * @throws SecurityException if a security manager exists and its
 - * <code>checkCreateClassLoader</code> method doesn't allow creation of a
 - * new class loader.
 - *
 - * @param parent the parent class loader
 - * @see java.lang.SecurityException
 - * @see java.lang.SecurityManager#checkCreateClassLoader()
 - * @since 1.2
 - */
 - protected ClassLoader(ClassLoader parent) {
 - SecurityManager security = System.getSecurityManager();
 - if (security != null) {
 - security.checkCreateClassLoader();
 - }
 - this.parent = parent;
 - initialized = true;
 - }
 - /**
 - * Creates a new class loader using the <code>ClassLoader</code>
 - * returned by the method <code>getSystemClassLoader()</code> as the
 - * parent class loader.
 - * <p>
 - * This constructor is invoked for every newly created class loader.
 - * Because the class <code>ClassLoader</code> is abstract, it is not
 - * possible to create a new instance of the class <code>ClassLoader</code>
 - * itself; however, every constructor for a subclass of
 - * <code>ClassLoader</code> necessarily invokes this constructor,
 - * explicitly or implicitly, directly or indirectly.
 - * <p>
 - * If there is a security manager, its <code>checkCreateClassLoader</code>
 - * method is called. This may result in a security exception.
 - *
 - * @throws SecurityException
 - * if a security manager exists and its <code>checkCreateClassLoader</code>
 - * method doesn't allow creation of a new class loader.
 - *
 - * @see java.lang.SecurityException
 - * @see java.lang.SecurityManager#checkCreateClassLoader()
 - */
 - protected ClassLoader() {
 - SecurityManager security = System.getSecurityManager();
 - if (security != null) {
 - security.checkCreateClassLoader();
 - }
 - this.parent = getSystemClassLoader();
 - initialized = true;
 - }
 - /**
 - * Loads the class with the specified name. This method searches for
 - * classes in the same manner as the {@link #loadClass(String, boolean)}
 - * method. It is called by the Java virtual machine to resolve class
 - * references. Calling this method is equivalent to calling
 - * <code>loadClass(name, false)</code>.
 - *
 - * @param name the name of the class
 - * @return the resulting <code>Class</code> object
 - * @exception ClassNotFoundException if the class was not found
 - */
 - public Class loadClass(String name) throws ClassNotFoundException
 - {
 - return loadClass(name, false);
 - }
 - /**
 - * Loads the class with the specified name. The default implementation of
 - * this method searches for classes in the following order:<p>
 - *
 - * <ol>
 - * <li> Call {@link #findLoadedClass(String)} to check if the class has
 - * already been loaded. <p>
 - * <li> Call the <code>loadClass</code> method on the parent class
 - * loader. If the parent is <code>null</code> the class loader
 - * built-in to the virtual machine is used, instead. <p>
 - * <li> Call the {@link #findClass(String)} method to find the class. <p>
 - * </ol>
 - *
 - * If the class was found using the above steps, and the
 - * <code>resolve</code> flag is true, this method will then call the
 - * {@link #resolveClass(Class)} method on the resulting class object.
 - * <p>
 - * From the Java 2 SDK, v1.2, subclasses of ClassLoader are
 - * encouraged to override
 - * {@link #findClass(String)}, rather than this method.<p>
 - *
 - * @param name the name of the class
 - * @param resolve if <code>true</code> then resolve the class
 - * @return the resulting <code>Class</code> object
 - * @exception ClassNotFoundException if the class could not be found
 - */
 - protected synchronized Class loadClass(String name, boolean resolve)
 - throws ClassNotFoundException
 - {
 - // First, check if the class has already been loaded
 - Class c = findLoadedClass(name);
 - if (c == null) {
 - try {
 - if (parent != null) {
 - c = parent.loadClass(name, false);
 - } else {
 - c = findBootstrapClass0(name);
 - }
 - } catch (ClassNotFoundException e) {
 - // If still not found, then call findClass in order
 - // to find the class.
 - c = findClass(name);
 - }
 - }
 - if (resolve) {
 - resolveClass(c);
 - }
 - return c;
 - }
 - /*
 - * This method is called by the virtual machine to load
 - * a class.
 - */
 - private synchronized Class loadClassInternal(String name)
 - throws ClassNotFoundException {
 - return loadClass(name);
 - }
 - private void checkPackageAccess(Class cls, ProtectionDomain pd) {
 - final SecurityManager sm = System.getSecurityManager();
 - if (sm != null) {
 - final String name = cls.getName();
 - final int i = name.lastIndexOf('.');
 - if (i != -1) {
 - AccessController.doPrivileged(new PrivilegedAction() {
 - public Object run() {
 - sm.checkPackageAccess(name.substring(0, i));
 - return null;
 - }
 - }, new AccessControlContext(new ProtectionDomain[] {pd}));
 - }
 - }
 - domains.add(pd);
 - }
 - /**
 - * Finds the specified class. This method should be overridden
 - * by class loader implementations that follow the new delegation model
 - * for loading classes, and will be called by the <code>loadClass</code>
 - * method after checking the parent class loader for the requested class.
 - * The default implementation throws <code>ClassNotFoundException</code>.
 - *
 - * @param name the name of the class
 - * @return the resulting <code>Class</code> object
 - * @exception ClassNotFoundException if the class could not be found
 - * @since 1.2
 - */
 - protected Class findClass(String name) throws ClassNotFoundException {
 - throw new ClassNotFoundException(name);
 - }
 - /**
 - * Converts an array of bytes into an instance of class
 - * <code>Class</code>. Before the Class can be used it must be
 - * resolved. This method is deprecated in favor of the version
 - * that takes the class name as its first argument, and is more
 - * secure.
 - *
 - * @param b the bytes that make up the class data. The bytes in
 - * positions <code>off</code> through <code>off+len-1</code>
 - * should have the format of a valid class file as defined
 - * by the
 - * <a href="http://java.sun.com/docs/books/vmspec/">Java
 - * Virtual Machine Specification</a>.
 - * @param off the start offset of the class data
 - * @param len the length of the class data
 - * @return the <code>Class</code> object that was created from the
 - * specified class data
 - * @exception ClassFormatError if the data did not contain a valid class
 - * @see ClassLoader#loadClass(java.lang.String, boolean)
 - * @see ClassLoader#resolveClass(java.lang.Class)
 - * @deprecated Replaced by defineClass(java.lang.String, byte[], int, int)
 - */
 - protected final Class defineClass(byte[] b, int off, int len)
 - throws ClassFormatError
 - {
 - return defineClass(null, b, off, len, null);
 - }
 - /**
 - * Converts an array of bytes into an instance of class <code>Class</code>.
 - * Before the Class can be used it must be resolved.
 - * <p>
 - * This method assigns a default <code>ProtectionDomain</code> to
 - * the newly defined class. The <code>ProtectionDomain</code>
 - * contains the set of permissions granted when
 - * a call to <code>Policy.getPolicy().getPermissions()</code> is made with
 - * a Codesource of <code>null,null</code>. The default domain is
 - * created on the first invocation of <code>defineClass</code>, and
 - * re-used on subsequent calls.
 - * <p>
 - * To assign a specific <code>ProtectionDomain</code> to the class,
 - * use the <code>defineClass</code> method that takes a
 - * <code>ProtectionDomain</code> as one of its arguments.
 - *
 - * @param name the expected name of the class, or <code>null</code>
 - * if not known, using '.' and not '/' as the separator
 - * and without a trailing ".class" suffix.
 - * @param b the bytes that make up the class data. The bytes in
 - * positions <code>off</code> through <code>off+len-1</code>
 - * should have the format of a valid class file as defined
 - * by the
 - * <a href="http://java.sun.com/docs/books/vmspec/">Java
 - * Virtual Machine Specification</a>.
 - * @param off the start offset of the class data
 - * @param len the length of the class data
 - * @return the <code>Class</code> object that was created from the
 - * specified class data
 - * @exception ClassFormatError if the data did not contain a valid class
 - * @exception IndexOutOfBoundsException if either <code>off</code> or
 - * <code>len</code> is negative, or if
 - * <code>off+len</code> is greater than <code>b.length</code>.
 - * @exception SecurityException if an attempt is made to add this class
 - * to a package that contains classes that were signed by
 - * a different set of certificates then this class, which
 - * is unsigned.
 - *
 - * @see ClassLoader#loadClass(java.lang.String, boolean)
 - * @see ClassLoader#resolveClass(java.lang.Class)
 - * @see java.security.ProtectionDomain
 - * @see java.security.Policy
 - * @see java.security.CodeSource
 - * @see java.security.SecureClassLoader
 - * @since JDK1.1
 - */
 - protected final Class defineClass(String name, byte[] b, int off, int len)
 - throws ClassFormatError
 - {
 - return defineClass(name, b, off, len, null);
 - }
 - /**
 - * Converts an array of bytes into an instance of class Class,
 - * with an optional ProtectionDomain. If the domain is <code>null</code>,
 - * then a default domain will be assigned to the class as specified
 - * in the documentation for {@link #defineClass(String,byte[],int,int)}.
 - * Before the class can be used it must be resolved.
 - *
 - * <p>The first class defined in a package determines the exact set of
 - * certificates that all subsequent classes defined in that package must
 - * contain. The set of certificates for a class is obtained from the
 - * <code>CodeSource</code> within the <code>ProtectionDomain</code> of
 - * the class. Any classes added to that package must contain
 - * the same set of certificates or a <code>SecurityException</code>
 - * will be thrown. Note that if the <code>name</code> argument is
 - * null, this check is not performed. You should always pass in the
 - * name of the class you are defining as well as the bytes. This
 - * ensures that the class you are defining is indeed the class
 - * you think it is.
 - *
 - * <p>The specified class name cannot begin with "java.", since all
 - * classes in the java.* packages can only be defined by the bootstrap
 - * class loader.
 - *
 - *
 - * @exception ClassFormatError if the data did not contain a valid class
 - * @exception IndexOutOfBoundsException if either <code>off</code> or
 - * <code>len</code> is negative, or if
 - * <code>off+len</code> is greater than <code>b.length</code>.
 - *
 - * @exception SecurityException if an attempt is made to add this class
 - * to a package that contains classes that were signed by
 - * a different set of certificates than this class, or if
 - * the class name begins with "java.".
 - *
 - * @param name the name of the class
 - * @param b the class bytes
 - * @param off the start offset of the class bytes
 - * @param len the length of the class bytes
 - * @param protectionDomain the ProtectionDomain of the class
 - * @return the <code>Class</code> object created from the data,
 - * and optional ProtectionDomain.
 - */
 - protected final Class defineClass(String name, byte[] b, int off, int len,
 - ProtectionDomain protectionDomain)
 - throws ClassFormatError
 - {
 - check();
 - if ((name != null) && name.startsWith("java.")) {
 - throw new SecurityException("Prohibited package name: " +
 - name.substring(0, name.lastIndexOf('.')));
 - }
 - if (protectionDomain == null) {
 - protectionDomain = getDefaultDomain();
 - }
 - if (name != null)
 - checkCerts(name, protectionDomain.getCodeSource());
 - Class c = defineClass0(name, b, off, len, protectionDomain);
 - if (protectionDomain.getCodeSource() != null) {
 - java.security.cert.Certificate certs[] =
 - protectionDomain.getCodeSource().getCertificates();
 - if (certs != null)
 - setSigners(c, certs);
 - }
 - return c;
 - }
 - private synchronized void checkCerts(String name, CodeSource cs)
 - {
 - int i = name.lastIndexOf('.');
 - String pname = (i == -1) ? "" : name.substring(0,i);
 - java.security.cert.Certificate[] pcerts =
 - (java.security.cert.Certificate[]) package2certs.get(pname);
 - if (pcerts == null) {
 - // first class in this package gets to define which
 - // certificates must be the same for all other classes
 - // in this package
 - if (cs != null) {
 - pcerts = cs.getCertificates();
 - }
 - if (pcerts == null) {
 - if (nocerts == null)
 - nocerts = new java.security.cert.Certificate[0];
 - pcerts = nocerts;
 - }
 - package2certs.put(pname, pcerts);
 - } else {
 - java.security.cert.Certificate[] certs = null;
 - if (cs != null) {
 - certs = cs.getCertificates();
 - }
 - if (!compareCerts(pcerts,certs)) {
 - throw new SecurityException("class \""+ name+
 - "\"'s signer information does not match signer information of other classes in the same package");
 - }
 - }
 - }
 - /**
 - * check to make sure the certs for the new class (certs) are
 - * the same as the certs for the first class inserted
 - * in the package (pcerts)
 - */
 - private boolean compareCerts(java.security.cert.Certificate[] pcerts,
 - java.security.cert.Certificate[] certs)
 - {
 - // certs can be null, indicating no certs.
 - if ((certs == null) || (certs.length == 0)) {
 - return pcerts.length == 0;
 - }
 - // the length must be the same at this point
 - if (certs.length != pcerts.length)
 - return false;
 - // go through and make sure all the certs in one array
 - // are in the other and vice-versa.
 - boolean match;
 - for (int i=0; i < certs.length; i++) {
 - match = false;
 - for (int j=0; j < pcerts.length; j++) {
 - if (certs[i].equals(pcerts[j])) {
 - match = true;
 - break;
 - }
 - }
 - if (!match) return false;
 - }
 - // now do the same for pcerts
 - for (int i=0; i < pcerts.length; i++) {
 - match = false;
 - for (int j=0; j < certs.length; j++) {
 - if (pcerts[i].equals(certs[j])) {
 - match = true;
 - break;
 - }
 - }
 - if (!match) return false;
 - }
 - return true;
 - }
 - /**
 - * Links the specified class.
 - * This (misleadingly named) method may be used by a class loader to
 - * link a class. If the class <code>c</code> has already been linked,
 - * then this method simply returns. Otherwise, the class is linked
 - * as described in the "Execution" chapter of the <i>Java Language
 - * Specification</i>.
 - *
 - * @param c the class to link
 - * @exception NullPointerException if <code>c</code> is <code>null</code>.
 - * @see java.lang.ClassLoader#defineClass(java.lang.String,byte[],int,int)
 - */
 - protected final void resolveClass(Class c) {
 - check();
 - resolveClass0(c);
 - }
 - /**
 - * Finds a class with the specified name, loading it if necessary.<p>
 - *
 - * Prior to the Java 2 SDK, this method loads a class from the local file
 - * system in a platform-dependent manner, and returns a class object
 - * that has no associated class loader.<p>
 - *
 - * Since the Java 2 SDK v1.2, this method loads the class through the
 - * system class loader(see {@link #getSystemClassLoader()}). Class objects
 - * returned might have <code>ClassLoader</code>s associated with them.
 - * Subclasses of <code>ClassLoader</code> need not usually call this
 - * method, because most class loaders need to override just {@link
 - * #findClass(String)}.<p>
 - *
 - * @param name the name of the class that is to be found
 - * @return the <code>Class</code> object for the specified
 - * <code>name</code>
 - * @exception ClassNotFoundException if the class could not be found
 - * @see #ClassLoader(ClassLoader)
 - * @see #getParent()
 - */
 - protected final Class findSystemClass(String name)
 - throws ClassNotFoundException
 - {
 - check();
 - ClassLoader system = getSystemClassLoader();
 - if (system == null) {
 - return findBootstrapClass(name);
 - }
 - return system.loadClass(name);
 - }
 - /**
 - * Returns the parent class loader for delegation. Some implementations
 - * may use <code>null</code> to represent the bootstrap class
 - * loader. This method will return <code>null</code> in such
 - * implementations if this class loader's parent is the bootstrap
 - * class loader.
 - * <p>
 - * If a security manager is present, and the caller's class loader is
 - * not null and is not an ancestor of this class loader, then
 - * this method calls the security manager's <code>checkPermission</code>
 - * method with a <code>RuntimePermission("getClassLoader")</code>
 - * permission to ensure it's ok to access the parent class loader.
 - * If not, a <code>SecurityException</code> will be thrown.
 - *
 - * @return the parent <code>ClassLoader</code>
 - * @throws SecurityException
 - * if a security manager exists and its
 - * <code>checkPermission</code> method doesn't allow
 - * access to this class loader's parent class loader.
 - *
 - * @see SecurityManager#checkPermission
 - * @see java.lang.RuntimePermission
 - *
 - * @since 1.2
 - */
 - public final ClassLoader getParent() {
 - if (parent == null)
 - return null;
 - SecurityManager sm = System.getSecurityManager();
 - if (sm != null) {
 - ClassLoader ccl = getCallerClassLoader();
 - if (ccl != null && !isAncestor(ccl)) {
 - sm.checkPermission(getGetClassLoaderPerm());
 - }
 - }
 - return parent;
 - }
 - /**
 - * Sets the signers of a class. This should be called after defining a
 - * class.
 - *
 - * @param c the <code>Class</code> object
 - * @param signers the signers for the class
 - * @since JDK1.1
 - */
 - protected final void setSigners(Class c, Object[] signers) {
 - check();
 - c.setSigners(signers);
 - }
 - private Class findBootstrapClass0(String name)
 - throws ClassNotFoundException {
 - check();
 - return findBootstrapClass(name);
 - }
 - private native Class defineClass0(String name, byte[] b, int off, int len,
 - ProtectionDomain pd);
 - private native void resolveClass0(Class c);
 - private native Class findBootstrapClass(String name)
 - throws ClassNotFoundException;
 - /*
 - * Check to make sure the class loader has been initialized.
 - */
 - private void check() {
 - if (!initialized) {
 - throw new SecurityException("ClassLoader object not initialized");
 - }
 - }
 - /**
 - * Finds the class with the given name if it had been previously loaded
 - * through this class loader.
 - *
 - * @param name the class name
 - * @return the <code>Class</code> object, or <code>null</code> if
 - * the class has not been loaded
 - * @since JDK1.1
 - */
 - protected native final Class findLoadedClass(String name);
 - /**
 - * Finds the resource with the given name. A resource is some data
 - * (images, audio, text, etc) that can be accessed by class code in a way
 - * that is independent of the location of the code.<p>
 - *
 - * The name of a resource is a "/"-separated path name that identifies
 - * the resource.<p>
 - *
 - * This method will first search the parent class loader for the resource;
 - * if the parent is <code>null</code> the path of the class loader
 - * built-in to the virtual machine is searched. That failing, this method
 - * will call <code>findResource</code> to find the resource.<p>
 - *
 - * @param name resource name
 - * @return a URL for reading the resource, or <code>null</code> if
 - * the resource could not be found or the caller doesn't have
 - * adequate privileges to get the resource.
 - * @since JDK1.1
 - * @see #findResource(String)
 - */
 - public URL getResource(String name) {
 - URL url;
 - if (parent != null) {
 - url = parent.getResource(name);
 - } else {
 - url = getBootstrapResource(name);
 - }
 - if (url == null) {
 - url = findResource(name);
 - }
 - return url;
 - }
 - /**
 - * Finds all the resources with the given name. A resource is some data
 - * (images, audio, text, etc) that can be accessed by class code in a way
 - * that is independent of the location of the code.<p>
 - *
 - * The name of a resource is a "/"-separated path name that identifies the
 - * resource.<p>
 - *
 - * The search order is described in the documentation for {@link
 - * #getResource(String)}.<p>
 - *
 - * @param name resource name
 - * @return an enumeration of URL to the resource. If no resources could
 - * be found, the enumeration will be empty. Resources that the
 - * doesn't have access to will not be in the enumeration.
 - * @throws IOException if I/O errors occur
 - * @since 1.2
 - * @see #getResource
 - * @see #findResources
 - */
 - public final Enumeration getResources(String name) throws IOException {
 - Enumeration[] tmp = new Enumeration[2];
 - if (parent != null) {
 - tmp[0] = parent.getResources(name);
 - } else {
 - tmp[0] = getBootstrapResources(name);
 - }
 - tmp[1] = findResources(name);
 - return new CompoundEnumeration(tmp);
 - }
 - /**
 - * Returns an Enumeration of URLs representing all the resources with
 - * the given name. Class loader implementations should override this
 - * method to specify where to load resources from.
 - *
 - * @param name the resource name
 - * @return an Enumeration of URLs for the resources
 - * @throws IOException if I/O errors occur
 - * @since 1.2
 - */
 - protected Enumeration findResources(String name) throws IOException {
 - return new CompoundEnumeration(new Enumeration[0]);
 - }
 - /**
 - * Finds the resource with the given name. Class loader
 - * implementations should override this method to specify where to
 - * find resources.
 - *
 - * @param name the resource name
 - * @return a URL for reading the resource, or <code>null</code>
 - * if the resource could not be found
 - * @since 1.2
 - */
 - protected URL findResource(String name) {
 - return null;
 - }
 - /**
 - * Find a resource of the specified name from the search path used to load
 - * classes.<p>
 - *
 - * In JDK1.1, the search path used is that of the virtual machine's
 - * built-in class loader.<p>
 - *
 - * Since the Java 2 SDK v1.2, this method locates the resource through the system class
 - * loader (see {@link #getSystemClassLoader()}).
 - *
 - * @param name the resource name
 - * @return a URL for reading the resource, or <code>null</code> if
 - * the resource could not be found
 - * @since JDK1.1
 - */
 - public static URL getSystemResource(String name) {
 - ClassLoader system = getSystemClassLoader();
 - if (system == null) {
 - return getBootstrapResource(name);
 - }
 - return system.getResource(name);
 - }
 - /**
 - * Find resources from the VM's built-in classloader.
 - */
 - private static URL getBootstrapResource(String name) {
 - URLClassPath ucp = getBootstrapClassPath();
 - Resource res = ucp.getResource(name);
 - return res != null ? res.getURL() : null;
 - }
 - /**
 - * Finds all resources of the specified name from the search path used to
 - * load classes. The resources thus found are returned as an
 - * <code>Enumeration</code> of <code>URL</code> objects. <p>
 - *
 - * The search order is described in the documentation for {@link
 - * #getSystemResource(String)}. <p>
 - *
 - * @param name the resource name
 - * @return an enumeration of resource URLs
 - * @throws IOException if I/O errors occur
 - * @since 1.2
 - */
 - public static Enumeration getSystemResources(String name)
 - throws IOException
 - {
 - ClassLoader system = getSystemClassLoader();
 - if (system == null) {
 - return getBootstrapResources(name);
 - }
 - return system.getResources(name);
 - }
 - /**
 - * Find resources from the VM's built-in classloader.
 - */
 - private static Enumeration getBootstrapResources(String name)
 - throws IOException
 - {
 - final Enumeration e = getBootstrapClassPath().getResources(name);
 - return new Enumeration () {
 - public Object nextElement() {
 - return ((Resource)e.nextElement()).getURL();
 - }
 - public boolean hasMoreElements() {
 - return e.hasMoreElements();
 - }
 - };
 - }
 - /*
 - * Returns the URLClassPath that is used for finding system resources.
 - */
 - static URLClassPath getBootstrapClassPath() {
 - if (bootstrapClassPath == null) {
 - bootstrapClassPath = sun.misc.Launcher.getBootstrapClassPath();
 - }
 - return bootstrapClassPath;
 - }
 - private static URLClassPath bootstrapClassPath;
 - /**
 - * Returns an input stream for reading the specified resource.
 - *
 - * The search order is described in the documentation for {@link
 - * #getResource(String)}.<p>
 - *
 - * @param name the resource name
 - * @return an input stream for reading the resource, or <code>null</code>
 - * if the resource could not be found
 - * @since JDK1.1
 - */
 - public InputStream getResourceAsStream(String name) {
 - URL url = getResource(name);
 - try {
 - return url != null ? url.openStream() : null;
 - } catch (IOException e) {
 - return null;
 - }
 - }
 - /**
 - * Open for reading, a resource of the specified name from the search path
 - * used to load classes.<p>
 - *
 - * The search order is described in the documentation for {@link
 - * #getSystemResource(String)}. <p>
 - *
 - * @param name the resource name
 - * @return an input stream for reading the resource, or <code>null</code>
 - * if the resource could not be found
 - * @since JDK1.1
 - */
 - public static InputStream getSystemResourceAsStream(String name) {
 - URL url = getSystemResource(name);
 - try {
 - return url != null ? url.openStream() : null;
 - } catch (IOException e) {
 - return null;
 - }
 - }
 - /**
 - * Returns the system class loader for delegation. This is the default
 - * delegation parent for new <code>ClassLoader</code> instances, and
 - * is typically the class loader used to start the application.
 - * <p>
 - * If a security manager is present, and the caller's class loader is
 - * not null and the caller's class loader is not the same as or an ancestor of
 - * the system class loader, then
 - * this method calls the security manager's <code>checkPermission</code>
 - * method with a <code>RuntimePermission("getClassLoader")</code>
 - * permission to ensure it's ok to access the system class loader.
 - * If not, a <code>SecurityException</code> will be thrown.
 - *
 - * @return the system <code>ClassLoader</code> for delegation, or
 - * <code>null</code> if none
 - * @throws SecurityException
 - * if a security manager exists and its
 - * <code>checkPermission</code> method doesn't allow
 - * access to the system class loader.
 - * @see SecurityManager#checkPermission
 - * @see java.lang.RuntimePermission
 - * @since 1.2
 - */
 - public static ClassLoader getSystemClassLoader() {
 - if (!sclSet) {
 - // Workaround for 4154308 (1.2FCS build breaker)
 - // Launcher l = Launcher.getLauncher();
 - sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
 - if (l != null) {
 - scl = l.getClassLoader();
 - }
 - sclSet = true;
 - }
 - if (scl == null) {
 - return null;
 - }
 - SecurityManager sm = System.getSecurityManager();
 - if (sm != null) {
 - ClassLoader ccl = getCallerClassLoader();
 - if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) {
 - sm.checkPermission(getGetClassLoaderPerm());
 - }
 - }
 - return scl;
 - }
 - // Returns true if the specified class loader can be found
 - // in this class loader's delegation chain.
 - boolean isAncestor(ClassLoader cl) {
 - ClassLoader acl = this;
 - do {
 - acl = acl.parent;
 - if (cl == acl) {
 - return true;
 - }
 - } while (acl != null);
 - return false;
 - }
 - // Returns the caller's class loader, or null if none
 - static native ClassLoader getCallerClassLoader();
 - // The class loader for the system
 - private static ClassLoader scl;
 - // Set to true once the system class loader has been set
 - private static boolean sclSet;
 - // Permission to access system or parent class loader
 - private static RuntimePermission getClassLoaderPerm = null;
 - static RuntimePermission getGetClassLoaderPerm()
 - {
 - if (getClassLoaderPerm == null)
 - getClassLoaderPerm = new RuntimePermission("getClassLoader");
 - return getClassLoaderPerm;
 - }
 - /**
 - * Defines a package by name in this ClassLoader. This allows class
 - * loaders to define the packages for their classes. Packages must be
 - * created before the class is defined, and package names must be
 - * unique within a class loader and cannot be redefined or changed
 - * once created.
 - *
 - * @param name the package name
 - * @param specTitle the specification title
 - * @param specVersion the specification version
 - * @param specVendor the specification vendor
 - * @param implTitle the implementation title
 - * @param implVersion the implementation version
 - * @param implVendor the implementation vendor
 - * @param sealBase If not null, then this package is sealed with
 - * respect to the given code source URL. Otherwise,
 - * the package is not sealed.
 - * @return the newly defined <code>Package</code> object
 - * @exception IllegalArgumentException if package name duplicates an
 - * existing package either in this class loader or one of
 - * its ancestors
 - * @since 1.2
 - */
 - protected Package definePackage(String name, String specTitle,
 - String specVersion, String specVendor,
 - String implTitle, String implVersion,
 - String implVendor, URL sealBase)
 - throws IllegalArgumentException
 - {
 - synchronized (packages) {
 - Package pkg = getPackage(name);
 - if (pkg != null) {
 - throw new IllegalArgumentException(name);
 - }
 - pkg = new Package(name, specTitle, specVersion, specVendor,
 - implTitle, implVersion, implVendor,
 - sealBase);
 - packages.put(name, pkg);
 - return pkg;
 - }
 - }
 - /**
 - * Returns a Package that has been defined by this class loader or any
 - * of its ancestors.
 - *
 - * @param name the package name
 - * @return the Package corresponding to the given name, or null if not
 - * found
 - * @since 1.2
 - */
 - protected Package getPackage(String name) {
 - synchronized (packages) {
 - Package pkg = (Package)packages.get(name);
 - if (pkg == null) {
 - if (parent != null) {
 - pkg = parent.getPackage(name);
 - } else {
 - pkg = Package.getSystemPackage(name);
 - }
 - if (pkg != null) {
 - packages.put(name, pkg);
 - }
 - }
 - return pkg;
 - }
 - }
 - /**
 - * Returns all of the Packages defined by this class loader and its
 - * ancestors.
 - *
 - * @return the array of <code>Package</code> objects defined by this
 - * <code>ClassLoader</code>
 - * @since 1.2
 - */
 - protected Package[] getPackages() {
 - Map map;
 - synchronized (packages) {
 - map = (Map)packages.clone();
 - }
 - Package[] pkgs;
 - if (parent != null) {
 - pkgs = parent.getPackages();
 - } else {
 - pkgs = Package.getSystemPackages();
 - }
 - if (pkgs != null) {
 - for (int i = 0; i < pkgs.length; i++) {
 - String pkgName = pkgs[i].getName();
 - if (map.get(pkgName) == null) {
 - map.put(pkgName, pkgs[i]);
 - }
 - }
 - }
 - return (Package[])map.values().toArray(new Package[map.size()]);
 - }
 - /**
 - * Returns the absolute path name of a native library. The VM
 - * invokes this method to locate the native libraries that belong
 - * to classes loaded with this class loader. If this method returns
 - * <code>null</code>, the VM searches the library along the path
 - * specified as the <code>java.library.path</code> property.
 - *
 - * @param libname the library name
 - * @return the absolute path of the native library
 - * @see java.lang.System#loadLibrary(java.lang.String)
 - * @see java.lang.System#mapLibraryName(java.lang.String)
 - * @since 1.2
 - */
 - protected String findLibrary(String libname) {
 - return null;
 - }
 - /**
 - * The inner class NativeLibrary denotes a loaded native library
 - * instance. Every classloader contains a vector of loaded native
 - * libraries in the private field <code>nativeLibraries</code>.
 - * The native libraries loaded into the system are entered into
 - * the <code>systemNativeLibraries</code> vector.
 - *
 - * Every native library reuqires a particular version of JNI. This
 - * is denoted by the private jniVersion field. This field is set
 - * by the VM when it loads the library, and used by the VM to pass
 - * the correct version of JNI to the native methods.
 - *
 - * @version 1.143, 04/06/00
 - * @see java.lang.ClassLoader
 - * @since 1.2
 - */
 - static class NativeLibrary {
 - /* opaque handle to native library, used in native code. */
 - long handle;
 - /* the version of JNI environment the native library requires. */
 - private int jniVersion;
 - /* the class from which the library is loaded, also indicates
 - the loader this native library belongs. */
 - private Class fromClass;
 - /* the canonicalized name of the native library. */
 - String name;
 - native void load(String name);
 - native long find(String name);
 - native void unload();
 - public NativeLibrary(Class fromClass, String name) {
 - this.name = name;
 - this.fromClass = fromClass;
 - }
 - protected void finalize() {
 - synchronized (loadedLibraryNames) {
 - if (fromClass.getClassLoader() != null && handle != 0) {
 - /* remove the native library name */
 - int size = loadedLibraryNames.size();
 - for (int i = 0; i < size; i++) {
 - if (name.equals(loadedLibraryNames.elementAt(i))) {
 - loadedLibraryNames.removeElementAt(i);
 - break;
 - }
 - }
 - /* unload the library. */
 - ClassLoader.nativeLibraryContext.push(this);
 - try {
 - unload();
 - } finally {
 - ClassLoader.nativeLibraryContext.pop();
 - }
 - }
 - }
 - }
 - /* Called in the VM to determine the context class in
 - JNI_Load/JNI_Unload */
 - static Class getFromClass() {
 - return ((NativeLibrary)
 - (ClassLoader.nativeLibraryContext.peek())).fromClass;
 - }
 - }
 - /* the "default" domain. Set as the default ProtectionDomain
 - * on newly created classses.
 - */
 - private ProtectionDomain defaultDomain = null;
 - /* the "default" permissions, shared by the default domains.
 - */
 - private static PermissionCollection defaultPermissions = null;
 - /*
 - * returns (and initializes) the default domain.
 - */
 - private ProtectionDomain getDefaultDomain() {
 - if (defaultDomain == null) {
 - synchronized(ClassLoader.class) {
 - if (defaultPermissions == null) {
 - defaultPermissions = (PermissionCollection)
 - AccessController.doPrivileged(new PrivilegedAction() {
 - public Object run() {
 - CodeSource cs = new CodeSource(null, null);
 - return Policy.getPolicy().getPermissions(cs);
 - }
 - });
 - }
 - if (defaultDomain == null) {
 - CodeSource cs = new CodeSource(null, null);
 - defaultDomain = new ProtectionDomain(cs,
 - defaultPermissions);
 - }
 - }
 - }
 - return defaultDomain;
 - }
 - /* All native library names we've loaded. */
 - private static Vector loadedLibraryNames = new Vector();
 - /* Native libraries belonging to system classes. */
 - private static Vector systemNativeLibraries = new Vector();
 - /* Native libraries associated with the class loader. */
 - private Vector nativeLibraries = new Vector();
 - /* native libraries being loaded/unloaded. */
 - private static Stack nativeLibraryContext = new Stack();
 - /* The paths searched for libraries */
 - static private String usr_paths[];
 - static private String sys_paths[];
 - private static String[] initializePath(String propname) {
 - String ldpath = System.getProperty(propname, "");
 - String ps = File.pathSeparator;
 - int ldlen = ldpath.length();
 - int i, j, n;
 - // Count the separators in the path
 - i = ldpath.indexOf(ps);
 - n = 0;
 - while (i >= 0) {
 - n++;
 - i = ldpath.indexOf(ps, i+1);
 - }
 - // allocate the array of paths - n :'s = n + 1 path elements
 - String[] paths = new String[n + 1];
 - // Fill the array with paths from the ldpath
 - n = i = 0;
 - j = ldpath.indexOf(ps);
 - while (j >= 0) {
 - if (j - i > 0) {
 - paths[n++] = ldpath.substring(i, j);
 - } else if (j - i == 0) {
 - paths[n++] = ".";
 - }
 - i = j + 1;
 - j = ldpath.indexOf(ps, i);
 - }
 - paths[n] = ldpath.substring(i, ldlen);
 - return paths;
 - }
 - /* Called in the java.lang.Runtime class to implement load
 - * and loadLibrary.
 - */
 - static void loadLibrary(Class fromClass, String name,
 - boolean isAbsolute) {
 - ClassLoader loader =
 - (fromClass == null) ? null : fromClass.getClassLoader();
 - if (sys_paths == null) {
 - usr_paths = initializePath("java.library.path");
 - sys_paths = initializePath("sun.boot.library.path");
 - }
 - if (isAbsolute) {
 - if (loadLibrary0(fromClass, new File(name))) {
 - return;
 - }
 - throw new UnsatisfiedLinkError("Can't load library: " + name);
 - }
 - if (loader != null) {
 - String libfilename = loader.findLibrary(name);
 - if (libfilename != null) {
 - File libfile = new File(libfilename);
 - if (!libfile.isAbsolute()) {
 - throw new UnsatisfiedLinkError(
 - "ClassLoader.findClass failed to return an absolute path: " + libfilename);
 - }
 - if (loadLibrary0(fromClass, libfile)) {
 - return;
 - }
 - throw new UnsatisfiedLinkError ("Can't load " + libfilename);
 - }
 - }
 - for (int i = 0 ; i < sys_paths.length ; i++) {
 - File libfile = new File(sys_paths[i], System.mapLibraryName(name));
 - if (loadLibrary0(fromClass, libfile)) {
 - return;
 - }
 - }
 - if (loader != null) {
 - for (int i = 0 ; i < usr_paths.length ; i++) {
 - File libfile = new File(usr_paths[i],
 - System.mapLibraryName(name));
 - if (loadLibrary0(fromClass, libfile)) {
 - return;
 - }
 - }
 - }
 - // Oops, it failed
 - throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
 - }
 - private static boolean loadLibrary0(Class fromClass, final File file) {
 - Boolean exists = (Boolean)
 - AccessController.doPrivileged(new PrivilegedAction() {
 - public Object run() {
 - return new Boolean(file.exists());
 - }
 - });
 - if (!exists.booleanValue()) {
 - return false;
 - }
 - String name;
 - try {
 - name = file.getCanonicalPath();
 - } catch (IOException e) {
 - return false;
 - }
 - ClassLoader loader =
 - (fromClass == null) ? null : fromClass.getClassLoader();
 - Vector libs =
 - loader != null ? loader.nativeLibraries : systemNativeLibraries;
 - synchronized (libs) {
 - int size = libs.size();
 - for (int i = 0; i < size; i++) {
 - NativeLibrary lib = (NativeLibrary)libs.elementAt(i);
 - if (name.equals(lib.name)) {
 - return true;
 - }
 - }
 - synchronized (loadedLibraryNames) {
 - if (loadedLibraryNames.contains(name)) {
 - throw new UnsatisfiedLinkError
 - ("Native Library " +
 - name +
 - " already loaded in another classloader");
 - }
 - /* If the library is being loaded (must be by
 - * the same thread, because Runtime.load and
 - * Runtime.loadLibrary are synchronous). The
 - * reason is can occur is that the JNI_OnLoad
 - * function can cause another loadLibrary call.
 - *
 - * Thus we can use a static stack to hold the list
 - * of libraries we are loading.
 - *
 - * If there is a pending load operation for the
 - * library, we immediately return success; otherwise,
 - * we raise UnsatisfiedLinkError.
 - */
 - int n = nativeLibraryContext.size();
 - for (int i = 0; i < n; i++) {
 - NativeLibrary lib = (NativeLibrary)
 - nativeLibraryContext.elementAt(i);
 - if (name.equals(lib.name)) {
 - if (loader == lib.fromClass.getClassLoader()) {
 - return true;
 - } else {
 - throw new UnsatisfiedLinkError
 - ("Native Library " +
 - name +
 - " is being loaded in another classloader");
 - }
 - }
 - }
 - NativeLibrary lib = new NativeLibrary(fromClass, name);
 - nativeLibraryContext.push(lib);
 - try {
 - lib.load(name);
 - } finally {
 - nativeLibraryContext.pop();
 - }
 - if (lib.handle != 0) {
 - loadedLibraryNames.addElement(name);
 - libs.addElement(lib);
 - return true;
 - }
 - return false;
 - }
 - }
 - }
 - /* Called in the VM class linking code. */
 - static long findNative(ClassLoader loader, String name) {
 - Vector libs =
 - loader != null ? loader.nativeLibraries : systemNativeLibraries;
 - synchronized (libs) {
 - int size = libs.size();
 - for (int i = 0; i < size; i++) {
 - NativeLibrary lib = (NativeLibrary)libs.elementAt(i);
 - long entry = lib.find(name);
 - if (entry != 0)
 - return entry;
 - }
 - }
 - return 0;
 - }
 - }