diff options
author | Eric Blake <ebb9@byu.net> | 2002-02-23 09:19:52 +0000 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2002-02-23 09:19:52 +0000 |
commit | 70f6e1ec80b4ffc5370564b2710ee194054da42f (patch) | |
tree | 9f2b7ce9aa35a53393b9876f6492f2ec90cfde62 | |
parent | e746a862de38f2e1a5d53b17e633ad2400a7e6c8 (diff) | |
download | classpath-70f6e1ec80b4ffc5370564b2710ee194054da42f.tar.gz |
2002-02-23 Eric Blake <ebb9@email.byu.edu>
* java/lang/Makefile.am (EXTRA_DIST): Add AssertionError.java and
StackTraceElement.java.
* java/lang/AssertionError.java: New file.
* java/lang/ClassLoader.java: Add some synchronization and code
cleanups to use improved VMClassLoader.
Add assertion status fields and methods.
* java/lang/StackTraceElement.java: New file.
* vm/reference/java/lang/Class.java (desiredAssertionStatus): Add.
Other locations: clean up code.
* vm/reference/java/lang/Throwable.java (cause, stackTrace): Add
exception chaining, and Java code for stack traces (native code
unimplemented).
* vm/reference/java/lang/VMClassLoader.java: Add (unimplemented)
hooks to compile assertion status.
(defineClass, loadClass): Add prototypes for missing native hooks.
* vm/reference/java/lang/VMSecurityManager.java: Formatting.
* gnu/java/lang/ClassHelper.java (getAllMethodsAtDeclaration),
(getAllFieldsAtDeclaration): Delete, as they were just duplicates.
(getAllMethods, getAllFields): Optimize.
* gnu/java/lang/ArrayHelper.java: Formatting and Javadoc.
(equalsArray): Delete, it duplicates java.util.Arrays.equals.
* gnu/java/beans/BeanInfoEmbryo.java (hasMethod): Use
Arrays.equals instead of ArrayHelper.equalsArray.
-rw-r--r-- | ChangeLog | 28 | ||||
-rw-r--r-- | gnu/java/beans/BeanInfoEmbryo.java | 19 | ||||
-rw-r--r-- | gnu/java/lang/ArrayHelper.java | 72 | ||||
-rw-r--r-- | gnu/java/lang/ClassHelper.java | 186 | ||||
-rw-r--r-- | java/lang/AssertionError.java | 148 | ||||
-rw-r--r-- | java/lang/ClassLoader.java | 190 | ||||
-rw-r--r-- | java/lang/Makefile.am | 2 | ||||
-rw-r--r-- | java/lang/StackTraceElement.java | 259 | ||||
-rwxr-xr-x | vm/reference/java/lang/Class.java | 35 | ||||
-rw-r--r-- | vm/reference/java/lang/Throwable.java | 162 | ||||
-rw-r--r-- | vm/reference/java/lang/VMClassLoader.java | 131 | ||||
-rw-r--r-- | vm/reference/java/lang/VMSecurityManager.java | 57 |
12 files changed, 893 insertions, 396 deletions
@@ -1,3 +1,29 @@ +2002-02-23 Eric Blake <ebb9@email.byu.edu> + + * java/lang/Makefile.am (EXTRA_DIST): Add AssertionError.java and + StackTraceElement.java. + * java/lang/AssertionError.java: New file. + * java/lang/ClassLoader.java: Add some synchronization and code + cleanups to use improved VMClassLoader. + Add assertion status fields and methods. + * java/lang/StackTraceElement.java: New file. + * vm/reference/java/lang/Class.java (desiredAssertionStatus): Add. + Other locations: clean up code. + * vm/reference/java/lang/Throwable.java (cause, stackTrace): Add + exception chaining, and Java code for stack traces (native code + unimplemented). + * vm/reference/java/lang/VMClassLoader.java: Add (unimplemented) + hooks to compile assertion status. + (defineClass, loadClass): Add prototypes for missing native hooks. + * vm/reference/java/lang/VMSecurityManager.java: Formatting. + * gnu/java/lang/ClassHelper.java (getAllMethodsAtDeclaration), + (getAllFieldsAtDeclaration): Delete, as they were just duplicates. + (getAllMethods, getAllFields): Optimize. + * gnu/java/lang/ArrayHelper.java: Formatting and Javadoc. + (equalsArray): Delete, it duplicates java.util.Arrays.equals. + * gnu/java/beans/BeanInfoEmbryo.java (hasMethod): Use + Arrays.equals instead of ArrayHelper.equalsArray. + 2002-02-22 Tom Tromey <tromey@redhat.com> * gnu/java/rmi/rmic/RMIC.java (parseOptions): Include the "Inc.". @@ -24,8 +50,8 @@ * vm/reference/java/lang/VMObject.java: Ditto. * java/lang/Boolean.java: Ditto. * java/lang/ClassLoader.java: Ditto. - * java/lang/Error.java: Ditto. * java/lang/Object.java: Ditto. + * java/lang/Error.java: Update to 1.4 with new constructors. 2002-02-22 Eric Blake <ebb9@email.byu.edu> diff --git a/gnu/java/beans/BeanInfoEmbryo.java b/gnu/java/beans/BeanInfoEmbryo.java index 4aed20b9f..473aa790c 100644 --- a/gnu/java/beans/BeanInfoEmbryo.java +++ b/gnu/java/beans/BeanInfoEmbryo.java @@ -1,5 +1,5 @@ /* gnu.java.beans.BeanInfoEmbryo - Copyright (C) 1998 Free Software Foundation, Inc. + Copyright (C) 1998, 2002 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -130,14 +130,15 @@ public class BeanInfoEmbryo { } public boolean hasMethod(MethodDescriptor m) { - for(int i=0;i<methods.size();i++) { - Method thisMethod = ((MethodDescriptor)methods.elementAt(i)).getMethod(); - if(m.getMethod().getName().equals(thisMethod.getName()) - && ArrayHelper.equalsArray(m.getMethod().getParameterTypes(), thisMethod.getParameterTypes())) { - return true; - } - } - return false; + for(int i=0;i<methods.size();i++) { + Method thisMethod = ((MethodDescriptor)methods.elementAt(i)).getMethod(); + if(m.getMethod().getName().equals(thisMethod.getName()) + && Arrays.equals(m.getMethod().getParameterTypes(), + thisMethod.getParameterTypes())) { + return true; + } + } + return false; } public void addMethod(MethodDescriptor m) { methods.addElement(m); diff --git a/gnu/java/lang/ArrayHelper.java b/gnu/java/lang/ArrayHelper.java index 271e248f5..5ce0a99f5 100644 --- a/gnu/java/lang/ArrayHelper.java +++ b/gnu/java/lang/ArrayHelper.java @@ -1,5 +1,5 @@ -/* gnu.java.lang.ArrayHelper - Copyright (C) 1998 Free Software Foundation, Inc. +/* ArrayHelper.java -- Helper methods for handling array operations + Copyright (C) 1998, 2002 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -39,36 +39,40 @@ exception statement from your version. */ package gnu.java.lang; /** - ** ArrayHelper helps you do things with arrays. - ** - ** @author John Keiser - ** @version 1.1.0, 29 Jul 1998 - **/ - -public class ArrayHelper { - public static boolean contains(Object[] array, Object searchFor) { - return indexOf(array,searchFor) != -1; - } - - public static int indexOf(Object[] array, Object searchFor) { - for(int i=0;i<array.length;i++) { - if(array[i].equals(searchFor)) { - return i; - } - } - return -1; - } + * ArrayHelper helps you do things with arrays. + * + * @author John Keiser + */ +public class ArrayHelper +{ + /** + * Counterpart to java.util.Collection.contains. + * + * @param array the array to search + * @param searchFor the object to locate + * @return true if some array element <code>equals(searchFor)</code> + */ + public static boolean contains(Object[] array, Object searchFor) + { + return indexOf(array, searchFor) != -1; + } - public static boolean equalsArray(Object[] a, Object[] b) { - if(a.length == b.length) { - for(int i=0;i<a.length;i++) { - if(!a[i].equals(b[i])) { - return false; - } - } - return true; - } else { - return false; - } - } + /** + * Counterpart to java.util.Collection.indexOf. + * + * @param array the array to search + * @param searchFor the object to locate + * @return the index of the first equal object, or -1 + */ + public static int indexOf(Object[] array, Object searchFor) + { + for (int i = 0; i < array.length; i++) + { + if(array[i].equals(searchFor)) + { + return i; + } + } + return -1; + } } diff --git a/gnu/java/lang/ClassHelper.java b/gnu/java/lang/ClassHelper.java index 8363248e7..16d699e34 100644 --- a/gnu/java/lang/ClassHelper.java +++ b/gnu/java/lang/ClassHelper.java @@ -90,14 +90,13 @@ public class ClassHelper } /** Cache of methods found in getAllMethods(). */ - static Hashtable allMethods = new Hashtable(); - - /** Cache of methods found in getAllMethodsAtDeclaration(). */ - static Hashtable allMethodsAtDeclaration = new Hashtable(); + private static Map allMethods = new HashMap(); /** * Get all the methods, public, private and otherwise, from the class, - * getting them from the most recent class to find them. + * getting them from the most recent class to find them. This may not + * be quite the correct approach, as this includes methods that are not + * inherited or accessible from clazz, so beware. * * @param clazz the class to start at * @return all methods declared or inherited in clazz @@ -107,91 +106,45 @@ public class ClassHelper Method[] retval = (Method[]) allMethods.get(clazz); if (retval == null) { - Method[] superMethods; - if (clazz.getSuperclass() != null) - superMethods = getAllMethods(clazz.getSuperclass()); - else - superMethods = new Method[0]; - Vector v = new Vector(); - Method[] currentMethods = clazz.getDeclaredMethods(); - for (int i = 0; i < currentMethods.length; i++) - v.addElement(currentMethods[i]); - for (int i = 0; i < superMethods.length; i++) - { - boolean addOK = true; - for (int j = 0; j < currentMethods.length; j++) - { - if (getTruncatedName(superMethods[i].getName()) - .equals(getTruncatedName(currentMethods[j].getName())) - && ArrayHelper.equalsArray(superMethods[i].getParameterTypes(), - currentMethods[j].getParameterTypes())) - { - addOK = false; - } - } - if(addOK) - v.addElement(superMethods[i]); - } - retval = new Method[v.size()]; - v.copyInto(retval); - allMethods.put(clazz,retval); - } - return retval; - } - - /** - * Get all the methods, public, private and otherwise, from the class, - * and get them from their point of declaration. - * - * @param clazz the class to start at - * @return all methods declared or inherited in clazz - */ - public static Method[] getAllMethodsAtDeclaration(Class clazz) - { - Method[] retval = (Method[]) allMethodsAtDeclaration.get(clazz); - if (retval == null) - { - Method[] superMethods; - if (clazz.getSuperclass() != null) - superMethods = getAllMethodsAtDeclaration(clazz.getSuperclass()); - else - superMethods = new Method[0]; - Vector v = new Vector(); - Method[] currentMethods = clazz.getDeclaredMethods(); - for (int i = 0; i < superMethods.length; i++) - v.addElement(superMethods[i]); - for (int i = 0; i < superMethods.length; i++) + Set methods = new HashSet(); + Class c = clazz; + while (c != null) { - boolean addOK = true; - for (int j = 0; j < currentMethods.length; j++) + Method[] currentMethods = c.getDeclaredMethods(); + loop: + for (int i = 0; i < currentMethods.length; i++) { - if (getTruncatedName(superMethods[i].getName()) - .equals(getTruncatedName(currentMethods[j].getName())) - && ArrayHelper.equalsArray(superMethods[i].getParameterTypes(), - currentMethods[j].getParameterTypes())) + Method current = currentMethods[i]; + int size = methods.size(); + Iterator iter = methods.iterator(); + while (--size >= 0) { - addOK = false; + Method override = (Method) iter.next(); + if (current.getName().equals(override.getName()) + && Arrays.equals(current.getParameterTypes(), + override.getParameterTypes()) + && current.getReturnType() == override.getReturnType()) + continue loop; } + methods.add(current); } - if(addOK) - v.addElement(superMethods[i]); + c = c.getSuperclass(); } - retval = new Method[v.size()]; - v.copyInto(retval); - allMethodsAtDeclaration.put(clazz,retval); + retval = new Method[methods.size()]; + methods.toArray(retval); + allMethods.put(clazz, retval); } return retval; } /** Cache of fields found in getAllFields(). */ - static Hashtable allFields = new Hashtable(); - - /** Cache of fields found in getAllFieldsAtDeclaration(). */ - static Hashtable allFieldsAtDeclaration = new Hashtable(); + private static Map allFields = new HashMap(); /** * Get all the fields, public, private and otherwise, from the class, - * getting them from the most recent class to find them. + * getting them from the most recent class to find them. This may not + * be quite the correct approach, as this includes fields that are not + * inherited or accessible from clazz, so beware. * * @param clazz the class to start at * @return all fields declared or inherited in clazz @@ -201,74 +154,31 @@ public class ClassHelper Field[] retval = (Field[]) allFields.get(clazz); if (retval == null) { - Field[] superFields; - if (clazz.getSuperclass() != null) - superFields = getAllFields(clazz.getSuperclass()); - else - superFields = new Field[0]; - Vector v = new Vector(); - Field[] currentFields = clazz.getDeclaredFields(); - for (int i = 0; i < currentFields.length; i++) - v.addElement(currentFields[i]); - for (int i = 0; i < superFields.length; i++) - { - boolean addOK = true; - for (int j = 0; j < currentFields.length; j++) - { - if (getTruncatedName(superFields[i].getName()) - .equals(getTruncatedName(currentFields[j].getName()))) - { - addOK = false; - } - } - if (addOK) - v.addElement(superFields[i]); - } - retval = new Field[v.size()]; - v.copyInto(retval); - allFields.put(clazz,retval); - } - return retval; - } - - /** - * Get all the fields, public, private and otherwise, from the class, - * and get them from their point of declaration. - * - * @param clazz the class to start at - * @return all fields declared or inherited in clazz - */ - public static Field[] getAllFieldsAtDeclaration(Class clazz) - { - Field[] retval = (Field[]) allFieldsAtDeclaration.get(clazz); - if (retval == null) - { - Field[] superFields; - if (clazz.getSuperclass() != null) - superFields = getAllFieldsAtDeclaration(clazz.getSuperclass()); - else - superFields = new Field[0]; - Vector v = new Vector(); - Field[] currentFields = clazz.getDeclaredFields(); - for (int i = 0; i < superFields.length; i++) - v.addElement(superFields[i]); - for (int i = 0; i < superFields.length; i++) + Set fields = new HashSet(); + Class c = clazz; + while (c != null) { - boolean addOK = true; - for (int j = 0; j < currentFields.length; j++) + Field[] currentFields = c.getDeclaredFields(); + loop: + for (int i = 0; i < currentFields.length; i++) { - if (getTruncatedName(superFields[i].getName()) - .equals(getTruncatedName(currentFields[j].getName()))) + Field current = currentFields[i]; + int size = fields.size(); + Iterator iter = fields.iterator(); + while (--size >= 0) { - addOK = false; + Field override = (Field) iter.next(); + if (current.getName().equals(override.getName()) + && current.getType() == override.getType()) + continue loop; } + fields.add(current); } - if(addOK) - v.addElement(superFields[i]); + c = c.getSuperclass(); } - retval = new Field[v.size()]; - v.copyInto(retval); - allFieldsAtDeclaration.put(clazz,retval); + retval = new Field[fields.size()]; + fields.toArray(retval); + allFields.put(clazz, retval); } return retval; } diff --git a/java/lang/AssertionError.java b/java/lang/AssertionError.java new file mode 100644 index 000000000..e51df4622 --- /dev/null +++ b/java/lang/AssertionError.java @@ -0,0 +1,148 @@ +/* AssertionError.java -- fIndication of a failed assertion + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An assertion error normally occurs as a result of the <code>assert</code> + * statement added in JDK 1.4, to indicate that an assertion failed. There + * are enough constructors to ensure that + * <code>new AssertionError(<em>expression</em)</code> will work for all + * espressions, regardless of type, as if the error message were given by + * the string <code>"" + <em>expression</em></code>. This extends Error, + * because you usually do not want to inadvertently trap an assertion failure. + * + * @author Eric Blake <ebb9@email.byu.edu> + * @since 1.4 + * @status updated to 1.4 + */ +public class AssertionError extends Error +{ + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = -5013299493970297370L; + + /** + * Construct an AssertionError with no detail message. + */ + public AssertionError() + { + } + + /** + * Construct an AssertionError with the string conversion of the given + * object as its error message. If the object is a Throwable, it is also + * set as the cause of this error. + * + * @param msg the source of the error message + * @see Throwable#getCause() + */ + public AssertionError(Object msg) + { + super("" + msg); + if (msg instanceof Throwable) + initCause((Throwable) msg); + } + + /** + * Construct an AssertionError with the string conversion of the given + * boolean as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(boolean msg) + { + super(msg ? "true" : "false"); + } + + /** + * Construct an AssertionError with the string conversion of the given + * char as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(char msg) + { + super(String.valueOf(msg)); + } + + /** + * Construct an AssertionError with the string conversion of the given + * int as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(int msg) + { + super(Integer.toString(msg, 10)); + } + + /** + * Construct an AssertionError with the string conversion of the given + * long as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(long msg) + { + super(Long.toString(msg)); + } + + /** + * Construct an AssertionError with the string conversion of the given + * float as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(float msg) + { + super(Float.toString(msg)); + } + + /** + * Construct an AssertionError with the string conversion of the given + * double as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(double msg) + { + super(Double.toString(msg)); + } +} diff --git a/java/lang/ClassLoader.java b/java/lang/ClassLoader.java index cd2d59a1c..b4546a933 100644 --- a/java/lang/ClassLoader.java +++ b/java/lang/ClassLoader.java @@ -114,10 +114,10 @@ import gnu.java.util.EmptyEnumeration; public abstract class ClassLoader { /** All classes loaded by this classloader. */ - private Hashtable loadedClasses = new Hashtable(); + private final Map loadedClasses = new HashMap(); /** All packages defined by this classloader. */ - private Hashtable definedPackages = new Hashtable(); + private final Map definedPackages = new HashMap(); /** * The classloader that is consulted before this classloader. @@ -126,57 +126,68 @@ public abstract class ClassLoader private final ClassLoader parent; /** - * System/Application classloader gnu.java.lang.SystemClassLoader. - * Due to bootstrapping issues, the VM must modify this field. + * System/Application classloader: defaults to an instance of + * gnu.java.lang.SystemClassLoader, unless the first invocation of + * getSystemClassLoader loads another class loader because of the + * java.system.class.loader property. + * + * XXX - The VM may needs to modify this field or set it to something + * else, until gnu.java.lang.SystemClassLoader is correctly implemented. + */ + static final ClassLoader systemClassLoader = getSystemClassLoader(); + + /** + * The default protection domain, used when defining a class with a null + * paramter for the domain. */ - static final ClassLoader systemClassLoader - = null; // XXX = SystemClassLoader.getInstance(); + static final ProtectionDomain defaultProtectionDomain; + static + { + CodeSource cs = new CodeSource(null, null); + PermissionCollection perm = Policy.getPolicy().getPermissions(cs); + defaultProtectionDomain = new ProtectionDomain(cs, perm); + } /** * The desired assertion status of classes loaded by this loader, if not * overridden by package or class instructions. - * @XXX Implement for 1.4 compatibility. + */ // Package visible for use by Class. boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus(); - */ /** * The command-line state of the package assertion status overrides. This * map is never modified, so it does not need to be synchronized. - * @XXX Implement for 1.4 compatibility. + */ // Package visible for use by Class. static final Map systemPackageAssertionStatus = VMClassLoader.packageAssertionStatus(); - */ /** * The map of package assertion status overrides, or null if no package * overrides have been specified yet. The values of the map should be * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented * by the null key. This map must be synchronized on this instance. - * @XXX Implement for 1.4 compatibility. + */ // Package visible for use by Class. Map packageAssertionStatus; - */ /** * The command-line state of the class assertion status overrides. This * map is never modified, so it does not need to be synchronized. - * @XXX Implement for 1.4 compatibility. + */ // Package visible for use by Class. static final Map systemClassAssertionStatus = VMClassLoader.classAssertionStatus(); - */ /** * The map of class assertion status overrides, or null if no class * overrides have been specified yet. The values of the map should be * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this * instance. - * @XXX Implement for 1.4 compatibility. + */ // Package visible for use by Class. Map classAssertionStatus; - */ /** * Create a new ClassLoader with as parent the system classloader. There @@ -186,8 +197,7 @@ public abstract class ClassLoader */ protected ClassLoader() throws SecurityException { - //XXX This should be this(getSystemClassLoader()); - this(systemClassLoader); + this(getSystemClassLoader()); } /** @@ -257,25 +267,21 @@ public abstract class ClassLoader if (c != null) return c; - // Can the class be loaded by one of our parent? + // Can the class been loaded by a parent? try { if (parent == null) - // XXX - use the bootstrap classloader - // return VMClassLoader.loadClass(name, resolve); - return findSystemClass(name); + return VMClassLoader.loadClass(name, resolve); return parent.loadClass(name, resolve); } catch (ClassNotFoundException e) { - // Ignore, use findClass(). + // Still not found, we have to do it ourself. + c = findClass(name); + if (resolve) + resolveClass(c); + return c; } - - // Still not found, we have to do it ourself. - c = findClass(name); - if (resolve) - resolveClass(c); - return c; } /** @@ -349,7 +355,8 @@ public abstract class ClassLoader * ProtectionDomain. Subclasses should call this method from their * <code>findClass()</code> implementation. The name should use '.' * separators, and discard the trailing ".class". The default protection - * domain is <code>Policy.getPolicy().getPermissions(null, null)<code>. + * domain has the permissions of + * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))<code>. * * @param name the name to give the class, or null if unknown * @param data the data representing the classfile, in classfile format @@ -365,22 +372,19 @@ public abstract class ClassLoader protected final Class defineClass(String name, byte[] data, int offset, int len) throws ClassFormatError { - // XXX - return defineClass(name, data, offset, len, null); - Class retval = VMClassLoader.defineClass(this, name, data, offset, len); - loadedClasses.put(retval.getName(), retval); - return retval; + return defineClass(name, data, offset, len, null); } /** * Helper to define a class using a string of bytes. Subclasses should call * this method from their <code>findClass()</code> implementation. If the * domain is null, the default of - * <code>Policy.getPolicy().getPermissions(null, null)<code> is used. - * Once a class has been defined in a package, all further classes in that - * package must have the same set of certificates or a SecurityException is - * thrown + * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))<code> + * is used. Once a class has been defined in a package, all further classes + * in that package must have the same set of certificates or a + * SecurityException is thrown. * - * XXX - not implemented yet. Needs native support. + * XXX - protection domain is not implemented yet; it needs native support. * * @param name the name to give the class. null if unknown * @param data the data representing the classfile, in classfile format @@ -400,13 +404,12 @@ public abstract class ClassLoader int len, ProtectionDomain domain) throws ClassFormatError { - /* XXX - needs native support. - Class retval - = VMClassLoader.defineClass(this, name, data, offset, len, domain); + if (domain == null) + domain = defaultProtectionDomain; + Class retval = VMClassLoader.defineClass(this, name, data, + offset, len, domain); loadedClasses.put(retval.getName(), retval); return retval; - */ - return defineClass(name, data, offset, len); } /** @@ -434,9 +437,7 @@ public abstract class ClassLoader protected final Class findSystemClass(String name) throws ClassNotFoundException { - // XXX This should be: - // return Class.forName(name, false, getSystemClassLoader()); - return Class.forName(name); + return Class.forName(name, false, getSystemClassLoader()); } /** @@ -506,10 +507,9 @@ public abstract class ClassLoader URL result; if (parent == null) - // XXX - try bootstrap classloader; - // result = VMClassLoader.getResource(name); - return ClassLoader.getSystemResource(name); - result = parent.getResource(name); + result = VMClassLoader.getResource(name); + else + result = parent.getResource(name); if (result == null) result = findResource(name); @@ -540,8 +540,7 @@ public abstract class ClassLoader { Enumeration parentResources; if (parent == null) - // XXX - Should use the bootstrap classloader - parentResources = EmptyEnumeration.getInstance(); + parentResources = VMClassLoader.getResources(name); else parentResources = parent.getResources(name); return new DoubleEnumeration(parentResources, findResources(name)); @@ -644,9 +643,7 @@ public abstract class ClassLoader */ public static Enumeration getSystemResources(String name) throws IOException { - // XXX should be - // return getSystemClassLoader().getResources(name); - return systemClassLoader.getResources(name); + return getSystemClassLoader().getResources(name); } /** @@ -664,14 +661,14 @@ public abstract class ClassLoader */ public InputStream getResourceAsStream(String name) { - URL url = getResource(name); - if (url == null) - return null; try { + URL url = getResource(name); + if (url == null) + return null; return url.openStream(); } - catch(IOException e) + catch (IOException e) { return null; } @@ -693,7 +690,7 @@ public abstract class ClassLoader return null; return url.openStream(); } - catch(IOException e) + catch (IOException e) { return null; } @@ -709,6 +706,8 @@ public abstract class ClassLoader * name of the class to use as the system class loader, otherwise this * uses gnu.java.lang.SystemClassLoader. * + * XXX - overriding the class loader does not currently work + * * <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). @@ -725,7 +724,13 @@ public abstract class ClassLoader */ public static ClassLoader getSystemClassLoader() { - //XXX This needs to check for java.system.class.loader. + // This method is called as the initialization of systemClassLoader, + // so if there is a null value, this is the first call and we must check + // for java.system.class.loader. + if (systemClassLoader == null) + { + // XXX return SystemClassLoader.getInstance(); + } // Check if we may return the system classloader SecurityManager sm = System.getSecurityManager(); if (sm != null) @@ -776,7 +781,10 @@ public abstract class ClassLoader + " already defined"); Package p = new Package(name, specTitle, specVendor, specVersion, implTitle, implVendor, implVersion, sealed); - definedPackages.put(name, p); + synchronized (definedPackages) + { + definedPackages.put(name, p); + } return p; } @@ -793,13 +801,15 @@ public abstract class ClassLoader { Package p; if (parent == null) - // XXX - Should we use the bootstrap classloader? - p = null; + p = VMClassLoader.getPackage(name); else p = parent.getPackage(name); if (p == null) - p = (Package)definedPackages.get(name); + synchronized (definedPackages) + { + p = (Package) definedPackages.get(name); + } return p; } @@ -811,35 +821,27 @@ public abstract class ClassLoader */ 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++; - } + definedPackages.values().toArray(packages); } // 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; - + Package[] parentPackages; + if (parent == null) + parentPackages = VMClassLoader.getPackages(); + else + parentPackages = parent.getPackages(); + + Package[] allPackages = new Package[parentPackages.length + + packages.length]; + System.arraycopy(parentPackages, 0, allPackages, 0, + parentPackages.length); + System.arraycopy(packages, 0, allPackages, parentPackages.length, + packages.length); return allPackages; } @@ -872,12 +874,11 @@ public abstract class ClassLoader * @see #setPackageAssertionStatus(String, boolean) * @see #clearAssertionStatus() * @since 1.4 - * @XXX Implement for 1.4 compatibility. + */ public void setDefaultAssertionStatus(boolean enabled) { defaultAssertionStatus = enabled; } - */ /** * Set the default assertion status for packages, used unless overridden @@ -890,7 +891,7 @@ public abstract class ClassLoader * @see #setClassAssertionStatus(String, boolean) * @see #clearAssertionStatus() * @since 1.4 - * @XXX Implement for 1.4 compatibility. + */ public synchronized void setPackageAssertionStatus(String name, boolean enabled) { @@ -899,7 +900,6 @@ public abstract class ClassLoader = new HashMap(systemPackageAssertionStatus); packageAssertionStatus.put(name, Boolean.valueOf(enabled)); } - */ /** * Set the default assertion status for a class. This only affects the @@ -912,7 +912,7 @@ public abstract class ClassLoader * @see #setPackageAssertionStatus(String, boolean) * @see #clearAssertionStatus() * @since 1.4 - * @XXX Implement for 1.4 compatibility. + */ public synchronized void setClassAssertionStatus(String name, boolean enabled) { @@ -921,7 +921,6 @@ public abstract class ClassLoader // The toString() hack catches null, as required. classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); } - */ /** * Resets the default assertion status of this classloader, its packages @@ -932,14 +931,11 @@ public abstract class ClassLoader * @see #setClassAssertionStatus(String, boolean) * @see #setPackageAssertionStatus(String, boolean) * @since 1.4 - * @XXX Implement for 1.4 compatibility. + */ public synchronized void clearAssertionStatus() { defaultAssertionStatus = false; packageAssertionStatus = new HashMap(); classAssertionStatus = new HashMap(); } - */ - } - diff --git a/java/lang/Makefile.am b/java/lang/Makefile.am index 554e92ebf..919c7f3ce 100644 --- a/java/lang/Makefile.am +++ b/java/lang/Makefile.am @@ -7,6 +7,7 @@ AbstractMethodError.java \ ArithmeticException.java \ ArrayIndexOutOfBoundsException.java \ ArrayStoreException.java \ +AssertionError.java \ Boolean.java \ Byte.java \ Character.java \ @@ -62,6 +63,7 @@ SecurityException.java \ SecurityManager.java \ Short.java \ StackOverflowError.java \ +StackTraceElement.java \ StrictMath.java \ StringBuffer.java \ StringIndexOutOfBoundsException.java \ diff --git a/java/lang/StackTraceElement.java b/java/lang/StackTraceElement.java new file mode 100644 index 000000000..9c60ab164 --- /dev/null +++ b/java/lang/StackTraceElement.java @@ -0,0 +1,259 @@ +/* StackTraceElement.java -- One function call or call stack element + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import java.io.Serializable; + +/** + * One function call or stack trace element. Gives information about + * the execution point such as the source file name, the line number, + * the fully qualified class name, the method name and whether this method + * is native, if this information is known. + * + * @author Mark Wielaard <mark@klomp.org> + * @author Eric Blake <ebb9@email.byu.edu> + * @since 1.4 + * @status updated to 1.4 + */ +public class StackTraceElement implements Serializable +{ + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = 6992337162326171013L; + + /** + * The name of the file, null if unknown. + * + * @serial the source code filename, if known + */ + private final String fileName; + + /** + * The line number in the file, negative if unknown. + * + * @serial the source code line number, if known + */ + private final int lineNumber; + + /** + * The fully qualified class name, null if unknown. + * + * @serial the enclosing class, if known + */ + private final String className; + + /** + * The method name in the class, null if unknown. + * + * @serial the enclosing method, if known + */ + private final String methodName; + + /** Whether the method is native. */ + private final transient boolean isNative; + + /** + * A package local constructor for the StackTraceElement class, to be + * called by the Virtual Machine as part of Throwable.fillInStackTrace. + * There are no public constructors defined for this class. Creation + * of new elements is implementation specific. + * + * @param fileName the name of the file, null if unknown + * @param lineNumber the line in the file, negative if unknown + * @param className the fully qualified name of the class, null if unknown + * @param methodName the name of the method, null if unknown + * @param isNative true if native, false otherwise + */ + StackTraceElement(String fileName, int lineNumber, String className, + String methodName, boolean isNative) + { + this.fileName = fileName; + this.lineNumber = lineNumber; + this.className = className; + this.methodName = methodName; + this.isNative = isNative; + } + + /** + * Returns the name of the file, or null if unknown. This is usually + * obtained from the <code>SourceFile</code> attribute of the class file + * format, if present. + * + * @return the file name + */ + public String getFileName() + { + return fileName; + } + + /** + * Returns the line number in the file, or a negative number if unknown. + * This is usually obtained from the <code>LineNumberTable</code> attribute + * of the method in the class file format, if present. + * + * @return the line number + */ + public int getLineNumber() + { + return lineNumber; + } + + /** + * Returns the fully qualified class name, or null if unknown. + * + * @return the class name + */ + public String getClassName() + { + return className; + } + + /** + * Returns the method name in the class, or null if unknown. If the + * execution point is in a constructor, the name is + * <code><init></code>; if the execution point is in the class + * initializer, the name is <code><clinit></code>. + * + * @return the method name + */ + public String getMethodName() + { + return methodName; + } + + /** + * Returns true if the method is native, or false if it is not or unknown. + * + * @return whether the method is native + */ + public boolean isNativeMethod() + { + return isNative; + } + + /** + * Returns a string representation of this stack trace element. The + * returned String is implementation specific. This implementation + * returns the following String: "[class][.][method]([file][:line])". + * If the fully qualified class name or the method is unknown it is + * omitted including the point seperator. If the source file name is + * unknown it is replaced by "Unknown Source" if the method is not native + * or by "Native Method" if the method is native. If the line number + * is unknown it and the colon are omitted. + * + * @return a string representation of this execution point + */ + public String toString() + { + StringBuffer sb = new StringBuffer(); + if (className != null) + { + sb.append(className); + if (methodName != null) + sb.append('.'); + } + if (methodName != null) + sb.append(methodName); + sb.append('('); + if (fileName != null) + sb.append(fileName); + else + sb.append(isNative ? "Native Method" : "Unknown Source"); + if (lineNumber >= 0) + sb.append(':').append(lineNumber); + sb.append(')'); + return sb.toString(); + } + + /** + * Returns true if the given object is also a StackTraceElement and all + * attributes, except the native flag, are equal (either the same attribute + * between the two elments are null, or both satisfy Object.equals). + * + * @param o the object to compare + * @return true if the two are equal + */ + public boolean equals(Object o) + { + if (! (o instanceof StackTraceElement)) + return false; + StackTraceElement e = (StackTraceElement) o; + return equals(fileName, e.fileName) + && lineNumber == e.lineNumber + && equals(className, e.className) + && equals(methodName, e.methodName); + } + + /** + * Returns the hashCode of this StackTraceElement. This implementation + * computes the hashcode by xor-ing the hashcode of all attributes except + * the native flag. + * + * @return the hashcode + */ + public int hashCode() + { + return hashCode(fileName) ^ lineNumber ^ hashCode(className) + ^ hashCode(methodName); + } + + /** + * Compare two objects according to Collection semantics. + * + * @param o1 the first object + * @param o2 the second object + * @return o1 == null ? o2 == null : o1.equals(o2) + */ + private static final boolean equals(Object o1, Object o2) + { + return o1 == null ? o2 == null : o1.equals(o2); + } + + /** + * Hash an object according to Collection semantics. + * + * @param o the object to hash + * @return o1 == null ? 0 : o1.hashCode() + */ + private static final int hashCode(Object o) + { + return o == null ? 0 : o.hashCode(); + } +} diff --git a/vm/reference/java/lang/Class.java b/vm/reference/java/lang/Class.java index 211b17fad..837d410a7 100755 --- a/vm/reference/java/lang/Class.java +++ b/vm/reference/java/lang/Class.java @@ -38,6 +38,7 @@ exception statement from your version. */ package java.lang; import java.io.Serializable; +import java.io.InputStream; import java.lang.reflect.*; import java.security.*; import java.net.URL; @@ -117,7 +118,8 @@ public final class Class implements Serializable */ public String toString() { - //XXX Fix for primitive types. + if (isPrimitive()) + return getName(); return (isInterface() ? "interface " : "class ") + getName(); } @@ -134,15 +136,11 @@ public final class Class implements Serializable * @throws ExceptionInInitializerError if the class loads, but an exception * occurs during initialization */ - //XXX This does not need to be native. - public static native Class forName(String name) - throws ClassNotFoundException; - /* + public static Class forName(String name) throws ClassNotFoundException { return forName(name, true, VMSecurityManager.getClassContext()[1].getClassLoader()); } - */ /** * Use the specified classloader to load and link a class. If the loader @@ -211,27 +209,21 @@ public final class Class implements Serializable { try { - //XXX What about getConstructor(null).newInstance(null)? - return getConstructor(new Class[0]).newInstance(new Object[0]); - } - catch(SecurityException e) - { - //XXX Why is this trapped? - throw new IllegalAccessException("Cannot access no-arg constructor"); + return getConstructor(null).newInstance(null); } catch(IllegalArgumentException e) { - throw new UnknownError("IllegalArgumentException thrown from Constructor.newInstance(). Something is rotten in Denmark."); + throw (Error) new InternalError("Should not happen").initCause(e); } catch(InvocationTargetException e) { - //XXX Chain this. - throw new InstantiationException("Target threw an exception."); + throw (InstantiationException) + new InstantiationException(e.toString()).initCause(e); } catch(NoSuchMethodException e) { - //XXX Chain this. - throw new InstantiationException("Method not found"); + throw (InstantiationException) + new InstantiationException(e.toString()).initCause(e); } } @@ -387,8 +379,8 @@ public final class Class implements Serializable if(isArray()) try { - //XXX This should not initialize the component type. - return Class.forName(getName().substring(1)); + return Class.forName(getName().substring(1), false, + getClassLoader()); } catch(ClassNotFoundException e) { @@ -772,7 +764,7 @@ public final class Class implements Serializable * @see ClassLoader#setPackageAssertionStatus(String, boolean) * @see ClassLoader#setDefaultAssertionStatus(boolean) * @since 1.4 - * @XXX For 1.4 compliance, implement this method. + */ public boolean desiredAssertionStatus() { ClassLoader c = getClassLoader(); @@ -825,6 +817,5 @@ public final class Class implements Serializable } return c.defaultAssertionStatus; } - */ } diff --git a/vm/reference/java/lang/Throwable.java b/vm/reference/java/lang/Throwable.java index 79877f2ee..16a24e07e 100644 --- a/vm/reference/java/lang/Throwable.java +++ b/vm/reference/java/lang/Throwable.java @@ -107,6 +107,7 @@ import java.io.IOException; * * @author Brian Jones * @author John Keiser + * @author Mark Wielaard * @author Eric Blake <ebb9@email.byu.edu> * @since 1.0 * @status still missing 1.4 functionality @@ -122,9 +123,8 @@ public class Throwable extends Object implements Serializable * The detail message. * * @serial specific details about the exception, may be null - * @XXX for serialization, renaming this detailMessage would be nice */ - private String message = null; + private String detailMessage; /** * The cause of the throwable, including null for an unknown or non-chained @@ -133,9 +133,8 @@ public class Throwable extends Object implements Serializable * * @serial the cause, or null if unknown, or this if not yet set * @since 1.4 - * @XXX for 1.4 compatibility, add this field - private Throwable cause = this; */ + private Throwable cause = this; /** * The stack trace, in a serialized form. @@ -143,9 +142,9 @@ public class Throwable extends Object implements Serializable * @serial the elements of the stack trace; this is non-null, and has * no null entries * @since 1.4 - * @XXX for 1.4 compatibility, add this field - private StackTraceElement[] stackTrace; */ + // XXX Don't initialize this, once fillInStackTrace() does it. + private StackTraceElement[] stackTrace = {}; /** * Instantiate this Throwable with an empty message. The cause remains @@ -154,7 +153,7 @@ public class Throwable extends Object implements Serializable */ public Throwable() { - this(null); + this((String) null); } /** @@ -167,7 +166,7 @@ public class Throwable extends Object implements Serializable public Throwable(String message) { fillInStackTrace(); - this.message = message; + detailMessage = message; } /** @@ -178,13 +177,12 @@ public class Throwable extends Object implements Serializable * @param message the message to associate with the Throwable * @param cause the cause, may be null * @since 1.4 - * @XXX for 1.4 compatibility, add this constructor + */ public Throwable(String message, Throwable cause) { this(message); initCause(cause); } - */ /** * Instantiate this Throwable with the given cause. The message is then @@ -193,12 +191,11 @@ public class Throwable extends Object implements Serializable * * @param cause the cause, may be null * @since 1.4 - * @XXX for 1.4 compatibility, add this constructor + */ public Throwable(Throwable cause) { this(cause == null ? null : cause.toString(), cause); } - */ /** * Get the message associated with this Throwable. @@ -207,7 +204,7 @@ public class Throwable extends Object implements Serializable */ public String getMessage() { - return message; + return detailMessage; } /** @@ -232,12 +229,11 @@ public class Throwable extends Object implements Serializable * * @return the cause of this Throwable * @since 1.4 - * @XXX for 1.4 compatibility, add this method + */ public Throwable getCause() { return cause == this ? null : cause; } - */ /** * Initialize the cause of this Throwable. This may only be called once @@ -250,7 +246,7 @@ public class Throwable extends Object implements Serializable * its own cause!) * @throws IllegalStateException if the cause has already been set * @since 1.4 - * @XXX for 1.4 compatibility, add this method + */ public Throwable initCause(Throwable cause) { if (cause == this) @@ -260,7 +256,6 @@ public class Throwable extends Object implements Serializable this.cause = cause; return this; } - */ /** * Get a human-readable representation of this Throwable. With a null @@ -272,7 +267,8 @@ public class Throwable extends Object implements Serializable */ public String toString() { - return getClass().getName() + (message != null ? ": " + message : ""); + return getClass().getName() + + (detailMessage == null ? "" : ": " + detailMessage); } /** @@ -310,7 +306,7 @@ public class Throwable extends Object implements Serializable * static void b() throws MidLevelException * { * c(); - * } + * } * static void c() throws MidLevelException * { * try @@ -373,8 +369,7 @@ public class Throwable extends Object implements Serializable */ public void printStackTrace(PrintStream s) { - s.println(toString()); - printStackTrace0(s); + printStackTrace(new PrintWriter(s)); } /** @@ -386,16 +381,99 @@ public class Throwable extends Object implements Serializable */ public void printStackTrace(PrintWriter w) { - w.println(toString()); + //XXX - should be printStackTrace1(w); printStackTrace0(w); } /** * The implentation for printing a stack trace. * - * @param stream either a PrintStream or PrintWriter + * @param stream the destination stream + */ + private native void printStackTrace0(PrintWriter stream); + + /** + * Alternative printStackTrace that uses <code>getStrackTrace0()</code> + * to print the exception, stack trace and cause (recursively). Not used + * since <code>getStackTrace()</code> does not yet work. + * + * <p>Prints the exception, the detailed message and the stack trace + * associated with this Throwable to the given <code>PrintWriter</code>. + * The actual output written is implemention specific. Use the result of + * <code>getStackTrace()</code> when more precise information is needed. + * + * <p>This implementation first prints a line with the result of this + * object's <code>toString()</code> method. + * <br> + * Then for all elements given by <code>getStackTrace</code> it prints + * a line containing a tab, the string "at " and the result of calling the + * <code>toString()</code> method on the <code>StackTraceElement</code> + * object. If <code>getStackTrace()</code> returns an empty array it prints + * a line containing a tab and the string "<<No stacktrace available>>". + * <br> + * Then if <code>getCause()</code> doesn't return null it adds a line + * starting with "Caused by: " and the result of calling + * <code>toString()</code> on the cause. + * <br> + * Then for every cause (of a cause, etc) the stacktrace is printed the + * same as for the top level <code>Throwable</code> except that as soon + * as all the remaining stack frames of the cause are the same as the + * the last stack frames of the throwable that the cause is wrapped in + * then a line starting with a tab and the string "... X more" is printed, + * where X is the number of remaining stackframes. */ - private native void printStackTrace0 (Object stream); + private void printStackTrace1(PrintWriter pw) + { + // First line + pw.println(toString()); + + // The stacktrace + StackTraceElement[] stack = getStackTrace(); + for (int i = 0; i < stack.length; i++) + pw.println("\tat " + stack[i]); + + // The cause(s) + Throwable cause = getCause(); + while (cause != null) + { + // Cause first line + pw.println("Caused by: " + cause); + + // Cause stacktrace + StackTraceElement[] parentStack = stack; + stack = cause.getStackTrace(); + boolean equal = false; // Is rest of stack equal to parent frame? + for (int i = 0; i < stack.length && ! equal; i++) + { + // Check if we already printed the rest of the stack + // since it was the tail of the parent stack + int remaining = stack.length - i; + int element = i; + int parentElement = parentStack.length - remaining; + equal = parentElement >= 0 + && parentElement < parentStack.length; // be optimistic + while (equal && element < stack.length) + { + if (stack[element].equals(parentStack[parentElement])) + { + element++; + parentElement++; + } + else + equal = false; + } + // Print stacktrace element or indicate the rest is equal + if (! equal) + pw.println("\tat " + stack[i]); + else + { + pw.println("\t..." + remaining + " more"); + break; // from stack printing for loop + } + } + cause = cause.getCause(); + } + } /** * Fill in the stack trace with the current execution stack. @@ -417,12 +495,11 @@ public class Throwable extends Object implements Serializable * * @return an array of stack trace information, as available from the VM * @since 1.4 - * @XXX for 1.4 compatibility, add this method + */ public StackTraceElement[] getStackTrace() { return stackTrace; } - */ /** * Change the stack trace manually. This method is designed for remote @@ -432,7 +509,7 @@ public class Throwable extends Object implements Serializable * @param stackTrace the new trace to use * @throws NullPointerException if stackTrace is null or has null elements * @since 1.4 - * @XXX for 1.4 compatibility, add this method + */ public void setStackTrace(StackTraceElement[] stackTrace) { for (int i = stackTrace.length; --i >= 0; ) @@ -440,35 +517,4 @@ public class Throwable extends Object implements Serializable throw new NullPointerException(); this.stackTrace = stackTrace; } - */ - - /** - * Serialize the object in a manner binary compatible with the JDK 1.2. - * - * @param s the stream to write to - * @throws IOException if the write fails - */ - private void writeObject(ObjectOutputStream s) - throws IOException - { - ObjectOutputStream.PutField oFields; - oFields = s.putFields(); - oFields.put("detailMessage", message); - s.writeFields(); - } - - /** - * Deserialize the object in a manner binary compatible with the JDK 1.2. - * - * @param s the stream to read from - * @throws IOException if the read fails - * @throws ClassNotFoundException if deserialization fails - */ - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException - { - ObjectInputStream.GetField oFields; - oFields = s.readFields(); - message = (String)oFields.get("detailMessage", (String)null); - } } diff --git a/vm/reference/java/lang/VMClassLoader.java b/vm/reference/java/lang/VMClassLoader.java index ce55b8dd4..ded080e9d 100644 --- a/vm/reference/java/lang/VMClassLoader.java +++ b/vm/reference/java/lang/VMClassLoader.java @@ -38,6 +38,13 @@ exception statement from your version. */ package java.lang; +import java.security.ProtectionDomain; +import java.net.URL; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Map; +import java.util.HashMap; + /** * java.lang.VMClassLoader is a package-private helper for VMs to implement * on behalf of java.lang.ClassLoader. @@ -49,7 +56,10 @@ package java.lang; final class VMClassLoader { /** - * Helper to define a class using a string of bytes. + * Helper to define a class using a string of bytes. This assumes that + * the security checks have already been performed, if necessary. + * <strong>This method will be removed in a future version of GNU + * Classpath</strong>. * * @param name the name to give the class, or null if unknown * @param data the data representing the classfile, in classfile format @@ -57,13 +67,39 @@ final class VMClassLoader * @param len the length of the classfile data in the array * @return the class that was defined * @throws ClassFormatError if data is not in proper classfile format - * @XXX This should also have a ProtectionDomain argument. + * @deprecated Implement + * {@link #defineClass(ClassLoader, String, byte[], int, int, ProtectionDomain)} + * instead. */ static final native Class defineClass(ClassLoader cl, String name, byte[] data, int offset, int len) throws ClassFormatError; /** + * Helper to define a class using a string of bytes. This assumes that + * the security checks have already been performed, if necessary. + * + * <strong>For backward compatibility, this just ignores the protection + * domain; that is the wrong behavior, and you should directly implement + * this method natively if you can.</strong> + * + * @param name the name to give the class, or null if unknown + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @param pd the protection domain + * @return the class that was defined + * @throws ClassFormatError if data is not in proper classfile format + */ + static final Class defineClass(ClassLoader cl, String name, + byte[] data, int offset, int len, + ProtectionDomain pd) + throws ClassFormatError + { + return defineClass(cl, name, data, offset, len); + } + + /** * Helper to resolve all references to other classes from this class. * * @param c the class to resolve @@ -71,6 +107,73 @@ final class VMClassLoader static final native void resolveClass(Class c); /** + * Helper to load a class from the bootstrap class loader. + * + * XXX - Not implemented yet; this requires native help. + * + * @param name the class name to load + * @param resolve whether to resolve it + * @return the class, loaded by the bootstrap classloader + */ + static final Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + return Class.forName(name, resolve, ClassLoader.getSystemClassLoader()); + } + + /** + * Helper to load a resource from the bootstrap class loader. + * + * XXX - Not implemented yet; this requires native help. + * + * @param name the resource to find + * @return the URL to the resource + */ + static URL getResource(String name) + { + return ClassLoader.getSystemResource(name); + } + + /** + * Helper to get a list of resources from the bootstrap class loader. + * + * XXX - Not implemented yet; this requires native help. + * + * @param name the resource to find + * @return an enumeration of resources + * @throws IOException if one occurs + */ + static Enumeration getResources(String name) throws IOException + { + return ClassLoader.getSystemResources(name); + } + + /** + * Helper to get a package from the bootstrap class loader. The default + * implementation of returning null may be adequate, or you may decide + * that this needs some native help. + * + * @param name the name to find + * @return the named package, if it exists + */ + static Package getPackage(String name) + { + return null; + } + + /** + * Helper to get all packages from the bootstrap class loader. The default + * implementation of returning an empty array may be adequate, or you may + * decide that this needs some native help. + * + * @return all named packages, if any exist + */ + static Package[] getPackages() + { + return new Package[0]; + } + + /** * Helper for java.lang.Integer, Byte, etc to get the TYPE class * at initialization time. The type code is one of the chars that * represents the primitive type as in JNI. @@ -153,10 +256,14 @@ final class VMClassLoader * classes (those with a null ClassLoader), as well as the initial value for * every ClassLoader's default assertion status. * + * XXX - Not implemented yet; this requires native help. + * * @return the system-wide default assertion status - * @XXX Implement this for 1.4 compatibility. - static final native boolean defaultAssertionStatus(); */ + static final boolean defaultAssertionStatus() + { + return true; + } /** * The system default for package assertion status. This is used for all @@ -164,18 +271,26 @@ final class VMClassLoader * package names to Boolean.TRUE or Boolean.FALSE, with the unnamed package * represented as a null key. * + * XXX - Not implemented yet; this requires native help. + * * @return a (read-only) map for the default packageAssertionStatus - * @XXX Implement this for 1.4 compatibility. - static final native Map packageAssertionStatus(); */ + static final Map packageAssertionStatus() + { + return new HashMap(); + } /** * The system default for class assertion status. This is used for all * ClassLoader's classAssertionStatus defaults. It must be a map of * class names to Boolean.TRUE or Boolean.FALSE * + * XXX - Not implemented yet; this requires native help. + * * @return a (read-only) map for the default classAssertionStatus - * @XXX Implement this for 1.4 compatibility. - static final native Map classAssertionStatus(); */ + static final Map classAssertionStatus() + { + return new HashMap(); + } } diff --git a/vm/reference/java/lang/VMSecurityManager.java b/vm/reference/java/lang/VMSecurityManager.java index bc2ef1382..a70d049d9 100644 --- a/vm/reference/java/lang/VMSecurityManager.java +++ b/vm/reference/java/lang/VMSecurityManager.java @@ -1,5 +1,5 @@ -/* VMSecurityManager.java - Copyright (C) 1998 Free Software Foundation +/* VMSecurityManager.java -- Reference implementation of VM hooks for security + Copyright (C) 1998, 2002 Free Software Foundation This file is part of GNU Classpath. @@ -37,33 +37,32 @@ exception statement from your version. */ package java.lang; -import java.net.*; -import java.util.*; -import java.io.*; - /** - ** VMSecurityManager is a helper class for SecurityManager the VM must - ** implement. - ** - ** @author John Keiser - ** @version 1.1.0, 31 May 1998 - **/ -class VMSecurityManager { - /** Get a list of all the classes currently executing - ** methods on the Java stack. getClassContext()[0] is - ** the currently executing method - ** <STRONG>Spec Note:</STRONG> does not say whether - ** the stack will include the getClassContext() call or - ** the one just before it. - ** - ** @return an array containing all the methods on classes - ** on the Java execution stack. - **/ - static native Class[] getClassContext(); + * VMSecurityManager is a helper class for SecurityManager the VM must + * implement. + * + * @author John Keiser + * @author Eric Blake <ebb9@email.byu.edu> + */ +final class VMSecurityManager +{ + /** + * Get a list of all the classes currently executing methods on the + * Java stack. getClassContext()[0] is the currently executing method, ie. + * the method which called SecurityManager.getClassContext(). (Hint: you + * may need to pop off one or more frames: don't include SecurityManager + * or VMSecurityManager.getClassContext in your result. Also, be sure that + * you correctly handle the context if SecurityManager.getClassContext + * was invoked by reflection). + * + * @return an array of the declaring classes of each stack frame + */ + static native Class[] getClassContext(); - /** Get the current ClassLoader--the one nearest to the - ** top of the stack. - ** @return the current ClassLoader. - **/ - static native ClassLoader currentClassLoader(); + /** + * Get the current ClassLoader--the one nearest to the top of the stack. + * + * @return the current ClassLoader + */ + static native ClassLoader currentClassLoader(); } |