0001: /*
0002: * Copyright 1994-2005 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025: package java.lang;
0026:
0027: import java.io.InputStream;
0028: import java.io.IOException;
0029: import java.io.File;
0030: import java.lang.reflect.Constructor;
0031: import java.lang.reflect.InvocationTargetException;
0032: import java.net.MalformedURLException;
0033: import java.net.URL;
0034: import java.security.AccessController;
0035: import java.security.AccessControlContext;
0036: import java.security.CodeSource;
0037: import java.security.Policy;
0038: import java.security.PrivilegedAction;
0039: import java.security.PrivilegedActionException;
0040: import java.security.PrivilegedExceptionAction;
0041: import java.security.ProtectionDomain;
0042: import java.util.Enumeration;
0043: import java.util.Hashtable;
0044: import java.util.HashMap;
0045: import java.util.HashSet;
0046: import java.util.Set;
0047: import java.util.Stack;
0048: import java.util.Map;
0049: import java.util.Vector;
0050: import sun.misc.ClassFileTransformer;
0051: import sun.misc.CompoundEnumeration;
0052: import sun.misc.Resource;
0053: import sun.misc.URLClassPath;
0054: import sun.misc.VM;
0055: import sun.reflect.Reflection;
0056: import sun.security.util.SecurityConstants;
0057:
0058: /**
0059: * A class loader is an object that is responsible for loading classes. The
0060: * class <tt>ClassLoader</tt> is an abstract class. Given the <a
0061: * href="#name">binary name</a> of a class, a class loader should attempt to
0062: * locate or generate data that constitutes a definition for the class. A
0063: * typical strategy is to transform the name into a file name and then read a
0064: * "class file" of that name from a file system.
0065: *
0066: * <p> Every {@link Class <tt>Class</tt>} object contains a {@link
0067: * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined
0068: * it.
0069: *
0070: * <p> <tt>Class</tt> objects for array classes are not created by class
0071: * loaders, but are created automatically as required by the Java runtime.
0072: * The class loader for an array class, as returned by {@link
0073: * Class#getClassLoader()} is the same as the class loader for its element
0074: * type; if the element type is a primitive type, then the array class has no
0075: * class loader.
0076: *
0077: * <p> Applications implement subclasses of <tt>ClassLoader</tt> in order to
0078: * extend the manner in which the Java virtual machine dynamically loads
0079: * classes.
0080: *
0081: * <p> Class loaders may typically be used by security managers to indicate
0082: * security domains.
0083: *
0084: * <p> The <tt>ClassLoader</tt> class uses a delegation model to search for
0085: * classes and resources. Each instance of <tt>ClassLoader</tt> has an
0086: * associated parent class loader. When requested to find a class or
0087: * resource, a <tt>ClassLoader</tt> instance will delegate the search for the
0088: * class or resource to its parent class loader before attempting to find the
0089: * class or resource itself. The virtual machine's built-in class loader,
0090: * called the "bootstrap class loader", does not itself have a parent but may
0091: * serve as the parent of a <tt>ClassLoader</tt> instance.
0092: *
0093: * <p> Normally, the Java virtual machine loads classes from the local file
0094: * system in a platform-dependent manner. For example, on UNIX systems, the
0095: * virtual machine loads classes from the directory defined by the
0096: * <tt>CLASSPATH</tt> environment variable.
0097: *
0098: * <p> However, some classes may not originate from a file; they may originate
0099: * from other sources, such as the network, or they could be constructed by an
0100: * application. The method {@link #defineClass(String, byte[], int, int)
0101: * <tt>defineClass</tt>} converts an array of bytes into an instance of class
0102: * <tt>Class</tt>. Instances of this newly defined class can be created using
0103: * {@link Class#newInstance <tt>Class.newInstance</tt>}.
0104: *
0105: * <p> The methods and constructors of objects created by a class loader may
0106: * reference other classes. To determine the class(es) referred to, the Java
0107: * virtual machine invokes the {@link #loadClass <tt>loadClass</tt>} method of
0108: * the class loader that originally created the class.
0109: *
0110: * <p> For example, an application could create a network class loader to
0111: * download class files from a server. Sample code might look like:
0112: *
0113: * <blockquote><pre>
0114: * ClassLoader loader = new NetworkClassLoader(host, port);
0115: * Object main = loader.loadClass("Main", true).newInstance();
0116: * . . .
0117: * </pre></blockquote>
0118: *
0119: * <p> The network class loader subclass must define the methods {@link
0120: * #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class
0121: * from the network. Once it has downloaded the bytes that make up the class,
0122: * it should use the method {@link #defineClass <tt>defineClass</tt>} to
0123: * create a class instance. A sample implementation is:
0124: *
0125: * <blockquote><pre>
0126: * class NetworkClassLoader extends ClassLoader {
0127: * String host;
0128: * int port;
0129: *
0130: * public Class findClass(String name) {
0131: * byte[] b = loadClassData(name);
0132: * return defineClass(name, b, 0, b.length);
0133: * }
0134: *
0135: * private byte[] loadClassData(String name) {
0136: * // load the class data from the connection
0137: * . . .
0138: * }
0139: * }
0140: * </pre></blockquote>
0141: *
0142: * <h4> <a name="name">Binary names</a> </h4>
0143: *
0144: * <p> Any class name provided as a {@link String} parameter to methods in
0145: * <tt>ClassLoader</tt> must be a binary name as defined by the <a
0146: * href="http://java.sun.com/docs/books/jls/">Java Language Specification</a>.
0147: *
0148: * <p> Examples of valid class names include:
0149: * <blockquote><pre>
0150: * "java.lang.String"
0151: * "javax.swing.JSpinner$DefaultEditor"
0152: * "java.security.KeyStore$Builder$FileBuilder$1"
0153: * "java.net.URLClassLoader$3$1"
0154: * </pre></blockquote>
0155: *
0156: * @version 1.195, 05/05/07
0157: * @see #resolveClass(Class)
0158: * @since 1.0
0159: */
0160: public abstract class ClassLoader {
0161:
0162: private static native void registerNatives();
0163:
0164: static {
0165: registerNatives();
0166: }
0167:
0168: // If initialization succeed this is set to true and security checks will
0169: // succeed. Otherwise the object is not initialized and the object is
0170: // useless.
0171: private boolean initialized = false;
0172:
0173: // The parent class loader for delegation
0174: private ClassLoader parent;
0175:
0176: // Hashtable that maps packages to certs
0177: private Hashtable package2certs = new Hashtable(11);
0178:
0179: // Shared among all packages with unsigned classes
0180: java.security.cert.Certificate[] nocerts;
0181:
0182: // The classes loaded by this class loader. The only purpose of this table
0183: // is to keep the classes from being GC'ed until the loader is GC'ed.
0184: private Vector classes = new Vector();
0185:
0186: // The initiating protection domains for all classes loaded by this loader
0187: private Set domains = new HashSet();
0188:
0189: // Invoked by the VM to record every loaded class with this loader.
0190: void addClass(Class c) {
0191: classes.addElement(c);
0192: }
0193:
0194: // The packages defined in this class loader. Each package name is mapped
0195: // to its corresponding Package object.
0196: private HashMap packages = new HashMap();
0197:
0198: /**
0199: * Creates a new class loader using the specified parent class loader for
0200: * delegation.
0201: *
0202: * <p> If there is a security manager, its {@link
0203: * SecurityManager#checkCreateClassLoader()
0204: * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in
0205: * a security exception. </p>
0206: *
0207: * @param parent
0208: * The parent class loader
0209: *
0210: * @throws SecurityException
0211: * If a security manager exists and its
0212: * <tt>checkCreateClassLoader</tt> method doesn't allow creation
0213: * of a new class loader.
0214: *
0215: * @since 1.2
0216: */
0217: protected ClassLoader(ClassLoader parent) {
0218: SecurityManager security = System.getSecurityManager();
0219: if (security != null) {
0220: security.checkCreateClassLoader();
0221: }
0222: this .parent = parent;
0223: initialized = true;
0224: }
0225:
0226: /**
0227: * Creates a new class loader using the <tt>ClassLoader</tt> returned by
0228: * the method {@link #getSystemClassLoader()
0229: * <tt>getSystemClassLoader()</tt>} as the parent class loader.
0230: *
0231: * <p> If there is a security manager, its {@link
0232: * SecurityManager#checkCreateClassLoader()
0233: * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in
0234: * a security exception. </p>
0235: *
0236: * @throws SecurityException
0237: * If a security manager exists and its
0238: * <tt>checkCreateClassLoader</tt> method doesn't allow creation
0239: * of a new class loader.
0240: */
0241: protected ClassLoader() {
0242: SecurityManager security = System.getSecurityManager();
0243: if (security != null) {
0244: security.checkCreateClassLoader();
0245: }
0246: this .parent = getSystemClassLoader();
0247: initialized = true;
0248: }
0249:
0250: // -- Class --
0251:
0252: /**
0253: * Loads the class with the specified <a href="#name">binary name</a>.
0254: * This method searches for classes in the same manner as the {@link
0255: * #loadClass(String, boolean)} method. It is invoked by the Java virtual
0256: * machine to resolve class references. Invoking this method is equivalent
0257: * to invoking {@link #loadClass(String, boolean) <tt>loadClass(name,
0258: * false)</tt>}. </p>
0259: *
0260: * @param name
0261: * The <a href="#name">binary name</a> of the class
0262: *
0263: * @return The resulting <tt>Class</tt> object
0264: *
0265: * @throws ClassNotFoundException
0266: * If the class was not found
0267: */
0268: public Class<?> loadClass(String name)
0269: throws ClassNotFoundException {
0270: return loadClass(name, false);
0271: }
0272:
0273: /**
0274: * Loads the class with the specified <a href="#name">binary name</a>. The
0275: * default implementation of this method searches for classes in the
0276: * following order:
0277: *
0278: * <p><ol>
0279: *
0280: * <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
0281: * has already been loaded. </p></li>
0282: *
0283: * <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
0284: * on the parent class loader. If the parent is <tt>null</tt> the class
0285: * loader built-in to the virtual machine is used, instead. </p></li>
0286: *
0287: * <li><p> Invoke the {@link #findClass(String)} method to find the
0288: * class. </p></li>
0289: *
0290: * </ol>
0291: *
0292: * <p> If the class was found using the above steps, and the
0293: * <tt>resolve</tt> flag is true, this method will then invoke the {@link
0294: * #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
0295: *
0296: * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
0297: * #findClass(String)}, rather than this method. </p>
0298: *
0299: * @param name
0300: * The <a href="#name">binary name</a> of the class
0301: *
0302: * @param resolve
0303: * If <tt>true</tt> then resolve the class
0304: *
0305: * @return The resulting <tt>Class</tt> object
0306: *
0307: * @throws ClassNotFoundException
0308: * If the class could not be found
0309: */
0310: protected synchronized Class<?> loadClass(String name,
0311: boolean resolve) throws ClassNotFoundException {
0312: // First, check if the class has already been loaded
0313: Class c = findLoadedClass(name);
0314: if (c == null) {
0315: try {
0316: if (parent != null) {
0317: c = parent.loadClass(name, false);
0318: } else {
0319: c = findBootstrapClass0(name);
0320: }
0321: } catch (ClassNotFoundException e) {
0322: // If still not found, then invoke findClass in order
0323: // to find the class.
0324: c = findClass(name);
0325: }
0326: }
0327: if (resolve) {
0328: resolveClass(c);
0329: }
0330: return c;
0331: }
0332:
0333: // This method is invoked by the virtual machine to load a class.
0334: private synchronized Class loadClassInternal(String name)
0335: throws ClassNotFoundException {
0336: return loadClass(name);
0337: }
0338:
0339: private void checkPackageAccess(Class cls, ProtectionDomain pd) {
0340: final SecurityManager sm = System.getSecurityManager();
0341: if (sm != null) {
0342: final String name = cls.getName();
0343: final int i = name.lastIndexOf('.');
0344: if (i != -1) {
0345: AccessController.doPrivileged(new PrivilegedAction() {
0346: public Object run() {
0347: sm.checkPackageAccess(name.substring(0, i));
0348: return null;
0349: }
0350: }, new AccessControlContext(
0351: new ProtectionDomain[] { pd }));
0352: }
0353: }
0354: domains.add(pd);
0355: }
0356:
0357: /**
0358: * Finds the class with the specified <a href="#name">binary name</a>.
0359: * This method should be overridden by class loader implementations that
0360: * follow the delegation model for loading classes, and will be invoked by
0361: * the {@link #loadClass <tt>loadClass</tt>} method after checking the
0362: * parent class loader for the requested class. The default implementation
0363: * throws a <tt>ClassNotFoundException</tt>. </p>
0364: *
0365: * @param name
0366: * The <a href="#name">binary name</a> of the class
0367: *
0368: * @return The resulting <tt>Class</tt> object
0369: *
0370: * @throws ClassNotFoundException
0371: * If the class could not be found
0372: *
0373: * @since 1.2
0374: */
0375: protected Class<?> findClass(String name)
0376: throws ClassNotFoundException {
0377: throw new ClassNotFoundException(name);
0378: }
0379:
0380: /**
0381: * Converts an array of bytes into an instance of class <tt>Class</tt>.
0382: * Before the <tt>Class</tt> can be used it must be resolved. This method
0383: * is deprecated in favor of the version that takes a <a
0384: * href="#name">binary name</a> as its first argument, and is more secure.
0385: *
0386: * @param b
0387: * The bytes that make up the class data. The bytes in positions
0388: * <tt>off</tt> through <tt>off+len-1</tt> should have the format
0389: * of a valid class file as defined by the <a
0390: * href="http://java.sun.com/docs/books/vmspec/">Java Virtual
0391: * Machine Specification</a>.
0392: *
0393: * @param off
0394: * The start offset in <tt>b</tt> of the class data
0395: *
0396: * @param len
0397: * The length of the class data
0398: *
0399: * @return The <tt>Class</tt> object that was created from the specified
0400: * class data
0401: *
0402: * @throws ClassFormatError
0403: * If the data did not contain a valid class
0404: *
0405: * @throws IndexOutOfBoundsException
0406: * If either <tt>off</tt> or <tt>len</tt> is negative, or if
0407: * <tt>off+len</tt> is greater than <tt>b.length</tt>.
0408: *
0409: * @see #loadClass(String, boolean)
0410: * @see #resolveClass(Class)
0411: *
0412: * @deprecated Replaced by {@link #defineClass(String, byte[], int, int)
0413: * defineClass(String, byte[], int, int)}
0414: */
0415: @Deprecated
0416: protected final Class<?> defineClass(byte[] b, int off, int len)
0417: throws ClassFormatError {
0418: return defineClass(null, b, off, len, null);
0419: }
0420:
0421: /**
0422: * Converts an array of bytes into an instance of class <tt>Class</tt>.
0423: * Before the <tt>Class</tt> can be used it must be resolved.
0424: *
0425: * <p> This method assigns a default {@link java.security.ProtectionDomain
0426: * <tt>ProtectionDomain</tt>} to the newly defined class. The
0427: * <tt>ProtectionDomain</tt> is effectively granted the same set of
0428: * permissions returned when {@link
0429: * java.security.Policy#getPermissions(java.security.CodeSource)
0430: * <tt>Policy.getPolicy().getPermissions(new CodeSource(null, null))</tt>}
0431: * is invoked. The default domain is created on the first invocation of
0432: * {@link #defineClass(String, byte[], int, int) <tt>defineClass</tt>},
0433: * and re-used on subsequent invocations.
0434: *
0435: * <p> To assign a specific <tt>ProtectionDomain</tt> to the class, use
0436: * the {@link #defineClass(String, byte[], int, int,
0437: * java.security.ProtectionDomain) <tt>defineClass</tt>} method that takes a
0438: * <tt>ProtectionDomain</tt> as one of its arguments. </p>
0439: *
0440: * @param name
0441: * The expected <a href="#name">binary name</a> of the class, or
0442: * <tt>null</tt> if not known
0443: *
0444: * @param b
0445: * The bytes that make up the class data. The bytes in positions
0446: * <tt>off</tt> through <tt>off+len-1</tt> should have the format
0447: * of a valid class file as defined by the <a
0448: * href="http://java.sun.com/docs/books/vmspec/">Java Virtual
0449: * Machine Specification</a>.
0450: *
0451: * @param off
0452: * The start offset in <tt>b</tt> of the class data
0453: *
0454: * @param len
0455: * The length of the class data
0456: *
0457: * @return The <tt>Class</tt> object that was created from the specified
0458: * class data.
0459: *
0460: * @throws ClassFormatError
0461: * If the data did not contain a valid class
0462: *
0463: * @throws IndexOutOfBoundsException
0464: * If either <tt>off</tt> or <tt>len</tt> is negative, or if
0465: * <tt>off+len</tt> is greater than <tt>b.length</tt>.
0466: *
0467: * @throws SecurityException
0468: * If an attempt is made to add this class to a package that
0469: * contains classes that were signed by a different set of
0470: * certificates than this class (which is unsigned), or if
0471: * <tt>name</tt> begins with "<tt>java.</tt>".
0472: *
0473: * @see #loadClass(String, boolean)
0474: * @see #resolveClass(Class)
0475: * @see java.security.CodeSource
0476: * @see java.security.SecureClassLoader
0477: *
0478: * @since 1.1
0479: */
0480: protected final Class<?> defineClass(String name, byte[] b,
0481: int off, int len) throws ClassFormatError {
0482: return defineClass(name, b, off, len, null);
0483: }
0484:
0485: /* Determine protection domain, and check that:
0486: - not define java.* class,
0487: - signer of this class matches signers for the rest of the classes in package.
0488: */
0489: private ProtectionDomain preDefineClass(String name,
0490: ProtectionDomain protectionDomain) {
0491: if (!checkName(name))
0492: throw new NoClassDefFoundError("IllegalName: " + name);
0493:
0494: if ((name != null) && name.startsWith("java.")) {
0495: throw new SecurityException("Prohibited package name: "
0496: + name.substring(0, name.lastIndexOf('.')));
0497: }
0498: if (protectionDomain == null) {
0499: protectionDomain = getDefaultDomain();
0500: }
0501:
0502: if (name != null)
0503: checkCerts(name, protectionDomain.getCodeSource());
0504:
0505: return protectionDomain;
0506: }
0507:
0508: private String defineClassSourceLocation(
0509: ProtectionDomain protectionDomain) {
0510: CodeSource cs = protectionDomain.getCodeSource();
0511: String source = null;
0512: if (cs != null && cs.getLocation() != null) {
0513: source = cs.getLocation().toString();
0514: }
0515: return source;
0516: }
0517:
0518: private Class defineTransformedClass(String name, byte[] b,
0519: int off, int len, ProtectionDomain protectionDomain,
0520: ClassFormatError cfe, String source)
0521: throws ClassFormatError {
0522: // Class format error - try to transform the bytecode and
0523: // define the class again
0524: //
0525: Object[] transformers = ClassFileTransformer.getTransformers();
0526: Class c = null;
0527:
0528: for (int i = 0; transformers != null && i < transformers.length; i++) {
0529: try {
0530: // Transform byte code using transformer
0531: byte[] tb = ((ClassFileTransformer) transformers[i])
0532: .transform(b, off, len);
0533: c = defineClass1(name, tb, 0, tb.length,
0534: protectionDomain, source);
0535: break;
0536: } catch (ClassFormatError cfe2) {
0537: // If ClassFormatError occurs, try next transformer
0538: }
0539: }
0540:
0541: // Rethrow original ClassFormatError if unable to transform
0542: // bytecode to well-formed
0543: //
0544: if (c == null)
0545: throw cfe;
0546:
0547: return c;
0548: }
0549:
0550: private void postDefineClass(Class c,
0551: ProtectionDomain protectionDomain) {
0552: if (protectionDomain.getCodeSource() != null) {
0553: java.security.cert.Certificate certs[] = protectionDomain
0554: .getCodeSource().getCertificates();
0555: if (certs != null)
0556: setSigners(c, certs);
0557: }
0558: }
0559:
0560: /**
0561: * Converts an array of bytes into an instance of class <tt>Class</tt>,
0562: * with an optional <tt>ProtectionDomain</tt>. If the domain is
0563: * <tt>null</tt>, then a default domain will be assigned to the class as
0564: * specified in the documentation for {@link #defineClass(String, byte[],
0565: * int, int)}. Before the class can be used it must be resolved.
0566: *
0567: * <p> The first class defined in a package determines the exact set of
0568: * certificates that all subsequent classes defined in that package must
0569: * contain. The set of certificates for a class is obtained from the
0570: * {@link java.security.CodeSource <tt>CodeSource</tt>} within the
0571: * <tt>ProtectionDomain</tt> of the class. Any classes added to that
0572: * package must contain the same set of certificates or a
0573: * <tt>SecurityException</tt> will be thrown. Note that if
0574: * <tt>name</tt> is <tt>null</tt>, this check is not performed.
0575: * You should always pass in the <a href="#name">binary name</a> of the
0576: * class you are defining as well as the bytes. This ensures that the
0577: * class you are defining is indeed the class you think it is.
0578: *
0579: * <p> The specified <tt>name</tt> cannot begin with "<tt>java.</tt>", since
0580: * all classes in the "<tt>java.*</tt> packages can only be defined by the
0581: * bootstrap class loader. If <tt>name</tt> is not <tt>null</tt>, it
0582: * must be equal to the <a href="#name">binary name</a> of the class
0583: * specified by the byte array "<tt>b</tt>", otherwise a {@link
0584: * <tt>NoClassDefFoundError</tt>} will be thrown. </p>
0585: *
0586: * @param name
0587: * The expected <a href="#name">binary name</a> of the class, or
0588: * <tt>null</tt> if not known
0589: *
0590: * @param b
0591: * The bytes that make up the class data. The bytes in positions
0592: * <tt>off</tt> through <tt>off+len-1</tt> should have the format
0593: * of a valid class file as defined by the <a
0594: * href="http://java.sun.com/docs/books/vmspec/">Java Virtual
0595: * Machine Specification</a>.
0596: *
0597: * @param off
0598: * The start offset in <tt>b</tt> of the class data
0599: *
0600: * @param len
0601: * The length of the class data
0602: *
0603: * @param protectionDomain
0604: * The ProtectionDomain of the class
0605: *
0606: * @return The <tt>Class</tt> object created from the data,
0607: * and optional <tt>ProtectionDomain</tt>.
0608: *
0609: * @throws ClassFormatError
0610: * If the data did not contain a valid class
0611: *
0612: * @throws NoClassDefFoundError
0613: * If <tt>name</tt> is not equal to the <a href="#name">binary
0614: * name</a> of the class specified by <tt>b</tt>
0615: *
0616: * @throws IndexOutOfBoundsException
0617: * If either <tt>off</tt> or <tt>len</tt> is negative, or if
0618: * <tt>off+len</tt> is greater than <tt>b.length</tt>.
0619: *
0620: * @throws SecurityException
0621: * If an attempt is made to add this class to a package that
0622: * contains classes that were signed by a different set of
0623: * certificates than this class, or if <tt>name</tt> begins with
0624: * "<tt>java.</tt>".
0625: */
0626: protected final Class<?> defineClass(String name, byte[] b,
0627: int off, int len, ProtectionDomain protectionDomain)
0628: throws ClassFormatError {
0629: check();
0630: protectionDomain = preDefineClass(name, protectionDomain);
0631:
0632: Class c = null;
0633: String source = defineClassSourceLocation(protectionDomain);
0634:
0635: try {
0636: c = defineClass1(name, b, off, len, protectionDomain,
0637: source);
0638: } catch (ClassFormatError cfe) {
0639: c = defineTransformedClass(name, b, off, len,
0640: protectionDomain, cfe, source);
0641: }
0642:
0643: postDefineClass(c, protectionDomain);
0644: return c;
0645: }
0646:
0647: /**
0648: * Converts a {@link java.nio.ByteBuffer <tt>ByteBuffer</tt>}
0649: * into an instance of class <tt>Class</tt>,
0650: * with an optional <tt>ProtectionDomain</tt>. If the domain is
0651: * <tt>null</tt>, then a default domain will be assigned to the class as
0652: * specified in the documentation for {@link #defineClass(String, byte[],
0653: * int, int)}. Before the class can be used it must be resolved.
0654: *
0655: * <p>The rules about the first class defined in a package determining the set of
0656: * certificates for the package, and the restrictions on class names are identical
0657: * to those specified in the documentation for {@link #defineClass(String, byte[],
0658: * int, int, ProtectionDomain)}.
0659: *
0660: * <p> An invocation of this method of the form
0661: * <i>cl</i><tt>.defineClass(</tt><i>name</i><tt>,</tt>
0662: * <i>bBuffer</i><tt>,</tt> <i>pd</i><tt>)</tt> yields exactly the same
0663: * result as the statements
0664: *
0665: * <blockquote><tt>
0666: * ...<br>
0667: * byte[] temp = new byte[</tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#remaining
0668: * remaining}()];<br>
0669: * </tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#get(byte[])
0670: * get}(temp);<br>
0671: * return {@link #defineClass(String, byte[], int, int, ProtectionDomain)
0672: * </tt><i>cl</i><tt>.defineClass}(</tt><i>name</i><tt>, temp, 0, temp.length, </tt><i>pd</i><tt>);<br>
0673: * </tt></blockquote>
0674: *
0675: * @param name
0676: * The expected <a href="#name">binary name</a. of the class, or
0677: * <tt>null</tt> if not known
0678: *
0679: * @param b
0680: * The bytes that make up the class data. The bytes from positions
0681: * <tt>b.position()</tt> through <tt>b.position() + b.limit() -1 </tt>
0682: * should have the format of a valid class file as defined by the <a
0683: * href="http://java.sun.com/docs/books/vmspec/">Java Virtual
0684: * Machine Specification</a>.
0685: *
0686: * @param protectionDomain
0687: * The ProtectionDomain of the class, or <tt>null</tt>.
0688: *
0689: * @return The <tt>Class</tt> object created from the data,
0690: * and optional <tt>ProtectionDomain</tt>.
0691: *
0692: * @throws ClassFormatError
0693: * If the data did not contain a valid class.
0694: *
0695: * @throws NoClassDefFoundError
0696: * If <tt>name</tt> is not equal to the <a href="#name">binary
0697: * name</a> of the class specified by <tt>b</tt>
0698: *
0699: * @throws SecurityException
0700: * If an attempt is made to add this class to a package that
0701: * contains classes that were signed by a different set of
0702: * certificates than this class, or if <tt>name</tt> begins with
0703: * "<tt>java.</tt>".
0704: *
0705: * @see #defineClass(String, byte[], int, int, ProtectionDomain)
0706: *
0707: * @since 1.5
0708: */
0709: protected final Class<?> defineClass(String name,
0710: java.nio.ByteBuffer b, ProtectionDomain protectionDomain)
0711: throws ClassFormatError {
0712: check();
0713:
0714: int len = b.remaining();
0715:
0716: // Use byte[] if not a direct ByteBufer:
0717: if (!b.isDirect()) {
0718: if (b.hasArray()) {
0719: return defineClass(name, b.array(), b.position()
0720: + b.arrayOffset(), len, protectionDomain);
0721: } else {
0722: // no array, or read-only array
0723: byte[] tb = new byte[len];
0724: b.get(tb); // get bytes out of byte buffer.
0725: return defineClass(name, tb, 0, len, protectionDomain);
0726: }
0727: }
0728:
0729: protectionDomain = preDefineClass(name, protectionDomain);
0730:
0731: Class c = null;
0732: String source = defineClassSourceLocation(protectionDomain);
0733:
0734: try {
0735: c = defineClass2(name, b, b.position(), len,
0736: protectionDomain, source);
0737: } catch (ClassFormatError cfe) {
0738: byte[] tb = new byte[len];
0739: b.get(tb); // get bytes out of byte buffer.
0740: c = defineTransformedClass(name, tb, 0, len,
0741: protectionDomain, cfe, source);
0742: }
0743:
0744: postDefineClass(c, protectionDomain);
0745: return c;
0746: }
0747:
0748: private native Class defineClass0(String name, byte[] b, int off,
0749: int len, ProtectionDomain pd);
0750:
0751: private native Class defineClass1(String name, byte[] b, int off,
0752: int len, ProtectionDomain pd, String source);
0753:
0754: private native Class defineClass2(String name,
0755: java.nio.ByteBuffer b, int off, int len,
0756: ProtectionDomain pd, String source);
0757:
0758: // true if the name is null or has the potential to be a valid binary name
0759: private boolean checkName(String name) {
0760: if ((name == null) || (name.length() == 0))
0761: return true;
0762: if ((name.indexOf('/') != -1)
0763: || (!VM.allowArraySyntax() && (name.charAt(0) == '[')))
0764: return false;
0765: return true;
0766: }
0767:
0768: private synchronized void checkCerts(String name, CodeSource cs) {
0769: int i = name.lastIndexOf('.');
0770: String pname = (i == -1) ? "" : name.substring(0, i);
0771: java.security.cert.Certificate[] pcerts = (java.security.cert.Certificate[]) package2certs
0772: .get(pname);
0773: if (pcerts == null) {
0774: // first class in this package gets to define which
0775: // certificates must be the same for all other classes
0776: // in this package
0777: if (cs != null) {
0778: pcerts = cs.getCertificates();
0779: }
0780: if (pcerts == null) {
0781: if (nocerts == null)
0782: nocerts = new java.security.cert.Certificate[0];
0783: pcerts = nocerts;
0784: }
0785: package2certs.put(pname, pcerts);
0786: } else {
0787: java.security.cert.Certificate[] certs = null;
0788: if (cs != null) {
0789: certs = cs.getCertificates();
0790: }
0791:
0792: if (!compareCerts(pcerts, certs)) {
0793: throw new SecurityException(
0794: "class \""
0795: + name
0796: + "\"'s signer information does not match signer information of other classes in the same package");
0797: }
0798: }
0799: }
0800:
0801: /**
0802: * check to make sure the certs for the new class (certs) are the same as
0803: * the certs for the first class inserted in the package (pcerts)
0804: */
0805: private boolean compareCerts(
0806: java.security.cert.Certificate[] pcerts,
0807: java.security.cert.Certificate[] certs) {
0808: // certs can be null, indicating no certs.
0809: if ((certs == null) || (certs.length == 0)) {
0810: return pcerts.length == 0;
0811: }
0812:
0813: // the length must be the same at this point
0814: if (certs.length != pcerts.length)
0815: return false;
0816:
0817: // go through and make sure all the certs in one array
0818: // are in the other and vice-versa.
0819: boolean match;
0820: for (int i = 0; i < certs.length; i++) {
0821: match = false;
0822: for (int j = 0; j < pcerts.length; j++) {
0823: if (certs[i].equals(pcerts[j])) {
0824: match = true;
0825: break;
0826: }
0827: }
0828: if (!match)
0829: return false;
0830: }
0831:
0832: // now do the same for pcerts
0833: for (int i = 0; i < pcerts.length; i++) {
0834: match = false;
0835: for (int j = 0; j < certs.length; j++) {
0836: if (pcerts[i].equals(certs[j])) {
0837: match = true;
0838: break;
0839: }
0840: }
0841: if (!match)
0842: return false;
0843: }
0844:
0845: return true;
0846: }
0847:
0848: /**
0849: * Links the specified class. This (misleadingly named) method may be
0850: * used by a class loader to link a class. If the class <tt>c</tt> has
0851: * already been linked, then this method simply returns. Otherwise, the
0852: * class is linked as described in the "Execution" chapter of the <a
0853: * href="http://java.sun.com/docs/books/jls/">Java Language
0854: * Specification</a>.
0855: * </p>
0856: *
0857: * @param c
0858: * The class to link
0859: *
0860: * @throws NullPointerException
0861: * If <tt>c</tt> is <tt>null</tt>.
0862: *
0863: * @see #defineClass(String, byte[], int, int)
0864: */
0865: protected final void resolveClass(Class<?> c) {
0866: check();
0867: resolveClass0(c);
0868: }
0869:
0870: private native void resolveClass0(Class c);
0871:
0872: /**
0873: * Finds a class with the specified <a href="#name">binary name</a>,
0874: * loading it if necessary.
0875: *
0876: * <p> This method loads the class through the system class loader (see
0877: * {@link #getSystemClassLoader()}). The <tt>Class</tt> object returned
0878: * might have more than one <tt>ClassLoader</tt> associated with it.
0879: * Subclasses of <tt>ClassLoader</tt> need not usually invoke this method,
0880: * because most class loaders need to override just {@link
0881: * #findClass(String)}. </p>
0882: *
0883: * @param name
0884: * The <a href="#name">binary name</a> of the class
0885: *
0886: * @return The <tt>Class</tt> object for the specified <tt>name</tt>
0887: *
0888: * @throws ClassNotFoundException
0889: * If the class could not be found
0890: *
0891: * @see #ClassLoader(ClassLoader)
0892: * @see #getParent()
0893: */
0894: protected final Class<?> findSystemClass(String name)
0895: throws ClassNotFoundException {
0896: check();
0897: ClassLoader system = getSystemClassLoader();
0898: if (system == null) {
0899: if (!checkName(name))
0900: throw new ClassNotFoundException(name);
0901: return findBootstrapClass(name);
0902: }
0903: return system.loadClass(name);
0904: }
0905:
0906: private Class findBootstrapClass0(String name)
0907: throws ClassNotFoundException {
0908: check();
0909: if (!checkName(name))
0910: throw new ClassNotFoundException(name);
0911: return findBootstrapClass(name);
0912: }
0913:
0914: private native Class findBootstrapClass(String name)
0915: throws ClassNotFoundException;
0916:
0917: // Check to make sure the class loader has been initialized.
0918: private void check() {
0919: if (!initialized) {
0920: throw new SecurityException(
0921: "ClassLoader object not initialized");
0922: }
0923: }
0924:
0925: /**
0926: * Returns the class with the given <a href="#name">binary name</a> if this
0927: * loader has been recorded by the Java virtual machine as an initiating
0928: * loader of a class with that <a href="#name">binary name</a>. Otherwise
0929: * <tt>null</tt> is returned. </p>
0930: *
0931: * @param name
0932: * The <a href="#name">binary name</a> of the class
0933: *
0934: * @return The <tt>Class</tt> object, or <tt>null</tt> if the class has
0935: * not been loaded
0936: *
0937: * @since 1.1
0938: */
0939: protected final Class<?> findLoadedClass(String name) {
0940: check();
0941: if (!checkName(name))
0942: return null;
0943: return findLoadedClass0(name);
0944: }
0945:
0946: private native final Class findLoadedClass0(String name);
0947:
0948: /**
0949: * Sets the signers of a class. This should be invoked after defining a
0950: * class. </p>
0951: *
0952: * @param c
0953: * The <tt>Class</tt> object
0954: *
0955: * @param signers
0956: * The signers for the class
0957: *
0958: * @since 1.1
0959: */
0960: protected final void setSigners(Class<?> c, Object[] signers) {
0961: check();
0962: c.setSigners(signers);
0963: }
0964:
0965: // -- Resource --
0966:
0967: /**
0968: * Finds the resource with the given name. A resource is some data
0969: * (images, audio, text, etc) that can be accessed by class code in a way
0970: * that is independent of the location of the code.
0971: *
0972: * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
0973: * identifies the resource.
0974: *
0975: * <p> This method will first search the parent class loader for the
0976: * resource; if the parent is <tt>null</tt> the path of the class loader
0977: * built-in to the virtual machine is searched. That failing, this method
0978: * will invoke {@link #findResource(String)} to find the resource. </p>
0979: *
0980: * @param name
0981: * The resource name
0982: *
0983: * @return A <tt>URL</tt> object for reading the resource, or
0984: * <tt>null</tt> if the resource could not be found or the invoker
0985: * doesn't have adequate privileges to get the resource.
0986: *
0987: * @since 1.1
0988: */
0989: public URL getResource(String name) {
0990: URL url;
0991: if (parent != null) {
0992: url = parent.getResource(name);
0993: } else {
0994: url = getBootstrapResource(name);
0995: }
0996: if (url == null) {
0997: url = findResource(name);
0998: }
0999: return url;
1000: }
1001:
1002: /**
1003: * Finds all the resources with the given name. A resource is some data
1004: * (images, audio, text, etc) that can be accessed by class code in a way
1005: * that is independent of the location of the code.
1006: *
1007: * <p>The name of a resource is a <tt>/</tt>-separated path name that
1008: * identifies the resource.
1009: *
1010: * <p> The search order is described in the documentation for {@link
1011: * #getResource(String)}. </p>
1012: *
1013: * @param name
1014: * The resource name
1015: *
1016: * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
1017: * the resource. If no resources could be found, the enumeration
1018: * will be empty. Resources that the class loader doesn't have
1019: * access to will not be in the enumeration.
1020: *
1021: * @throws IOException
1022: * If I/O errors occur
1023: *
1024: * @see #findResources(String)
1025: *
1026: * @since 1.2
1027: */
1028: public Enumeration<URL> getResources(String name)
1029: throws IOException {
1030: Enumeration[] tmp = new Enumeration[2];
1031: if (parent != null) {
1032: tmp[0] = parent.getResources(name);
1033: } else {
1034: tmp[0] = getBootstrapResources(name);
1035: }
1036: tmp[1] = findResources(name);
1037:
1038: return new CompoundEnumeration(tmp);
1039: }
1040:
1041: /**
1042: * Finds the resource with the given name. Class loader implementations
1043: * should override this method to specify where to find resources. </p>
1044: *
1045: * @param name
1046: * The resource name
1047: *
1048: * @return A <tt>URL</tt> object for reading the resource, or
1049: * <tt>null</tt> if the resource could not be found
1050: *
1051: * @since 1.2
1052: */
1053: protected URL findResource(String name) {
1054: return null;
1055: }
1056:
1057: /**
1058: * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects
1059: * representing all the resources with the given name. Class loader
1060: * implementations should override this method to specify where to load
1061: * resources from. </p>
1062: *
1063: * @param name
1064: * The resource name
1065: *
1066: * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
1067: * the resources
1068: *
1069: * @throws IOException
1070: * If I/O errors occur
1071: *
1072: * @since 1.2
1073: */
1074: protected Enumeration<URL> findResources(String name)
1075: throws IOException {
1076: return new CompoundEnumeration(new Enumeration[0]);
1077: }
1078:
1079: /**
1080: * Find a resource of the specified name from the search path used to load
1081: * classes. This method locates the resource through the system class
1082: * loader (see {@link #getSystemClassLoader()}). </p>
1083: *
1084: * @param name
1085: * The resource name
1086: *
1087: * @return A {@link java.net.URL <tt>URL</tt>} object for reading the
1088: * resource, or <tt>null</tt> if the resource could not be found
1089: *
1090: * @since 1.1
1091: */
1092: public static URL getSystemResource(String name) {
1093: ClassLoader system = getSystemClassLoader();
1094: if (system == null) {
1095: return getBootstrapResource(name);
1096: }
1097: return system.getResource(name);
1098: }
1099:
1100: /**
1101: * Finds all resources of the specified name from the search path used to
1102: * load classes. The resources thus found are returned as an
1103: * {@link java.util.Enumeration <tt>Enumeration</tt>} of {@link
1104: * java.net.URL <tt>URL</tt>} objects.
1105: *
1106: * <p> The search order is described in the documentation for {@link
1107: * #getSystemResource(String)}. </p>
1108: *
1109: * @param name
1110: * The resource name
1111: *
1112: * @return An enumeration of resource {@link java.net.URL <tt>URL</tt>}
1113: * objects
1114: *
1115: * @throws IOException
1116: * If I/O errors occur
1117:
1118: * @since 1.2
1119: */
1120: public static Enumeration<URL> getSystemResources(String name)
1121: throws IOException {
1122: ClassLoader system = getSystemClassLoader();
1123: if (system == null) {
1124: return getBootstrapResources(name);
1125: }
1126: return system.getResources(name);
1127: }
1128:
1129: /**
1130: * Find resources from the VM's built-in classloader.
1131: */
1132: private static URL getBootstrapResource(String name) {
1133: URLClassPath ucp = getBootstrapClassPath();
1134: Resource res = ucp.getResource(name);
1135: return res != null ? res.getURL() : null;
1136: }
1137:
1138: /**
1139: * Find resources from the VM's built-in classloader.
1140: */
1141: private static Enumeration getBootstrapResources(String name)
1142: throws IOException {
1143: final Enumeration e = getBootstrapClassPath()
1144: .getResources(name);
1145: return new Enumeration() {
1146: public Object nextElement() {
1147: return ((Resource) e.nextElement()).getURL();
1148: }
1149:
1150: public boolean hasMoreElements() {
1151: return e.hasMoreElements();
1152: }
1153: };
1154: }
1155:
1156: // Returns the URLClassPath that is used for finding system resources.
1157: static URLClassPath getBootstrapClassPath() {
1158: if (bootstrapClassPath == null) {
1159: bootstrapClassPath = sun.misc.Launcher
1160: .getBootstrapClassPath();
1161: }
1162: return bootstrapClassPath;
1163: }
1164:
1165: private static URLClassPath bootstrapClassPath;
1166:
1167: /**
1168: * Returns an input stream for reading the specified resource.
1169: *
1170: * <p> The search order is described in the documentation for {@link
1171: * #getResource(String)}. </p>
1172: *
1173: * @param name
1174: * The resource name
1175: *
1176: * @return An input stream for reading the resource, or <tt>null</tt>
1177: * if the resource could not be found
1178: *
1179: * @since 1.1
1180: */
1181: public InputStream getResourceAsStream(String name) {
1182: URL url = getResource(name);
1183: try {
1184: return url != null ? url.openStream() : null;
1185: } catch (IOException e) {
1186: return null;
1187: }
1188: }
1189:
1190: /**
1191: * Open for reading, a resource of the specified name from the search path
1192: * used to load classes. This method locates the resource through the
1193: * system class loader (see {@link #getSystemClassLoader()}). </p>
1194: *
1195: * @param name
1196: * The resource name
1197: *
1198: * @return An input stream for reading the resource, or <tt>null</tt>
1199: * if the resource could not be found
1200: *
1201: * @since 1.1
1202: */
1203: public static InputStream getSystemResourceAsStream(String name) {
1204: URL url = getSystemResource(name);
1205: try {
1206: return url != null ? url.openStream() : null;
1207: } catch (IOException e) {
1208: return null;
1209: }
1210: }
1211:
1212: // -- Hierarchy --
1213:
1214: /**
1215: * Returns the parent class loader for delegation. Some implementations may
1216: * use <tt>null</tt> to represent the bootstrap class loader. This method
1217: * will return <tt>null</tt> in such implementations if this class loader's
1218: * parent is the bootstrap class loader.
1219: *
1220: * <p> If a security manager is present, and the invoker's class loader is
1221: * not <tt>null</tt> and is not an ancestor of this class loader, then this
1222: * method invokes the security manager's {@link
1223: * SecurityManager#checkPermission(java.security.Permission)
1224: * <tt>checkPermission</tt>} method with a {@link
1225: * RuntimePermission#RuntimePermission(String)
1226: * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
1227: * access to the parent class loader is permitted. If not, a
1228: * <tt>SecurityException</tt> will be thrown. </p>
1229: *
1230: * @return The parent <tt>ClassLoader</tt>
1231: *
1232: * @throws SecurityException
1233: * If a security manager exists and its <tt>checkPermission</tt>
1234: * method doesn't allow access to this class loader's parent class
1235: * loader.
1236: *
1237: * @since 1.2
1238: */
1239: public final ClassLoader getParent() {
1240: if (parent == null)
1241: return null;
1242: SecurityManager sm = System.getSecurityManager();
1243: if (sm != null) {
1244: ClassLoader ccl = getCallerClassLoader();
1245: if (ccl != null && !isAncestor(ccl)) {
1246: sm
1247: .checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
1248: }
1249: }
1250: return parent;
1251: }
1252:
1253: /**
1254: * Returns the system class loader for delegation. This is the default
1255: * delegation parent for new <tt>ClassLoader</tt> instances, and is
1256: * typically the class loader used to start the application.
1257: *
1258: * <p> This method is first invoked early in the runtime's startup
1259: * sequence, at which point it creates the system class loader and sets it
1260: * as the context class loader of the invoking <tt>Thread</tt>.
1261: *
1262: * <p> The default system class loader is an implementation-dependent
1263: * instance of this class.
1264: *
1265: * <p> If the system property "<tt>java.system.class.loader</tt>" is defined
1266: * when this method is first invoked then the value of that property is
1267: * taken to be the name of a class that will be returned as the system
1268: * class loader. The class is loaded using the default system class loader
1269: * and must define a public constructor that takes a single parameter of
1270: * type <tt>ClassLoader</tt> which is used as the delegation parent. An
1271: * instance is then created using this constructor with the default system
1272: * class loader as the parameter. The resulting class loader is defined
1273: * to be the system class loader.
1274: *
1275: * <p> If a security manager is present, and the invoker's class loader is
1276: * not <tt>null</tt> and the invoker's class loader is not the same as or
1277: * an ancestor of the system class loader, then this method invokes the
1278: * security manager's {@link
1279: * SecurityManager#checkPermission(java.security.Permission)
1280: * <tt>checkPermission</tt>} method with a {@link
1281: * RuntimePermission#RuntimePermission(String)
1282: * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
1283: * access to the system class loader. If not, a
1284: * <tt>SecurityException</tt> will be thrown. </p>
1285: *
1286: * @return The system <tt>ClassLoader</tt> for delegation, or
1287: * <tt>null</tt> if none
1288: *
1289: * @throws SecurityException
1290: * If a security manager exists and its <tt>checkPermission</tt>
1291: * method doesn't allow access to the system class loader.
1292: *
1293: * @throws IllegalStateException
1294: * If invoked recursively during the construction of the class
1295: * loader specified by the "<tt>java.system.class.loader</tt>"
1296: * property.
1297: *
1298: * @throws Error
1299: * If the system property "<tt>java.system.class.loader</tt>"
1300: * is defined but the named class could not be loaded, the
1301: * provider class does not define the required constructor, or an
1302: * exception is thrown by that constructor when it is invoked. The
1303: * underlying cause of the error can be retrieved via the
1304: * {@link Throwable#getCause()} method.
1305: *
1306: * @revised 1.4
1307: */
1308: public static ClassLoader getSystemClassLoader() {
1309: initSystemClassLoader();
1310: if (scl == null) {
1311: return null;
1312: }
1313: SecurityManager sm = System.getSecurityManager();
1314: if (sm != null) {
1315: ClassLoader ccl = getCallerClassLoader();
1316: if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) {
1317: sm
1318: .checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
1319: }
1320: }
1321: return scl;
1322: }
1323:
1324: private static synchronized void initSystemClassLoader() {
1325: if (!sclSet) {
1326: if (scl != null)
1327: throw new IllegalStateException("recursive invocation");
1328: sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
1329: if (l != null) {
1330: Throwable oops = null;
1331: scl = l.getClassLoader();
1332: try {
1333: PrivilegedExceptionAction a;
1334: a = new SystemClassLoaderAction(scl);
1335: scl = (ClassLoader) AccessController
1336: .doPrivileged(a);
1337: } catch (PrivilegedActionException pae) {
1338: oops = pae.getCause();
1339: if (oops instanceof InvocationTargetException) {
1340: oops = oops.getCause();
1341: }
1342: }
1343: if (oops != null) {
1344: if (oops instanceof Error) {
1345: throw (Error) oops;
1346: } else {
1347: // wrap the exception
1348: throw new Error(oops);
1349: }
1350: }
1351: }
1352: sclSet = true;
1353: }
1354: }
1355:
1356: // Returns true if the specified class loader can be found in this class
1357: // loader's delegation chain.
1358: boolean isAncestor(ClassLoader cl) {
1359: ClassLoader acl = this ;
1360: do {
1361: acl = acl.parent;
1362: if (cl == acl) {
1363: return true;
1364: }
1365: } while (acl != null);
1366: return false;
1367: }
1368:
1369: // Returns the invoker's class loader, or null if none.
1370: // NOTE: This must always be invoked when there is exactly one intervening
1371: // frame from the core libraries on the stack between this method's
1372: // invocation and the desired invoker.
1373: static ClassLoader getCallerClassLoader() {
1374: // NOTE use of more generic Reflection.getCallerClass()
1375: Class caller = Reflection.getCallerClass(3);
1376: // This can be null if the VM is requesting it
1377: if (caller == null) {
1378: return null;
1379: }
1380: // Circumvent security check since this is package-private
1381: return caller.getClassLoader0();
1382: }
1383:
1384: // The class loader for the system
1385: private static ClassLoader scl;
1386:
1387: // Set to true once the system class loader has been set
1388: private static boolean sclSet;
1389:
1390: // -- Package --
1391:
1392: /**
1393: * Defines a package by name in this <tt>ClassLoader</tt>. This allows
1394: * class loaders to define the packages for their classes. Packages must
1395: * be created before the class is defined, and package names must be
1396: * unique within a class loader and cannot be redefined or changed once
1397: * created. </p>
1398: *
1399: * @param name
1400: * The package name
1401: *
1402: * @param specTitle
1403: * The specification title
1404: *
1405: * @param specVersion
1406: * The specification version
1407: *
1408: * @param specVendor
1409: * The specification vendor
1410: *
1411: * @param implTitle
1412: * The implementation title
1413: *
1414: * @param implVersion
1415: * The implementation version
1416: *
1417: * @param implVendor
1418: * The implementation vendor
1419: *
1420: * @param sealBase
1421: * If not <tt>null</tt>, then this package is sealed with
1422: * respect to the given code source {@link java.net.URL
1423: * <tt>URL</tt>} object. Otherwise, the package is not sealed.
1424: *
1425: * @return The newly defined <tt>Package</tt> object
1426: *
1427: * @throws IllegalArgumentException
1428: * If package name duplicates an existing package either in this
1429: * class loader or one of its ancestors
1430: *
1431: * @since 1.2
1432: */
1433: protected Package definePackage(String name, String specTitle,
1434: String specVersion, String specVendor, String implTitle,
1435: String implVersion, String implVendor, URL sealBase)
1436: throws IllegalArgumentException {
1437: synchronized (packages) {
1438: Package pkg = getPackage(name);
1439: if (pkg != null) {
1440: throw new IllegalArgumentException(name);
1441: }
1442: pkg = new Package(name, specTitle, specVersion, specVendor,
1443: implTitle, implVersion, implVendor, sealBase, this );
1444: packages.put(name, pkg);
1445: return pkg;
1446: }
1447: }
1448:
1449: /**
1450: * Returns a <tt>Package</tt> that has been defined by this class loader
1451: * or any of its ancestors. </p>
1452: *
1453: * @param name
1454: * The package name
1455: *
1456: * @return The <tt>Package</tt> corresponding to the given name, or
1457: * <tt>null</tt> if not found
1458: *
1459: * @since 1.2
1460: */
1461: protected Package getPackage(String name) {
1462: synchronized (packages) {
1463: Package pkg = (Package) packages.get(name);
1464: if (pkg == null) {
1465: if (parent != null) {
1466: pkg = parent.getPackage(name);
1467: } else {
1468: pkg = Package.getSystemPackage(name);
1469: }
1470: if (pkg != null) {
1471: packages.put(name, pkg);
1472: }
1473: }
1474: return pkg;
1475: }
1476: }
1477:
1478: /**
1479: * Returns all of the <tt>Packages</tt> defined by this class loader and
1480: * its ancestors. </p>
1481: *
1482: * @return The array of <tt>Package</tt> objects defined by this
1483: * <tt>ClassLoader</tt>
1484: *
1485: * @since 1.2
1486: */
1487: protected Package[] getPackages() {
1488: Map map;
1489: synchronized (packages) {
1490: map = (Map) packages.clone();
1491: }
1492: Package[] pkgs;
1493: if (parent != null) {
1494: pkgs = parent.getPackages();
1495: } else {
1496: pkgs = Package.getSystemPackages();
1497: }
1498: if (pkgs != null) {
1499: for (int i = 0; i < pkgs.length; i++) {
1500: String pkgName = pkgs[i].getName();
1501: if (map.get(pkgName) == null) {
1502: map.put(pkgName, pkgs[i]);
1503: }
1504: }
1505: }
1506: return (Package[]) map.values()
1507: .toArray(new Package[map.size()]);
1508: }
1509:
1510: // -- Native library access --
1511:
1512: /**
1513: * Returns the absolute path name of a native library. The VM invokes this
1514: * method to locate the native libraries that belong to classes loaded with
1515: * this class loader. If this method returns <tt>null</tt>, the VM
1516: * searches the library along the path specified as the
1517: * "<tt>java.library.path</tt>" property. </p>
1518: *
1519: * @param libname
1520: * The library name
1521: *
1522: * @return The absolute path of the native library
1523: *
1524: * @see System#loadLibrary(String)
1525: * @see System#mapLibraryName(String)
1526: *
1527: * @since 1.2
1528: */
1529: protected String findLibrary(String libname) {
1530: return null;
1531: }
1532:
1533: /**
1534: * The inner class NativeLibrary denotes a loaded native library instance.
1535: * Every classloader contains a vector of loaded native libraries in the
1536: * private field <tt>nativeLibraries</tt>. The native libraries loaded
1537: * into the system are entered into the <tt>systemNativeLibraries</tt>
1538: * vector.
1539: *
1540: * <p> Every native library requires a particular version of JNI. This is
1541: * denoted by the private <tt>jniVersion</tt> field. This field is set by
1542: * the VM when it loads the library, and used by the VM to pass the correct
1543: * version of JNI to the native methods. </p>
1544: *
1545: * @version 1.195 05/05/07
1546: * @see ClassLoader
1547: * @since 1.2
1548: */
1549: static class NativeLibrary {
1550: // opaque handle to native library, used in native code.
1551: long handle;
1552: // the version of JNI environment the native library requires.
1553: private int jniVersion;
1554: // the class from which the library is loaded, also indicates
1555: // the loader this native library belongs.
1556: private Class fromClass;
1557: // the canonicalized name of the native library.
1558: String name;
1559:
1560: native void load(String name);
1561:
1562: native long find(String name);
1563:
1564: native void unload();
1565:
1566: public NativeLibrary(Class fromClass, String name) {
1567: this .name = name;
1568: this .fromClass = fromClass;
1569: }
1570:
1571: protected void finalize() {
1572: synchronized (loadedLibraryNames) {
1573: if (fromClass.getClassLoader() != null && handle != 0) {
1574: /* remove the native library name */
1575: int size = loadedLibraryNames.size();
1576: for (int i = 0; i < size; i++) {
1577: if (name
1578: .equals(loadedLibraryNames.elementAt(i))) {
1579: loadedLibraryNames.removeElementAt(i);
1580: break;
1581: }
1582: }
1583: /* unload the library. */
1584: ClassLoader.nativeLibraryContext.push(this );
1585: try {
1586: unload();
1587: } finally {
1588: ClassLoader.nativeLibraryContext.pop();
1589: }
1590: }
1591: }
1592: }
1593:
1594: // Invoked in the VM to determine the context class in
1595: // JNI_Load/JNI_Unload
1596: static Class getFromClass() {
1597: return ((NativeLibrary) (ClassLoader.nativeLibraryContext
1598: .peek())).fromClass;
1599: }
1600: }
1601:
1602: // The "default" domain. Set as the default ProtectionDomain on newly
1603: // created classes.
1604: private ProtectionDomain defaultDomain = null;
1605:
1606: // Returns (and initializes) the default domain.
1607: private synchronized ProtectionDomain getDefaultDomain() {
1608: if (defaultDomain == null) {
1609: CodeSource cs = new CodeSource(null,
1610: (java.security.cert.Certificate[]) null);
1611: defaultDomain = new ProtectionDomain(cs, null, this , null);
1612: }
1613: return defaultDomain;
1614: }
1615:
1616: // All native library names we've loaded.
1617: private static Vector loadedLibraryNames = new Vector();
1618: // Native libraries belonging to system classes.
1619: private static Vector systemNativeLibraries = new Vector();
1620: // Native libraries associated with the class loader.
1621: private Vector nativeLibraries = new Vector();
1622:
1623: // native libraries being loaded/unloaded.
1624: private static Stack nativeLibraryContext = new Stack();
1625:
1626: // The paths searched for libraries
1627: static private String usr_paths[];
1628: static private String sys_paths[];
1629:
1630: private static String[] initializePath(String propname) {
1631: String ldpath = System.getProperty(propname, "");
1632: String ps = File.pathSeparator;
1633: int ldlen = ldpath.length();
1634: int i, j, n;
1635: // Count the separators in the path
1636: i = ldpath.indexOf(ps);
1637: n = 0;
1638: while (i >= 0) {
1639: n++;
1640: i = ldpath.indexOf(ps, i + 1);
1641: }
1642:
1643: // allocate the array of paths - n :'s = n + 1 path elements
1644: String[] paths = new String[n + 1];
1645:
1646: // Fill the array with paths from the ldpath
1647: n = i = 0;
1648: j = ldpath.indexOf(ps);
1649: while (j >= 0) {
1650: if (j - i > 0) {
1651: paths[n++] = ldpath.substring(i, j);
1652: } else if (j - i == 0) {
1653: paths[n++] = ".";
1654: }
1655: i = j + 1;
1656: j = ldpath.indexOf(ps, i);
1657: }
1658: paths[n] = ldpath.substring(i, ldlen);
1659: return paths;
1660: }
1661:
1662: // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
1663: static void loadLibrary(Class fromClass, String name,
1664: boolean isAbsolute) {
1665: ClassLoader loader = (fromClass == null) ? null : fromClass
1666: .getClassLoader();
1667: if (sys_paths == null) {
1668: usr_paths = initializePath("java.library.path");
1669: sys_paths = initializePath("sun.boot.library.path");
1670: }
1671: if (isAbsolute) {
1672: if (loadLibrary0(fromClass, new File(name))) {
1673: return;
1674: }
1675: throw new UnsatisfiedLinkError("Can't load library: "
1676: + name);
1677: }
1678: if (loader != null) {
1679: String libfilename = loader.findLibrary(name);
1680: if (libfilename != null) {
1681: File libfile = new File(libfilename);
1682: if (!libfile.isAbsolute()) {
1683: throw new UnsatisfiedLinkError(
1684: "ClassLoader.findLibrary failed to return an absolute path: "
1685: + libfilename);
1686: }
1687: if (loadLibrary0(fromClass, libfile)) {
1688: return;
1689: }
1690: throw new UnsatisfiedLinkError("Can't load "
1691: + libfilename);
1692: }
1693: }
1694: for (int i = 0; i < sys_paths.length; i++) {
1695: File libfile = new File(sys_paths[i], System
1696: .mapLibraryName(name));
1697: if (loadLibrary0(fromClass, libfile)) {
1698: return;
1699: }
1700: }
1701: if (loader != null) {
1702: for (int i = 0; i < usr_paths.length; i++) {
1703: File libfile = new File(usr_paths[i], System
1704: .mapLibraryName(name));
1705: if (loadLibrary0(fromClass, libfile)) {
1706: return;
1707: }
1708: }
1709: }
1710: // Oops, it failed
1711: throw new UnsatisfiedLinkError("no " + name
1712: + " in java.library.path");
1713: }
1714:
1715: private static boolean loadLibrary0(Class fromClass, final File file) {
1716: Boolean exists = (Boolean) AccessController
1717: .doPrivileged(new PrivilegedAction() {
1718: public Object run() {
1719: return new Boolean(file.exists());
1720: }
1721: });
1722: if (!exists.booleanValue()) {
1723: return false;
1724: }
1725: String name;
1726: try {
1727: name = file.getCanonicalPath();
1728: } catch (IOException e) {
1729: return false;
1730: }
1731: ClassLoader loader = (fromClass == null) ? null : fromClass
1732: .getClassLoader();
1733: Vector libs = loader != null ? loader.nativeLibraries
1734: : systemNativeLibraries;
1735: synchronized (libs) {
1736: int size = libs.size();
1737: for (int i = 0; i < size; i++) {
1738: NativeLibrary lib = (NativeLibrary) libs.elementAt(i);
1739: if (name.equals(lib.name)) {
1740: return true;
1741: }
1742: }
1743:
1744: synchronized (loadedLibraryNames) {
1745: if (loadedLibraryNames.contains(name)) {
1746: throw new UnsatisfiedLinkError("Native Library "
1747: + name
1748: + " already loaded in another classloader");
1749: }
1750: /* If the library is being loaded (must be by the same thread,
1751: * because Runtime.load and Runtime.loadLibrary are
1752: * synchronous). The reason is can occur is that the JNI_OnLoad
1753: * function can cause another loadLibrary invocation.
1754: *
1755: * Thus we can use a static stack to hold the list of libraries
1756: * we are loading.
1757: *
1758: * If there is a pending load operation for the library, we
1759: * immediately return success; otherwise, we raise
1760: * UnsatisfiedLinkError.
1761: */
1762: int n = nativeLibraryContext.size();
1763: for (int i = 0; i < n; i++) {
1764: NativeLibrary lib = (NativeLibrary) nativeLibraryContext
1765: .elementAt(i);
1766: if (name.equals(lib.name)) {
1767: if (loader == lib.fromClass.getClassLoader()) {
1768: return true;
1769: } else {
1770: throw new UnsatisfiedLinkError(
1771: "Native Library "
1772: + name
1773: + " is being loaded in another classloader");
1774: }
1775: }
1776: }
1777: NativeLibrary lib = new NativeLibrary(fromClass, name);
1778: nativeLibraryContext.push(lib);
1779: try {
1780: lib.load(name);
1781: } finally {
1782: nativeLibraryContext.pop();
1783: }
1784: if (lib.handle != 0) {
1785: loadedLibraryNames.addElement(name);
1786: libs.addElement(lib);
1787: return true;
1788: }
1789: return false;
1790: }
1791: }
1792: }
1793:
1794: // Invoked in the VM class linking code.
1795: static long findNative(ClassLoader loader, String name) {
1796: Vector libs = loader != null ? loader.nativeLibraries
1797: : systemNativeLibraries;
1798: synchronized (libs) {
1799: int size = libs.size();
1800: for (int i = 0; i < size; i++) {
1801: NativeLibrary lib = (NativeLibrary) libs.elementAt(i);
1802: long entry = lib.find(name);
1803: if (entry != 0)
1804: return entry;
1805: }
1806: }
1807: return 0;
1808: }
1809:
1810: // -- Assertion management --
1811:
1812: // The default toggle for assertion checking.
1813: private boolean defaultAssertionStatus = false;
1814:
1815: // Maps String packageName to Boolean package default assertion status Note
1816: // that the default package is placed under a null map key. If this field
1817: // is null then we are delegating assertion status queries to the VM, i.e.,
1818: // none of this ClassLoader's assertion status modification methods have
1819: // been invoked.
1820: private Map packageAssertionStatus = null;
1821:
1822: // Maps String fullyQualifiedClassName to Boolean assertionStatus If this
1823: // field is null then we are delegating assertion status queries to the VM,
1824: // i.e., none of this ClassLoader's assertion status modification methods
1825: // have been invoked.
1826: Map classAssertionStatus = null;
1827:
1828: /**
1829: * Sets the default assertion status for this class loader. This setting
1830: * determines whether classes loaded by this class loader and initialized
1831: * in the future will have assertions enabled or disabled by default.
1832: * This setting may be overridden on a per-package or per-class basis by
1833: * invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link
1834: * #setClassAssertionStatus(String, boolean)}. </p>
1835: *
1836: * @param enabled
1837: * <tt>true</tt> if classes loaded by this class loader will
1838: * henceforth have assertions enabled by default, <tt>false</tt>
1839: * if they will have assertions disabled by default.
1840: *
1841: * @since 1.4
1842: */
1843: public synchronized void setDefaultAssertionStatus(boolean enabled) {
1844: if (classAssertionStatus == null)
1845: initializeJavaAssertionMaps();
1846:
1847: defaultAssertionStatus = enabled;
1848: }
1849:
1850: /**
1851: * Sets the package default assertion status for the named package. The
1852: * package default assertion status determines the assertion status for
1853: * classes initialized in the future that belong to the named package or
1854: * any of its "subpackages".
1855: *
1856: * <p> A subpackage of a package named p is any package whose name begins
1857: * with "<tt>p.</tt>". For example, <tt>javax.swing.text</tt> is a
1858: * subpackage of <tt>javax.swing</tt>, and both <tt>java.util</tt> and
1859: * <tt>java.lang.reflect</tt> are subpackages of <tt>java</tt>.
1860: *
1861: * <p> In the event that multiple package defaults apply to a given class,
1862: * the package default pertaining to the most specific package takes
1863: * precedence over the others. For example, if <tt>javax.lang</tt> and
1864: * <tt>javax.lang.reflect</tt> both have package defaults associated with
1865: * them, the latter package default applies to classes in
1866: * <tt>javax.lang.reflect</tt>.
1867: *
1868: * <p> Package defaults take precedence over the class loader's default
1869: * assertion status, and may be overridden on a per-class basis by invoking
1870: * {@link #setClassAssertionStatus(String, boolean)}. </p>
1871: *
1872: * @param packageName
1873: * The name of the package whose package default assertion status
1874: * is to be set. A <tt>null</tt> value indicates the unnamed
1875: * package that is "current"
1876: * (<a href="http://java.sun.com/docs/books/jls/">Java Language
1877: * Specification</a>, section 7.4.2).
1878: *
1879: * @param enabled
1880: * <tt>true</tt> if classes loaded by this classloader and
1881: * belonging to the named package or any of its subpackages will
1882: * have assertions enabled by default, <tt>false</tt> if they will
1883: * have assertions disabled by default.
1884: *
1885: * @since 1.4
1886: */
1887: public synchronized void setPackageAssertionStatus(
1888: String packageName, boolean enabled) {
1889: if (packageAssertionStatus == null)
1890: initializeJavaAssertionMaps();
1891:
1892: packageAssertionStatus.put(packageName, Boolean
1893: .valueOf(enabled));
1894: }
1895:
1896: /**
1897: * Sets the desired assertion status for the named top-level class in this
1898: * class loader and any nested classes contained therein. This setting
1899: * takes precedence over the class loader's default assertion status, and
1900: * over any applicable per-package default. This method has no effect if
1901: * the named class has already been initialized. (Once a class is
1902: * initialized, its assertion status cannot change.)
1903: *
1904: * <p> If the named class is not a top-level class, this invocation will
1905: * have no effect on the actual assertion status of any class. </p>
1906: *
1907: * @param className
1908: * The fully qualified class name of the top-level class whose
1909: * assertion status is to be set.
1910: *
1911: * @param enabled
1912: * <tt>true</tt> if the named class is to have assertions
1913: * enabled when (and if) it is initialized, <tt>false</tt> if the
1914: * class is to have assertions disabled.
1915: *
1916: * @since 1.4
1917: */
1918: public synchronized void setClassAssertionStatus(String className,
1919: boolean enabled) {
1920: if (classAssertionStatus == null)
1921: initializeJavaAssertionMaps();
1922:
1923: classAssertionStatus.put(className, Boolean.valueOf(enabled));
1924: }
1925:
1926: /**
1927: * Sets the default assertion status for this class loader to
1928: * <tt>false</tt> and discards any package defaults or class assertion
1929: * status settings associated with the class loader. This method is
1930: * provided so that class loaders can be made to ignore any command line or
1931: * persistent assertion status settings and "start with a clean slate."
1932: * </p>
1933: *
1934: * @since 1.4
1935: */
1936: public synchronized void clearAssertionStatus() {
1937: /*
1938: * Whether or not "Java assertion maps" are initialized, set
1939: * them to empty maps, effectively ignoring any present settings.
1940: */
1941: classAssertionStatus = new HashMap();
1942: packageAssertionStatus = new HashMap();
1943:
1944: defaultAssertionStatus = false;
1945: }
1946:
1947: /**
1948: * Returns the assertion status that would be assigned to the specified
1949: * class if it were to be initialized at the time this method is invoked.
1950: * If the named class has had its assertion status set, the most recent
1951: * setting will be returned; otherwise, if any package default assertion
1952: * status pertains to this class, the most recent setting for the most
1953: * specific pertinent package default assertion status is returned;
1954: * otherwise, this class loader's default assertion status is returned.
1955: * </p>
1956: *
1957: * @param className
1958: * The fully qualified class name of the class whose desired
1959: * assertion status is being queried.
1960: *
1961: * @return The desired assertion status of the specified class.
1962: *
1963: * @see #setClassAssertionStatus(String, boolean)
1964: * @see #setPackageAssertionStatus(String, boolean)
1965: * @see #setDefaultAssertionStatus(boolean)
1966: *
1967: * @since 1.4
1968: */
1969: synchronized boolean desiredAssertionStatus(String className) {
1970: Boolean result;
1971:
1972: // assert classAssertionStatus != null;
1973: // assert packageAssertionStatus != null;
1974:
1975: // Check for a class entry
1976: result = (Boolean) classAssertionStatus.get(className);
1977: if (result != null)
1978: return result.booleanValue();
1979:
1980: // Check for most specific package entry
1981: int dotIndex = className.lastIndexOf(".");
1982: if (dotIndex < 0) { // default package
1983: result = (Boolean) packageAssertionStatus.get(null);
1984: if (result != null)
1985: return result.booleanValue();
1986: }
1987: while (dotIndex > 0) {
1988: className = className.substring(0, dotIndex);
1989: result = (Boolean) packageAssertionStatus.get(className);
1990: if (result != null)
1991: return result.booleanValue();
1992: dotIndex = className.lastIndexOf(".", dotIndex - 1);
1993: }
1994:
1995: // Return the classloader default
1996: return defaultAssertionStatus;
1997: }
1998:
1999: // Set up the assertions with information provided by the VM.
2000: private void initializeJavaAssertionMaps() {
2001: // assert Thread.holdsLock(this);
2002:
2003: classAssertionStatus = new HashMap();
2004: packageAssertionStatus = new HashMap();
2005: AssertionStatusDirectives directives = retrieveDirectives();
2006:
2007: for (int i = 0; i < directives.classes.length; i++)
2008: classAssertionStatus.put(directives.classes[i], Boolean
2009: .valueOf(directives.classEnabled[i]));
2010:
2011: for (int i = 0; i < directives.packages.length; i++)
2012: packageAssertionStatus.put(directives.packages[i], Boolean
2013: .valueOf(directives.packageEnabled[i]));
2014:
2015: defaultAssertionStatus = directives.deflt;
2016: }
2017:
2018: // Retrieves the assertion directives from the VM.
2019: private static native AssertionStatusDirectives retrieveDirectives();
2020: }
2021:
2022: class SystemClassLoaderAction implements PrivilegedExceptionAction {
2023: private ClassLoader parent;
2024:
2025: SystemClassLoaderAction(ClassLoader parent) {
2026: this .parent = parent;
2027: }
2028:
2029: public Object run() throws Exception {
2030: ClassLoader sys;
2031: Constructor ctor;
2032: Class c;
2033: Class cp[] = { ClassLoader.class };
2034: Object params[] = { parent };
2035:
2036: String cls = System.getProperty("java.system.class.loader");
2037: if (cls == null) {
2038: return parent;
2039: }
2040:
2041: c = Class.forName(cls, true, parent);
2042: ctor = c.getDeclaredConstructor(cp);
2043: sys = (ClassLoader) ctor.newInstance(params);
2044: Thread.currentThread().setContextClassLoader(sys);
2045: return sys;
2046: }
2047: }
|