KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > lang > ClassLoader


1 /*
2  * @(#)ClassLoader.java 1.186 04/08/02
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package java.lang;
8
9 import java.io.InputStream JavaDoc;
10 import java.io.IOException JavaDoc;
11 import java.io.File JavaDoc;
12 import java.lang.reflect.Constructor JavaDoc;
13 import java.lang.reflect.InvocationTargetException JavaDoc;
14 import java.net.MalformedURLException JavaDoc;
15 import java.net.URL JavaDoc;
16 import java.security.AccessController JavaDoc;
17 import java.security.AccessControlContext JavaDoc;
18 import java.security.CodeSource JavaDoc;
19 import java.security.Policy JavaDoc;
20 import java.security.PrivilegedAction JavaDoc;
21 import java.security.PrivilegedActionException JavaDoc;
22 import java.security.PrivilegedExceptionAction JavaDoc;
23 import java.security.ProtectionDomain JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import java.util.Hashtable JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.Stack JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Vector JavaDoc;
32 import sun.misc.ClassFileTransformer;
33 import sun.misc.CompoundEnumeration;
34 import sun.misc.Resource;
35 import sun.misc.URLClassPath;
36 import sun.misc.VM;
37 import sun.reflect.Reflection;
38 import sun.security.util.SecurityConstants;
39
40 /**
41  * A class loader is an object that is responsible for loading classes. The
42  * class <tt>ClassLoader</tt> is an abstract class. Given the <a
43  * HREF="#name">binary name</a> of a class, a class loader should attempt to
44  * locate or generate data that constitutes a definition for the class. A
45  * typical strategy is to transform the name into a file name and then read a
46  * "class file" of that name from a file system.
47  *
48  * <p> Every {@link Class <tt>Class</tt>} object contains a {@link
49  * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined
50  * it.
51  *
52  * <p> <tt>Class</tt> objects for array classes are not created by class
53  * loaders, but are created automatically as required by the Java runtime.
54  * The class loader for an array class, as returned by {@link
55  * Class#getClassLoader()} is the same as the class loader for its element
56  * type; if the element type is a primitive type, then the array class has no
57  * class loader.
58  *
59  * <p> Applications implement subclasses of <tt>ClassLoader</tt> in order to
60  * extend the manner in which the Java virtual machine dynamically loads
61  * classes.
62  *
63  * <p> Class loaders may typically be used by security managers to indicate
64  * security domains.
65  *
66  * <p> The <tt>ClassLoader</tt> class uses a delegation model to search for
67  * classes and resources. Each instance of <tt>ClassLoader</tt> has an
68  * associated parent class loader. When requested to find a class or
69  * resource, a <tt>ClassLoader</tt> instance will delegate the search for the
70  * class or resource to its parent class loader before attempting to find the
71  * class or resource itself. The virtual machine's built-in class loader,
72  * called the "bootstrap class loader", does not itself have a parent but may
73  * serve as the parent of a <tt>ClassLoader</tt> instance.
74  *
75  * <p> Normally, the Java virtual machine loads classes from the local file
76  * system in a platform-dependent manner. For example, on UNIX systems, the
77  * virtual machine loads classes from the directory defined by the
78  * <tt>CLASSPATH</tt> environment variable.
79  *
80  * <p> However, some classes may not originate from a file; they may originate
81  * from other sources, such as the network, or they could be constructed by an
82  * application. The method {@link #defineClass(String, byte[], int, int)
83  * <tt>defineClass</tt>} converts an array of bytes into an instance of class
84  * <tt>Class</tt>. Instances of this newly defined class can be created using
85  * {@link Class#newInstance <tt>Class.newInstance</tt>}.
86  *
87  * <p> The methods and constructors of objects created by a class loader may
88  * reference other classes. To determine the class(es) referred to, the Java
89  * virtual machine invokes the {@link #loadClass <tt>loadClass</tt>} method of
90  * the class loader that originally created the class.
91  *
92  * <p> For example, an application could create a network class loader to
93  * download class files from a server. Sample code might look like:
94  *
95  * <blockquote><pre>
96  * ClassLoader loader&nbsp;= new NetworkClassLoader(host,&nbsp;port);
97  * Object main&nbsp;= loader.loadClass("Main", true).newInstance();
98  * &nbsp;.&nbsp;.&nbsp;.
99  * </pre></blockquote>
100  *
101  * <p> The network class loader subclass must define the methods {@link
102  * #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class
103  * from the network. Once it has downloaded the bytes that make up the class,
104  * it should use the method {@link #defineClass <tt>defineClass</tt>} to
105  * create a class instance. A sample implementation is:
106  *
107  * <blockquote><pre>
108  * class NetworkClassLoader extends ClassLoader {
109  * String host;
110  * int port;
111  *
112  * public Class findClass(String name) {
113  * byte[] b = loadClassData(name);
114  * return defineClass(name, b, 0, b.length);
115  * }
116  *
117  * private byte[] loadClassData(String name) {
118  * // load the class data from the connection
119  * &nbsp;.&nbsp;.&nbsp;.
120  * }
121  * }
122  * </pre></blockquote>
123  *
124  * <h4> <a name="name">Binary names</a> </h4>
125  *
126  * <p> Any class name provided as a {@link String} parameter to methods in
127  * <tt>ClassLoader</tt> must be a binary name as defined by the <a
128  * HREF="http://java.sun.com/docs/books/jls/">Java Language Specification</a>.
129  *
130  * <p> Examples of valid class names include:
131  * <blockquote><pre>
132  * "java.lang.String"
133  * "javax.swing.JSpinner$DefaultEditor"
134  * "java.security.KeyStore$Builder$FileBuilder$1"
135  * "java.net.URLClassLoader$3$1"
136  * </pre></blockquote>
137  *
138  * @version 1.186, 08/02/04
139  * @see #resolveClass(Class)
140  * @since 1.0
141  */

142 public abstract class ClassLoader {
143
144     private static native void registerNatives();
145     static {
146         registerNatives();
147     }
148
149     // If initialization succeed this is set to true and security checks will
150
// succeed. Otherwise the object is not initialized and the object is
151
// useless.
152
private boolean initialized = false;
153
154     // The parent class loader for delegation
155
private ClassLoader JavaDoc parent;
156
157     // Hashtable that maps packages to certs
158
private Hashtable JavaDoc package2certs = new Hashtable JavaDoc(11);
159
160     // Shared among all packages with unsigned classes
161
java.security.cert.Certificate JavaDoc[] nocerts;
162
163     // The classes loaded by this class loader. The only purpose of this table
164
// is to keep the classes from being GC'ed until the loader is GC'ed.
165
private Vector JavaDoc classes = new Vector JavaDoc();
166
167     // The initiating protection domains for all classes loaded by this loader
168
private Set JavaDoc domains = new HashSet JavaDoc();
169
170     // Invoked by the VM to record every loaded class with this loader.
171
void addClass(Class JavaDoc c) {
172         classes.addElement(c);
173     }
174
175     // The packages defined in this class loader. Each package name is mapped
176
// to its corresponding Package object.
177
private HashMap JavaDoc packages = new HashMap JavaDoc();
178
179     /**
180      * Creates a new class loader using the specified parent class loader for
181      * delegation.
182      *
183      * <p> If there is a security manager, its {@link
184      * SecurityManager#checkCreateClassLoader()
185      * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in
186      * a security exception. </p>
187      *
188      * @param parent
189      * The parent class loader
190      *
191      * @throws SecurityException
192      * If a security manager exists and its
193      * <tt>checkCreateClassLoader</tt> method doesn't allow creation
194      * of a new class loader.
195      *
196      * @since 1.2
197      */

198     protected ClassLoader(ClassLoader JavaDoc parent) {
199     SecurityManager JavaDoc security = System.getSecurityManager();
200     if (security != null) {
201         security.checkCreateClassLoader();
202     }
203     this.parent = parent;
204     initialized = true;
205     }
206
207     /**
208      * Creates a new class loader using the <tt>ClassLoader</tt> returned by
209      * the method {@link #getSystemClassLoader()
210      * <tt>getSystemClassLoader()</tt>} as the parent class loader.
211      *
212      * <p> If there is a security manager, its {@link
213      * SecurityManager#checkCreateClassLoader()
214      * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in
215      * a security exception. </p>
216      *
217      * @throws SecurityException
218      * If a security manager exists and its
219      * <tt>checkCreateClassLoader</tt> method doesn't allow creation
220      * of a new class loader.
221      */

222     protected ClassLoader() {
223     SecurityManager JavaDoc security = System.getSecurityManager();
224     if (security != null) {
225         security.checkCreateClassLoader();
226     }
227     this.parent = getSystemClassLoader();
228     initialized = true;
229     }
230
231
232     // -- Class --
233

234     /**
235      * Loads the class with the specified <a HREF="#name">binary name</a>.
236      * This method searches for classes in the same manner as the {@link
237      * #loadClass(String, boolean)} method. It is invoked by the Java virtual
238      * machine to resolve class references. Invoking this method is equivalent
239      * to invoking {@link #loadClass(String, boolean) <tt>loadClass(name,
240      * false)</tt>}. </p>
241      *
242      * @param name
243      * The <a HREF="#name">binary name</a> of the class
244      *
245      * @return The resulting <tt>Class</tt> object
246      *
247      * @throws ClassNotFoundException
248      * If the class was not found
249      */

250     public Class JavaDoc<?> loadClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
251     return loadClass(name, false);
252     }
253
254     /**
255      * Loads the class with the specified <a HREF="#name">binary name</a>. The
256      * default implementation of this method searches for classes in the
257      * following order:
258      *
259      * <p><ol>
260      *
261      * <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
262      * has already been loaded. </p></li>
263      *
264      * <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
265      * on the parent class loader. If the parent is <tt>null</tt> the class
266      * loader built-in to the virtual machine is used, instead. </p></li>
267      *
268      * <li><p> Invoke the {@link #findClass(String)} method to find the
269      * class. </p></li>
270      *
271      * </ol>
272      *
273      * <p> If the class was found using the above steps, and the
274      * <tt>resolve</tt> flag is true, this method will then invoke the {@link
275      * #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
276      *
277      * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
278      * #findClass(String)}, rather than this method. </p>
279      *
280      * @param name
281      * The <a HREF="#name">binary name</a> of the class
282      *
283      * @param resolve
284      * If <tt>true</tt> then resolve the class
285      *
286      * @return The resulting <tt>Class</tt> object
287      *
288      * @throws ClassNotFoundException
289      * If the class could not be found
290      */

291     protected synchronized Class JavaDoc<?> loadClass(String JavaDoc name, boolean resolve)
292     throws ClassNotFoundException JavaDoc
293     {
294     // First, check if the class has already been loaded
295
Class JavaDoc c = findLoadedClass(name);
296     if (c == null) {
297         try {
298         if (parent != null) {
299             c = parent.loadClass(name, false);
300         } else {
301             c = findBootstrapClass0(name);
302         }
303         } catch (ClassNotFoundException JavaDoc e) {
304             // If still not found, then invoke findClass in order
305
// to find the class.
306
c = findClass(name);
307         }
308     }
309     if (resolve) {
310         resolveClass(c);
311     }
312     return c;
313     }
314
315     // This method is invoked by the virtual machine to load a class.
316
private synchronized Class JavaDoc loadClassInternal(String JavaDoc name)
317     throws ClassNotFoundException JavaDoc
318     {
319     return loadClass(name);
320     }
321
322     private void checkPackageAccess(Class JavaDoc cls, ProtectionDomain JavaDoc pd) {
323     final SecurityManager JavaDoc sm = System.getSecurityManager();
324     if (sm != null) {
325         final String JavaDoc name = cls.getName();
326             final int i = name.lastIndexOf('.');
327         if (i != -1) {
328                 AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
329                     public Object JavaDoc run() {
330                 sm.checkPackageAccess(name.substring(0, i));
331                 return null;
332                     }
333                 }, new AccessControlContext JavaDoc(new ProtectionDomain JavaDoc[] {pd}));
334         }
335     }
336     domains.add(pd);
337     }
338
339     /**
340      * Finds the class with the specified <a HREF="#name">binary name</a>.
341      * This method should be overridden by class loader implementations that
342      * follow the delegation model for loading classes, and will be invoked by
343      * the {@link #loadClass <tt>loadClass</tt>} method after checking the
344      * parent class loader for the requested class. The default implementation
345      * throws a <tt>ClassNotFoundException</tt>. </p>
346      *
347      * @param name
348      * The <a HREF="#name">binary name</a> of the class
349      *
350      * @return The resulting <tt>Class</tt> object
351      *
352      * @throws ClassNotFoundException
353      * If the class could not be found
354      *
355      * @since 1.2
356      */

357     protected Class JavaDoc<?> findClass(String JavaDoc name) throws ClassNotFoundException JavaDoc {
358     throw new ClassNotFoundException JavaDoc(name);
359     }
360
361     /**
362      * Converts an array of bytes into an instance of class <tt>Class</tt>.
363      * Before the <tt>Class</tt> can be used it must be resolved. This method
364      * is deprecated in favor of the version that takes a <a
365      * HREF="#name">binary name</a> as its first argument, and is more secure.
366      *
367      * @param b
368      * The bytes that make up the class data. The bytes in positions
369      * <tt>off</tt> through <tt>off+len-1</tt> should have the format
370      * of a valid class file as defined by the <a
371      * HREF="http://java.sun.com/docs/books/vmspec/">Java Virtual
372      * Machine Specification</a>.
373      *
374      * @param off
375      * The start offset in <tt>b</tt> of the class data
376      *
377      * @param len
378      * The length of the class data
379      *
380      * @return The <tt>Class</tt> object that was created from the specified
381      * class data
382      *
383      * @throws ClassFormatError
384      * If the data did not contain a valid class
385      *
386      * @throws IndexOutOfBoundsException
387      * If either <tt>off</tt> or <tt>len</tt> is negative, or if
388      * <tt>off+len</tt> is greater than <tt>b.length</tt>.
389      *
390      * @see #loadClass(String, boolean)
391      * @see #resolveClass(Class)
392      *
393      * @deprecated Replaced by {@link #defineClass(String, byte[], int, int)
394      * defineClass(String, byte[], int, int)}
395      */

396     @Deprecated JavaDoc
397     protected final Class JavaDoc<?> defineClass(byte[] b, int off, int len)
398     throws ClassFormatError JavaDoc
399     {
400     return defineClass(null, b, off, len, null);
401     }
402
403     /**
404      * Converts an array of bytes into an instance of class <tt>Class</tt>.
405      * Before the <tt>Class</tt> can be used it must be resolved.
406      *
407      * <p> This method assigns a default {@link java.security.ProtectionDomain
408      * <tt>ProtectionDomain</tt>} to the newly defined class. The
409      * <tt>ProtectionDomain</tt> is effectively granted the same set of
410      * permissions returned when {@link
411      * java.security.Policy#getPermissions(java.security.CodeSource)
412      * <tt>Policy.getPolicy().getPermissions(new CodeSource(null, null))</tt>}
413      * is invoked. The default domain is created on the first invocation of
414      * {@link #defineClass(String, byte[], int, int) <tt>defineClass</tt>},
415      * and re-used on subsequent invocations.
416      *
417      * <p> To assign a specific <tt>ProtectionDomain</tt> to the class, use
418      * the {@link #defineClass(String, byte[], int, int,
419      * java.security.ProtectionDomain) <tt>defineClass</tt>} method that takes a
420      * <tt>ProtectionDomain</tt> as one of its arguments. </p>
421      *
422      * @param name
423      * The expected <a HREF="#name">binary name</a> of the class, or
424      * <tt>null</tt> if not known
425      *
426      * @param b
427      * The bytes that make up the class data. The bytes in positions
428      * <tt>off</tt> through <tt>off+len-1</tt> should have the format
429      * of a valid class file as defined by the <a
430      * HREF="http://java.sun.com/docs/books/vmspec/">Java Virtual
431      * Machine Specification</a>.
432      *
433      * @param off
434      * The start offset in <tt>b</tt> of the class data
435      *
436      * @param len
437      * The length of the class data
438      *
439      * @return The <tt>Class</tt> object that was created from the specified
440      * class data.
441      *
442      * @throws ClassFormatError
443      * If the data did not contain a valid class
444      *
445      * @throws IndexOutOfBoundsException
446      * If either <tt>off</tt> or <tt>len</tt> is negative, or if
447      * <tt>off+len</tt> is greater than <tt>b.length</tt>.
448      *
449      * @throws SecurityException
450      * If an attempt is made to add this class to a package that
451      * contains classes that were signed by a different set of
452      * certificates than this class (which is unsigned), or if
453      * <tt>name</tt> begins with "<tt>java.</tt>".
454      *
455      * @see #loadClass(String, boolean)
456      * @see #resolveClass(Class)
457      * @see java.security.CodeSource
458      * @see java.security.SecureClassLoader
459      *
460      * @since 1.1
461      */

462     protected final Class JavaDoc<?> defineClass(String JavaDoc name, byte[] b, int off, int len)
463     throws ClassFormatError JavaDoc
464     {
465     return defineClass(name, b, off, len, null);
466     }
467
468     /* Determine protection domain, and check that:
469         - not define java.* class,
470     - signer of this class matches signers for the rest of the classes in package.
471     */

472     private ProtectionDomain JavaDoc preDefineClass(String JavaDoc name,
473                         ProtectionDomain JavaDoc protectionDomain)
474     {
475     if (!checkName(name))
476         throw new NoClassDefFoundError JavaDoc("IllegalName: " + name);
477
478     if ((name != null) && name.startsWith("java.")) {
479         throw new SecurityException JavaDoc("Prohibited package name: " +
480                     name.substring(0, name.lastIndexOf('.')));
481     }
482     if (protectionDomain == null) {
483         protectionDomain = getDefaultDomain();
484     }
485
486     if (name != null)
487         checkCerts(name, protectionDomain.getCodeSource());
488
489     return protectionDomain;
490     }
491
492     private String JavaDoc defineClassSourceLocation(ProtectionDomain JavaDoc protectionDomain)
493     {
494     CodeSource JavaDoc cs = protectionDomain.getCodeSource();
495     String JavaDoc source = null;
496     if (cs != null && cs.getLocation() != null) {
497         source = cs.getLocation().toString();
498     }
499     return source;
500     }
501
502     private Class JavaDoc defineTransformedClass(String JavaDoc name, byte[] b, int off, int len,
503                      ProtectionDomain JavaDoc protectionDomain,
504                      ClassFormatError JavaDoc cfe, String JavaDoc source)
505       throws ClassFormatError JavaDoc
506     {
507         // Class format error - try to transform the bytecode and
508
// define the class again
509
//
510
Object JavaDoc[] transformers = ClassFileTransformer.getTransformers();
511     Class JavaDoc c = null;
512
513     for (int i = 0; transformers != null && i < transformers.length; i++) {
514         try {
515           // Transform byte code using transformer
516
byte[] tb = ((ClassFileTransformer) transformers[i]).transform(b, off, len);
517           c = defineClass1(name, tb, 0, tb.length, protectionDomain, source);
518           break;
519         } catch (ClassFormatError JavaDoc cfe2) {
520           // If ClassFormatError occurs, try next transformer
521
}
522     }
523
524     // Rethrow original ClassFormatError if unable to transform
525
// bytecode to well-formed
526
//
527
if (c == null)
528         throw cfe;
529
530     return c;
531     }
532
533     private void postDefineClass(Class JavaDoc c, ProtectionDomain JavaDoc protectionDomain)
534     {
535     if (protectionDomain.getCodeSource() != null) {
536         java.security.cert.Certificate JavaDoc certs[] =
537         protectionDomain.getCodeSource().getCertificates();
538         if (certs != null)
539         setSigners(c, certs);
540     }
541     }
542
543     /**
544      * Converts an array of bytes into an instance of class <tt>Class</tt>,
545      * with an optional <tt>ProtectionDomain</tt>. If the domain is
546      * <tt>null</tt>, then a default domain will be assigned to the class as
547      * specified in the documentation for {@link #defineClass(String, byte[],
548      * int, int)}. Before the class can be used it must be resolved.
549      *
550      * <p> The first class defined in a package determines the exact set of
551      * certificates that all subsequent classes defined in that package must
552      * contain. The set of certificates for a class is obtained from the
553      * {@link java.security.CodeSource <tt>CodeSource</tt>} within the
554      * <tt>ProtectionDomain</tt> of the class. Any classes added to that
555      * package must contain the same set of certificates or a
556      * <tt>SecurityException</tt> will be thrown. Note that if
557      * <tt>name</tt> is <tt>null</tt>, this check is not performed.
558      * You should always pass in the <a HREF="#name">binary name</a> of the
559      * class you are defining as well as the bytes. This ensures that the
560      * class you are defining is indeed the class you think it is.
561      *
562      * <p> The specified <tt>name</tt> cannot begin with "<tt>java.</tt>", since
563      * all classes in the "<tt>java.*</tt> packages can only be defined by the
564      * bootstrap class loader. If <tt>name</tt> is not <tt>null</tt>, it
565      * must be equal to the <a HREF="#name">binary name</a> of the class
566      * specified by the byte array "<tt>b</tt>", otherwise a {@link
567      * <tt>NoClassDefFoundError</tt>} will be thrown. </p>
568      *
569      * @param name
570      * The expected <a HREF="#name">binary name</a> of the class, or
571      * <tt>null</tt> if not known
572      *
573      * @param b
574      * The bytes that make up the class data. The bytes in positions
575      * <tt>off</tt> through <tt>off+len-1</tt> should have the format
576      * of a valid class file as defined by the <a
577      * HREF="http://java.sun.com/docs/books/vmspec/">Java Virtual
578      * Machine Specification</a>.
579      *
580      * @param off
581      * The start offset in <tt>b</tt> of the class data
582      *
583      * @param len
584      * The length of the class data
585      *
586      * @param protectionDomain
587      * The ProtectionDomain of the class
588      *
589      * @return The <tt>Class</tt> object created from the data,
590      * and optional <tt>ProtectionDomain</tt>.
591      *
592      * @throws ClassFormatError
593      * If the data did not contain a valid class
594      *
595      * @throws NoClassDefFoundError
596      * If <tt>name</tt> is not equal to the <a HREF="#name">binary
597      * name</a> of the class specified by <tt>b</tt>
598      *
599      * @throws IndexOutOfBoundsException
600      * If either <tt>off</tt> or <tt>len</tt> is negative, or if
601      * <tt>off+len</tt> is greater than <tt>b.length</tt>.
602      *
603      * @throws SecurityException
604      * If an attempt is made to add this class to a package that
605      * contains classes that were signed by a different set of
606      * certificates than this class, or if <tt>name</tt> begins with
607      * "<tt>java.</tt>".
608      */

609     protected final Class JavaDoc<?> defineClass(String JavaDoc name, byte[] b, int off, int len,
610                      ProtectionDomain JavaDoc protectionDomain)
611     throws ClassFormatError JavaDoc
612     {
613     check();
614     protectionDomain = preDefineClass(name, protectionDomain);
615
616     Class JavaDoc c = null;
617         String JavaDoc source = defineClassSourceLocation(protectionDomain);
618
619     try {
620         c = defineClass1(name, b, off, len, protectionDomain, source);
621     } catch (ClassFormatError JavaDoc cfe) {
622         c = defineTransformedClass(name, b, off, len, protectionDomain, cfe, source);
623     }
624
625     postDefineClass(c, protectionDomain);
626     return c;
627     }
628
629     /**
630      * Converts a {@link java.nio.ByteBuffer <tt>ByteBuffer</tt>}
631      * into an instance of class <tt>Class</tt>,
632      * with an optional <tt>ProtectionDomain</tt>. If the domain is
633      * <tt>null</tt>, then a default domain will be assigned to the class as
634      * specified in the documentation for {@link #defineClass(String, byte[],
635      * int, int)}. Before the class can be used it must be resolved.
636      *
637      * <p>The rules about the first class defined in a package determining the set of
638      * certificates for the package, and the restrictions on class names are identical
639      * to those specified in the documentation for {@link #defineClass(String, byte[],
640      * int, int, ProtectionDomain)}.
641      *
642      * <p> An invocation of this method of the form
643      * <i>cl</i><tt>.defineClass(</tt><i>name</i><tt>,</tt>
644      * <i>bBuffer</i><tt>,</tt> <i>pd</i><tt>)</tt> yields exactly the same
645      * result as the statements
646      *
647      * <blockquote><tt>
648      * ...<br>
649      * byte[] temp = new byte[</tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#remaining
650      * remaining}()];<br>
651      * </tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#get(byte[])
652      * get}(temp);<br>
653      * return {@link #defineClass(String, byte[], int, int, ProtectionDomain)
654      * </tt><i>cl</i><tt>.defineClass}(</tt><i>name</i><tt>, temp, 0, temp.length, </tt><i>pd</i><tt>);<br>
655      * </tt></blockquote>
656      *
657      * @param name
658      * The expected <a HREF="#name">binary name</a. of the class, or
659      * <tt>null</tt> if not known
660      *
661      * @param b
662      * The bytes that make up the class data. The bytes from positions
663      * <tt>b.position()</tt> through <tt>b.position() + b.limit() -1 </tt>
664      * should have the format of a valid class file as defined by the <a
665      * HREF="http://java.sun.com/docs/books/vmspec/">Java Virtual
666      * Machine Specification</a>.
667      *
668      * @param protectionDomain
669      * The ProtectionDomain of the class, or <tt>null</tt>.
670      *
671      * @return The <tt>Class</tt> object created from the data,
672      * and optional <tt>ProtectionDomain</tt>.
673      *
674      * @throws ClassFormatError
675      * If the data did not contain a valid class.
676      *
677      * @throws NoClassDefFoundError
678      * If <tt>name</tt> is not equal to the <a HREF="#name">binary
679      * name</a> of the class specified by <tt>b</tt>
680      *
681      * @throws SecurityException
682      * If an attempt is made to add this class to a package that
683      * contains classes that were signed by a different set of
684      * certificates than this class, or if <tt>name</tt> begins with
685      * "<tt>java.</tt>".
686      *
687      * @see #defineClass(String, byte[], int, int, ProtectionDomain)
688      *
689      * @since 1.5
690      */

691     protected final Class JavaDoc<?> defineClass(String JavaDoc name, java.nio.ByteBuffer JavaDoc b,
692                      ProtectionDomain JavaDoc protectionDomain)
693     throws ClassFormatError JavaDoc
694     {
695     check();
696
697     int len = b.remaining();
698
699     // Use byte[] if not a direct ByteBufer:
700
if (!b.isDirect()) {
701         if (b.hasArray()) {
702         return defineClass(name, b.array(),
703                    b.position() + b.arrayOffset(), len,
704                    protectionDomain);
705         } else {
706         // no array, or read-only array
707
byte[] tb = new byte[len];
708         b.get(tb); // get bytes out of byte buffer.
709
return defineClass(name, tb, 0, len, protectionDomain);
710         }
711     }
712
713         protectionDomain = preDefineClass(name, protectionDomain);
714
715     Class JavaDoc c = null;
716     String JavaDoc source = defineClassSourceLocation(protectionDomain);
717
718     try {
719         c = defineClass2(name, b, b.position(), len, protectionDomain, source);
720     } catch (ClassFormatError JavaDoc cfe) {
721         byte[] tb = new byte[len];
722         b.get(tb); // get bytes out of byte buffer.
723
c = defineTransformedClass(name, tb, 0, len, protectionDomain, cfe, source);
724     }
725
726     postDefineClass(c, protectionDomain);
727     return c;
728     }
729
730     private native Class JavaDoc defineClass0(String JavaDoc name, byte[] b, int off, int len,
731                                   ProtectionDomain JavaDoc pd);
732
733     private native Class JavaDoc defineClass1(String JavaDoc name, byte[] b, int off, int len,
734                                   ProtectionDomain JavaDoc pd, String JavaDoc source);
735
736     private native Class JavaDoc defineClass2(String JavaDoc name, java.nio.ByteBuffer JavaDoc b,
737                       int off, int len, ProtectionDomain JavaDoc pd,
738                       String JavaDoc source);
739
740     // true if the name is null or has the potential to be a valid binary name
741
private boolean checkName(String JavaDoc name) {
742     if ((name == null) || (name.length() == 0))
743         return true;
744     if ((name.indexOf('/') != -1)
745         || (!VM.allowArraySyntax() && (name.charAt(0) == '[')))
746         return false;
747     return true;
748     }
749
750     private synchronized void checkCerts(String JavaDoc name, CodeSource JavaDoc cs) {
751     int i = name.lastIndexOf('.');
752     String JavaDoc pname = (i == -1) ? "" : name.substring(0, i);
753     java.security.cert.Certificate JavaDoc[] pcerts =
754         (java.security.cert.Certificate JavaDoc[]) package2certs.get(pname);
755         if (pcerts == null) {
756         // first class in this package gets to define which
757
// certificates must be the same for all other classes
758
// in this package
759
if (cs != null) {
760         pcerts = cs.getCertificates();
761         }
762         if (pcerts == null) {
763         if (nocerts == null)
764             nocerts = new java.security.cert.Certificate JavaDoc[0];
765         pcerts = nocerts;
766         }
767         package2certs.put(pname, pcerts);
768     } else {
769         java.security.cert.Certificate JavaDoc[] certs = null;
770         if (cs != null) {
771         certs = cs.getCertificates();
772         }
773
774         if (!compareCerts(pcerts, certs)) {
775         throw new SecurityException JavaDoc("class \""+ name +
776                         "\"'s signer information does not match signer information of other classes in the same package");
777         }
778     }
779     }
780
781     /**
782      * check to make sure the certs for the new class (certs) are the same as
783      * the certs for the first class inserted in the package (pcerts)
784      */

785     private boolean compareCerts(java.security.cert.Certificate JavaDoc[] pcerts,
786                  java.security.cert.Certificate JavaDoc[] certs)
787     {
788     // certs can be null, indicating no certs.
789
if ((certs == null) || (certs.length == 0)) {
790         return pcerts.length == 0;
791     }
792
793     // the length must be the same at this point
794
if (certs.length != pcerts.length)
795         return false;
796
797     // go through and make sure all the certs in one array
798
// are in the other and vice-versa.
799
boolean match;
800     for (int i = 0; i < certs.length; i++) {
801         match = false;
802         for (int j = 0; j < pcerts.length; j++) {
803         if (certs[i].equals(pcerts[j])) {
804             match = true;
805             break;
806         }
807         }
808         if (!match) return false;
809     }
810
811     // now do the same for pcerts
812
for (int i = 0; i < pcerts.length; i++) {
813         match = false;
814         for (int j = 0; j < certs.length; j++) {
815         if (pcerts[i].equals(certs[j])) {
816             match = true;
817             break;
818         }
819         }
820         if (!match) return false;
821     }
822
823     return true;
824     }
825
826     /**
827      * Links the specified class. This (misleadingly named) method may be
828      * used by a class loader to link a class. If the class <tt>c</tt> has
829      * already been linked, then this method simply returns. Otherwise, the
830      * class is linked as described in the "Execution" chapter of the <a
831      * HREF="http://java.sun.com/docs/books/jls/">Java Language
832      * Specification</a>.
833      * </p>
834      *
835      * @param c
836      * The class to link
837      *
838      * @throws NullPointerException
839      * If <tt>c</tt> is <tt>null</tt>.
840      *
841      * @see #defineClass(String, byte[], int, int)
842      */

843     protected final void resolveClass(Class JavaDoc<?> c) {
844     check();
845     resolveClass0(c);
846     }
847
848     private native void resolveClass0(Class JavaDoc c);
849
850     /**
851      * Finds a class with the specified <a HREF="#name">binary name</a>,
852      * loading it if necessary.
853      *
854      * <p> This method loads the class through the system class loader (see
855      * {@link #getSystemClassLoader()}). The <tt>Class</tt> object returned
856      * might have more than one <tt>ClassLoader</tt> associated with it.
857      * Subclasses of <tt>ClassLoader</tt> need not usually invoke this method,
858      * because most class loaders need to override just {@link
859      * #findClass(String)}. </p>
860      *
861      * @param name
862      * The <a HREF="#name">binary name</a> of the class
863      *
864      * @return The <tt>Class</tt> object for the specified <tt>name</tt>
865      *
866      * @throws ClassNotFoundException
867      * If the class could not be found
868      *
869      * @see #ClassLoader(ClassLoader)
870      * @see #getParent()
871      */

872     protected final Class JavaDoc<?> findSystemClass(String JavaDoc name)
873     throws ClassNotFoundException JavaDoc
874     {
875     check();
876     ClassLoader JavaDoc system = getSystemClassLoader();
877     if (system == null) {
878         if (!checkName(name))
879         throw new ClassNotFoundException JavaDoc(name);
880         return findBootstrapClass(name);
881     }
882     return system.loadClass(name);
883     }
884
885     private Class JavaDoc findBootstrapClass0(String JavaDoc name)
886     throws ClassNotFoundException JavaDoc
887     {
888     check();
889     if (!checkName(name))
890         throw new ClassNotFoundException JavaDoc(name);
891     return findBootstrapClass(name);
892     }
893
894     private native Class JavaDoc findBootstrapClass(String JavaDoc name)
895     throws ClassNotFoundException JavaDoc;
896
897     // Check to make sure the class loader has been initialized.
898
private void check() {
899     if (!initialized) {
900         throw new SecurityException JavaDoc("ClassLoader object not initialized");
901     }
902     }
903
904     /**
905      * Returns the class with the given <a HREF="#name">binary name</a> if this
906      * loader has been recorded by the Java virtual machine as an initiating
907      * loader of a class with that <a HREF="#name">binary name</a>. Otherwise
908      * <tt>null</tt> is returned. </p>
909      *
910      * @param name
911      * The <a HREF="#name">binary name</a> of the class
912      *
913      * @return The <tt>Class</tt> object, or <tt>null</tt> if the class has
914      * not been loaded
915      *
916      * @since 1.1
917      */

918     protected final Class JavaDoc<?> findLoadedClass(String JavaDoc name) {
919     check();
920     if (!checkName(name))
921         return null;
922     return findLoadedClass0(name);
923     }
924
925     private native final Class JavaDoc findLoadedClass0(String JavaDoc name);
926
927     /**
928      * Sets the signers of a class. This should be invoked after defining a
929      * class. </p>
930      *
931      * @param c
932      * The <tt>Class</tt> object
933      *
934      * @param signers
935      * The signers for the class
936      *
937      * @since 1.1
938      */

939     protected final void setSigners(Class JavaDoc<?> c, Object JavaDoc[] signers) {
940         check();
941     c.setSigners(signers);
942     }
943
944
945     // -- Resource --
946

947     /**
948      * Finds the resource with the given name. A resource is some data
949      * (images, audio, text, etc) that can be accessed by class code in a way
950      * that is independent of the location of the code.
951      *
952      * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
953      * identifies the resource.
954      *
955      * <p> This method will first search the parent class loader for the
956      * resource; if the parent is <tt>null</tt> the path of the class loader
957      * built-in to the virtual machine is searched. That failing, this method
958      * will invoke {@link #findResource(String)} to find the resource. </p>
959      *
960      * @param name
961      * The resource name
962      *
963      * @return A <tt>URL</tt> object for reading the resource, or
964      * <tt>null</tt> if the resource could not be found or the invoker
965      * doesn't have adequate privileges to get the resource.
966      *
967      * @since 1.1
968      */

969     public URL JavaDoc getResource(String JavaDoc name) {
970     URL JavaDoc url;
971     if (parent != null) {
972         url = parent.getResource(name);
973     } else {
974         url = getBootstrapResource(name);
975     }
976     if (url == null) {
977         url = findResource(name);
978     }
979     return url;
980     }
981
982     /**
983      * Finds all the resources with the given name. A resource is some data
984      * (images, audio, text, etc) that can be accessed by class code in a way
985      * that is independent of the location of the code.
986      *
987      * <p>The name of a resource is a <tt>/</tt>-separated path name that
988      * identifies the resource.
989      *
990      * <p> The search order is described in the documentation for {@link
991      * #getResource(String)}. </p>
992      *
993      * @param name
994      * The resource name
995      *
996      * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
997      * the resource. If no resources could be found, the enumeration
998      * will be empty. Resources that the class loader doesn't have
999      * access to will not be in the enumeration.
1000     *
1001     * @throws IOException
1002     * If I/O errors occur
1003     *
1004     * @see #findResources(String)
1005     *
1006     * @since 1.2
1007     */

1008    public Enumeration JavaDoc<URL JavaDoc> getResources(String JavaDoc name) throws IOException JavaDoc {
1009    Enumeration JavaDoc[] tmp = new Enumeration JavaDoc[2];
1010    if (parent != null) {
1011        tmp[0] = parent.getResources(name);
1012    } else {
1013        tmp[0] = getBootstrapResources(name);
1014    }
1015    tmp[1] = findResources(name);
1016
1017    return new CompoundEnumeration(tmp);
1018    }
1019
1020    /**
1021     * Finds the resource with the given name. Class loader implementations
1022     * should override this method to specify where to find resources. </p>
1023     *
1024     * @param name
1025     * The resource name
1026     *
1027     * @return A <tt>URL</tt> object for reading the resource, or
1028     * <tt>null</tt> if the resource could not be found
1029     *
1030     * @since 1.2
1031     */

1032    protected URL JavaDoc findResource(String JavaDoc name) {
1033    return null;
1034    }
1035
1036    /**
1037     * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects
1038     * representing all the resources with the given name. Class loader
1039     * implementations should override this method to specify where to load
1040     * resources from. </p>
1041     *
1042     * @param name
1043     * The resource name
1044     *
1045     * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
1046     * the resources
1047     *
1048     * @throws IOException
1049     * If I/O errors occur
1050     *
1051     * @since 1.2
1052     */

1053    protected Enumeration JavaDoc<URL JavaDoc> findResources(String JavaDoc name) throws IOException JavaDoc {
1054    return new CompoundEnumeration(new Enumeration JavaDoc[0]);
1055    }
1056
1057    /**
1058     * Find a resource of the specified name from the search path used to load
1059     * classes. This method locates the resource through the system class
1060     * loader (see {@link #getSystemClassLoader()}). </p>
1061     *
1062     * @param name
1063     * The resource name
1064     *
1065     * @return A {@link java.net.URL <tt>URL</tt>} object for reading the
1066     * resource, or <tt>null</tt> if the resource could not be found
1067     *
1068     * @since 1.1
1069     */

1070    public static URL JavaDoc getSystemResource(String JavaDoc name) {
1071    ClassLoader JavaDoc system = getSystemClassLoader();
1072    if (system == null) {
1073        return getBootstrapResource(name);
1074    }
1075    return system.getResource(name);
1076    }
1077
1078    /**
1079     * Finds all resources of the specified name from the search path used to
1080     * load classes. The resources thus found are returned as an
1081     * {@link java.util.Enumeration <tt>Enumeration</tt>} of {@link
1082     * java.net.URL <tt>URL</tt>} objects.
1083     *
1084     * <p> The search order is described in the documentation for {@link
1085     * #getSystemResource(String)}. </p>
1086     *
1087     * @param name
1088     * The resource name
1089     *
1090     * @return An enumeration of resource {@link java.net.URL <tt>URL</tt>}
1091     * objects
1092     *
1093     * @throws IOException
1094     * If I/O errors occur
1095
1096     * @since 1.2
1097     */

1098    public static Enumeration JavaDoc<URL JavaDoc> getSystemResources(String JavaDoc name)
1099    throws IOException JavaDoc
1100    {
1101    ClassLoader JavaDoc system = getSystemClassLoader();
1102    if (system == null) {
1103        return getBootstrapResources(name);
1104    }
1105    return system.getResources(name);
1106    }
1107
1108    /**
1109     * Find resources from the VM's built-in classloader.
1110     */

1111    private static URL JavaDoc getBootstrapResource(String JavaDoc name) {
1112    URLClassPath ucp = getBootstrapClassPath();
1113    Resource res = ucp.getResource(name);
1114    return res != null ? res.getURL() : null;
1115    }
1116
1117    /**
1118     * Find resources from the VM's built-in classloader.
1119     */

1120    private static Enumeration JavaDoc getBootstrapResources(String JavaDoc name)
1121    throws IOException JavaDoc
1122    {
1123    final Enumeration JavaDoc e = getBootstrapClassPath().getResources(name);
1124    return new Enumeration JavaDoc () {
1125        public Object JavaDoc nextElement() {
1126        return ((Resource)e.nextElement()).getURL();
1127        }
1128        public boolean hasMoreElements() {
1129        return e.hasMoreElements();
1130        }
1131    };
1132    }
1133
1134    // Returns the URLClassPath that is used for finding system resources.
1135
static URLClassPath getBootstrapClassPath() {
1136    if (bootstrapClassPath == null) {
1137        bootstrapClassPath = sun.misc.Launcher.getBootstrapClassPath();
1138    }
1139    return bootstrapClassPath;
1140    }
1141
1142    private static URLClassPath bootstrapClassPath;
1143
1144    /**
1145     * Returns an input stream for reading the specified resource.
1146     *
1147     * <p> The search order is described in the documentation for {@link
1148     * #getResource(String)}. </p>
1149     *
1150     * @param name
1151     * The resource name
1152     *
1153     * @return An input stream for reading the resource, or <tt>null</tt>
1154     * if the resource could not be found
1155     *
1156     * @since 1.1
1157     */

1158    public InputStream JavaDoc getResourceAsStream(String JavaDoc name) {
1159    URL JavaDoc url = getResource(name);
1160    try {
1161        return url != null ? url.openStream() : null;
1162    } catch (IOException JavaDoc e) {
1163        return null;
1164    }
1165    }
1166
1167    /**
1168     * Open for reading, a resource of the specified name from the search path
1169     * used to load classes. This method locates the resource through the
1170     * system class loader (see {@link #getSystemClassLoader()}). </p>
1171     *
1172     * @param name
1173     * The resource name
1174     *
1175     * @return An input stream for reading the resource, or <tt>null</tt>
1176     * if the resource could not be found
1177     *
1178     * @since 1.1
1179     */

1180    public static InputStream JavaDoc getSystemResourceAsStream(String JavaDoc name) {
1181        URL JavaDoc url = getSystemResource(name);
1182        try {
1183            return url != null ? url.openStream() : null;
1184        } catch (IOException JavaDoc e) {
1185            return null;
1186        }
1187    }
1188
1189
1190    // -- Hierarchy --
1191

1192    /**
1193     * Returns the parent class loader for delegation. Some implementations may
1194     * use <tt>null</tt> to represent the bootstrap class loader. This method
1195     * will return <tt>null</tt> in such implementations if this class loader's
1196     * parent is the bootstrap class loader.
1197     *
1198     * <p> If a security manager is present, and the invoker's class loader is
1199     * not <tt>null</tt> and is not an ancestor of this class loader, then this
1200     * method invokes the security manager's {@link
1201     * SecurityManager#checkPermission(java.security.Permission)
1202     * <tt>checkPermission</tt>} method with a {@link
1203     * RuntimePermission#RuntimePermission(String)
1204     * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
1205     * access to the parent class loader is permitted. If not, a
1206     * <tt>SecurityException</tt> will be thrown. </p>
1207     *
1208     * @return The parent <tt>ClassLoader</tt>
1209     *
1210     * @throws SecurityException
1211     * If a security manager exists and its <tt>checkPermission</tt>
1212     * method doesn't allow access to this class loader's parent class
1213     * loader.
1214     *
1215     * @since 1.2
1216     */

1217    public final ClassLoader JavaDoc getParent() {
1218    if (parent == null)
1219        return null;
1220    SecurityManager JavaDoc sm = System.getSecurityManager();
1221    if (sm != null) {
1222        ClassLoader JavaDoc ccl = getCallerClassLoader();
1223        if (ccl != null && !isAncestor(ccl)) {
1224        sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
1225        }
1226    }
1227    return parent;
1228    }
1229
1230    /**
1231     * Returns the system class loader for delegation. This is the default
1232     * delegation parent for new <tt>ClassLoader</tt> instances, and is
1233     * typically the class loader used to start the application.
1234     *
1235     * <p> This method is first invoked early in the runtime's startup
1236     * sequence, at which point it creates the system class loader and sets it
1237     * as the context class loader of the invoking <tt>Thread</tt>.
1238     *
1239     * <p> The default system class loader is an implementation-dependent
1240     * instance of this class.
1241     *
1242     * <p> If the system property "<tt>java.system.class.loader</tt>" is defined
1243     * when this method is first invoked then the value of that property is
1244     * taken to be the name of a class that will be returned as the system
1245     * class loader. The class is loaded using the default system class loader
1246     * and must define a public constructor that takes a single parameter of
1247     * type <tt>ClassLoader</tt> which is used as the delegation parent. An
1248     * instance is then created using this constructor with the default system
1249     * class loader as the parameter. The resulting class loader is defined
1250     * to be the system class loader.
1251     *
1252     * <p> If a security manager is present, and the invoker's class loader is
1253     * not <tt>null</tt> and the invoker's class loader is not the same as or
1254     * an ancestor of the system class loader, then this method invokes the
1255     * security manager's {@link
1256     * SecurityManager#checkPermission(java.security.Permission)
1257     * <tt>checkPermission</tt>} method with a {@link
1258     * RuntimePermission#RuntimePermission(String)
1259     * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
1260     * access to the system class loader. If not, a
1261     * <tt>SecurityException</tt> will be thrown. </p>
1262     *
1263     * @return The system <tt>ClassLoader</tt> for delegation, or
1264     * <tt>null</tt> if none
1265     *
1266     * @throws SecurityException
1267     * If a security manager exists and its <tt>checkPermission</tt>
1268     * method doesn't allow access to the system class loader.
1269     *
1270     * @throws IllegalStateException
1271     * If invoked recursively during the construction of the class
1272     * loader specified by the "<tt>java.system.class.loader</tt>"
1273     * property.
1274     *
1275     * @throws Error
1276     * If the system property "<tt>java.system.class.loader</tt>"
1277     * is defined but the named class could not be loaded, the
1278     * provider class does not define the required constructor, or an
1279     * exception is thrown by that constructor when it is invoked. The
1280     * underlying cause of the error can be retrieved via the
1281     * {@link Throwable#getCause()} method.
1282     *
1283     * @revised 1.4
1284     */

1285    public static ClassLoader JavaDoc getSystemClassLoader() {
1286    initSystemClassLoader();
1287    if (scl == null) {
1288        return null;
1289    }
1290    SecurityManager JavaDoc sm = System.getSecurityManager();
1291    if (sm != null) {
1292        ClassLoader JavaDoc ccl = getCallerClassLoader();
1293        if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) {
1294        sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
1295        }
1296    }
1297    return scl;
1298    }
1299
1300    private static synchronized void initSystemClassLoader() {
1301    if (!sclSet) {
1302        if (scl != null)
1303        throw new IllegalStateException JavaDoc("recursive invocation");
1304            sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
1305        if (l != null) {
1306        Throwable JavaDoc oops = null;
1307        scl = l.getClassLoader();
1308            try {
1309            PrivilegedExceptionAction JavaDoc a;
1310            a = new SystemClassLoaderAction(scl);
1311                    scl = (ClassLoader JavaDoc) AccessController.doPrivileged(a);
1312            } catch (PrivilegedActionException JavaDoc pae) {
1313            oops = pae.getCause();
1314                if (oops instanceof InvocationTargetException JavaDoc) {
1315                oops = oops.getCause();
1316            }
1317            }
1318        if (oops != null) {
1319            if (oops instanceof Error JavaDoc) {
1320            throw (Error JavaDoc) oops;
1321            } else {
1322                // wrap the exception
1323
throw new Error JavaDoc(oops);
1324            }
1325        }
1326        }
1327        sclSet = true;
1328    }
1329    }
1330
1331    // Returns true if the specified class loader can be found in this class
1332
// loader's delegation chain.
1333
boolean isAncestor(ClassLoader JavaDoc cl) {
1334    ClassLoader JavaDoc acl = this;
1335    do {
1336        acl = acl.parent;
1337        if (cl == acl) {
1338        return true;
1339        }
1340    } while (acl != null);
1341    return false;
1342    }
1343
1344    // Returns the invoker's class loader, or null if none.
1345
// NOTE: This must always be invoked when there is exactly one intervening
1346
// frame from the core libraries on the stack between this method's
1347
// invocation and the desired invoker.
1348
static ClassLoader JavaDoc getCallerClassLoader() {
1349        // NOTE use of more generic Reflection.getCallerClass()
1350
Class JavaDoc caller = Reflection.getCallerClass(3);
1351        // This can be null if the VM is requesting it
1352
if (caller == null) {
1353            return null;
1354        }
1355        // Circumvent security check since this is package-private
1356
return caller.getClassLoader0();
1357    }
1358
1359    // The class loader for the system
1360
private static ClassLoader JavaDoc scl;
1361
1362    // Set to true once the system class loader has been set
1363
private static boolean sclSet;
1364
1365
1366    // -- Package --
1367

1368    /**
1369     * Defines a package by name in this <tt>ClassLoader</tt>. This allows
1370     * class loaders to define the packages for their classes. Packages must
1371     * be created before the class is defined, and package names must be
1372     * unique within a class loader and cannot be redefined or changed once
1373     * created. </p>
1374     *
1375     * @param name
1376     * The package name
1377     *
1378     * @param specTitle
1379     * The specification title
1380     *
1381     * @param specVersion
1382     * The specification version
1383     *
1384     * @param specVendor
1385     * The specification vendor
1386     *
1387     * @param implTitle
1388     * The implementation title
1389     *
1390     * @param implVersion
1391     * The implementation version
1392     *
1393     * @param implVendor
1394     * The implementation vendor
1395     *
1396     * @param sealBase
1397     * If not <tt>null</tt>, then this package is sealed with
1398     * respect to the given code source {@link java.net.URL
1399     * <tt>URL</tt>} object. Otherwise, the package is not sealed.
1400     *
1401     * @return The newly defined <tt>Package</tt> object
1402     *
1403     * @throws IllegalArgumentException
1404     * If package name duplicates an existing package either in this
1405     * class loader or one of its ancestors
1406     *
1407     * @since 1.2
1408     */

1409    protected Package JavaDoc definePackage(String JavaDoc name, String JavaDoc specTitle,
1410                    String JavaDoc specVersion, String JavaDoc specVendor,
1411                    String JavaDoc implTitle, String JavaDoc implVersion,
1412                    String JavaDoc implVendor, URL JavaDoc sealBase)
1413    throws IllegalArgumentException JavaDoc
1414    {
1415    synchronized (packages) {
1416        Package JavaDoc pkg = getPackage(name);
1417        if (pkg != null) {
1418        throw new IllegalArgumentException JavaDoc(name);
1419        }
1420        pkg = new Package JavaDoc(name, specTitle, specVersion, specVendor,
1421                  implTitle, implVersion, implVendor,
1422                  sealBase, this);
1423        packages.put(name, pkg);
1424        return pkg;
1425    }
1426    }
1427
1428    /**
1429     * Returns a <tt>Package</tt> that has been defined by this class loader
1430     * or any of its ancestors. </p>
1431     *
1432     * @param name
1433     * The package name
1434     *
1435     * @return The <tt>Package</tt> corresponding to the given name, or
1436     * <tt>null</tt> if not found
1437     *
1438     * @since 1.2
1439     */

1440    protected Package JavaDoc getPackage(String JavaDoc name) {
1441    synchronized (packages) {
1442        Package JavaDoc pkg = (Package JavaDoc)packages.get(name);
1443        if (pkg == null) {
1444        if (parent != null) {
1445            pkg = parent.getPackage(name);
1446        } else {
1447            pkg = Package.getSystemPackage(name);
1448        }
1449        if (pkg != null) {
1450            packages.put(name, pkg);
1451        }
1452        }
1453        return pkg;
1454    }
1455    }
1456
1457    /**
1458     * Returns all of the <tt>Packages</tt> defined by this class loader and
1459     * its ancestors. </p>
1460     *
1461     * @return The array of <tt>Package</tt> objects defined by this
1462     * <tt>ClassLoader</tt>
1463     *
1464     * @since 1.2
1465     */

1466    protected Package JavaDoc[] getPackages() {
1467    Map JavaDoc map;
1468    synchronized (packages) {
1469        map = (Map JavaDoc)packages.clone();
1470    }
1471    Package JavaDoc[] pkgs;
1472    if (parent != null) {
1473        pkgs = parent.getPackages();
1474    } else {
1475        pkgs = Package.getSystemPackages();
1476    }
1477    if (pkgs != null) {
1478        for (int i = 0; i < pkgs.length; i++) {
1479                String JavaDoc pkgName = pkgs[i].getName();
1480                if (map.get(pkgName) == null) {
1481                    map.put(pkgName, pkgs[i]);
1482                }
1483        }
1484    }
1485    return (Package JavaDoc[])map.values().toArray(new Package JavaDoc[map.size()]);
1486    }
1487
1488
1489    // -- Native library access --
1490

1491    /**
1492     * Returns the absolute path name of a native library. The VM invokes this
1493     * method to locate the native libraries that belong to classes loaded with
1494     * this class loader. If this method returns <tt>null</tt>, the VM
1495     * searches the library along the path specified as the
1496     * "<tt>java.library.path</tt>" property. </p>
1497     *
1498     * @param libname
1499     * The library name
1500     *
1501     * @return The absolute path of the native library
1502     *
1503     * @see System#loadLibrary(String)
1504     * @see System#mapLibraryName(String)
1505     *
1506     * @since 1.2
1507     */

1508    protected String JavaDoc findLibrary(String JavaDoc libname) {
1509        return null;
1510    }
1511
1512    /**
1513     * The inner class NativeLibrary denotes a loaded native library instance.
1514     * Every classloader contains a vector of loaded native libraries in the
1515     * private field <tt>nativeLibraries</tt>. The native libraries loaded
1516     * into the system are entered into the <tt>systemNativeLibraries</tt>
1517     * vector.
1518     *
1519     * <p> Every native library requires a particular version of JNI. This is
1520     * denoted by the private <tt>jniVersion</tt> field. This field is set by
1521     * the VM when it loads the library, and used by the VM to pass the correct
1522     * version of JNI to the native methods. </p>
1523     *
1524     * @version 1.186 08/02/04
1525     * @see ClassLoader
1526     * @since 1.2
1527     */

1528    static class NativeLibrary {
1529    // opaque handle to native library, used in native code.
1530
long handle;
1531        // the version of JNI environment the native library requires.
1532
private int jniVersion;
1533        // the class from which the library is loaded, also indicates
1534
// the loader this native library belongs.
1535
private Class JavaDoc fromClass;
1536        // the canonicalized name of the native library.
1537
String JavaDoc name;
1538
1539        native void load(String JavaDoc name);
1540        native long find(String JavaDoc name);
1541        native void unload();
1542
1543        public NativeLibrary(Class JavaDoc fromClass, String JavaDoc name) {
1544            this.name = name;
1545        this.fromClass = fromClass;
1546    }
1547
1548        protected void finalize() {
1549        synchronized (loadedLibraryNames) {
1550            if (fromClass.getClassLoader() != null && handle != 0) {
1551            /* remove the native library name */
1552            int size = loadedLibraryNames.size();
1553            for (int i = 0; i < size; i++) {
1554                if (name.equals(loadedLibraryNames.elementAt(i))) {
1555                loadedLibraryNames.removeElementAt(i);
1556                break;
1557            }
1558            }
1559            /* unload the library. */
1560            ClassLoader.nativeLibraryContext.push(this);
1561            try {
1562            unload();
1563            } finally {
1564                ClassLoader.nativeLibraryContext.pop();
1565            }
1566        }
1567        }
1568    }
1569        // Invoked in the VM to determine the context class in
1570
// JNI_Load/JNI_Unload
1571
static Class JavaDoc getFromClass() {
1572            return ((NativeLibrary)
1573            (ClassLoader.nativeLibraryContext.peek())).fromClass;
1574    }
1575    }
1576
1577    // The "default" domain. Set as the default ProtectionDomain on newly
1578
// created classes.
1579
private ProtectionDomain JavaDoc defaultDomain = null;
1580
1581    // Returns (and initializes) the default domain.
1582
private synchronized ProtectionDomain JavaDoc getDefaultDomain() {
1583    if (defaultDomain == null) {
1584        CodeSource JavaDoc cs =
1585        new CodeSource JavaDoc(null, (java.security.cert.Certificate JavaDoc[]) null);
1586        defaultDomain = new ProtectionDomain JavaDoc(cs, null, this, null);
1587    }
1588    return defaultDomain;
1589    }
1590
1591    // All native library names we've loaded.
1592
private static Vector JavaDoc loadedLibraryNames = new Vector JavaDoc();
1593    // Native libraries belonging to system classes.
1594
private static Vector JavaDoc systemNativeLibraries = new Vector JavaDoc();
1595    // Native libraries associated with the class loader.
1596
private Vector JavaDoc nativeLibraries = new Vector JavaDoc();
1597
1598    // native libraries being loaded/unloaded.
1599
private static Stack JavaDoc nativeLibraryContext = new Stack JavaDoc();
1600
1601    // The paths searched for libraries
1602
static private String JavaDoc usr_paths[];
1603    static private String JavaDoc sys_paths[];
1604
1605    private static String JavaDoc[] initializePath(String JavaDoc propname) {
1606        String JavaDoc ldpath = System.getProperty(propname, "");
1607    String JavaDoc ps = File.pathSeparator;
1608    int ldlen = ldpath.length();
1609    int i, j, n;
1610    // Count the separators in the path
1611
i = ldpath.indexOf(ps);
1612    n = 0;
1613    while (i >= 0) {
1614        n++;
1615        i = ldpath.indexOf(ps, i + 1);
1616    }
1617
1618    // allocate the array of paths - n :'s = n + 1 path elements
1619
String JavaDoc[] paths = new String JavaDoc[n + 1];
1620
1621    // Fill the array with paths from the ldpath
1622
n = i = 0;
1623    j = ldpath.indexOf(ps);
1624    while (j >= 0) {
1625        if (j - i > 0) {
1626            paths[n++] = ldpath.substring(i, j);
1627        } else if (j - i == 0) {
1628            paths[n++] = ".";
1629        }
1630        i = j + 1;
1631        j = ldpath.indexOf(ps, i);
1632    }
1633    paths[n] = ldpath.substring(i, ldlen);
1634    return paths;
1635    }
1636
1637    // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
1638
static void loadLibrary(Class JavaDoc fromClass, String JavaDoc name,
1639                boolean isAbsolute) {
1640        ClassLoader JavaDoc loader =
1641        (fromClass == null) ? null : fromClass.getClassLoader();
1642        if (sys_paths == null) {
1643        usr_paths = initializePath("java.library.path");
1644        sys_paths = initializePath("sun.boot.library.path");
1645        }
1646        if (isAbsolute) {
1647        if (loadLibrary0(fromClass, new File JavaDoc(name))) {
1648            return;
1649        }
1650        throw new UnsatisfiedLinkError JavaDoc("Can't load library: " + name);
1651    }
1652    if (loader != null) {
1653        String JavaDoc libfilename = loader.findLibrary(name);
1654        if (libfilename != null) {
1655            File JavaDoc libfile = new File JavaDoc(libfilename);
1656            if (!libfile.isAbsolute()) {
1657            throw new UnsatisfiedLinkError JavaDoc(
1658    "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
1659        }
1660        if (loadLibrary0(fromClass, libfile)) {
1661            return;
1662        }
1663        throw new UnsatisfiedLinkError JavaDoc("Can't load " + libfilename);
1664        }
1665    }
1666    for (int i = 0 ; i < sys_paths.length ; i++) {
1667        File JavaDoc libfile = new File JavaDoc(sys_paths[i], System.mapLibraryName(name));
1668        if (loadLibrary0(fromClass, libfile)) {
1669            return;
1670        }
1671    }
1672    if (loader != null) {
1673        for (int i = 0 ; i < usr_paths.length ; i++) {
1674            File JavaDoc libfile = new File JavaDoc(usr_paths[i],
1675                    System.mapLibraryName(name));
1676        if (loadLibrary0(fromClass, libfile)) {
1677            return;
1678        }
1679        }
1680    }
1681    // Oops, it failed
1682
throw new UnsatisfiedLinkError JavaDoc("no " + name + " in java.library.path");
1683    }
1684
1685    private static boolean loadLibrary0(Class JavaDoc fromClass, final File JavaDoc file) {
1686    Boolean JavaDoc exists = (Boolean JavaDoc)
1687        AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
1688        public Object JavaDoc run() {
1689            return new Boolean JavaDoc(file.exists());
1690        }
1691        });
1692    if (!exists.booleanValue()) {
1693        return false;
1694    }
1695        String JavaDoc name;
1696    try {
1697        name = file.getCanonicalPath();
1698    } catch (IOException JavaDoc e) {
1699        return false;
1700    }
1701        ClassLoader JavaDoc loader =
1702        (fromClass == null) ? null : fromClass.getClassLoader();
1703        Vector JavaDoc libs =
1704        loader != null ? loader.nativeLibraries : systemNativeLibraries;
1705    synchronized (libs) {
1706        int size = libs.size();
1707        for (int i = 0; i < size; i++) {
1708            NativeLibrary lib = (NativeLibrary)libs.elementAt(i);
1709        if (name.equals(lib.name)) {
1710            return true;
1711        }
1712        }
1713
1714        synchronized (loadedLibraryNames) {
1715            if (loadedLibraryNames.contains(name)) {
1716            throw new UnsatisfiedLinkError JavaDoc
1717                ("Native Library " +
1718             name +
1719             " already loaded in another classloader");
1720        }
1721        /* If the library is being loaded (must be by the same thread,
1722         * because Runtime.load and Runtime.loadLibrary are
1723         * synchronous). The reason is can occur is that the JNI_OnLoad
1724         * function can cause another loadLibrary invocation.
1725         *
1726         * Thus we can use a static stack to hold the list of libraries
1727         * we are loading.
1728         *
1729         * If there is a pending load operation for the library, we
1730         * immediately return success; otherwise, we raise
1731         * UnsatisfiedLinkError.
1732         */

1733        int n = nativeLibraryContext.size();
1734        for (int i = 0; i < n; i++) {
1735            NativeLibrary lib = (NativeLibrary)
1736                nativeLibraryContext.elementAt(i);
1737            if (name.equals(lib.name)) {
1738                if (loader == lib.fromClass.getClassLoader()) {
1739                return true;
1740            } else {
1741                throw new UnsatisfiedLinkError JavaDoc
1742                    ("Native Library " +
1743                 name +
1744                 " is being loaded in another classloader");
1745            }
1746            }
1747        }
1748        NativeLibrary lib = new NativeLibrary(fromClass, name);
1749        nativeLibraryContext.push(lib);
1750        try {
1751            lib.load(name);
1752        } finally {
1753            nativeLibraryContext.pop();
1754        }
1755        if (lib.handle != 0) {
1756            loadedLibraryNames.addElement(name);
1757            libs.addElement(lib);
1758            return true;
1759        }
1760        return false;
1761        }
1762    }
1763    }
1764
1765    // Invoked in the VM class linking code.
1766
static long findNative(ClassLoader JavaDoc loader, String JavaDoc name) {
1767        Vector JavaDoc libs =
1768        loader != null ? loader.nativeLibraries : systemNativeLibraries;
1769    synchronized (libs) {
1770        int size = libs.size();
1771        for (int i = 0; i < size; i++) {
1772            NativeLibrary lib = (NativeLibrary)libs.elementAt(i);
1773        long entry = lib.find(name);
1774        if (entry != 0)
1775            return entry;
1776        }
1777    }
1778    return 0;
1779    }
1780
1781
1782    // -- Assertion management --
1783

1784    // The default toggle for assertion checking.
1785
private boolean defaultAssertionStatus = false;
1786
1787    // Maps String packageName to Boolean package default assertion status Note
1788
// that the default package is placed under a null map key. If this field
1789
// is null then we are delegating assertion status queries to the VM, i.e.,
1790
// none of this ClassLoader's assertion status modification methods have
1791
// been invoked.
1792
private Map JavaDoc packageAssertionStatus = null;
1793
1794    // Maps String fullyQualifiedClassName to Boolean assertionStatus If this
1795
// field is null then we are delegating assertion status queries to the VM,
1796
// i.e., none of this ClassLoader's assertion status modification methods
1797
// have been invoked.
1798
Map JavaDoc classAssertionStatus = null;
1799
1800    /**
1801     * Sets the default assertion status for this class loader. This setting
1802     * determines whether classes loaded by this class loader and initialized
1803     * in the future will have assertions enabled or disabled by default.
1804     * This setting may be overridden on a per-package or per-class basis by
1805     * invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link
1806     * #setClassAssertionStatus(String, boolean)}. </p>
1807     *
1808     * @param enabled
1809     * <tt>true</tt> if classes loaded by this class loader will
1810     * henceforth have assertions enabled by default, <tt>false</tt>
1811     * if they will have assertions disabled by default.
1812     *
1813     * @since 1.4
1814     */

1815    public synchronized void setDefaultAssertionStatus(boolean enabled) {
1816        if (classAssertionStatus == null)
1817            initializeJavaAssertionMaps();
1818
1819        defaultAssertionStatus = enabled;
1820    }
1821
1822    /**
1823     * Sets the package default assertion status for the named package. The
1824     * package default assertion status determines the assertion status for
1825     * classes initialized in the future that belong to the named package or
1826     * any of its "subpackages".
1827     *
1828     * <p> A subpackage of a package named p is any package whose name begins
1829     * with "<tt>p.</tt>". For example, <tt>javax.swing.text</tt> is a
1830     * subpackage of <tt>javax.swing</tt>, and both <tt>java.util</tt> and
1831     * <tt>java.lang.reflect</tt> are subpackages of <tt>java</tt>.
1832     *
1833     * <p> In the event that multiple package defaults apply to a given class,
1834     * the package default pertaining to the most specific package takes
1835     * precedence over the others. For example, if <tt>javax.lang</tt> and
1836     * <tt>javax.lang.reflect</tt> both have package defaults associated with
1837     * them, the latter package default applies to classes in
1838     * <tt>javax.lang.reflect</tt>.
1839     *
1840     * <p> Package defaults take precedence over the class loader's default
1841     * assertion status, and may be overridden on a per-class basis by invoking
1842     * {@link #setClassAssertionStatus(String, boolean)}. </p>
1843     *
1844     * @param packageName
1845     * The name of the package whose package default assertion status
1846     * is to be set. A <tt>null</tt> value indicates the unnamed
1847     * package that is "current" (<a *
1848     * HREF="http://java.sun.com/docs/books/jls/">Java Language
1849     * Specification</a>, section 7.4.2).
1850     *
1851     * @param enabled
1852     * <tt>true</tt> if classes loaded by this classloader and
1853     * belonging to the named package or any of its subpackages will
1854     * have assertions enabled by default, <tt>false</tt> if they will
1855     * have assertions disabled by default.
1856     *
1857     * @since 1.4
1858     */

1859    public synchronized void setPackageAssertionStatus(String JavaDoc packageName,
1860                                                       boolean enabled)
1861    {
1862        if (packageAssertionStatus == null)
1863            initializeJavaAssertionMaps();
1864
1865        packageAssertionStatus.put(packageName, Boolean.valueOf(enabled));
1866    }
1867
1868    /**
1869     * Sets the desired assertion status for the named top-level class in this
1870     * class loader and any nested classes contained therein. This setting
1871     * takes precedence over the class loader's default assertion status, and
1872     * over any applicable per-package default. This method has no effect if
1873     * the named class has already been initialized. (Once a class is
1874     * initialized, its assertion status cannot change.)
1875     *
1876     * <p> If the named class is not a top-level class, this invocation will
1877     * have no effect on the actual assertion status of any class, and its
1878     * return value is undefined. </p>
1879     *
1880     * @param className
1881     * The fully qualified class name of the top-level class whose
1882     * assertion status is to be set.
1883     *
1884     * @param enabled
1885     * <tt>true</tt> if the named class is to have assertions
1886     * enabled when (and if) it is initialized, <tt>false</tt> if the
1887     * class is to have assertions disabled.
1888     *
1889     * @since 1.4
1890     */

1891    public synchronized void setClassAssertionStatus(String JavaDoc className,
1892                                                     boolean enabled)
1893    {
1894        if (classAssertionStatus == null)
1895            initializeJavaAssertionMaps();
1896
1897        classAssertionStatus.put(className, Boolean.valueOf(enabled));
1898    }
1899
1900    /**
1901     * Sets the default assertion status for this class loader to
1902     * <tt>false</tt> and discards any package defaults or class assertion
1903     * status settings associated with the class loader. This method is
1904     * provided so that class loaders can be made to ignore any command line or
1905     * persistent assertion status settings and "start with a clean slate."
1906     * </p>
1907     *
1908     * @since 1.4
1909     */

1910    public synchronized void clearAssertionStatus() {
1911        /*
1912         * Whether or not "Java assertion maps" are initialized, set
1913         * them to empty maps, effectively ignoring any present settings.
1914         */

1915        classAssertionStatus = new HashMap JavaDoc();
1916        packageAssertionStatus = new HashMap JavaDoc();
1917
1918        defaultAssertionStatus = false;
1919    }
1920
1921    /**
1922     * Returns the assertion status that would be assigned to the specified
1923     * class if it were to be initialized at the time this method is invoked.
1924     * If the named class has had its assertion status set, the most recent
1925     * setting will be returned; otherwise, if any package default assertion
1926     * status pertains to this class, the most recent setting for the most
1927     * specific pertinent package default assertion status is returned;
1928     * otherwise, this class loader's default assertion status is returned.
1929     * </p>
1930     *
1931     * @param className
1932     * The fully qualified class name of the class whose desired
1933     * assertion status is being queried.
1934     *
1935     * @return The desired assertion status of the specified class.
1936     *
1937     * @see #setClassAssertionStatus(String, boolean)
1938     * @see #setPackageAssertionStatus(String, boolean)
1939     * @see #setDefaultAssertionStatus(boolean)
1940     *
1941     * @since 1.4
1942     */

1943    synchronized boolean desiredAssertionStatus(String JavaDoc className) {
1944        Boolean JavaDoc result;
1945
1946        // assert classAssertionStatus != null;
1947
// assert packageAssertionStatus != null;
1948

1949        // Check for a class entry
1950
result = (Boolean JavaDoc)classAssertionStatus.get(className);
1951        if (result != null)
1952            return result.booleanValue();
1953
1954        // Check for most specific package entry
1955
int dotIndex = className.lastIndexOf(".");
1956        if (dotIndex < 0) { // default package
1957
result = (Boolean JavaDoc)packageAssertionStatus.get(null);
1958            if (result != null)
1959                return result.booleanValue();
1960        }
1961        while(dotIndex > 0) {
1962            className = className.substring(0, dotIndex);
1963            result = (Boolean JavaDoc)packageAssertionStatus.get(className);
1964            if (result != null)
1965                return result.booleanValue();
1966            dotIndex = className.lastIndexOf(".", dotIndex-1);
1967        }
1968
1969        // Return the classloader default
1970
return defaultAssertionStatus;
1971    }
1972
1973    // Set up the assertions with information provided by the VM.
1974
private void initializeJavaAssertionMaps() {
1975        // assert Thread.holdsLock(this);
1976

1977        classAssertionStatus = new HashMap JavaDoc();
1978        packageAssertionStatus = new HashMap JavaDoc();
1979        AssertionStatusDirectives JavaDoc directives = retrieveDirectives();
1980
1981        for(int i = 0; i < directives.classes.length; i++)
1982            classAssertionStatus.put(directives.classes[i],
1983                              Boolean.valueOf(directives.classEnabled[i]));
1984
1985        for(int i = 0; i < directives.packages.length; i++)
1986            packageAssertionStatus.put(directives.packages[i],
1987                              Boolean.valueOf(directives.packageEnabled[i]));
1988
1989        defaultAssertionStatus = directives.deflt;
1990    }
1991
1992    // Retrieves the assertion directives from the VM.
1993
private static native AssertionStatusDirectives JavaDoc retrieveDirectives();
1994}
1995
1996
1997class SystemClassLoaderAction implements PrivilegedExceptionAction JavaDoc {
1998    private ClassLoader JavaDoc parent;
1999
2000    SystemClassLoaderAction(ClassLoader JavaDoc parent) {
2001    this.parent = parent;
2002    }
2003
2004    public Object JavaDoc run() throws Exception JavaDoc {
2005    ClassLoader JavaDoc sys;
2006    Constructor JavaDoc ctor;
2007    Class JavaDoc c;
2008    Class JavaDoc cp[] = { ClassLoader JavaDoc.class };
2009    Object JavaDoc params[] = { parent };
2010
2011        String JavaDoc cls = System.getProperty("java.system.class.loader");
2012    if (cls == null) {
2013        return parent;
2014    }
2015
2016    c = Class.forName(cls, true, parent);
2017    ctor = c.getDeclaredConstructor(cp);
2018    sys = (ClassLoader JavaDoc) ctor.newInstance(params);
2019    Thread.currentThread().setContextClassLoader(sys);
2020    return sys;
2021    }
2022}
2023
Popular Tags