// ClassLoader.java - Define policies for loading Java classes.
/* Copyright (C) 1998, 1999 Cygnus Solutions
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.net.URL;
import java.net.URLConnection;
import java.util.Stack;
/**
* The class ClassLoader
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 {
static private ClassLoader system;
private ClassLoader parent;
public ClassLoader getParent ()
{
/* FIXME: security */
return parent;
}
public static native ClassLoader getSystemClassLoader ();
/**
* Creates a ClassLoader
with no parent.
* @exception java.lang.SecurityException if not allowed
*/
protected ClassLoader()
{
this (null);
}
/**
* Creates a ClassLoader
with the given parent.
* The parent may be null
.
* The only thing this
* constructor does, is to call
* checkCreateClassLoader
on the current
* security manager.
* @exception java.lang.SecurityException if not allowed
*/
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, java.lang.LinkageError
{
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)
*
findLoadedClass
.
* parent.loadClass
;
* otherwise findSystemClass
.
* findClass
.
* link
is true, resolveClass
is then
* called. Normally, this need not be overridden; override
* findClass
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, java.lang.LinkageError
{
Class c = findLoadedClass (name);
if (c == null)
{
try {
if (parent != null)
return parent.loadClass (name, link);
else
c = findSystemClass (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;
}
/** Find a class. This should be overridden by subclasses; the
* default implementation throws ClassNotFoundException.
*
* @param name Name of the class to find.
* @return The class found.
* @exception java.lang.ClassNotFoundException
*/
protected Class findClass (String name)
throws ClassNotFoundException
{
throw new ClassNotFoundException ();
}
/**
* 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.
*
* 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
* java.lang.ClassNotFoundException
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 java.lang.ClassNotFoundException, java.lang.LinkageError
{
return defineClass (null, data, off, len);
}
/**
* Defines a class, given the class-data. This is preferable
* over defineClass(byte[],off,len)
since it is more
* secure. If the expected name does not match that of the class
* file, ClassNotFoundException
is thrown. If
* name
denotes the name of an already loaded class, a
* LinkageError
is thrown.
*
* * 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. * @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) throws java.lang.ClassNotFoundException, java.lang.LinkageError { 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"); 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); } catch (java.lang.LinkageError x) { throw x; // rethrow } catch (java.lang.ClassNotFoundException 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) throws java.lang.ClassNotFoundException, java.lang.LinkageError; /** This is called by defineClass0, once the "raw" and uninitialized * class object has been created, and handles exceptions generated * while actually defining the class (_Jv_DefineClass). defineClass0 * holds the lock on the new class object, so it needs to capture * these exceptions. */ private static Throwable defineClass1 (Class klass, byte[] data, int offset, int length) { try { defineClass2 (klass, data, offset, length); } catch (Throwable x) { return x; } return null; } /** This is just a wrapper for _Jv_DefineClass */ private static native void defineClass2 (Class klass, byte[] data, int offset, int length) throws Throwable; /** * Link the given class. This will bring the class to a state where * the class initializer can be run. Linking involves the following * steps: *
gcj
-compiled classes, only the first step is
* performed. The compiler will have done the rest already.
* * This is called by the system automatically, * as part of class initialization; there is no reason to ever call * this method directly. *
* 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)
throws java.lang.LinkageError
{
resolveClass0(clazz);
}
static void resolveClass0(Class clazz)
throws java.lang.LinkageError
{
synchronized (clazz)
{
try {
linkClass0 (clazz);
} catch (Throwable x) {
markClassErrorState0 (clazz);
if (x instanceof Error)
throw (Error)x;
else
throw new java.lang.InternalError
("unexpected exception during linking: " + x);
}
}
}
/** Internal method. Calls _Jv_PrepareClass and
* _Jv_PrepareCompiledClass. This is only called from resolveClass. */
private static native void linkClass0(Class clazz)
throws java.lang.LinkageError;
/** 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);
/**
* Returns a class found in a system-specific way, typically
* via the java.class.path
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 Class findSystemClass(String name)
throws java.lang.ClassNotFoundException, java.lang.LinkageError
{
return getSystemClassLoader ().loadClass (name);
}
/*
* Does currently nothing.
*/
protected final void setSigners(Class claz, Object[] signers) {
/* claz.setSigners (signers); */
}
/**
* If a class named name
was previously loaded using
* this ClassLoader
, then it is returned. Otherwise
* it returns null
. (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 native Class findLoadedClass(String name);
public static final InputStream getSystemResourceAsStream(String name) {
return getSystemClassLoader().getResourceAsStream (name);
}
public static final URL getSystemResource(String name) {
return getSystemClassLoader().getResource (name);
}
/**
* Return an InputStream representing the resource name.
* This is essentially like
* getResource(name).openStream()
, 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 name
.
* The default implementation just returns null
.
* @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) {
return null;
}
}