summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2002-02-23 09:19:52 +0000
committerEric Blake <ebb9@byu.net>2002-02-23 09:19:52 +0000
commit70f6e1ec80b4ffc5370564b2710ee194054da42f (patch)
tree9f2b7ce9aa35a53393b9876f6492f2ec90cfde62
parente746a862de38f2e1a5d53b17e633ad2400a7e6c8 (diff)
downloadclasspath-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--ChangeLog28
-rw-r--r--gnu/java/beans/BeanInfoEmbryo.java19
-rw-r--r--gnu/java/lang/ArrayHelper.java72
-rw-r--r--gnu/java/lang/ClassHelper.java186
-rw-r--r--java/lang/AssertionError.java148
-rw-r--r--java/lang/ClassLoader.java190
-rw-r--r--java/lang/Makefile.am2
-rw-r--r--java/lang/StackTraceElement.java259
-rwxr-xr-xvm/reference/java/lang/Class.java35
-rw-r--r--vm/reference/java/lang/Throwable.java162
-rw-r--r--vm/reference/java/lang/VMClassLoader.java131
-rw-r--r--vm/reference/java/lang/VMSecurityManager.java57
12 files changed, 893 insertions, 396 deletions
diff --git a/ChangeLog b/ChangeLog
index 5f7e0b4ce..16b589a2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>&lt;init&gt;</code>; if the execution point is in the class
+ * initializer, the name is <code>&lt;clinit&gt;</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();
}