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 classloader.loadclass(name, initialize). + * @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 null this methods acts the + * same as forName(String) (and uses the system class loader). + * @exception ClassNotFoundException if the class was not + * found by the specified classloader. + * @exception SecurityException if the classloader argument + * is null and the caller does not have the + * RuntimePermission("getClassLoader") + * (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 Package 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 null + * code source and all permissions. + * + * @exception SecurityException if a security manager exists and the caller + * does not have RuntimePermission("getProtectionDomain"). + * + * @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 null. + * + * @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 + * RuntimePermission("getClassLoader"). + * + * @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 java.class.path. + *

+ * 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 RuntimePermission("getClassLoader"). + * + * @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 + * loadClass() after both findLoadedClass() and + * parent.loadClass() couldn't provide the requested class. + *

+ * The default implementation throws a ClassNotFoundException. + * 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: + *

+

+         // 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);
+     
+ *

+ * loadClass() makes sure that the Class + * returned by findClass() will later be returned by + * findLoadedClass() 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 + * getResource() after parent.getResource() + * couldn't provide the requested resource. + *

+ * 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 getResources() after it has called + * parent.getResources(). The results are combined by + * the getResources() method. + *

+ * 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 findResource. + * + * @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. getResource() only offers the first resource (of the + * parent) with a given name. This method lists all resources with the + * same name. + *

+ * The Enumeration is created by first calling getResources() + * on the parent classloader and then calling findResources() + * 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)); } }