mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			872 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			872 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
// ClassLoader.java - Define policies for loading Java classes.
 | 
						|
 | 
						|
/* Copyright (C) 1998, 1999, 2000, 2001, 2002  Free Software Foundation
 | 
						|
 | 
						|
   This file is part of libgcj.
 | 
						|
 | 
						|
This software is copyrighted work licensed under the terms of the
 | 
						|
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 | 
						|
details.  */
 | 
						|
 | 
						|
package java.lang;
 | 
						|
 | 
						|
import java.io.InputStream;
 | 
						|
import java.io.IOException;
 | 
						|
import java.net.URL;
 | 
						|
import java.net.URLConnection;
 | 
						|
import java.security.AllPermission;
 | 
						|
import java.security.CodeSource;
 | 
						|
import java.security.Permission;
 | 
						|
import java.security.Permissions;
 | 
						|
import java.security.Policy;
 | 
						|
import java.security.ProtectionDomain;
 | 
						|
import java.util.*;
 | 
						|
 | 
						|
/**
 | 
						|
 * The class <code>ClassLoader</code> is intended to be subclassed by
 | 
						|
 * applications in order to describe new ways of loading classes,
 | 
						|
 * such as over the network.
 | 
						|
 *
 | 
						|
 * @author  Kresten Krab Thorup
 | 
						|
 */
 | 
						|
 | 
						|
public abstract class ClassLoader
 | 
						|
{
 | 
						|
  /**
 | 
						|
   * The desired assertion status of classes loaded by this loader, if not
 | 
						|
   * overridden by package or class instructions.
 | 
						|
   */
 | 
						|
  // Package visible for use by Class.
 | 
						|
  boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus();
 | 
						|
 | 
						|
  /**
 | 
						|
   * The command-line state of the package assertion status overrides. This
 | 
						|
   * map is never modified, so it does not need to be synchronized.
 | 
						|
   */
 | 
						|
  // Package visible for use by Class.
 | 
						|
  static final Map systemPackageAssertionStatus
 | 
						|
    = VMClassLoader.packageAssertionStatus();
 | 
						|
 | 
						|
  /**
 | 
						|
   * The map of package assertion status overrides, or null if no package
 | 
						|
   * overrides have been specified yet. The values of the map should be
 | 
						|
   * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented
 | 
						|
   * by the null key. This map must be synchronized on this instance.
 | 
						|
   */
 | 
						|
  // Package visible for use by Class.
 | 
						|
  Map packageAssertionStatus;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The command-line state of the class assertion status overrides. This
 | 
						|
   * map is never modified, so it does not need to be synchronized.
 | 
						|
   */
 | 
						|
  // Package visible for use by Class.
 | 
						|
  static final Map systemClassAssertionStatus
 | 
						|
    = VMClassLoader.classAssertionStatus();
 | 
						|
 | 
						|
  /**
 | 
						|
   * The map of class assertion status overrides, or null if no class
 | 
						|
   * overrides have been specified yet. The values of the map should be
 | 
						|
   * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this
 | 
						|
   * instance.
 | 
						|
   */
 | 
						|
  // Package visible for use by Class.
 | 
						|
  Map classAssertionStatus;
 | 
						|
 | 
						|
  private ClassLoader parent;
 | 
						|
  private HashMap definedPackages = new HashMap();
 | 
						|
 | 
						|
  public final ClassLoader getParent ()
 | 
						|
  {
 | 
						|
    /* FIXME: security */
 | 
						|
    return parent;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the system classloader. The system classloader (also called
 | 
						|
   * the application classloader) is the classloader that was used to
 | 
						|
   * load the application classes on the classpath (given by the system
 | 
						|
   * property <code>java.class.path</code>. This is set as the context
 | 
						|
   * class loader for a thread. The system property
 | 
						|
   * <code>java.system.class.loader</code>, if defined, is taken to be the
 | 
						|
   * name of the class to use as the system class loader, which must have
 | 
						|
   * a public constructor which takes a ClassLoader as a parent; otherwise this
 | 
						|
   * uses gnu.java.lang.SystemClassLoader.
 | 
						|
   *
 | 
						|
   * <p>Note that this is different from the bootstrap classloader that
 | 
						|
   * actually loads all the real "system" classes (the bootstrap classloader
 | 
						|
   * is the parent of the returned system classloader).
 | 
						|
   *
 | 
						|
   * <p>A security check will be performed for
 | 
						|
   * <code>RuntimePermission("getClassLoader")</code> if the calling class
 | 
						|
   * is not a parent of the system class loader.
 | 
						|
   *
 | 
						|
   * @return the system class loader
 | 
						|
   * @throws SecurityException if the security check fails
 | 
						|
   * @throws IllegalStateException if this is called recursively
 | 
						|
   * @throws Error if <code>java.system.class.loader</code> fails to load
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  public static ClassLoader getSystemClassLoader ()
 | 
						|
  {
 | 
						|
    return gnu.gcj.runtime.VMClassLoader.instance;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a <code>ClassLoader</code> with no parent.
 | 
						|
   * @exception java.lang.SecurityException if not allowed
 | 
						|
   */
 | 
						|
  protected ClassLoader() 
 | 
						|
  {
 | 
						|
    this (null);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a <code>ClassLoader</code> with the given parent.   
 | 
						|
   * The parent may be <code>null</code>.
 | 
						|
   * The only thing this 
 | 
						|
   * constructor does, is to call
 | 
						|
   * <code>checkCreateClassLoader</code> on the current 
 | 
						|
   * security manager. 
 | 
						|
   * @exception java.lang.SecurityException if not allowed
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  protected ClassLoader(ClassLoader parent) 
 | 
						|
  {
 | 
						|
    SecurityManager security = System.getSecurityManager ();
 | 
						|
    if (security != null)
 | 
						|
      security.checkCreateClassLoader ();
 | 
						|
    this.parent = parent;
 | 
						|
  }
 | 
						|
 | 
						|
  /** 
 | 
						|
   * Loads and link the class by the given name.
 | 
						|
   * @param     name the name of the class.
 | 
						|
   * @return    the class loaded.
 | 
						|
   * @see       ClassLoader#loadClass(String,boolean)
 | 
						|
   * @exception java.lang.ClassNotFoundException 
 | 
						|
   */ 
 | 
						|
  public Class loadClass(String name)
 | 
						|
    throws java.lang.ClassNotFoundException
 | 
						|
  { 
 | 
						|
    return loadClass (name, false);
 | 
						|
  }
 | 
						|
  
 | 
						|
  /** 
 | 
						|
   * Loads the class by the given name.  The default implementation
 | 
						|
   * will search for the class in the following order (similar to jdk 1.2)
 | 
						|
   * <ul>
 | 
						|
   *  <li> First <code>findLoadedClass</code>.
 | 
						|
   *  <li> If parent is non-null, <code>parent.loadClass</code>;
 | 
						|
   *       otherwise <code>findSystemClass</code>.
 | 
						|
   *  <li> <code>findClass</code>.
 | 
						|
   * </ul>
 | 
						|
   * If <code>link</code> is true, <code>resolveClass</code> is then
 | 
						|
   * called.  <p> Normally, this need not be overridden; override
 | 
						|
   * <code>findClass</code> instead.
 | 
						|
   * @param     name the name of the class.
 | 
						|
   * @param     link if the class should be linked.
 | 
						|
   * @return    the class loaded.
 | 
						|
   * @exception java.lang.ClassNotFoundException 
 | 
						|
   * @deprecated 
 | 
						|
   */ 
 | 
						|
  protected Class loadClass(String name, boolean link)
 | 
						|
    throws java.lang.ClassNotFoundException
 | 
						|
  {
 | 
						|
    Class c = findLoadedClass (name);
 | 
						|
 | 
						|
    if (c == null)
 | 
						|
      {
 | 
						|
	try {
 | 
						|
	  if (parent != null)
 | 
						|
	    return parent.loadClass (name, link);
 | 
						|
	  else
 | 
						|
	    c = gnu.gcj.runtime.VMClassLoader.instance.findClass (name);
 | 
						|
	} catch (ClassNotFoundException ex) {
 | 
						|
	  /* ignore, we'll try findClass */;
 | 
						|
	}
 | 
						|
      }
 | 
						|
 | 
						|
    if (c == null)
 | 
						|
      c = findClass (name);
 | 
						|
 | 
						|
    if (c == null)
 | 
						|
      throw new ClassNotFoundException (name);
 | 
						|
 | 
						|
    if (link)
 | 
						|
      resolveClass (c);
 | 
						|
 | 
						|
    return c;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Called for every class name that is needed but has not yet been
 | 
						|
   * defined by this classloader or one of its parents. It is called by
 | 
						|
   * <code>loadClass()</code> after both <code>findLoadedClass()</code> and
 | 
						|
   * <code>parent.loadClass()</code> couldn't provide the requested class.
 | 
						|
   *
 | 
						|
   * <p>The default implementation throws a
 | 
						|
   * <code>ClassNotFoundException</code>. Subclasses should override this
 | 
						|
   * method. An implementation of this method in a subclass should get the
 | 
						|
   * class bytes of the class (if it can find them), if the package of the
 | 
						|
   * requested class doesn't exist it should define the package and finally
 | 
						|
   * it should call define the actual class. It does not have to resolve the
 | 
						|
   * class. It should look something like the following:<br>
 | 
						|
   *
 | 
						|
   * <pre>
 | 
						|
   * // Get the bytes that describe the requested class
 | 
						|
   * byte[] classBytes = classLoaderSpecificWayToFindClassBytes(name);
 | 
						|
   * // Get the package name
 | 
						|
   * int lastDot = name.lastIndexOf('.');
 | 
						|
   * if (lastDot != -1)
 | 
						|
   *   {
 | 
						|
   *     String packageName = name.substring(0, lastDot);
 | 
						|
   *     // Look if the package already exists
 | 
						|
   *     if (getPackage(pkg) == null)
 | 
						|
   *       {
 | 
						|
   *         // define the package
 | 
						|
   *         definePackage(packageName, ...);
 | 
						|
   *       }
 | 
						|
   *   }
 | 
						|
   * // Define and return the class
 | 
						|
   *  return defineClass(name, classBytes, 0, classBytes.length);
 | 
						|
   * </pre>
 | 
						|
   *
 | 
						|
   * <p><code>loadClass()</code> makes sure that the <code>Class</code>
 | 
						|
   * returned by <code>findClass()</code> will later be returned by
 | 
						|
   * <code>findLoadedClass()</code> when the same class name is requested.
 | 
						|
   *
 | 
						|
   * @param name class name to find (including the package name)
 | 
						|
   * @return the requested Class
 | 
						|
   * @throws ClassNotFoundException when the class can not be found
 | 
						|
   * @since 1.2
 | 
						|
   */   
 | 
						|
  protected Class findClass (String name)
 | 
						|
    throws ClassNotFoundException
 | 
						|
  {
 | 
						|
    throw new ClassNotFoundException (name);
 | 
						|
  }
 | 
						|
 | 
						|
  // Protection Domain definitions 
 | 
						|
  // FIXME: should there be a special protection domain used for native code?
 | 
						|
  
 | 
						|
  // The permission required to check what a classes protection domain is.
 | 
						|
  static final Permission protectionDomainPermission
 | 
						|
    = new RuntimePermission("getProtectionDomain");
 | 
						|
  // The protection domain returned if we cannot determine it. 
 | 
						|
  static ProtectionDomain unknownProtectionDomain;
 | 
						|
  // Protection domain to use when a class is defined without one specified.
 | 
						|
  static ProtectionDomain defaultProtectionDomain;
 | 
						|
 | 
						|
  static
 | 
						|
  {
 | 
						|
    Permissions permissions = new Permissions();
 | 
						|
    permissions.add(new AllPermission());
 | 
						|
    unknownProtectionDomain = new ProtectionDomain(null, permissions);  
 | 
						|
 | 
						|
    CodeSource cs = new CodeSource(null, null);
 | 
						|
    defaultProtectionDomain =
 | 
						|
      new ProtectionDomain(cs, Policy.getPolicy().getPermissions(cs));
 | 
						|
  }
 | 
						|
 | 
						|
  /** 
 | 
						|
   * Defines a class, given the class-data.  According to the JVM, this
 | 
						|
   * method should not be used; instead use the variant of this method
 | 
						|
   * in which the name of the class being defined is specified
 | 
						|
   * explicitly.   
 | 
						|
   * <P>
 | 
						|
   * If the name of the class, as specified (implicitly) in the class
 | 
						|
   * data, denotes a class which has already been loaded by this class
 | 
						|
   * loader, an instance of
 | 
						|
   * <code>java.lang.ClassNotFoundException</code> will be thrown.
 | 
						|
   *
 | 
						|
   * @param     data    bytes in class file format.
 | 
						|
   * @param     off     offset to start interpreting data.
 | 
						|
   * @param     len     length of data in class file.
 | 
						|
   * @return    the class defined.
 | 
						|
   * @exception java.lang.ClassNotFoundException 
 | 
						|
   * @exception java.lang.LinkageError
 | 
						|
   * @see ClassLoader#defineClass(String,byte[],int,int) */
 | 
						|
  protected final Class defineClass(byte[] data, int off, int len) 
 | 
						|
    throws ClassFormatError
 | 
						|
  {
 | 
						|
    return defineClass (null, data, off, len, defaultProtectionDomain);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Helper to define a class using a string of bytes without a
 | 
						|
   * ProtectionDomain. Subclasses should call this method from their
 | 
						|
   * <code>findClass()</code> implementation. The name should use '.'
 | 
						|
   * separators, and discard the trailing ".class".  The default protection
 | 
						|
   * domain has the permissions of
 | 
						|
   * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))<code>.
 | 
						|
   *
 | 
						|
   * @param name the name to give the class, or null if unknown
 | 
						|
   * @param data the data representing the classfile, in classfile format
 | 
						|
   * @param offset the offset into the data where the classfile starts
 | 
						|
   * @param len the length of the classfile data in the array
 | 
						|
   * @return the class that was defined
 | 
						|
   * @throws ClassFormatError if data is not in proper classfile format
 | 
						|
   * @throws IndexOutOfBoundsException if offset or len is negative, or
 | 
						|
   *         offset + len exceeds data
 | 
						|
   * @throws SecurityException if name starts with "java."
 | 
						|
   * @since 1.1
 | 
						|
   */
 | 
						|
  protected final Class defineClass(String name, byte[] data, int off, int len)
 | 
						|
    throws ClassFormatError
 | 
						|
  {
 | 
						|
    return defineClass (name, data, off, len, defaultProtectionDomain);
 | 
						|
  }
 | 
						|
  
 | 
						|
  /** 
 | 
						|
   * Defines a class, given the class-data.  This is preferable
 | 
						|
   * over <code>defineClass(byte[],off,len)</code> since it is more
 | 
						|
   * secure.  If the expected name does not match that of the class
 | 
						|
   * file, <code>ClassNotFoundException</code> is thrown.  If
 | 
						|
   * <code>name</code> denotes the name of an already loaded class, a
 | 
						|
   * <code>LinkageError</code> is thrown.
 | 
						|
   * <p>
 | 
						|
   * 
 | 
						|
   * FIXME: How do we assure that the class-file data is not being
 | 
						|
   * modified, simultaneously with the class loader running!?  If this
 | 
						|
   * was done in some very clever way, it might break security.  
 | 
						|
   * Right now I am thinking that defineclass should make sure never to
 | 
						|
   * read an element of this array more than once, and that that would
 | 
						|
   * assure the ``immutable'' appearance.  It is still to be determined
 | 
						|
   * if this is in fact how defineClass operates.
 | 
						|
   *
 | 
						|
   * @param     name    the expected name.
 | 
						|
   * @param     data    bytes in class file format.
 | 
						|
   * @param     off     offset to start interpreting data.
 | 
						|
   * @param     len     length of data in class file.
 | 
						|
   * @param     protectionDomain security protection domain for the class.
 | 
						|
   * @return    the class defined.
 | 
						|
   * @exception java.lang.ClassNotFoundException 
 | 
						|
   * @exception java.lang.LinkageError
 | 
						|
   */
 | 
						|
  protected final synchronized Class defineClass(String name,
 | 
						|
						 byte[] data,
 | 
						|
						 int off,
 | 
						|
						 int len,
 | 
						|
						 ProtectionDomain protectionDomain)
 | 
						|
    throws ClassFormatError
 | 
						|
  {
 | 
						|
    if (data==null || data.length < off+len || off<0 || len<0)
 | 
						|
      throw new ClassFormatError ("arguments to defineClass "
 | 
						|
				  + "are meaningless");
 | 
						|
 | 
						|
    // as per 5.3.5.1
 | 
						|
    if (name != null  &&  findLoadedClass (name) != null)
 | 
						|
      throw new java.lang.LinkageError ("class " 
 | 
						|
					+ name 
 | 
						|
					+ " already loaded");
 | 
						|
    
 | 
						|
    if (protectionDomain == null)
 | 
						|
      protectionDomain = defaultProtectionDomain;
 | 
						|
 | 
						|
    try {
 | 
						|
      // Since we're calling into native code here, 
 | 
						|
      // we better make sure that any generated
 | 
						|
      // exception is to spec!
 | 
						|
 | 
						|
      return defineClass0 (name, data, off, len, protectionDomain);
 | 
						|
 | 
						|
    } catch (LinkageError x) {
 | 
						|
      throw x;		// rethrow
 | 
						|
 | 
						|
    } catch (java.lang.VirtualMachineError x) {
 | 
						|
      throw x;		// rethrow
 | 
						|
 | 
						|
    } catch (java.lang.Throwable x) {
 | 
						|
      // This should never happen, or we are beyond spec.  
 | 
						|
      
 | 
						|
      throw new InternalError ("Unexpected exception "
 | 
						|
			       + "while defining class "
 | 
						|
			       + name + ": " 
 | 
						|
			       + x.toString ());
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /** This is the entry point of defineClass into the native code */
 | 
						|
  private native Class defineClass0 (String name,
 | 
						|
				     byte[] data,
 | 
						|
				     int off,
 | 
						|
				     int len,
 | 
						|
				     ProtectionDomain protectionDomain)
 | 
						|
    throws ClassFormatError;
 | 
						|
 | 
						|
  /** 
 | 
						|
   * Link the given class.  This will bring the class to a state where
 | 
						|
   * the class initializer can be run.  Linking involves the following
 | 
						|
   * steps: 
 | 
						|
   * <UL>
 | 
						|
   * <LI>  Prepare (allocate and internalize) the constant strings that
 | 
						|
   *       are used in this class.
 | 
						|
   * <LI>  Allocate storage for static fields, and define the layout
 | 
						|
   *       of instance fields.
 | 
						|
   * <LI>  Perform static initialization of ``static final'' int,
 | 
						|
   *       long, float, double and String fields for which there is a
 | 
						|
   *       compile-time constant initializer.
 | 
						|
   * <LI>  Create the internal representation of the ``vtable''.
 | 
						|
   * </UL>
 | 
						|
   * For <code>gcj</code>-compiled classes, only the first step is
 | 
						|
   * performed.  The compiler will have done the rest already.
 | 
						|
   * <P>
 | 
						|
   * This is called by the system automatically,
 | 
						|
   * as part of class initialization; there is no reason to ever call
 | 
						|
   * this method directly.  
 | 
						|
   * <P> 
 | 
						|
   * For historical reasons, this method has a name which is easily
 | 
						|
   * misunderstood.  Java classes are never ``resolved''.  Classes are
 | 
						|
   * linked; whereas method and field references are resolved.
 | 
						|
   *
 | 
						|
   * @param     clazz the class to link.
 | 
						|
   * @exception java.lang.LinkageError
 | 
						|
   */
 | 
						|
  protected final void resolveClass(Class clazz)
 | 
						|
  {
 | 
						|
    resolveClass0(clazz);
 | 
						|
  }
 | 
						|
 | 
						|
  static void resolveClass0(Class clazz)
 | 
						|
  {
 | 
						|
    synchronized (clazz)
 | 
						|
      {
 | 
						|
	try
 | 
						|
	  {
 | 
						|
	    linkClass0 (clazz);
 | 
						|
	  }
 | 
						|
	catch (Throwable x)
 | 
						|
	  {
 | 
						|
	    markClassErrorState0 (clazz);
 | 
						|
 | 
						|
	    if (x instanceof Error)
 | 
						|
	      throw (Error)x;
 | 
						|
	    else
 | 
						|
	      {
 | 
						|
		InternalError e
 | 
						|
		  = new InternalError ("unexpected exception during linking");
 | 
						|
		e.initCause (x);
 | 
						|
		throw e;
 | 
						|
	      }
 | 
						|
	  }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /** Internal method.  Calls _Jv_PrepareClass and
 | 
						|
   * _Jv_PrepareCompiledClass.  This is only called from resolveClass.  */ 
 | 
						|
  private static native void linkClass0(Class clazz);
 | 
						|
 | 
						|
  /** Internal method.  Marks the given clazz to be in an erroneous
 | 
						|
   * state, and calls notifyAll() on the class object.  This should only
 | 
						|
   * be called when the caller has the lock on the class object.  */
 | 
						|
  private static native void markClassErrorState0(Class clazz);
 | 
						|
 | 
						|
  /**
 | 
						|
   * Defines a new package and creates a Package object.
 | 
						|
   * The package should be defined before any class in the package is
 | 
						|
   * defined with <code>defineClass()</code>. The package should not yet
 | 
						|
   * be defined before in this classloader or in one of its parents (which
 | 
						|
   * means that <code>getPackage()</code> should return <code>null</code>).
 | 
						|
   * All parameters except the <code>name</code> of the package may be
 | 
						|
   * <code>null</code>.
 | 
						|
   * <p>
 | 
						|
   * Subclasses should call this method from their <code>findClass()</code>
 | 
						|
   * implementation before calling <code>defineClass()</code> on a Class
 | 
						|
   * in a not yet defined Package (which can be checked by calling
 | 
						|
   * <code>getPackage()</code>).
 | 
						|
   *
 | 
						|
   * @param name The name of the Package
 | 
						|
   * @param specTitle The name of the specification
 | 
						|
   * @param specVendor The name of the specification designer
 | 
						|
   * @param specVersion The version of this specification
 | 
						|
   * @param implTitle The name of the implementation
 | 
						|
   * @param implVendor The vendor that wrote this implementation
 | 
						|
   * @param implVersion The version of this implementation
 | 
						|
   * @param sealed If sealed the origin of the package classes
 | 
						|
   * @return the Package object for the specified package
 | 
						|
   *
 | 
						|
   * @exception IllegalArgumentException if the package name is null or if
 | 
						|
   * it was already defined by this classloader or one of its parents.
 | 
						|
   *
 | 
						|
   * @see Package
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  protected Package definePackage(String name,
 | 
						|
				  String specTitle, String specVendor,
 | 
						|
				  String specVersion, String implTitle,
 | 
						|
				  String implVendor, String implVersion,
 | 
						|
				  URL sealed)
 | 
						|
  {
 | 
						|
    if (getPackage(name) != null)
 | 
						|
      throw new IllegalArgumentException("Package " + name
 | 
						|
					 + " already defined");
 | 
						|
    Package p = new Package(name,
 | 
						|
			    specTitle, specVendor, specVersion,
 | 
						|
			    implTitle, implVendor, implVersion,
 | 
						|
			    sealed);
 | 
						|
    synchronized (definedPackages)
 | 
						|
    {
 | 
						|
      definedPackages.put(name, p);
 | 
						|
    }
 | 
						|
    return p;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the Package object for the requested package name. It returns
 | 
						|
   * null when the package is not defined by this classloader or one of its
 | 
						|
   * parents.
 | 
						|
   *
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  protected Package getPackage(String name)
 | 
						|
  {
 | 
						|
    Package p;
 | 
						|
    if (parent == null)
 | 
						|
      // XXX - Should we use the bootstrap classloader?
 | 
						|
      p = null;
 | 
						|
    else
 | 
						|
      p = parent.getPackage(name);
 | 
						|
 | 
						|
    if (p == null)
 | 
						|
      {
 | 
						|
        synchronized (definedPackages)
 | 
						|
	{
 | 
						|
	  p = (Package) definedPackages.get(name);
 | 
						|
	}
 | 
						|
      }
 | 
						|
 | 
						|
    return p;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns all Package objects defined by this classloader and its parents.
 | 
						|
   *
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  protected Package[] getPackages()
 | 
						|
  {
 | 
						|
    Package[] allPackages;
 | 
						|
 | 
						|
    // Get all our packages.
 | 
						|
    Package[] packages;
 | 
						|
    synchronized(definedPackages)
 | 
						|
    {
 | 
						|
      packages = new Package[definedPackages.size()];
 | 
						|
      definedPackages.values().toArray(packages);
 | 
						|
    }
 | 
						|
 | 
						|
    // If we have a parent get all packages defined by our parents.
 | 
						|
    if (parent != null)
 | 
						|
      {
 | 
						|
	Package[] parentPackages = parent.getPackages();
 | 
						|
	allPackages = new Package[parentPackages.length + packages.length];
 | 
						|
	System.arraycopy(parentPackages, 0, allPackages, 0,
 | 
						|
			 parentPackages.length);
 | 
						|
	System.arraycopy(packages, 0, allPackages, parentPackages.length,
 | 
						|
			 packages.length);
 | 
						|
      }
 | 
						|
    else
 | 
						|
      // XXX - Should we use the bootstrap classloader?
 | 
						|
      allPackages = packages;
 | 
						|
 | 
						|
    return allPackages;
 | 
						|
  }
 | 
						|
 | 
						|
  /** 
 | 
						|
   * Returns a class found in a system-specific way, typically
 | 
						|
   * via the <code>java.class.path</code> system property.  Loads the 
 | 
						|
   * class if necessary.
 | 
						|
   *
 | 
						|
   * @param     name the class to resolve.
 | 
						|
   * @return    the class loaded.
 | 
						|
   * @exception java.lang.LinkageError 
 | 
						|
   * @exception java.lang.ClassNotFoundException 
 | 
						|
   */
 | 
						|
  protected final Class findSystemClass(String name) 
 | 
						|
    throws java.lang.ClassNotFoundException
 | 
						|
  {
 | 
						|
    return gnu.gcj.runtime.VMClassLoader.instance.loadClass (name);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Helper to set the signers of a class. This should be called after
 | 
						|
   * defining the class.
 | 
						|
   *
 | 
						|
   * @param c the Class to set signers of
 | 
						|
   * @param signers the signers to set
 | 
						|
   * @since 1.1
 | 
						|
   */   
 | 
						|
  protected final void setSigners(Class c, Object[] signers)
 | 
						|
  {
 | 
						|
    /*
 | 
						|
     * Does currently nothing. FIXME.
 | 
						|
     */ 
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * If a class named <code>name</code> was previously loaded using
 | 
						|
   * this <code>ClassLoader</code>, then it is returned.  Otherwise
 | 
						|
   * it returns <code>null</code>.  (Unlike the JDK this is native,
 | 
						|
   * since we implement the class table internally.)
 | 
						|
   * @param     name  class to find.
 | 
						|
   * @return    the class loaded, or null.
 | 
						|
   */ 
 | 
						|
  protected final native Class findLoadedClass(String name);
 | 
						|
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get a resource using the system classloader.
 | 
						|
   *
 | 
						|
   * @param name the name of the resource relative to the system classloader
 | 
						|
   * @return an input stream for the resource, or null
 | 
						|
   * @since 1.1
 | 
						|
   */
 | 
						|
  public static InputStream getSystemResourceAsStream(String name) {
 | 
						|
    return getSystemClassLoader().getResourceAsStream (name);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the URL to a resource using the system classloader.
 | 
						|
   *
 | 
						|
   * @param name the name of the resource relative to the system classloader
 | 
						|
   * @return the URL to the resource
 | 
						|
   * @since 1.1
 | 
						|
   */
 | 
						|
  public static URL getSystemResource(String name) {
 | 
						|
    return getSystemClassLoader().getResource (name);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get an Enumeration of URLs to resources with a given name using the
 | 
						|
   * the system classloader. The enumeration firsts lists the resources with
 | 
						|
   * the given name that can be found by the bootstrap classloader followed
 | 
						|
   * by the resources with the given name that can be found on the classpath.
 | 
						|
   *
 | 
						|
   * @param name the name of the resource relative to the system classloader
 | 
						|
   * @return an Enumeration of URLs to the resources
 | 
						|
   * @throws IOException if I/O errors occur in the process
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  public static Enumeration getSystemResources(String name) throws IOException
 | 
						|
  {
 | 
						|
    return getSystemClassLoader().getResources(name);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   *   Return an InputStream representing the resource name.  
 | 
						|
   *   This is essentially like 
 | 
						|
   *   <code>getResource(name).openStream()</code>, except
 | 
						|
   *   it masks out any IOException and returns null on failure.
 | 
						|
   * @param   name  resource to load
 | 
						|
   * @return  an InputStream, or null
 | 
						|
   * @see     java.lang.ClassLoader#getResource(String)
 | 
						|
   * @see     java.io.InputStream
 | 
						|
   */
 | 
						|
  public InputStream getResourceAsStream(String name) 
 | 
						|
  {
 | 
						|
    try
 | 
						|
      {
 | 
						|
	URL res = getResource (name);
 | 
						|
	if (res == null)
 | 
						|
          return null;
 | 
						|
	return res.openStream ();
 | 
						|
      }
 | 
						|
    catch (java.io.IOException x)
 | 
						|
      {
 | 
						|
	return null;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 
 | 
						|
  /**
 | 
						|
   * Return an java.io.URL representing the resouce <code>name</code>.  
 | 
						|
   * The default implementation just returns <code>null</code>.
 | 
						|
   * @param   name  resource to load
 | 
						|
   * @return  a URL, or null if there is no such resource.
 | 
						|
   * @see     java.lang.ClassLoader#getResourceAsBytes(String)
 | 
						|
   * @see     java.lang.ClassLoader#getResourceAsStream(String)
 | 
						|
   * @see     java.io.URL
 | 
						|
   */
 | 
						|
  public URL getResource (String name) 
 | 
						|
  {
 | 
						|
    // The rules say search the parent class if non-null,
 | 
						|
    // otherwise search the built-in class loader (assumed to be
 | 
						|
    // the system ClassLoader).  If not found, call
 | 
						|
    // findResource().
 | 
						|
    URL result = null;
 | 
						|
 | 
						|
    ClassLoader delegate = parent;
 | 
						|
 | 
						|
    if (delegate == null)
 | 
						|
      delegate = getSystemClassLoader ();
 | 
						|
	
 | 
						|
    // Protect ourselves from looping.
 | 
						|
    if (this != delegate)
 | 
						|
      result = delegate.getResource (name);
 | 
						|
 | 
						|
    if (result != null)
 | 
						|
      return result;
 | 
						|
    else
 | 
						|
      return findResource (name);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Called whenever a resource is needed that could not be provided by
 | 
						|
   * one of the parents of this classloader. It is called by
 | 
						|
   * <code>getResource()</code> after <code>parent.getResource()</code>
 | 
						|
   * couldn't provide the requested resource.
 | 
						|
   *
 | 
						|
   * <p>The default implementation always returns null. Subclasses should
 | 
						|
   * override this method when they can provide a way to return a URL
 | 
						|
   * to a named resource.
 | 
						|
   *
 | 
						|
   * @param name the name of the resource to be found
 | 
						|
   * @return a URL to the named resource or null when not found
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  protected URL findResource (String name)
 | 
						|
  {
 | 
						|
    // Default to returning null.  Derived classes implement this.
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns an Enumeration of all resources with a given name that can
 | 
						|
   * be found by this classloader and its parents. Certain classloaders
 | 
						|
   * (such as the URLClassLoader when given multiple jar files) can have
 | 
						|
   * multiple resources with the same name that come from multiple locations.
 | 
						|
   * It can also occur that a parent classloader offers a resource with a
 | 
						|
   * certain name and the child classloader also offers a resource with that
 | 
						|
   * same name. <code>getResource() only offers the first resource (of the
 | 
						|
   * parent) with a given name. This method lists all resources with the
 | 
						|
   * same name. The name should use '/' as path separators.
 | 
						|
   *
 | 
						|
   * <p>The Enumeration is created by first calling <code>getResources()</code>
 | 
						|
   * on the parent classloader and then calling <code>findResources()</code>
 | 
						|
   * on this classloader.
 | 
						|
   *
 | 
						|
   * @param name the resource name
 | 
						|
   * @return an enumaration of all resources found
 | 
						|
   * @throws IOException if I/O errors occur in the process
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  public final Enumeration getResources(String name) throws IOException
 | 
						|
  {
 | 
						|
    // The rules say search the parent class if non-null,
 | 
						|
    // otherwise search the built-in class loader (assumed to be
 | 
						|
    // the system ClassLoader).  If not found, call
 | 
						|
    // findResource().
 | 
						|
    Enumeration result = null;
 | 
						|
 | 
						|
    ClassLoader delegate = parent;
 | 
						|
 | 
						|
    if (delegate == null)
 | 
						|
      delegate = getSystemClassLoader ();
 | 
						|
	
 | 
						|
    // Protect ourselves from looping.
 | 
						|
    if (this != delegate)
 | 
						|
      result = delegate.getResources (name);
 | 
						|
 | 
						|
    if (result != null)
 | 
						|
      return result;
 | 
						|
    else
 | 
						|
      return findResources (name);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Called whenever all locations of a named resource are needed.
 | 
						|
   * It is called by <code>getResources()</code> after it has called
 | 
						|
   * <code>parent.getResources()</code>. The results are combined by
 | 
						|
   * the <code>getResources()</code> method.
 | 
						|
   *
 | 
						|
   * <p>The default implementation always returns an empty Enumeration.
 | 
						|
   * Subclasses should override it when they can provide an Enumeration of
 | 
						|
   * URLs (possibly just one element) to the named resource.
 | 
						|
   * The first URL of the Enumeration should be the same as the one
 | 
						|
   * returned by <code>findResource</code>.
 | 
						|
   *
 | 
						|
   * @param name the name of the resource to be found
 | 
						|
   * @return a possibly empty Enumeration of URLs to the named resource
 | 
						|
   * @throws IOException if I/O errors occur in the process
 | 
						|
   * @since 1.2
 | 
						|
   */
 | 
						|
  protected Enumeration findResources(String name) throws IOException
 | 
						|
  {
 | 
						|
    return Collections.enumeration(Collections.EMPTY_LIST);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the default assertion status for classes loaded by this classloader,
 | 
						|
   * used unless overridden by a package or class request.
 | 
						|
   *
 | 
						|
   * @param enabled true to set the default to enabled
 | 
						|
   * @see #setClassAssertionStatus(String, boolean)
 | 
						|
   * @see #setPackageAssertionStatus(String, boolean)
 | 
						|
   * @see #clearAssertionStatus()
 | 
						|
   * @since 1.4
 | 
						|
   */
 | 
						|
  public void setDefaultAssertionStatus(boolean enabled)
 | 
						|
  {
 | 
						|
    defaultAssertionStatus = enabled;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the default assertion status for packages, used unless overridden
 | 
						|
   * by a class request. This default also covers subpackages, unless they
 | 
						|
   * are also specified. The unnamed package should use null for the name.
 | 
						|
   *
 | 
						|
   * @param name the package (and subpackages) to affect
 | 
						|
   * @param enabled true to set the default to enabled
 | 
						|
   * @see #setDefaultAssertionStatus(String, boolean)
 | 
						|
   * @see #setClassAssertionStatus(String, boolean)
 | 
						|
   * @see #clearAssertionStatus()
 | 
						|
   * @since 1.4
 | 
						|
   */
 | 
						|
  public synchronized void setPackageAssertionStatus(String name,
 | 
						|
                                                     boolean enabled)
 | 
						|
  {
 | 
						|
    if (packageAssertionStatus == null)
 | 
						|
      packageAssertionStatus
 | 
						|
        = new HashMap(systemPackageAssertionStatus);
 | 
						|
    packageAssertionStatus.put(name, Boolean.valueOf(enabled));
 | 
						|
  }
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * Set the default assertion status for a class. This only affects the
 | 
						|
   * status of top-level classes, any other string is harmless.
 | 
						|
   *
 | 
						|
   * @param name the class to affect
 | 
						|
   * @param enabled true to set the default to enabled
 | 
						|
   * @throws NullPointerException if name is null
 | 
						|
   * @see #setDefaultAssertionStatus(String, boolean)
 | 
						|
   * @see #setPackageAssertionStatus(String, boolean)
 | 
						|
   * @see #clearAssertionStatus()
 | 
						|
   * @since 1.4
 | 
						|
   */
 | 
						|
  public synchronized void setClassAssertionStatus(String name,
 | 
						|
                                                   boolean enabled)
 | 
						|
  {
 | 
						|
    if (classAssertionStatus == null)
 | 
						|
      classAssertionStatus = new HashMap(systemClassAssertionStatus);
 | 
						|
    // The toString() hack catches null, as required.
 | 
						|
    classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled));
 | 
						|
  }
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * Resets the default assertion status of this classloader, its packages
 | 
						|
   * and classes, all to false. This allows overriding defaults inherited
 | 
						|
   * from the command line.
 | 
						|
   *
 | 
						|
   * @see #setDefaultAssertionStatus(boolean)
 | 
						|
   * @see #setClassAssertionStatus(String, boolean)
 | 
						|
   * @see #setPackageAssertionStatus(String, boolean)
 | 
						|
   * @since 1.4
 | 
						|
   */
 | 
						|
  public synchronized void clearAssertionStatus()
 | 
						|
  {
 | 
						|
    defaultAssertionStatus = false;
 | 
						|
    packageAssertionStatus = new HashMap();
 | 
						|
    classAssertionStatus = new HashMap();
 | 
						|
  }
 | 
						|
}
 |