Hi,

Here are some updates to java.lang.System,Package,ClassLoader.

2001-01-08  Mark Wielaard  <[EMAIL PROTECTED]>
    * java/lang/ClassLoader.java: 1.2 updates
    (definedPackages, parent, systemClassLoader): new private fields
    (ClassLoader): new constructor that takes a parent classloader
    (definePackage, getPackage, getPackages): new protected methods
    * java/lang/Package.java: 1.2 updates
    (Package): change argument order to match ClassLoader.definePackage(),
    throw NullPointerException when name == null
    (getPackage, getPackages): implemented
    * java/lang/Sysem.java: 1.2 updates
    (setProperty): new method
    (runFinalizersOnExit): deprecated

Although there is now a ClassLoader constructor that takes a parent argument
this does not make the classloading 1.2 compatible. I have some ideas and
code for that but it needs native support and I have to think a bit more
about it.

Cheers,

Mark
Index: java/lang/ClassLoader.java
===================================================================
RCS file: /cvs/classpath/java/lang/ClassLoader.java,v
retrieving revision 1.8
diff -u -r1.8 ClassLoader.java
--- java/lang/ClassLoader.java  2000/06/20 21:16:48     1.8
+++ java/lang/ClassLoader.java  2001/01/08 22:53:21
@@ -1,5 +1,5 @@
 /* java.lang.ClassLoader
-   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -50,17 +50,50 @@
        /* Each instance gets a list of these. */
        private Hashtable loadedClasses = new Hashtable();
 
-       /** Create a new ClassLoader.
-        ** @exception SecurityException if you do not have permission
-        **            to create a ClassLoader.
-        **/
-       protected ClassLoader() throws SecurityException {
-               try {
-                       System.getSecurityManager().checkCreateClassLoader();
-               } catch(NullPointerException e) {
-               }
-       }
+    /* Each instance gets a list of these. */
+    private Hashtable definedPackages = new Hashtable();
 
+    /* The classloader that is consulted before this classloader.
+       if null then the parent is the bootstrap classloader. */
+    private final ClassLoader parent;
+
+    /* System/Application classloader gnu.java.lang.SystemClassLoader. */
+    static final ClassLoader systemClassLoader
+        = null; // XXX = SystemClassLoader.getInstance();
+
+    /** Create a new ClassLoader with as parent the system classloader.
+     ** @exception SecurityException if you do not have permission
+     **            to create a ClassLoader.
+     **/
+    protected ClassLoader() throws SecurityException {
+        this(systemClassLoader);
+    }
+ 
+    /** Create a new ClassLoader with the specified parent.
+     ** The parent will be consulted when a class or resource is
+     ** requested through <code>loadClass()</code> or
+     ** <code>getResource()</code>. Only when the parent classloader
+     ** cannot provide the requested class or resource the
+     ** <code>findClass()</code> or <code>findResource()</code> method
+     ** of this classloader will be called.
+     **
+     ** @param parent the classloader that should be consulted before
+     ** this classloader. Use <code>null</code> to specify the bootstrap
+     ** classloader.
+     ** @exception SecurityException if you do not have permission
+     **            to create a ClassLoader.
+     **
+     ** @since 1.2
+     **/
+    protected ClassLoader(ClassLoader parent) {
+        // May we create a new classloader?
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkCreateClassLoader();
+        
+        this.parent = parent;
+    }
+    
        /** Load a class using this ClassLoader, resolving it as well.
         ** @param name the name of the class relative to this ClassLoader.
         ** @exception ClassNotFoundException if the class cannot be found to
@@ -209,5 +242,109 @@
                        return null;
                }
        }
+
+    /**
+     * 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);
+        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 final 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)
+            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()];
+            Enumeration e = definedPackages.elements();
+            int i = 0;
+            while (e.hasMoreElements()) {
+                packages[i] = (Package)e.nextElement();
+                i++;
+            }
+        }
+        
+        // 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;
+    }
+
 }
 
Index: java/lang/Package.java
===================================================================
RCS file: /cvs/classpath/java/lang/Package.java,v
retrieving revision 1.1
diff -u -r1.1 Package.java
--- java/lang/Package.java      2000/05/30 22:02:02     1.1
+++ java/lang/Package.java      2001/01/08 22:53:21
@@ -1,5 +1,5 @@
-/* java.lang.Object - Everything you ever wanted to know about a package.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+/* java.lang.Package - Everything you ever wanted to know about a package.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -43,7 +43,7 @@
  * compares a desired version of a specification with the version of the
  * specification as implemented by a package. A package is considered
  * compatible with another version if the version of the specification is
- * equal or higer then the requested version. Version numbers are represented
+ * equal or higher then the requested version. Version numbers are represented
  * as strings of positive numbers seperated by dots (e.g. "1.2.0").
  * The first number is called the major number, the second the minor,
  * the third the micro, etc. A version is considered higher then another
@@ -51,9 +51,6 @@
  * the major numbers of the versions are equal if it has a bigger minor number
  * then the other version, etc. (If a version has no minor, micro, etc numbers
  * then they are considered the be 0.)
- * <p>
- * XXX - Two methods (getPackage and getPackages) need support in ClassLoader
- * and are currently not implemented.
  *
  * @since 1.2
  * @author Mark Wielaard ([EMAIL PROTECTED])
@@ -86,24 +83,28 @@
 
     /** 
      * A package local constructor for the Package class.
-     * There are no public constructors defined for Package so I just
-     * invented a package local constructor that can be used by classes in
-     * java.lang.
+     * All parameters except the <code>name</code> of the package may be
+     * <code>null</code>.
+     * There are no public constructors defined for Package this is a package
+     * local constructor that is used by java.lang.Classloader.definePackage().
      * 
      * @param name The name of the Package
-     * @param implTitle The name of the implementation
-     * @param implVendor The vendor that wrote this implementation
-     * @param implVersion The version of this implementation
      * @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
      */
     Package(String name,
-            String implTitle, String implVendor, String implVersion,
             String specTitle, String specVendor, String specVersion,
+            String implTitle, String implVendor, String implVersion,
             URL sealed) {
 
+       if (name == null)
+           throw new IllegalArgumentException("null Package name");
+
         this.name = name;
 
         this.implTitle = implTitle;
@@ -221,27 +222,35 @@
 
     /**
      * Returns the named package if it is known by the callers class loader.
-     * It may return null if the package is unknown or when there is no
-     * information on that particular package available.
-     * <p>
-     * XXX - Since ClassLoader.getPackage() is not yet implemented it just
-     * returns null.
+     * It may return null if the package is unknown, when there is no
+     * information on that particular package available or when the callers
+     * classloader is null.
      * @param name the name of the desired package
      */
     public static Package getPackage(String name) {
-        // ClassLoader.getPackage(name);
-        return null;
+        // get the callers classloader
+        Class c = VMSecurityManager.getClassContext()[1];
+        ClassLoader cl = c.getClassLoader();
+        
+        if (cl != null)
+            return cl.getPackage(name);
+        else
+            return null;
     }
 
     /**
      * Returns all the packages that are known to the callers class loader.
-     * <p>
-     * XXX - Since ClassLoader.getPackages() is not yet implemented it just
-     * returns null.
+     * It may return an empty array if the classloader of the caller is null.
      */
     public static Package[] getPackages() {
-        // ClassLoader.getPackages();
-        return null;
+        // get the callers classloader
+        Class c = VMSecurityManager.getClassContext()[1];
+        ClassLoader cl = c.getClassLoader();
+        
+        if (cl != null)
+            return cl.getPackages();
+        else
+            return new Package[0];
     }
 
     /** 
Index: java/lang/System.java
===================================================================
RCS file: /cvs/classpath/java/lang/System.java,v
retrieving revision 1.9
diff -u -r1.9 System.java
--- java/lang/System.java       2000/06/25 07:22:07     1.9
+++ java/lang/System.java       2001/01/08 22:53:21
@@ -1,5 +1,5 @@
 /* java.lang.System
-   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -222,6 +222,24 @@
                return properties.getProperty(name);
        }
 
+       /** Set a single system property by name.
+        ** @param name the name of the system property to set
+        ** @param value the new value of the system property
+        ** @return the old property value, or null if not yet set
+        ** @exception SecurityException if a SecurityManager is set
+     **            and the caller doesn't have
+        **            <code>PropertyPermission(name, "write")</code>
+        **
+        ** @since 1.2
+        **/
+       public static String setProperty(String name, String value) {
+           SecurityManager sm = getSecurityManager();
+        if (sm != null)
+            sm.checkPermission(new PropertyPermission(name, "write"));
+        
+        return (String)properties.setProperty(name, value);
+       }
+
        /** Get a single property by name, with a possible default
         ** value returned if not found.
         ** @param name the name of the system property to set
@@ -275,6 +293,11 @@
         ** exiting the JVM.  Just uses
         ** <CODE>Runtime.getRuntime().runFinalizersOnExit()</CODE>.
         ** @see java.lang.Runtime#runFinalizersOnExit()
+        **
+        ** @deprecated Since 1.2 this method is officially deprecated
+        ** because there is no guarantee and doing the actual finalization
+        ** on all objects is unsafe since not all (daemon) threads might
+        ** be finished with all objects when the VM terminates.
         **/
        public static void runFinalizersOnExit(boolean finalizeOnExit) {
                Runtime.getRuntime().runFinalizersOnExit(finalizeOnExit);

Reply via email to