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