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);