Hi,
Here are some more updates to make our classloading more 1.2 compatible.
This is all java code. We do need some native support (and some more
java code). But this is all for today.
2001-01-08 Mark Wielaard <[EMAIL PROTECTED]>
* vm/reference/java/lang/Class.java: 1.2 updates
(forName(String,boolean,ClassLoader)): new method
(getPackage): Ditto
(getProtectionDomain): Ditto
* java/lang/ClassLoader.java: 1.2 updates
(getParent): new method
(getSystemClassLoader): Ditto
(findClass): Ditto
(findResource): Ditto
(findResources): Ditto
(getResources): Ditto
Cheers,
Mark
Index: vm/reference/java/lang/Class.java
===================================================================
RCS file: /cvs/classpath/vm/reference/java/lang/Class.java,v
retrieving revision 1.10
diff -u -u -r1.10 Class.java
--- vm/reference/java/lang/Class.java 1999/12/10 14:42:01 1.10
+++ vm/reference/java/lang/Class.java 2001/01/09 23:20:15
@@ -21,6 +21,7 @@
package java.lang;
import java.lang.reflect.*;
+import java.security.*;
import gnu.java.lang.*;
/**
@@ -50,7 +51,21 @@
public class Class {
private Object[] signers = null;
+ private ProtectionDomain protectionDomain = null;
+ // The unknown protection domain.
+ private final static ProtectionDomain unknownProtectionDomain;
+
+ static {
+ Permissions permissions = new Permissions();
+ permissions.add(new AllPermission());
+ unknownProtectionDomain = new ProtectionDomain(null, permissions);
+ }
+
+ // Permission needed to get the protection domain
+ private final static Permission protectionDomainPermission
+ = new RuntimePermission("getProtectionDomain");
+
private Class() {
}
@@ -146,6 +161,47 @@
*/
public static native Class forName(String name) throws ClassNotFoundException;
+ /**
+ * Use the specified classloader to load and link a class.
+ * Calls <code>classloader.loadclass(name, initialize)</code>.
+ * @param name the name of the class to find.
+ * @param initialize wether or not to initialize the class.
+ * This is only a hint for optimization. Set this to false if the class
+ * will not (immediatly) be used to initialize objects.
+ * @param classloader the classloader to use to find the class.
+ * When classloader is <code>null</code> this methods acts the
+ * same as <code>forName(String)</code> (and uses the system class loader).
+ * @exception ClassNotFoundException if the class was not
+ * found by the specified classloader.
+ * @exception SecurityException if the <code>classloader</code> argument
+ * is <code>null</code> and the caller does not have the
+ * <code>RuntimePermission("getClassLoader")</code>
+ * (to get the system classloader) and was not loaded by the
+ * system classloader (or bootstrap classloader).
+ * @since 1.2
+ */
+ public static Class forName(String name,
+ boolean initialize,
+ ClassLoader classloader)
+ throws ClassNotFoundException
+ {
+ if (classloader == null) {
+ // Check if we may get the system classloader
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ // Get the calling class and classloader
+ Class c = VMSecurityManager.getClassContext()[1];
+ ClassLoader cl = c.getClassLoader();
+ if (cl != null && cl != ClassLoader.systemClassLoader)
+ sm.checkPermission
+ (new RuntimePermission("getClassLoader"));
+ }
+ classloader = ClassLoader.systemClassLoader;
+ }
+
+ return classloader.loadClass(name, initialize);
+ }
+
/**
* Discover whether an Object is an instance of this
* Class. Think of it as almost like
@@ -440,6 +496,44 @@
* non-public members of this class.
*/
public native Field[] getDeclaredFields() throws SecurityException;
+
+ /**
+ * Returns the <code>Package</code> in which this class is defined
+ * Returns null when this information is not available from the
+ * classloader of this class or when the classloader of this class
+ * is null.
+ *
+ * @since 1.2
+ */
+ public Package getPackage() {
+ ClassLoader cl = getClassLoader();
+ if (cl != null)
+ return cl.getPackage(ClassHelper.getPackagePortion(getName()));
+ else
+ return null;
+ }
+
+ /**
+ * Returns the protection domain of this class. If the classloader
+ * did not record the protection domain when creating this class
+ * the unknown protection domain is returned which has a <code>null</code>
+ * code source and all permissions.
+ *
+ * @exception SecurityException if a security manager exists and the caller
+ * does not have <code>RuntimePermission("getProtectionDomain")</code>.
+ *
+ * @since 1.2
+ */
+ public ProtectionDomain getProtectionDomain() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(protectionDomainPermission);
+
+ if (protectionDomain == null)
+ return unknownProtectionDomain;
+ else
+ return protectionDomain;
+ }
}
Index: java/lang/ClassLoader.java
===================================================================
RCS file: /cvs/classpath/java/lang/ClassLoader.java,v
retrieving revision 1.9
diff -u -u -r1.9 ClassLoader.java
--- java/lang/ClassLoader.java 2001/01/08 23:10:32 1.9
+++ java/lang/ClassLoader.java 2001/01/09 23:20:15
@@ -32,6 +32,8 @@
import java.io.*;
import java.net.*;
import java.util.*;
+import gnu.java.util.DoubleEnumeration;
+import gnu.java.util.EmptyEnumeration;
/**
** The ClassLoader is a way of customizing the way Java
@@ -41,6 +43,8 @@
** determining where to get the classfiles and when to
** load and resolve them.
**
+ ** XXX - Not all support has been written for the new 1.2 methods yet!
+ **
** @author John Keiser
** @version 1.1.0, Aug 6 1998
** @since JDK1.0
@@ -344,6 +348,171 @@
allPackages = packages;
return allPackages;
+ }
+
+ /**
+ * Returns the parent of this classloader.
+ * If the parent of this classloader is the bootstrap classloader then
+ * this method returns <code>null</code>.
+ *
+ * @exception SecurityException thrown when the classloader of the calling
+ * class is not the bootstrap (null) or the current classloader and the
+ * caller also doesn't have the
+ * <code>RuntimePermission("getClassLoader")</code>.
+ *
+ * @since 1.2
+ */
+ public final ClassLoader getParent() {
+ // Check if we may return the parent classloader
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ Class c = VMSecurityManager.getClassContext()[1];
+ ClassLoader cl = c.getClassLoader();
+ if (cl != null && cl != this)
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ }
+ 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>.
+ * <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).
+ *
+ * @exception SecurityException thrown when the classloader of the calling
+ * class is not the bootstrap (null) or system classloader and the caller
+ * also doesn't have the <code>RuntimePermission("getClassLoader")</code>.
+ *
+ * @since 1.2
+ */
+ public static ClassLoader getSystemClassLoader() {
+ // Check if we may return the system classloader
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ Class c = VMSecurityManager.getClassContext()[1];
+ ClassLoader cl = c.getClassLoader();
+ if (cl != null && cl != systemClassLoader)
+ sm.checkPermission(new RuntimePermission("getClassLoader"));
+ }
+ return systemClassLoader;
+ }
+
+ /**
+ * 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:
+ * <p>
+ <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
+ * @exception ClassNotFoundException when the class can not be found
+ *
+ * @since 1.2
+ */
+ protected Class findClass(String name) throws ClassNotFoundException {
+ throw new ClassNotFoundException(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) {
+ return null;
+ }
+
+ /**
+ * 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.
+ *
+ * @since 1.2
+ */
+ protected Enumeration findResources(String name) throws IOException {
+ return EmptyEnumeration.getInstance();
+ }
+
+ /**
+ * 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.
+ * <p>
+ * The Enumeration is created by first calling <code>getResources()</code>
+ * on the parent classloader and then calling <code>findResources()</code>
+ * on this classloader.
+ *
+ * @since 1.2
+ */
+ public final Enumeration getResources(String name) throws IOException {
+ Enumeration parentResources;
+ if (parent == null)
+ // XXX - Should use the bootstrap classloader
+ parentResources = EmptyEnumeration.getInstance();
+ else
+ parentResources = parent.getResources(name);
+
+ return new DoubleEnumeration(parentResources, findResources(name));
}
}