jtulach@119: /* jtulach@119: * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. jtulach@119: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jtulach@119: * jtulach@119: * This code is free software; you can redistribute it and/or modify it jtulach@119: * under the terms of the GNU General Public License version 2 only, as jtulach@119: * published by the Free Software Foundation. Oracle designates this jtulach@119: * particular file as subject to the "Classpath" exception as provided jtulach@119: * by Oracle in the LICENSE file that accompanied this code. jtulach@119: * jtulach@119: * This code is distributed in the hope that it will be useful, but WITHOUT jtulach@119: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jtulach@119: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jtulach@119: * version 2 for more details (a copy is included in the LICENSE file that jtulach@119: * accompanied this code). jtulach@119: * jtulach@119: * You should have received a copy of the GNU General Public License version jtulach@119: * 2 along with this work; if not, write to the Free Software Foundation, jtulach@119: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jtulach@119: * jtulach@119: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jtulach@119: * or visit www.oracle.com if you need additional information or have any jtulach@119: * questions. jtulach@119: */ jtulach@119: package java.lang; jtulach@119: jaroslav@1375: import java.io.ByteArrayInputStream; jtulach@119: import java.io.InputStream; jtulach@119: import java.io.IOException; jtulach@119: import java.net.URL; jtulach@119: import java.util.Enumeration; jaroslav@122: import java.util.NoSuchElementException; jaroslav@232: import org.apidesign.bck2brwsr.core.JavaScriptBody; jtulach@119: jtulach@119: /** jtulach@119: * A class loader is an object that is responsible for loading classes. The jtulach@119: * class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to jtulach@119: * locate or generate data that constitutes a definition for the class. A jtulach@119: * typical strategy is to transform the name into a file name and then read a jtulach@119: * "class file" of that name from a file system. jtulach@119: * jtulach@119: *

Every {@link Class Class} object contains a {@link jtulach@119: * Class#getClassLoader() reference} to the ClassLoader that defined jtulach@119: * it. jtulach@119: * jtulach@119: *

Class objects for array classes are not created by class jtulach@119: * loaders, but are created automatically as required by the Java runtime. jtulach@119: * The class loader for an array class, as returned by {@link jtulach@119: * Class#getClassLoader()} is the same as the class loader for its element jtulach@119: * type; if the element type is a primitive type, then the array class has no jtulach@119: * class loader. jtulach@119: * jtulach@119: *

Applications implement subclasses of ClassLoader in order to jtulach@119: * extend the manner in which the Java virtual machine dynamically loads jtulach@119: * classes. jtulach@119: * jtulach@119: *

Class loaders may typically be used by security managers to indicate jtulach@119: * security domains. jtulach@119: * jtulach@119: *

The ClassLoader class uses a delegation model to search for jtulach@119: * classes and resources. Each instance of ClassLoader has an jtulach@119: * associated parent class loader. When requested to find a class or jtulach@119: * resource, a ClassLoader instance will delegate the search for the jtulach@119: * class or resource to its parent class loader before attempting to find the jtulach@119: * class or resource itself. The virtual machine's built-in class loader, jtulach@119: * called the "bootstrap class loader", does not itself have a parent but may jtulach@119: * serve as the parent of a ClassLoader instance. jtulach@119: * jtulach@119: *

Class loaders that support concurrent loading of classes are known as jtulach@119: * parallel capable class loaders and are required to register jtulach@119: * themselves at their class initialization time by invoking the jtulach@119: * {@link jtulach@119: * #registerAsParallelCapable ClassLoader.registerAsParallelCapable} jtulach@119: * method. Note that the ClassLoader class is registered as parallel jtulach@119: * capable by default. However, its subclasses still need to register themselves jtulach@119: * if they are parallel capable.
jtulach@119: * In environments in which the delegation model is not strictly jtulach@119: * hierarchical, class loaders need to be parallel capable, otherwise class jtulach@119: * loading can lead to deadlocks because the loader lock is held for the jtulach@119: * duration of the class loading process (see {@link #loadClass jtulach@119: * loadClass} methods). jtulach@119: * jtulach@119: *

Normally, the Java virtual machine loads classes from the local file jtulach@119: * system in a platform-dependent manner. For example, on UNIX systems, the jtulach@119: * virtual machine loads classes from the directory defined by the jtulach@119: * CLASSPATH environment variable. jtulach@119: * jtulach@119: *

However, some classes may not originate from a file; they may originate jtulach@119: * from other sources, such as the network, or they could be constructed by an jtulach@119: * application. The method {@link #defineClass(String, byte[], int, int) jtulach@119: * defineClass} converts an array of bytes into an instance of class jtulach@119: * Class. Instances of this newly defined class can be created using jtulach@119: * {@link Class#newInstance Class.newInstance}. jtulach@119: * jtulach@119: *

The methods and constructors of objects created by a class loader may jtulach@119: * reference other classes. To determine the class(es) referred to, the Java jtulach@119: * virtual machine invokes the {@link #loadClass loadClass} method of jtulach@119: * the class loader that originally created the class. jtulach@119: * jtulach@119: *

For example, an application could create a network class loader to jtulach@119: * download class files from a server. Sample code might look like: jtulach@119: * jtulach@119: *

jtulach@119:  *   ClassLoader loader = new NetworkClassLoader(host, port);
jtulach@119:  *   Object main = loader.loadClass("Main", true).newInstance();
jtulach@119:  *        . . .
jtulach@119:  * 
jtulach@119: * jtulach@119: *

The network class loader subclass must define the methods {@link jtulach@119: * #findClass findClass} and loadClassData to load a class jtulach@119: * from the network. Once it has downloaded the bytes that make up the class, jtulach@119: * it should use the method {@link #defineClass defineClass} to jtulach@119: * create a class instance. A sample implementation is: jtulach@119: * jtulach@119: *

jtulach@119:  *     class NetworkClassLoader extends ClassLoader {
jtulach@119:  *         String host;
jtulach@119:  *         int port;
jtulach@119:  *
jtulach@119:  *         public Class findClass(String name) {
jtulach@119:  *             byte[] b = loadClassData(name);
jtulach@119:  *             return defineClass(name, b, 0, b.length);
jtulach@119:  *         }
jtulach@119:  *
jtulach@119:  *         private byte[] loadClassData(String name) {
jtulach@119:  *             // load the class data from the connection
jtulach@119:  *              . . .
jtulach@119:  *         }
jtulach@119:  *     }
jtulach@119:  * 
jtulach@119: * jtulach@119: *

Binary names

jtulach@119: * jtulach@119: *

Any class name provided as a {@link String} parameter to methods in jtulach@119: * ClassLoader must be a binary name as defined by jtulach@119: * The Java™ Language Specification. jtulach@119: * jtulach@119: *

Examples of valid class names include: jtulach@119: *

jtulach@119:  *   "java.lang.String"
jtulach@119:  *   "javax.swing.JSpinner$DefaultEditor"
jtulach@119:  *   "java.security.KeyStore$Builder$FileBuilder$1"
jtulach@119:  *   "java.net.URLClassLoader$3$1"
jtulach@119:  * 
jtulach@119: * jtulach@119: * @see #resolveClass(Class) jtulach@119: * @since 1.0 jtulach@119: */ jtulach@119: public abstract class ClassLoader { jtulach@119: jaroslav@232: @JavaScriptBody(args = {}, body = "") jtulach@119: private static native void registerNatives(); jtulach@119: static { jtulach@119: registerNatives(); jtulach@119: } jtulach@119: jtulach@119: // The parent class loader for delegation jtulach@119: // Note: VM hardcoded the offset of this field, thus all new fields jtulach@119: // must be added *after* it. jtulach@119: private final ClassLoader parent; jtulach@119: jtulach@119: jtulach@119: /** jtulach@119: * Creates a new class loader using the specified parent class loader for jtulach@119: * delegation. jtulach@119: * jtulach@119: *

If there is a security manager, its {@link jtulach@119: * SecurityManager#checkCreateClassLoader() jtulach@119: * checkCreateClassLoader} method is invoked. This may result in jtulach@119: * a security exception.

jtulach@119: * jtulach@119: * @param parent jtulach@119: * The parent class loader jtulach@119: * jtulach@119: * @throws SecurityException jtulach@119: * If a security manager exists and its jtulach@119: * checkCreateClassLoader method doesn't allow creation jtulach@119: * of a new class loader. jtulach@119: * jtulach@119: * @since 1.2 jtulach@119: */ jtulach@119: protected ClassLoader(ClassLoader parent) { jaroslav@1333: this.parent = parent; jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Creates a new class loader using the ClassLoader returned by jtulach@119: * the method {@link #getSystemClassLoader() jtulach@119: * getSystemClassLoader()} as the parent class loader. jtulach@119: * jtulach@119: *

If there is a security manager, its {@link jtulach@119: * SecurityManager#checkCreateClassLoader() jtulach@119: * checkCreateClassLoader} method is invoked. This may result in jtulach@119: * a security exception.

jtulach@119: * jtulach@119: * @throws SecurityException jtulach@119: * If a security manager exists and its jtulach@119: * checkCreateClassLoader method doesn't allow creation jtulach@119: * of a new class loader. jtulach@119: */ jtulach@119: protected ClassLoader() { jaroslav@1333: this.parent = null; jtulach@119: } jtulach@119: jtulach@119: // -- Class -- jtulach@119: jtulach@119: /** jtulach@119: * Loads the class with the specified binary name. jtulach@119: * This method searches for classes in the same manner as the {@link jtulach@119: * #loadClass(String, boolean)} method. It is invoked by the Java virtual jtulach@119: * machine to resolve class references. Invoking this method is equivalent jtulach@119: * to invoking {@link #loadClass(String, boolean) loadClass(name, jtulach@119: * false)}.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The binary name of the class jtulach@119: * jtulach@119: * @return The resulting Class object jtulach@119: * jtulach@119: * @throws ClassNotFoundException jtulach@119: * If the class was not found jtulach@119: */ jtulach@119: public Class loadClass(String name) throws ClassNotFoundException { jtulach@119: return loadClass(name, false); jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Loads the class with the specified binary name. The jtulach@119: * default implementation of this method searches for classes in the jtulach@119: * following order: jtulach@119: * jtulach@119: *

    jtulach@119: * jtulach@119: *
  1. Invoke {@link #findLoadedClass(String)} to check if the class jtulach@119: * has already been loaded.

  2. jtulach@119: * jtulach@119: *
  3. Invoke the {@link #loadClass(String) loadClass} method jtulach@119: * on the parent class loader. If the parent is null the class jtulach@119: * loader built-in to the virtual machine is used, instead.

  4. jtulach@119: * jtulach@119: *
  5. Invoke the {@link #findClass(String)} method to find the jtulach@119: * class.

  6. jtulach@119: * jtulach@119: *
jtulach@119: * jtulach@119: *

If the class was found using the above steps, and the jtulach@119: * resolve flag is true, this method will then invoke the {@link jtulach@119: * #resolveClass(Class)} method on the resulting Class object. jtulach@119: * jtulach@119: *

Subclasses of ClassLoader are encouraged to override {@link jtulach@119: * #findClass(String)}, rather than this method.

jtulach@119: * jtulach@119: *

Unless overridden, this method synchronizes on the result of jtulach@119: * {@link #getClassLoadingLock getClassLoadingLock} method jtulach@119: * during the entire class loading process. jtulach@119: * jtulach@119: * @param name jtulach@119: * The binary name of the class jtulach@119: * jtulach@119: * @param resolve jtulach@119: * If true then resolve the class jtulach@119: * jtulach@119: * @return The resulting Class object jtulach@119: * jtulach@119: * @throws ClassNotFoundException jtulach@119: * If the class could not be found jtulach@119: */ jtulach@119: protected Class loadClass(String name, boolean resolve) jtulach@119: throws ClassNotFoundException jtulach@119: { jtulach@119: synchronized (getClassLoadingLock(name)) { jtulach@119: // First, check if the class has already been loaded jtulach@119: Class c = findLoadedClass(name); jtulach@119: if (c == null) { jtulach@119: try { jtulach@119: if (parent != null) { jtulach@119: c = parent.loadClass(name, false); jtulach@119: } else { jtulach@119: c = findBootstrapClassOrNull(name); jtulach@119: } jtulach@119: } catch (ClassNotFoundException e) { jtulach@119: // ClassNotFoundException thrown if class not found jtulach@119: // from the non-null parent class loader jtulach@119: } jtulach@119: jtulach@119: if (c == null) { jtulach@119: // If still not found, then invoke findClass in order jtulach@119: // to find the class. jtulach@119: c = findClass(name); jtulach@119: jaroslav@122: // // this is the defining class loader; record the stats jaroslav@122: // sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); jaroslav@122: // sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); jaroslav@122: // sun.misc.PerfCounter.getFindClasses().increment(); jtulach@119: } jtulach@119: } jtulach@119: if (resolve) { jtulach@119: resolveClass(c); jtulach@119: } jtulach@119: return c; jtulach@119: } jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Returns the lock object for class loading operations. jtulach@119: * For backward compatibility, the default implementation of this method jtulach@119: * behaves as follows. If this ClassLoader object is registered as jtulach@119: * parallel capable, the method returns a dedicated object associated jtulach@119: * with the specified class name. Otherwise, the method returns this jtulach@119: * ClassLoader object.

jtulach@119: * jtulach@119: * @param className jtulach@119: * The name of the to-be-loaded class jtulach@119: * jtulach@119: * @return the lock for class loading operations jtulach@119: * jtulach@119: * @throws NullPointerException jtulach@119: * If registered as parallel capable and className is null jtulach@119: * jtulach@119: * @see #loadClass(String, boolean) jtulach@119: * jtulach@119: * @since 1.7 jtulach@119: */ jtulach@119: protected Object getClassLoadingLock(String className) { jtulach@119: Object lock = this; jtulach@119: return lock; jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Finds the class with the specified binary name. jtulach@119: * This method should be overridden by class loader implementations that jtulach@119: * follow the delegation model for loading classes, and will be invoked by jtulach@119: * the {@link #loadClass loadClass} method after checking the jtulach@119: * parent class loader for the requested class. The default implementation jtulach@119: * throws a ClassNotFoundException.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The binary name of the class jtulach@119: * jtulach@119: * @return The resulting Class object jtulach@119: * jtulach@119: * @throws ClassNotFoundException jtulach@119: * If the class could not be found jtulach@119: * jtulach@119: * @since 1.2 jtulach@119: */ jtulach@119: protected Class findClass(String name) throws ClassNotFoundException { jtulach@119: throw new ClassNotFoundException(name); jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Converts an array of bytes into an instance of class Class. jtulach@119: * Before the Class can be used it must be resolved. This method jtulach@119: * is deprecated in favor of the version that takes a binary name as its first argument, and is more secure. jtulach@119: * jtulach@119: * @param b jtulach@119: * The bytes that make up the class data. The bytes in positions jtulach@119: * off through off+len-1 should have the format jtulach@119: * of a valid class file as defined by jtulach@119: * The Java™ Virtual Machine Specification. jtulach@119: * jtulach@119: * @param off jtulach@119: * The start offset in b of the class data jtulach@119: * jtulach@119: * @param len jtulach@119: * The length of the class data jtulach@119: * jtulach@119: * @return The Class object that was created from the specified jtulach@119: * class data jtulach@119: * jtulach@119: * @throws ClassFormatError jtulach@119: * If the data did not contain a valid class jtulach@119: * jtulach@119: * @throws IndexOutOfBoundsException jtulach@119: * If either off or len is negative, or if jtulach@119: * off+len is greater than b.length. jtulach@119: * jtulach@119: * @throws SecurityException jtulach@119: * If an attempt is made to add this class to a package that jtulach@119: * contains classes that were signed by a different set of jtulach@119: * certificates than this class, or if an attempt is made jtulach@119: * to define a class in a package with a fully-qualified name jtulach@119: * that starts with "{@code java.}". jtulach@119: * jtulach@119: * @see #loadClass(String, boolean) jtulach@119: * @see #resolveClass(Class) jtulach@119: * jtulach@119: * @deprecated Replaced by {@link #defineClass(String, byte[], int, int) jtulach@119: * defineClass(String, byte[], int, int)} jtulach@119: */ jtulach@119: @Deprecated jtulach@119: protected final Class defineClass(byte[] b, int off, int len) jtulach@119: throws ClassFormatError jtulach@119: { jaroslav@122: throw new SecurityException(); jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Converts an array of bytes into an instance of class Class. jtulach@119: * Before the Class can be used it must be resolved. jtulach@119: * jtulach@119: *

This method assigns a default {@link java.security.ProtectionDomain jtulach@119: * ProtectionDomain} to the newly defined class. The jtulach@119: * ProtectionDomain is effectively granted the same set of jtulach@119: * permissions returned when {@link jtulach@119: * java.security.Policy#getPermissions(java.security.CodeSource) jtulach@119: * Policy.getPolicy().getPermissions(new CodeSource(null, null))} jtulach@119: * is invoked. The default domain is created on the first invocation of jtulach@119: * {@link #defineClass(String, byte[], int, int) defineClass}, jtulach@119: * and re-used on subsequent invocations. jtulach@119: * jtulach@119: *

To assign a specific ProtectionDomain to the class, use jtulach@119: * the {@link #defineClass(String, byte[], int, int, jtulach@119: * java.security.ProtectionDomain) defineClass} method that takes a jtulach@119: * ProtectionDomain as one of its arguments.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The expected binary name of the class, or jtulach@119: * null if not known jtulach@119: * jtulach@119: * @param b jtulach@119: * The bytes that make up the class data. The bytes in positions jtulach@119: * off through off+len-1 should have the format jtulach@119: * of a valid class file as defined by jtulach@119: * The Java™ Virtual Machine Specification. jtulach@119: * jtulach@119: * @param off jtulach@119: * The start offset in b of the class data jtulach@119: * jtulach@119: * @param len jtulach@119: * The length of the class data jtulach@119: * jtulach@119: * @return The Class object that was created from the specified jtulach@119: * class data. jtulach@119: * jtulach@119: * @throws ClassFormatError jtulach@119: * If the data did not contain a valid class jtulach@119: * jtulach@119: * @throws IndexOutOfBoundsException jtulach@119: * If either off or len is negative, or if jtulach@119: * off+len is greater than b.length. jtulach@119: * jtulach@119: * @throws SecurityException jtulach@119: * If an attempt is made to add this class to a package that jtulach@119: * contains classes that were signed by a different set of jtulach@119: * certificates than this class (which is unsigned), or if jtulach@119: * name begins with "java.". jtulach@119: * jtulach@119: * @see #loadClass(String, boolean) jtulach@119: * @see #resolveClass(Class) jtulach@119: * @see java.security.CodeSource jtulach@119: * @see java.security.SecureClassLoader jtulach@119: * jtulach@119: * @since 1.1 jtulach@119: */ jtulach@119: protected final Class defineClass(String name, byte[] b, int off, int len) jtulach@119: throws ClassFormatError jtulach@119: { jaroslav@122: throw new SecurityException(); jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Links the specified class. This (misleadingly named) method may be jtulach@119: * used by a class loader to link a class. If the class c has jtulach@119: * already been linked, then this method simply returns. Otherwise, the jtulach@119: * class is linked as described in the "Execution" chapter of jtulach@119: * The Java™ Language Specification. jtulach@119: *

jtulach@119: * jtulach@119: * @param c jtulach@119: * The class to link jtulach@119: * jtulach@119: * @throws NullPointerException jtulach@119: * If c is null. jtulach@119: * jtulach@119: * @see #defineClass(String, byte[], int, int) jtulach@119: */ jtulach@119: protected final void resolveClass(Class c) { jtulach@119: resolveClass0(c); jtulach@119: } jtulach@119: jtulach@119: private native void resolveClass0(Class c); jtulach@119: jtulach@119: jtulach@119: /** jtulach@119: * Returns the class with the given binary name if this jtulach@119: * loader has been recorded by the Java virtual machine as an initiating jtulach@119: * loader of a class with that binary name. Otherwise jtulach@119: * null is returned.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The binary name of the class jtulach@119: * jtulach@119: * @return The Class object, or null if the class has jtulach@119: * not been loaded jtulach@119: * jtulach@119: * @since 1.1 jtulach@119: */ jtulach@119: protected final Class findLoadedClass(String name) { jtulach@119: if (!checkName(name)) jtulach@119: return null; jtulach@119: return findLoadedClass0(name); jtulach@119: } jtulach@119: jtulach@119: private native final Class findLoadedClass0(String name); jtulach@119: jtulach@119: /** jtulach@119: * Sets the signers of a class. This should be invoked after defining a jtulach@119: * class.

jtulach@119: * jtulach@119: * @param c jtulach@119: * The Class object jtulach@119: * jtulach@119: * @param signers jtulach@119: * The signers for the class jtulach@119: * jtulach@119: * @since 1.1 jtulach@119: */ jtulach@119: protected final void setSigners(Class c, Object[] signers) { jaroslav@122: //c.setSigners(signers); jaroslav@122: throw new UnsupportedOperationException(); jtulach@119: } jtulach@119: jtulach@119: jtulach@119: // -- Resource -- jtulach@119: jtulach@119: /** jtulach@119: * Finds the resource with the given name. A resource is some data jtulach@119: * (images, audio, text, etc) that can be accessed by class code in a way jtulach@119: * that is independent of the location of the code. jtulach@119: * jtulach@119: *

The name of a resource is a '/'-separated path name that jtulach@119: * identifies the resource. jtulach@119: * jtulach@119: *

This method will first search the parent class loader for the jtulach@119: * resource; if the parent is null the path of the class loader jtulach@119: * built-in to the virtual machine is searched. That failing, this method jtulach@119: * will invoke {@link #findResource(String)} to find the resource.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The resource name jtulach@119: * jtulach@119: * @return A URL object for reading the resource, or jtulach@119: * null if the resource could not be found or the invoker jtulach@119: * doesn't have adequate privileges to get the resource. jtulach@119: * jtulach@119: * @since 1.1 jtulach@119: */ jtulach@119: public URL getResource(String name) { jtulach@119: URL url; jtulach@119: if (parent != null) { jtulach@119: url = parent.getResource(name); jtulach@119: } else { jtulach@119: url = getBootstrapResource(name); jtulach@119: } jtulach@119: if (url == null) { jtulach@119: url = findResource(name); jtulach@119: } jtulach@119: return url; jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Finds all the resources with the given name. A resource is some data jtulach@119: * (images, audio, text, etc) that can be accessed by class code in a way jtulach@119: * that is independent of the location of the code. jtulach@119: * jtulach@119: *

The name of a resource is a /-separated path name that jtulach@119: * identifies the resource. jtulach@119: * jtulach@119: *

The search order is described in the documentation for {@link jtulach@119: * #getResource(String)}.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The resource name jtulach@119: * jtulach@119: * @return An enumeration of {@link java.net.URL URL} objects for jtulach@119: * the resource. If no resources could be found, the enumeration jtulach@119: * will be empty. Resources that the class loader doesn't have jtulach@119: * access to will not be in the enumeration. jtulach@119: * jtulach@119: * @throws IOException jtulach@119: * If I/O errors occur jtulach@119: * jtulach@119: * @see #findResources(String) jtulach@119: * jtulach@119: * @since 1.2 jtulach@119: */ jtulach@119: public Enumeration getResources(String name) throws IOException { jtulach@119: Enumeration[] tmp = new Enumeration[2]; jtulach@119: if (parent != null) { jtulach@119: tmp[0] = parent.getResources(name); jtulach@119: } else { jtulach@119: tmp[0] = getBootstrapResources(name); jtulach@119: } jtulach@119: tmp[1] = findResources(name); jtulach@119: jaroslav@122: return new CompoundEnumeration(tmp); jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Finds the resource with the given name. Class loader implementations jtulach@119: * should override this method to specify where to find resources.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The resource name jtulach@119: * jtulach@119: * @return A URL object for reading the resource, or jtulach@119: * null if the resource could not be found jtulach@119: * jtulach@119: * @since 1.2 jtulach@119: */ jtulach@119: protected URL findResource(String name) { jtulach@119: return null; jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Returns an enumeration of {@link java.net.URL URL} objects jtulach@119: * representing all the resources with the given name. Class loader jtulach@119: * implementations should override this method to specify where to load jtulach@119: * resources from.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The resource name jtulach@119: * jtulach@119: * @return An enumeration of {@link java.net.URL URL} objects for jtulach@119: * the resources jtulach@119: * jtulach@119: * @throws IOException jtulach@119: * If I/O errors occur jtulach@119: * jtulach@119: * @since 1.2 jtulach@119: */ jtulach@119: protected Enumeration findResources(String name) throws IOException { jaroslav@122: return new CompoundEnumeration(new Enumeration[0]); jtulach@119: } jtulach@119: jtulach@119: // index 0: java.lang.ClassLoader.class jtulach@119: // index 1: the immediate caller of index 0. jtulach@119: // index 2: the immediate caller of index 1. jtulach@119: private static native Class getCaller(int index); jtulach@119: jtulach@119: /** jtulach@119: * Registers the caller as parallel capable.

jtulach@119: * The registration succeeds if and only if all of the following jtulach@119: * conditions are met:
jtulach@119: * 1. no instance of the caller has been created

jtulach@119: * 2. all of the super classes (except class Object) of the caller are jtulach@119: * registered as parallel capable

jtulach@119: * Note that once a class loader is registered as parallel capable, there jtulach@119: * is no way to change it back.

jtulach@119: * jtulach@119: * @return true if the caller is successfully registered as jtulach@119: * parallel capable and false if otherwise. jtulach@119: * jtulach@119: * @since 1.7 jtulach@119: */ jaroslav@122: // protected static boolean registerAsParallelCapable() { jaroslav@122: // return false; jaroslav@122: // } jtulach@119: jtulach@119: /** jtulach@119: * Find a resource of the specified name from the search path used to load jtulach@119: * classes. This method locates the resource through the system class jtulach@119: * loader (see {@link #getSystemClassLoader()}).

jtulach@119: * jtulach@119: * @param name jtulach@119: * The resource name jtulach@119: * jtulach@119: * @return A {@link java.net.URL URL} object for reading the jtulach@119: * resource, or null if the resource could not be found jtulach@119: * jtulach@119: * @since 1.1 jtulach@119: */ jtulach@119: public static URL getSystemResource(String name) { jtulach@119: ClassLoader system = getSystemClassLoader(); jtulach@119: if (system == null) { jtulach@119: return getBootstrapResource(name); jtulach@119: } jtulach@119: return system.getResource(name); jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Finds all resources of the specified name from the search path used to jtulach@119: * load classes. The resources thus found are returned as an jtulach@119: * {@link java.util.Enumeration Enumeration} of {@link jtulach@119: * java.net.URL URL} objects. jtulach@119: * jtulach@119: *

The search order is described in the documentation for {@link jtulach@119: * #getSystemResource(String)}.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The resource name jtulach@119: * jtulach@119: * @return An enumeration of resource {@link java.net.URL URL} jtulach@119: * objects jtulach@119: * jtulach@119: * @throws IOException jtulach@119: * If I/O errors occur jtulach@119: jtulach@119: * @since 1.2 jtulach@119: */ jtulach@119: public static Enumeration getSystemResources(String name) jtulach@119: throws IOException jtulach@119: { jaroslav@576: ClassLoader system = null; // getSystemClassLoader(); jtulach@119: if (system == null) { jtulach@119: return getBootstrapResources(name); jtulach@119: } jtulach@119: return system.getResources(name); jtulach@119: } jtulach@119: jtulach@119: jtulach@119: jtulach@119: /** jtulach@119: * Returns an input stream for reading the specified resource. jtulach@119: * jtulach@119: *

The search order is described in the documentation for {@link jtulach@119: * #getResource(String)}.

jtulach@119: * jtulach@119: * @param name jtulach@119: * The resource name jtulach@119: * jtulach@119: * @return An input stream for reading the resource, or null jtulach@119: * if the resource could not be found jtulach@119: * jtulach@119: * @since 1.1 jtulach@119: */ jtulach@119: public InputStream getResourceAsStream(String name) { jtulach@119: URL url = getResource(name); jtulach@119: try { jtulach@119: return url != null ? url.openStream() : null; jtulach@119: } catch (IOException e) { jtulach@119: return null; jtulach@119: } jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Open for reading, a resource of the specified name from the search path jtulach@119: * used to load classes. This method locates the resource through the jtulach@119: * system class loader (see {@link #getSystemClassLoader()}).

jtulach@119: * jtulach@119: * @param name jtulach@119: * The resource name jtulach@119: * jtulach@119: * @return An input stream for reading the resource, or null jtulach@119: * if the resource could not be found jtulach@119: * jtulach@119: * @since 1.1 jtulach@119: */ jtulach@119: public static InputStream getSystemResourceAsStream(String name) { jtulach@119: URL url = getSystemResource(name); jtulach@119: try { jtulach@119: return url != null ? url.openStream() : null; jtulach@119: } catch (IOException e) { jtulach@119: return null; jtulach@119: } jtulach@119: } jtulach@119: jtulach@119: jtulach@119: // -- Hierarchy -- jtulach@119: jtulach@119: /** jtulach@119: * Returns the parent class loader for delegation. Some implementations may jtulach@119: * use null to represent the bootstrap class loader. This method jtulach@119: * will return null in such implementations if this class loader's jtulach@119: * parent is the bootstrap class loader. jtulach@119: * jtulach@119: *

If a security manager is present, and the invoker's class loader is jtulach@119: * not null and is not an ancestor of this class loader, then this jtulach@119: * method invokes the security manager's {@link jtulach@119: * SecurityManager#checkPermission(java.security.Permission) jtulach@119: * checkPermission} method with a {@link jtulach@119: * RuntimePermission#RuntimePermission(String) jtulach@119: * RuntimePermission("getClassLoader")} permission to verify jtulach@119: * access to the parent class loader is permitted. If not, a jtulach@119: * SecurityException will be thrown.

jtulach@119: * jtulach@119: * @return The parent ClassLoader jtulach@119: * jtulach@119: * @throws SecurityException jtulach@119: * If a security manager exists and its checkPermission jtulach@119: * method doesn't allow access to this class loader's parent class jtulach@119: * loader. jtulach@119: * jtulach@119: * @since 1.2 jtulach@119: */ jtulach@119: public final ClassLoader getParent() { jaroslav@122: throw new SecurityException(); jtulach@119: } jtulach@119: jtulach@119: /** jtulach@119: * Returns the system class loader for delegation. This is the default jtulach@119: * delegation parent for new ClassLoader instances, and is jtulach@119: * typically the class loader used to start the application. jtulach@119: * jtulach@119: *

This method is first invoked early in the runtime's startup jtulach@119: * sequence, at which point it creates the system class loader and sets it jtulach@119: * as the context class loader of the invoking Thread. jtulach@119: * jtulach@119: *

The default system class loader is an implementation-dependent jtulach@119: * instance of this class. jtulach@119: * jtulach@119: *

If the system property "java.system.class.loader" is defined jtulach@119: * when this method is first invoked then the value of that property is jtulach@119: * taken to be the name of a class that will be returned as the system jtulach@119: * class loader. The class is loaded using the default system class loader jtulach@119: * and must define a public constructor that takes a single parameter of jtulach@119: * type ClassLoader which is used as the delegation parent. An jtulach@119: * instance is then created using this constructor with the default system jtulach@119: * class loader as the parameter. The resulting class loader is defined jtulach@119: * to be the system class loader. jtulach@119: * jtulach@119: *

If a security manager is present, and the invoker's class loader is jtulach@119: * not null and the invoker's class loader is not the same as or jtulach@119: * an ancestor of the system class loader, then this method invokes the jtulach@119: * security manager's {@link jtulach@119: * SecurityManager#checkPermission(java.security.Permission) jtulach@119: * checkPermission} method with a {@link jtulach@119: * RuntimePermission#RuntimePermission(String) jtulach@119: * RuntimePermission("getClassLoader")} permission to verify jtulach@119: * access to the system class loader. If not, a jtulach@119: * SecurityException will be thrown.

jtulach@119: * jtulach@119: * @return The system ClassLoader for delegation, or jtulach@119: * null if none jtulach@119: * jtulach@119: * @throws SecurityException jtulach@119: * If a security manager exists and its checkPermission jtulach@119: * method doesn't allow access to the system class loader. jtulach@119: * jtulach@119: * @throws IllegalStateException jtulach@119: * If invoked recursively during the construction of the class jtulach@119: * loader specified by the "java.system.class.loader" jtulach@119: * property. jtulach@119: * jtulach@119: * @throws Error jtulach@119: * If the system property "java.system.class.loader" jtulach@119: * is defined but the named class could not be loaded, the jtulach@119: * provider class does not define the required constructor, or an jtulach@119: * exception is thrown by that constructor when it is invoked. The jtulach@119: * underlying cause of the error can be retrieved via the jtulach@119: * {@link Throwable#getCause()} method. jtulach@119: * jtulach@119: * @revised 1.4 jtulach@119: */ jtulach@119: public static ClassLoader getSystemClassLoader() { jaroslav@1333: if (SYSTEM == null) { jaroslav@1333: SYSTEM = new ClassLoader() { jaroslav@1333: @Override jaroslav@1333: protected Enumeration findResources(String name) throws IOException { jaroslav@1388: return getBootstrapResources(name); jaroslav@1333: } jaroslav@1333: jaroslav@1333: @Override jaroslav@1333: protected URL findResource(String name) { jaroslav@1388: return getBootstrapResource(name); jaroslav@1333: } jaroslav@1333: jaroslav@1333: @Override jaroslav@1333: protected Class findClass(String name) throws ClassNotFoundException { jaroslav@1333: return Class.forName(name); jaroslav@1333: } jaroslav@1333: }; jaroslav@1333: } jaroslav@1333: return SYSTEM; jtulach@119: } jaroslav@1333: private static ClassLoader SYSTEM; jtulach@119: jtulach@119: // Returns true if the specified class loader can be found in this class jtulach@119: // loader's delegation chain. jtulach@119: boolean isAncestor(ClassLoader cl) { jtulach@119: ClassLoader acl = this; jtulach@119: do { jtulach@119: acl = acl.parent; jtulach@119: if (cl == acl) { jtulach@119: return true; jtulach@119: } jtulach@119: } while (acl != null); jtulach@119: return false; jtulach@119: } jtulach@119: jaroslav@122: private boolean checkName(String name) { jaroslav@122: throw new UnsupportedOperationException(); jtulach@119: } jtulach@119: jaroslav@122: private Class findBootstrapClassOrNull(String name) { jaroslav@122: throw new UnsupportedOperationException(); jtulach@119: } jtulach@119: jaroslav@122: private static URL getBootstrapResource(String name) { jaroslav@1333: return Object.class.getResource("/" + name); jaroslav@122: } jaroslav@122: jaroslav@1375: @JavaScriptBody(args = { "name", "skip" }, body jaroslav@1375: = "return (vm.loadBytes) ? vm.loadBytes(name, skip) : null;" jaroslav@1375: ) jaroslav@1375: static native byte[] getResourceAsStream0(String name, int skip); jaroslav@1375: jaroslav@122: private static Enumeration getBootstrapResources(String name) { jaroslav@1375: return new ResEnum(name); jaroslav@1375: } jaroslav@1375: jaroslav@1375: private static class ResEnum implements Enumeration { jaroslav@1375: private final String name; jaroslav@1375: private URL next; jaroslav@1375: private int skip; jaroslav@1375: jaroslav@1375: public ResEnum(String name) { jaroslav@1375: this.name = name; jaroslav@1375: } jaroslav@1375: jaroslav@1375: jaroslav@1375: public boolean hasMoreElements() { jaroslav@1375: if (next == null && skip >= 0) { jaroslav@1375: byte[] arr = getResourceAsStream0(name, skip++); jaroslav@1375: if (arr != null) { jaroslav@1375: next = Class.newResourceURL(name, new ByteArrayInputStream(arr)); jaroslav@1375: } else { jaroslav@1375: skip = -1; jaroslav@1375: } jaroslav@1375: } jaroslav@1375: return next != null; jaroslav@1375: } jaroslav@1375: jaroslav@1375: public URL nextElement() { jaroslav@1375: URL r = next; jaroslav@1375: if (r == null) { jaroslav@1375: throw new NoSuchElementException(); jaroslav@1375: } jaroslav@1375: next = null; jaroslav@1375: return r; jaroslav@1375: } jaroslav@576: } jaroslav@576: jaroslav@576: private static class OneOrZeroEnum implements Enumeration { jaroslav@576: private URL u; jaroslav@576: jaroslav@576: public OneOrZeroEnum(URL u) { jaroslav@576: this.u = u; jaroslav@576: } jaroslav@576: jaroslav@576: public boolean hasMoreElements() { jaroslav@576: return u != null; jaroslav@576: } jaroslav@576: jaroslav@576: public URL nextElement() { jaroslav@576: URL r = u; jaroslav@576: if (r == null) { jaroslav@576: throw new NoSuchElementException(); jaroslav@576: } jaroslav@576: u = null; jaroslav@576: return r; jaroslav@576: } jaroslav@122: } jaroslav@122: jaroslav@122: private static class CompoundEnumeration implements Enumeration { jaroslav@122: private URL next; jaroslav@122: private int index; jaroslav@122: private final Enumeration[] arr; jaroslav@122: jaroslav@122: public CompoundEnumeration(Enumeration[] arr) { jaroslav@122: this.arr = arr; jaroslav@122: this.index = 0; jtulach@119: } jaroslav@122: jaroslav@122: public boolean hasMoreElements() { jaroslav@1333: if (next == null && index < arr.length) { jaroslav@122: if (arr[index].hasMoreElements()) { jaroslav@122: next = (URL) arr[index].nextElement(); jaroslav@122: } else { jaroslav@122: if (index < arr.length) { jaroslav@122: index++; jaroslav@122: return hasMoreElements(); jtulach@119: } jtulach@119: } jtulach@119: } jaroslav@122: return next != null; jtulach@119: } jtulach@119: jaroslav@122: public URL nextElement() { jaroslav@122: if (!hasMoreElements()) { jaroslav@122: throw new NoSuchElementException(); jtulach@119: } jaroslav@122: URL r = next; jaroslav@122: next = null; jaroslav@122: return r; jtulach@119: } jaroslav@122: jtulach@119: } jtulach@119: }