OSDN Git Service

* java/lang/ClassLoader.java (resolveClass0): Set cause for
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / ClassLoader.java
1 // ClassLoader.java - Define policies for loading Java classes.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 package java.lang;
12
13 import java.io.InputStream;
14 import java.io.IOException;
15 import java.net.URL;
16 import java.net.URLConnection;
17 import java.security.AllPermission;
18 import java.security.CodeSource;
19 import java.security.Permission;
20 import java.security.Permissions;
21 import java.security.Policy;
22 import java.security.ProtectionDomain;
23 import java.util.*;
24
25 /**
26  * The class <code>ClassLoader</code> is intended to be subclassed by
27  * applications in order to describe new ways of loading classes,
28  * such as over the network.
29  *
30  * @author  Kresten Krab Thorup
31  */
32
33 public abstract class ClassLoader
34 {
35   /**
36    * The desired assertion status of classes loaded by this loader, if not
37    * overridden by package or class instructions.
38    */
39   // Package visible for use by Class.
40   boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus();
41
42   /**
43    * The command-line state of the package assertion status overrides. This
44    * map is never modified, so it does not need to be synchronized.
45    */
46   // Package visible for use by Class.
47   static final Map systemPackageAssertionStatus
48     = VMClassLoader.packageAssertionStatus();
49
50   /**
51    * The map of package assertion status overrides, or null if no package
52    * overrides have been specified yet. The values of the map should be
53    * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented
54    * by the null key. This map must be synchronized on this instance.
55    */
56   // Package visible for use by Class.
57   Map packageAssertionStatus;
58
59   /**
60    * The command-line state of the class assertion status overrides. This
61    * map is never modified, so it does not need to be synchronized.
62    */
63   // Package visible for use by Class.
64   static final Map systemClassAssertionStatus
65     = VMClassLoader.classAssertionStatus();
66
67   /**
68    * The map of class assertion status overrides, or null if no class
69    * overrides have been specified yet. The values of the map should be
70    * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this
71    * instance.
72    */
73   // Package visible for use by Class.
74   Map classAssertionStatus;
75
76   private ClassLoader parent;
77   private HashMap definedPackages = new HashMap();
78
79   public final ClassLoader getParent ()
80   {
81     /* FIXME: security */
82     return parent;
83   }
84
85   /**
86    * Returns the system classloader. The system classloader (also called
87    * the application classloader) is the classloader that was used to
88    * load the application classes on the classpath (given by the system
89    * property <code>java.class.path</code>. This is set as the context
90    * class loader for a thread. The system property
91    * <code>java.system.class.loader</code>, if defined, is taken to be the
92    * name of the class to use as the system class loader, which must have
93    * a public constructor which takes a ClassLoader as a parent; otherwise this
94    * uses gnu.java.lang.SystemClassLoader.
95    *
96    * <p>Note that this is different from the bootstrap classloader that
97    * actually loads all the real "system" classes (the bootstrap classloader
98    * is the parent of the returned system classloader).
99    *
100    * <p>A security check will be performed for
101    * <code>RuntimePermission("getClassLoader")</code> if the calling class
102    * is not a parent of the system class loader.
103    *
104    * @return the system class loader
105    * @throws SecurityException if the security check fails
106    * @throws IllegalStateException if this is called recursively
107    * @throws Error if <code>java.system.class.loader</code> fails to load
108    * @since 1.2
109    */
110   public static ClassLoader getSystemClassLoader ()
111   {
112     return gnu.gcj.runtime.VMClassLoader.instance;
113   }
114
115   /**
116    * Creates a <code>ClassLoader</code> with no parent.
117    * @exception java.lang.SecurityException if not allowed
118    */
119   protected ClassLoader() 
120   {
121     this (null);
122   }
123
124   /**
125    * Creates a <code>ClassLoader</code> with the given parent.   
126    * The parent may be <code>null</code>.
127    * The only thing this 
128    * constructor does, is to call
129    * <code>checkCreateClassLoader</code> on the current 
130    * security manager. 
131    * @exception java.lang.SecurityException if not allowed
132    * @since 1.2
133    */
134   protected ClassLoader(ClassLoader parent) 
135   {
136     SecurityManager security = System.getSecurityManager ();
137     if (security != null)
138       security.checkCreateClassLoader ();
139     this.parent = parent;
140   }
141
142   /** 
143    * Loads and link the class by the given name.
144    * @param     name the name of the class.
145    * @return    the class loaded.
146    * @see       ClassLoader#loadClass(String,boolean)
147    * @exception java.lang.ClassNotFoundException 
148    */ 
149   public Class loadClass(String name)
150     throws java.lang.ClassNotFoundException
151   { 
152     return loadClass (name, false);
153   }
154   
155   /** 
156    * Loads the class by the given name.  The default implementation
157    * will search for the class in the following order (similar to jdk 1.2)
158    * <ul>
159    *  <li> First <code>findLoadedClass</code>.
160    *  <li> If parent is non-null, <code>parent.loadClass</code>;
161    *       otherwise <code>findSystemClass</code>.
162    *  <li> <code>findClass</code>.
163    * </ul>
164    * If <code>link</code> is true, <code>resolveClass</code> is then
165    * called.  <p> Normally, this need not be overridden; override
166    * <code>findClass</code> instead.
167    * @param     name the name of the class.
168    * @param     link if the class should be linked.
169    * @return    the class loaded.
170    * @exception java.lang.ClassNotFoundException 
171    * @deprecated 
172    */ 
173   protected Class loadClass(String name, boolean link)
174     throws java.lang.ClassNotFoundException
175   {
176     Class c = findLoadedClass (name);
177
178     if (c == null)
179       {
180         try {
181           if (parent != null)
182             return parent.loadClass (name, link);
183           else
184             c = gnu.gcj.runtime.VMClassLoader.instance.findClass (name);
185         } catch (ClassNotFoundException ex) {
186           /* ignore, we'll try findClass */;
187         }
188       }
189
190     if (c == null)
191       c = findClass (name);
192
193     if (c == null)
194       throw new ClassNotFoundException (name);
195
196     if (link)
197       resolveClass (c);
198
199     return c;
200   }
201
202   /**
203    * Called for every class name that is needed but has not yet been
204    * defined by this classloader or one of its parents. It is called by
205    * <code>loadClass()</code> after both <code>findLoadedClass()</code> and
206    * <code>parent.loadClass()</code> couldn't provide the requested class.
207    *
208    * <p>The default implementation throws a
209    * <code>ClassNotFoundException</code>. Subclasses should override this
210    * method. An implementation of this method in a subclass should get the
211    * class bytes of the class (if it can find them), if the package of the
212    * requested class doesn't exist it should define the package and finally
213    * it should call define the actual class. It does not have to resolve the
214    * class. It should look something like the following:<br>
215    *
216    * <pre>
217    * // Get the bytes that describe the requested class
218    * byte[] classBytes = classLoaderSpecificWayToFindClassBytes(name);
219    * // Get the package name
220    * int lastDot = name.lastIndexOf('.');
221    * if (lastDot != -1)
222    *   {
223    *     String packageName = name.substring(0, lastDot);
224    *     // Look if the package already exists
225    *     if (getPackage(pkg) == null)
226    *       {
227    *         // define the package
228    *         definePackage(packageName, ...);
229    *       }
230    *   }
231    * // Define and return the class
232    *  return defineClass(name, classBytes, 0, classBytes.length);
233    * </pre>
234    *
235    * <p><code>loadClass()</code> makes sure that the <code>Class</code>
236    * returned by <code>findClass()</code> will later be returned by
237    * <code>findLoadedClass()</code> when the same class name is requested.
238    *
239    * @param name class name to find (including the package name)
240    * @return the requested Class
241    * @throws ClassNotFoundException when the class can not be found
242    * @since 1.2
243    */   
244   protected Class findClass (String name)
245     throws ClassNotFoundException
246   {
247     throw new ClassNotFoundException (name);
248   }
249
250   // Protection Domain definitions 
251   // FIXME: should there be a special protection domain used for native code?
252   
253   // The permission required to check what a classes protection domain is.
254   static final Permission protectionDomainPermission
255     = new RuntimePermission("getProtectionDomain");
256   // The protection domain returned if we cannot determine it. 
257   static ProtectionDomain unknownProtectionDomain;
258   // Protection domain to use when a class is defined without one specified.
259   static ProtectionDomain defaultProtectionDomain;
260
261   static
262   {
263     Permissions permissions = new Permissions();
264     permissions.add(new AllPermission());
265     unknownProtectionDomain = new ProtectionDomain(null, permissions);  
266
267     CodeSource cs = new CodeSource(null, null);
268     defaultProtectionDomain =
269       new ProtectionDomain(cs, Policy.getPolicy().getPermissions(cs));
270   }
271
272   /** 
273    * Defines a class, given the class-data.  According to the JVM, this
274    * method should not be used; instead use the variant of this method
275    * in which the name of the class being defined is specified
276    * explicitly.   
277    * <P>
278    * If the name of the class, as specified (implicitly) in the class
279    * data, denotes a class which has already been loaded by this class
280    * loader, an instance of
281    * <code>java.lang.ClassNotFoundException</code> will be thrown.
282    *
283    * @param     data    bytes in class file format.
284    * @param     off     offset to start interpreting data.
285    * @param     len     length of data in class file.
286    * @return    the class defined.
287    * @exception java.lang.ClassNotFoundException 
288    * @exception java.lang.LinkageError
289    * @see ClassLoader#defineClass(String,byte[],int,int) */
290   protected final Class defineClass(byte[] data, int off, int len) 
291     throws ClassFormatError
292   {
293     return defineClass (null, data, off, len, defaultProtectionDomain);
294   }
295
296   /**
297    * Helper to define a class using a string of bytes without a
298    * ProtectionDomain. Subclasses should call this method from their
299    * <code>findClass()</code> implementation. The name should use '.'
300    * separators, and discard the trailing ".class".  The default protection
301    * domain has the permissions of
302    * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))<code>.
303    *
304    * @param name the name to give the class, or null if unknown
305    * @param data the data representing the classfile, in classfile format
306    * @param offset the offset into the data where the classfile starts
307    * @param len the length of the classfile data in the array
308    * @return the class that was defined
309    * @throws ClassFormatError if data is not in proper classfile format
310    * @throws IndexOutOfBoundsException if offset or len is negative, or
311    *         offset + len exceeds data
312    * @throws SecurityException if name starts with "java."
313    * @since 1.1
314    */
315   protected final Class defineClass(String name, byte[] data, int off, int len)
316     throws ClassFormatError
317   {
318     return defineClass (name, data, off, len, defaultProtectionDomain);
319   }
320   
321   /** 
322    * Defines a class, given the class-data.  This is preferable
323    * over <code>defineClass(byte[],off,len)</code> since it is more
324    * secure.  If the expected name does not match that of the class
325    * file, <code>ClassNotFoundException</code> is thrown.  If
326    * <code>name</code> denotes the name of an already loaded class, a
327    * <code>LinkageError</code> is thrown.
328    * <p>
329    * 
330    * FIXME: How do we assure that the class-file data is not being
331    * modified, simultaneously with the class loader running!?  If this
332    * was done in some very clever way, it might break security.  
333    * Right now I am thinking that defineclass should make sure never to
334    * read an element of this array more than once, and that that would
335    * assure the ``immutable'' appearance.  It is still to be determined
336    * if this is in fact how defineClass operates.
337    *
338    * @param     name    the expected name.
339    * @param     data    bytes in class file format.
340    * @param     off     offset to start interpreting data.
341    * @param     len     length of data in class file.
342    * @param     protectionDomain security protection domain for the class.
343    * @return    the class defined.
344    * @exception java.lang.ClassNotFoundException 
345    * @exception java.lang.LinkageError
346    */
347   protected final synchronized Class defineClass(String name,
348                                                  byte[] data,
349                                                  int off,
350                                                  int len,
351                                                  ProtectionDomain protectionDomain)
352     throws ClassFormatError
353   {
354     if (data==null || data.length < off+len || off<0 || len<0)
355       throw new ClassFormatError ("arguments to defineClass "
356                                   + "are meaningless");
357
358     // as per 5.3.5.1
359     if (name != null  &&  findLoadedClass (name) != null)
360       throw new java.lang.LinkageError ("class " 
361                                         + name 
362                                         + " already loaded");
363     
364     if (protectionDomain == null)
365       protectionDomain = defaultProtectionDomain;
366
367     try {
368       // Since we're calling into native code here, 
369       // we better make sure that any generated
370       // exception is to spec!
371
372       return defineClass0 (name, data, off, len, protectionDomain);
373
374     } catch (LinkageError x) {
375       throw x;          // rethrow
376
377     } catch (java.lang.VirtualMachineError x) {
378       throw x;          // rethrow
379
380     } catch (java.lang.Throwable x) {
381       // This should never happen, or we are beyond spec.  
382       
383       throw new InternalError ("Unexpected exception "
384                                + "while defining class "
385                                + name + ": " 
386                                + x.toString ());
387     }
388   }
389
390   /** This is the entry point of defineClass into the native code */
391   private native Class defineClass0 (String name,
392                                      byte[] data,
393                                      int off,
394                                      int len,
395                                      ProtectionDomain protectionDomain)
396     throws ClassFormatError;
397
398   /** 
399    * Link the given class.  This will bring the class to a state where
400    * the class initializer can be run.  Linking involves the following
401    * steps: 
402    * <UL>
403    * <LI>  Prepare (allocate and internalize) the constant strings that
404    *       are used in this class.
405    * <LI>  Allocate storage for static fields, and define the layout
406    *       of instance fields.
407    * <LI>  Perform static initialization of ``static final'' int,
408    *       long, float, double and String fields for which there is a
409    *       compile-time constant initializer.
410    * <LI>  Create the internal representation of the ``vtable''.
411    * </UL>
412    * For <code>gcj</code>-compiled classes, only the first step is
413    * performed.  The compiler will have done the rest already.
414    * <P>
415    * This is called by the system automatically,
416    * as part of class initialization; there is no reason to ever call
417    * this method directly.  
418    * <P> 
419    * For historical reasons, this method has a name which is easily
420    * misunderstood.  Java classes are never ``resolved''.  Classes are
421    * linked; whereas method and field references are resolved.
422    *
423    * @param     clazz the class to link.
424    * @exception java.lang.LinkageError
425    */
426   protected final void resolveClass(Class clazz)
427   {
428     resolveClass0(clazz);
429   }
430
431   static void resolveClass0(Class clazz)
432   {
433     synchronized (clazz)
434       {
435         try
436           {
437             linkClass0 (clazz);
438           }
439         catch (Throwable x)
440           {
441             markClassErrorState0 (clazz);
442
443             if (x instanceof Error)
444               throw (Error)x;
445             else
446               {
447                 InternalError e
448                   = new InternalError ("unexpected exception during linking");
449                 e.initCause (x);
450                 throw e;
451               }
452           }
453       }
454   }
455
456   /** Internal method.  Calls _Jv_PrepareClass and
457    * _Jv_PrepareCompiledClass.  This is only called from resolveClass.  */ 
458   private static native void linkClass0(Class clazz);
459
460   /** Internal method.  Marks the given clazz to be in an erroneous
461    * state, and calls notifyAll() on the class object.  This should only
462    * be called when the caller has the lock on the class object.  */
463   private static native void markClassErrorState0(Class clazz);
464
465   /**
466    * Defines a new package and creates a Package object.
467    * The package should be defined before any class in the package is
468    * defined with <code>defineClass()</code>. The package should not yet
469    * be defined before in this classloader or in one of its parents (which
470    * means that <code>getPackage()</code> should return <code>null</code>).
471    * All parameters except the <code>name</code> of the package may be
472    * <code>null</code>.
473    * <p>
474    * Subclasses should call this method from their <code>findClass()</code>
475    * implementation before calling <code>defineClass()</code> on a Class
476    * in a not yet defined Package (which can be checked by calling
477    * <code>getPackage()</code>).
478    *
479    * @param name The name of the Package
480    * @param specTitle The name of the specification
481    * @param specVendor The name of the specification designer
482    * @param specVersion The version of this specification
483    * @param implTitle The name of the implementation
484    * @param implVendor The vendor that wrote this implementation
485    * @param implVersion The version of this implementation
486    * @param sealed If sealed the origin of the package classes
487    * @return the Package object for the specified package
488    *
489    * @exception IllegalArgumentException if the package name is null or if
490    * it was already defined by this classloader or one of its parents.
491    *
492    * @see Package
493    * @since 1.2
494    */
495   protected Package definePackage(String name,
496                                   String specTitle, String specVendor,
497                                   String specVersion, String implTitle,
498                                   String implVendor, String implVersion,
499                                   URL sealed)
500   {
501     if (getPackage(name) != null)
502       throw new IllegalArgumentException("Package " + name
503                                          + " already defined");
504     Package p = new Package(name,
505                             specTitle, specVendor, specVersion,
506                             implTitle, implVendor, implVersion,
507                             sealed);
508     synchronized (definedPackages)
509     {
510       definedPackages.put(name, p);
511     }
512     return p;
513   }
514
515   /**
516    * Returns the Package object for the requested package name. It returns
517    * null when the package is not defined by this classloader or one of its
518    * parents.
519    *
520    * @since 1.2
521    */
522   protected Package getPackage(String name)
523   {
524     Package p;
525     if (parent == null)
526       // XXX - Should we use the bootstrap classloader?
527       p = null;
528     else
529       p = parent.getPackage(name);
530
531     if (p == null)
532       {
533         synchronized (definedPackages)
534         {
535           p = (Package) definedPackages.get(name);
536         }
537       }
538
539     return p;
540   }
541
542   /**
543    * Returns all Package objects defined by this classloader and its parents.
544    *
545    * @since 1.2
546    */
547   protected Package[] getPackages()
548   {
549     Package[] allPackages;
550
551     // Get all our packages.
552     Package[] packages;
553     synchronized(definedPackages)
554     {
555       packages = new Package[definedPackages.size()];
556       definedPackages.values().toArray(packages);
557     }
558
559     // If we have a parent get all packages defined by our parents.
560     if (parent != null)
561       {
562         Package[] parentPackages = parent.getPackages();
563         allPackages = new Package[parentPackages.length + packages.length];
564         System.arraycopy(parentPackages, 0, allPackages, 0,
565                          parentPackages.length);
566         System.arraycopy(packages, 0, allPackages, parentPackages.length,
567                          packages.length);
568       }
569     else
570       // XXX - Should we use the bootstrap classloader?
571       allPackages = packages;
572
573     return allPackages;
574   }
575
576   /** 
577    * Returns a class found in a system-specific way, typically
578    * via the <code>java.class.path</code> system property.  Loads the 
579    * class if necessary.
580    *
581    * @param     name the class to resolve.
582    * @return    the class loaded.
583    * @exception java.lang.LinkageError 
584    * @exception java.lang.ClassNotFoundException 
585    */
586   protected final Class findSystemClass(String name) 
587     throws java.lang.ClassNotFoundException
588   {
589     return gnu.gcj.runtime.VMClassLoader.instance.loadClass (name);
590   }
591
592   /**
593    * Helper to set the signers of a class. This should be called after
594    * defining the class.
595    *
596    * @param c the Class to set signers of
597    * @param signers the signers to set
598    * @since 1.1
599    */   
600   protected final void setSigners(Class c, Object[] signers)
601   {
602     /*
603      * Does currently nothing. FIXME.
604      */ 
605   }
606
607   /**
608    * If a class named <code>name</code> was previously loaded using
609    * this <code>ClassLoader</code>, then it is returned.  Otherwise
610    * it returns <code>null</code>.  (Unlike the JDK this is native,
611    * since we implement the class table internally.)
612    * @param     name  class to find.
613    * @return    the class loaded, or null.
614    */ 
615   protected final native Class findLoadedClass(String name);
616
617
618   /**
619    * Get a resource using the system classloader.
620    *
621    * @param name the name of the resource relative to the system classloader
622    * @return an input stream for the resource, or null
623    * @since 1.1
624    */
625   public static InputStream getSystemResourceAsStream(String name) {
626     return getSystemClassLoader().getResourceAsStream (name);
627   }
628
629   /**
630    * Get the URL to a resource using the system classloader.
631    *
632    * @param name the name of the resource relative to the system classloader
633    * @return the URL to the resource
634    * @since 1.1
635    */
636   public static URL getSystemResource(String name) {
637     return getSystemClassLoader().getResource (name);
638   }
639
640   /**
641    * Get an Enumeration of URLs to resources with a given name using the
642    * the system classloader. The enumeration firsts lists the resources with
643    * the given name that can be found by the bootstrap classloader followed
644    * by the resources with the given name that can be found on the classpath.
645    *
646    * @param name the name of the resource relative to the system classloader
647    * @return an Enumeration of URLs to the resources
648    * @throws IOException if I/O errors occur in the process
649    * @since 1.2
650    */
651   public static Enumeration getSystemResources(String name) throws IOException
652   {
653     return getSystemClassLoader().getResources(name);
654   }
655
656   /**
657    *   Return an InputStream representing the resource name.  
658    *   This is essentially like 
659    *   <code>getResource(name).openStream()</code>, except
660    *   it masks out any IOException and returns null on failure.
661    * @param   name  resource to load
662    * @return  an InputStream, or null
663    * @see     java.lang.ClassLoader#getResource(String)
664    * @see     java.io.InputStream
665    */
666   public InputStream getResourceAsStream(String name) 
667   {
668     try
669       {
670         URL res = getResource (name);
671         if (res == null)
672           return null;
673         return res.openStream ();
674       }
675     catch (java.io.IOException x)
676       {
677         return null;
678       }
679   }
680  
681   /**
682    * Return an java.io.URL representing the resouce <code>name</code>.  
683    * The default implementation just returns <code>null</code>.
684    * @param   name  resource to load
685    * @return  a URL, or null if there is no such resource.
686    * @see     java.lang.ClassLoader#getResourceAsBytes(String)
687    * @see     java.lang.ClassLoader#getResourceAsStream(String)
688    * @see     java.io.URL
689    */
690   public URL getResource (String name) 
691   {
692     // The rules say search the parent class if non-null,
693     // otherwise search the built-in class loader (assumed to be
694     // the system ClassLoader).  If not found, call
695     // findResource().
696     URL result = null;
697
698     ClassLoader delegate = parent;
699
700     if (delegate == null)
701       delegate = getSystemClassLoader ();
702         
703     // Protect ourselves from looping.
704     if (this != delegate)
705       result = delegate.getResource (name);
706
707     if (result != null)
708       return result;
709     else
710       return findResource (name);
711   }
712
713   /**
714    * Called whenever a resource is needed that could not be provided by
715    * one of the parents of this classloader. It is called by
716    * <code>getResource()</code> after <code>parent.getResource()</code>
717    * couldn't provide the requested resource.
718    *
719    * <p>The default implementation always returns null. Subclasses should
720    * override this method when they can provide a way to return a URL
721    * to a named resource.
722    *
723    * @param name the name of the resource to be found
724    * @return a URL to the named resource or null when not found
725    * @since 1.2
726    */
727   protected URL findResource (String name)
728   {
729     // Default to returning null.  Derived classes implement this.
730     return null;
731   }
732
733   /**
734    * Returns an Enumeration of all resources with a given name that can
735    * be found by this classloader and its parents. Certain classloaders
736    * (such as the URLClassLoader when given multiple jar files) can have
737    * multiple resources with the same name that come from multiple locations.
738    * It can also occur that a parent classloader offers a resource with a
739    * certain name and the child classloader also offers a resource with that
740    * same name. <code>getResource() only offers the first resource (of the
741    * parent) with a given name. This method lists all resources with the
742    * same name. The name should use '/' as path separators.
743    *
744    * <p>The Enumeration is created by first calling <code>getResources()</code>
745    * on the parent classloader and then calling <code>findResources()</code>
746    * on this classloader.
747    *
748    * @param name the resource name
749    * @return an enumaration of all resources found
750    * @throws IOException if I/O errors occur in the process
751    * @since 1.2
752    */
753   public final Enumeration getResources(String name) throws IOException
754   {
755     // The rules say search the parent class if non-null,
756     // otherwise search the built-in class loader (assumed to be
757     // the system ClassLoader).  If not found, call
758     // findResource().
759     Enumeration result = null;
760
761     ClassLoader delegate = parent;
762
763     if (delegate == null)
764       delegate = getSystemClassLoader ();
765         
766     // Protect ourselves from looping.
767     if (this != delegate)
768       result = delegate.getResources (name);
769
770     if (result != null)
771       return result;
772     else
773       return findResources (name);
774   }
775
776   /**
777    * Called whenever all locations of a named resource are needed.
778    * It is called by <code>getResources()</code> after it has called
779    * <code>parent.getResources()</code>. The results are combined by
780    * the <code>getResources()</code> method.
781    *
782    * <p>The default implementation always returns an empty Enumeration.
783    * Subclasses should override it when they can provide an Enumeration of
784    * URLs (possibly just one element) to the named resource.
785    * The first URL of the Enumeration should be the same as the one
786    * returned by <code>findResource</code>.
787    *
788    * @param name the name of the resource to be found
789    * @return a possibly empty Enumeration of URLs to the named resource
790    * @throws IOException if I/O errors occur in the process
791    * @since 1.2
792    */
793   protected Enumeration findResources(String name) throws IOException
794   {
795     return Collections.enumeration(Collections.EMPTY_LIST);
796   }
797
798   /**
799    * Set the default assertion status for classes loaded by this classloader,
800    * used unless overridden by a package or class request.
801    *
802    * @param enabled true to set the default to enabled
803    * @see #setClassAssertionStatus(String, boolean)
804    * @see #setPackageAssertionStatus(String, boolean)
805    * @see #clearAssertionStatus()
806    * @since 1.4
807    */
808   public void setDefaultAssertionStatus(boolean enabled)
809   {
810     defaultAssertionStatus = enabled;
811   }
812
813   /**
814    * Set the default assertion status for packages, used unless overridden
815    * by a class request. This default also covers subpackages, unless they
816    * are also specified. The unnamed package should use null for the name.
817    *
818    * @param name the package (and subpackages) to affect
819    * @param enabled true to set the default to enabled
820    * @see #setDefaultAssertionStatus(String, boolean)
821    * @see #setClassAssertionStatus(String, boolean)
822    * @see #clearAssertionStatus()
823    * @since 1.4
824    */
825   public synchronized void setPackageAssertionStatus(String name,
826                                                      boolean enabled)
827   {
828     if (packageAssertionStatus == null)
829       packageAssertionStatus
830         = new HashMap(systemPackageAssertionStatus);
831     packageAssertionStatus.put(name, Boolean.valueOf(enabled));
832   }
833   
834   /**
835    * Set the default assertion status for a class. This only affects the
836    * status of top-level classes, any other string is harmless.
837    *
838    * @param name the class to affect
839    * @param enabled true to set the default to enabled
840    * @throws NullPointerException if name is null
841    * @see #setDefaultAssertionStatus(String, boolean)
842    * @see #setPackageAssertionStatus(String, boolean)
843    * @see #clearAssertionStatus()
844    * @since 1.4
845    */
846   public synchronized void setClassAssertionStatus(String name,
847                                                    boolean enabled)
848   {
849     if (classAssertionStatus == null)
850       classAssertionStatus = new HashMap(systemClassAssertionStatus);
851     // The toString() hack catches null, as required.
852     classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled));
853   }
854   
855   /**
856    * Resets the default assertion status of this classloader, its packages
857    * and classes, all to false. This allows overriding defaults inherited
858    * from the command line.
859    *
860    * @see #setDefaultAssertionStatus(boolean)
861    * @see #setClassAssertionStatus(String, boolean)
862    * @see #setPackageAssertionStatus(String, boolean)
863    * @since 1.4
864    */
865   public synchronized void clearAssertionStatus()
866   {
867     defaultAssertionStatus = false;
868     packageAssertionStatus = new HashMap();
869     classAssertionStatus = new HashMap();
870   }
871 }