home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1998 February
/
VPR9802A.ISO
/
APP_DEMO
/
VC
/
MAIN.BIN
/
ClassLoader.java
< prev
next >
Wrap
Text File
|
1997-10-27
|
16KB
|
418 lines
/*
* @(#)ClassLoader.java 1.56 97/02/10
*
* Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
* CopyrightVersion 1.1_beta
*
*/
package java.lang;
import java.io.InputStream;
import java.util.Hashtable;
/**
* The class <code>ClassLoader</code> is an abstract class.
* Applications implement subclasses of <code>ClassLoader</code> in
* order to extend the manner in which the Java Virtual Machine
* dynamically loads classes.
* <p>
* Normally, the Java Virtual Machine loads classes from the local
* file system in a platform-dependent manner. For example, on UNIX
* systems, the Virtual Machine loads classes from the directory
* defined by the <code>CLASSPATH</code> environment variable.
* <p>
* However, some classes may not originate from a file; they may
* originate from other sources, such as the network, or they could
* be constructed by an application. The method
* <code>defineClass</code> converts an array of bytes into an
* instance of class <code>Class</code>. Instances of this newly
* defined class can be created using the <code>newInstance</code>
* method in class <code>Class</code>.
* <p>
* The methods and constructors of objects created by a class loader
* may reference other classes. To determine the class(es) referred
* to, the Java Virtual Machine calls the <code>loadClass</code>
* method of the class loader that originally created the class. If
* the Java Virtual Machine only needs to determine if the class
* exists and if it does exist to know its superclass, the
* <code>resolve</code> flag is set to <code>false</code>. However,
* if an instance of the class is being created or any of its methods
* are being called, the class must also be resolved. In this case
* the <code>resolve</code> flag is set to <code>true</code>, and the
* <code>resolveClass</code> method should be called.
* <p>
* For example, an application could create a network class loader
* to download class files from a server. Sample code might look like:
* <ul><code>
* ClassLoader loader = new NetworkClassLoader(host, port);<br>
* Object main = loader.loadClass("Main", true).newInstance();<br>
* . . .
* </code></ul>
* <p>
* The network class loader subclass must define the method
* <code>loadClass</code> to load a class from the network. Once it
* has downloaded the bytes that make up the class, it should use the
* method <code>defineClass</code> to create a class instance. A
* sample implementation is:
* <p><hr><blockquote><pre>
* class NetworkClassLoader {
* String host;
* int port;
* Hashtable cache = new Hashtable();
* private byte loadClassData(String name)[] {
* // load the class data from the connection
* . . .
* }
*
* public synchronized Class loadClass(String name,
* boolean resolve) {
* Class c = cache.get(name);
* if (c == null) {
* byte data[] = loadClassData(name);
* c = defineClass(data, 0, data.length);
* cache.put(name, c);
* }
* if (resolve)
* resolveClass(c);
* return c;
* }
* }
* </pre></blockquote><hr>
*
* @author Arthur van Hoff
* @version 1.56, 02/10/97
* @see java.lang.Class
* @see java.lang.Class#newInstance()
* @see java.lang.ClassLoader#defineClass(byte[], int, int)
* @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
* @see java.lang.ClassLoader#resolveClass(java.lang.Class)
* @since JDK1.0
*/
public abstract class ClassLoader {
/**
* If initialization succeed this is set to true and security checks will
* succeed. Otherwise the object is not initialized and the object is
* useless.
*/
private boolean initialized = false;
/**
* This is a mapping of all String => Class done by this classloader.
* Each Class in the table will either have a null class loader, or
* "this" as its classloader
*/
private Hashtable classes = new Hashtable();
/**
* Constructs a new class loader and initializes it.
* <p>
* If there is a security manager, its
* <code>checkCreateClassLoader</code> method is called. This may
* result in a security exception.
*
* @exception SecurityException if the current thread does not have
* permission to create a new class loader.
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkCreateClassLoader()
* @since JDK1.0
*/
protected ClassLoader() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
init();
initialized = true;
}
/**
* Requests the class loader to load a class with the specified
* name. The <code>loadClass</code> method is called by the Java
* Virtual Machine when a class loaded by a class loader first
* references another class. Every subclass of class
* <code>ClassLoader</code> must define this method.
* <p>
* If the <code>resolve</code> flag is true, the method should call
* the <code>resolveClass</code> method on the resulting class object.
* <p>
* Class loaders should use a hashtable or other cache to avoid
* defining classes with the same name multiple times.
*
* @param name the name of the desired <code>Class</code>.
* @param resolve <code>true</code> if the <code>Class</code>
* must be resolved.
* @return the resulting <code>Class</code>, or <code>null</code>
* if it was not found.
* @exception ClassNotFoundException if the class loader cannot find
* a definition for the class.
* @since JDK1.0
*/
public Class loadClass(String name) throws ClassNotFoundException
{
return loadClass(name, true);
}
/**
* Resolves the specified name to a Class. The method loadClass() is
* called by the virtual machine.
* As an abstract method, loadClass() must be defined in a subclass of
* ClassLoader. By using a Hashtable, you can avoid loading the same
* Class more than once.
*
* @param name the name of the desired Class.
* @param resolve true if the Class needs to be resolved.
* @return the resulting Class, or null if it was not found.
* @exception ClassNotFoundException if the class loader cannot find
* a definition for the class.
* @see java.util.Hashtable
* @since JDK1.1
*/
protected abstract Class loadClass(String name, boolean resolve)
throws ClassNotFoundException;
/**
* Converts an array of bytes into an instance of class
* <code>Class</code>.
* Before the Class can be used it must be resolved. This
* method is deprecated in favor of the version that takes a
* "name" as a first argument, and is more secure.
*
* @param data the bytes that make up the <code>Class</code>.
* @param offset the start offset of the <code>Class</code> data.
* @param length the length of the <code>Class</code> data.
* @return the <code>Class</code> object that was created from the data.
* @exception ClassFormatError if the data does not contain a valid Class.
* @see ClassLoader#loadClass(java.lang.String, boolean)
* @see ClassLoader#resolveClass(java.lang.Class)
* @since JDK1.0
* @deprecated Replaced by defineClass(java.lang.String, byte[], int, int).
*/
protected final Class defineClass(byte data[], int offset, int length) {
return defineClass(null, data, offset, length);
}
/**
* Converts an array of bytes to an instance of class
* Class. Before the Class can be used it must be resolved.
*
* @param name the expected name of the class; null if unknown;
* using '.' and not '/' as separator, and without
* a trailing ".class" suffix.
* @param data the bytes that make up the <code>Class</code>.
* @param offset the start offset of the <code>Class</code> data.
* @param length the length of the <code>Class</code> data.
* @return the <code>Class</code> object that was created from the data.
* @exception ClassFormatError if the data does not contain a valid Class.
* @see ClassLoader#loadClass(java.lang.String, boolean)
* @see ClassLoader#resolveClass(java.lang.Class)
* @since JDK1.1
*/
protected final Class defineClass(String name,
byte data[], int offset, int length) {
check();
Class result = defineClass0(name, data, offset, length);
if (result != null)
classes.put(result.getName(), result);
return result;
}
/**
* Resolves the class so that an instance of the class can be
* created, or so that one of its methods can be called. This method
* should be called by <code>loadClass</code> if the resolve flag is
* <code>true</code>.
*
* @param c the <code>Class</code> instance to be resolved.
* @see java.lang.ClassLoader#defineClass(java.lang.String, byte[], int, int)
* @since JDK1.0
*/
protected final void resolveClass(Class c) {
check();
resolveClass0(c);
}
/**
* Finds the system class with the specified name, loading it in if
* necessary.
* <p>
* A system class is a class loaded from the local file system in a
* platform- dependent way. It has no class loader.
*
* @param name the name of the system <code>class</code>.
* @return a system class with the given name.
* @exception ClassNotFoundException if it could not find a definition
* for the class.
* @exception NoClassDefFoundError if the class is not found.
* @since JDK1.0
*/
protected final Class findSystemClass(String name)
throws ClassNotFoundException {
check();
return findSystemClass0(name);
}
/**
* Sets the signers of a class. This is called after defining a class,
* by signature-aware class loading code.
*
* @since JDK1.1
*/
protected final void setSigners(Class cl, Object[] signers) {
check();
// make a check which will take cl.getClassLoader and
// check if it is != this.
cl.setSigners(signers);
}
/**
* Initializes the Class loader.
*/
private native void init();
private native Class defineClass0(String name,
byte data[], int offset, int length);
private native void resolveClass0(Class c);
private native Class findSystemClass0(String name)
throws ClassNotFoundException;
private void check() {
if (initialized == true)
return;
throw new SecurityException("ClassLoader object not initialized.");
}
/**
* @since JDK1.1
*/
final protected Class findLoadedClass(String name) {
return (Class)classes.get(name);
}
/**
* Load and resolve a class.
*/
final Class loadClassInternal(String name, boolean resolve)
throws ClassNotFoundException {
name = name.replace('/', '.');
Class cl = (Class)classes.get(name);
if (cl == null) {
cl = loadClass(name, false);
if (cl == null)
throw new ClassNotFoundException(name);
String realName = cl.getName();
if (!realName.equals(name)) {
throw new ClassNotFoundException(name);
}
classes.put(realName, cl);
}
if (resolve)
resolveClass(cl);
return cl;
}
/**
* A resource is some data (images, audio, text, etc) that wants to be
* accessed by some class code in a way that is independent of the
* location of the code. Resources are found with cooperation of the
* class loaders, since they are the only ones who know where the class
* actually came from. <p>
*
* System resources are those that are handled by the host implemenation
* directly. For example, they may be located in the CLASSPATH.<p>
*
* The name of a resource is a "/"-separated sequence of identifiers.
* The class Class provides convenience methods for accessing resources;
* the methods implement a convention where the package name is prefixed
* to the short name of the resource.<p>
*
* Resources can be accessed as an InputStream, or as a URL.
*
* @see Class
*/
/**
* Get an InputStream on a given resource.. Will return null if no
* resource with this name is found. <p>
*
* The resource name may be any system resource (e.g. follows CLASSPATH
* order).
*
* @param name the name of the resource, to be used as is.
* @return an InputStream on the resource, or null if not found.
* @since JDK1.1
*/
public static final InputStream getSystemResourceAsStream(String name) {
// REMIND - This is equivalent to getSystemResource() call plus a openStream()
return getSystemResourceAsStream0(name);
}
/**
* Find a resource with a given name. The return is a URL to the resource
* Doing a getContent() on the URL may return an Image, an AudioClip, or
* an InputStream.<p>
*
* The resource name may be any system resource (e.g. follows CLASSPATH
* order).
*
* @param name the name of the resource, to be used as is.
* @return the URL on the resource, or null if not found.
* @since JDK1.1
*/
public static final java.net.URL getSystemResource(String name) {
String s = getSystemResourceAsName0(name);
java.net.URL back;
try {
back = new java.net.URL(s);
} catch (Exception ex) {
back = null;
}
return back;
}
/**
* Get an InputStream on a given resource. Will return null if no
* resource with this name is found. <p>
*
* The class loader can choose what to do to locate the resource.
*
* @param name the name of the resource, to be used as is.
* @return an InputStream on the resource, or null if not found.
* @since JDK1.1
*/
public InputStream getResourceAsStream(String name) {
return null;
}
/**
* Find a resource with a given name. The return is a URL to the resource.
* Doing a getContent() on the URL may return an Image, an AudioClip,
* or an InputStream.<p>
*
* The class loader can choose what to do to locate the resource.
*
* @param name the name of the resource, to be used as is.
* @return an InputStream on the resource, or null if not found.
* @since JDK1.1
*/
public java.net.URL getResource(String name) {
return null;
}
private static native InputStream getSystemResourceAsStream0(String name);
private static native String getSystemResourceAsName0(String name);
}