summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/lang/reflect
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/lang/reflect')
-rw-r--r--libjava/classpath/java/lang/reflect/AccessibleObject.java159
-rw-r--r--libjava/classpath/java/lang/reflect/Array.java675
-rw-r--r--libjava/classpath/java/lang/reflect/GenericArrayType.java61
-rw-r--r--libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java62
-rw-r--r--libjava/classpath/java/lang/reflect/InvocationHandler.java137
-rw-r--r--libjava/classpath/java/lang/reflect/InvocationTargetException.java123
-rw-r--r--libjava/classpath/java/lang/reflect/Member.java100
-rw-r--r--libjava/classpath/java/lang/reflect/Modifier.java332
-rw-r--r--libjava/classpath/java/lang/reflect/ParameterizedType.java122
-rw-r--r--libjava/classpath/java/lang/reflect/Proxy.java1615
-rw-r--r--libjava/classpath/java/lang/reflect/README4
-rw-r--r--libjava/classpath/java/lang/reflect/ReflectPermission.java102
-rwxr-xr-xlibjava/classpath/java/lang/reflect/TODO4
-rw-r--r--libjava/classpath/java/lang/reflect/Type.java55
-rw-r--r--libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java128
-rw-r--r--libjava/classpath/java/lang/reflect/WildcardType.java115
-rw-r--r--libjava/classpath/java/lang/reflect/package.html47
17 files changed, 3841 insertions, 0 deletions
diff --git a/libjava/classpath/java/lang/reflect/AccessibleObject.java b/libjava/classpath/java/lang/reflect/AccessibleObject.java
new file mode 100644
index 00000000000..24418c971c7
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/AccessibleObject.java
@@ -0,0 +1,159 @@
+/* java.lang.reflect.AccessibleObject
+ Copyright (C) 2001, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * This class is the superclass of various reflection classes, and
+ * allows sufficiently trusted code to bypass normal restrictions to
+ * do necessary things like invoke private methods outside of the
+ * class during Serialization. If you don't have a good reason
+ * to mess with this, don't try. Fortunately, there are adequate
+ * security checks before you can set a reflection object as accessible.
+ *
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Field
+ * @see Constructor
+ * @see Method
+ * @see ReflectPermission
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public class AccessibleObject
+{
+ /**
+ * True if this object is marked accessible, which means the reflected
+ * object bypasses normal security checks.
+ */
+ // default visibility for use by inherited classes
+ boolean flag = false;
+
+ /**
+ * Only the three reflection classes that extend this can create an
+ * accessible object. This is not serializable for security reasons.
+ */
+ protected AccessibleObject()
+ {
+ }
+
+ /**
+ * Return the accessibility status of this object.
+ *
+ * @return true if this object bypasses security checks
+ */
+ public boolean isAccessible()
+ {
+ return flag;
+ }
+
+ /**
+ * Convenience method to set the flag on a number of objects with a single
+ * security check. If a security manager exists, it is checked for
+ * <code>ReflectPermission("suppressAccessChecks")</code>.<p>
+ *
+ * It is forbidden to set the accessibility flag to true on any constructor
+ * for java.lang.Class. This will result in a SecurityException. If the
+ * SecurityException is thrown for any of the passed AccessibleObjects,
+ * the accessibility flag will be set on AccessibleObjects in the array prior
+ * to the one which resulted in the exception.
+ *
+ * @param array the array of accessible objects
+ * @param flag the desired state of accessibility, true to bypass security
+ * @throws NullPointerException if array is null
+ * @throws SecurityException if the request is denied
+ * @see SecurityManager#checkPermission(java.security.Permission)
+ * @see RuntimePermission
+ */
+ public static void setAccessible(AccessibleObject[] array, boolean flag)
+ {
+ checkPermission();
+ for (int i = 0; i < array.length; i++)
+ array[i].secureSetAccessible(flag);
+ }
+
+ /**
+ * Sets the accessibility flag for this reflection object. If a security
+ * manager exists, it is checked for
+ * <code>ReflectPermission("suppressAccessChecks")</code>.<p>
+ *
+ * It is forbidden to set the accessibility flag to true on any constructor for
+ * java.lang.Class. This will result in a SecurityException.
+ *
+ * @param flag the desired state of accessibility, true to bypass security
+ * @throws NullPointerException if array is null
+ * @throws SecurityException if the request is denied
+ * @see SecurityManager#checkPermission(java.security.Permission)
+ * @see RuntimePermission
+ */
+ public void setAccessible(boolean flag)
+ {
+ checkPermission();
+ secureSetAccessible(flag);
+ }
+
+ /**
+ * Performs the specified security check, for
+ * <code>ReflectPermission("suppressAccessChecks")</code>.
+ *
+ * @throws SecurityException if permission is denied
+ */
+ private static void checkPermission()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new ReflectPermission("suppressAccessChecks"));
+ }
+
+ /**
+ * Performs the actual accessibility change, this must always be invoked
+ * after calling checkPermission.
+ *
+ * @param flag the desired status
+ * @throws SecurityException if flag is true and this is a constructor
+ * for <code>java.lang.Class</code>.
+ */
+ private void secureSetAccessible(boolean flag)
+ {
+ if (flag &&
+ (this instanceof Constructor
+ && ((Constructor) this).getDeclaringClass() == Class.class))
+ throw new SecurityException("Cannot make object accessible: " + this);
+ this.flag = flag;
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/Array.java b/libjava/classpath/java/lang/reflect/Array.java
new file mode 100644
index 00000000000..35c77da369a
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Array.java
@@ -0,0 +1,675 @@
+/* java.lang.reflect.Array - manipulate arrays by reflection
+ Copyright (C) 1998, 1999, 2001, 2003, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+import gnu.classpath.Configuration;
+
+/**
+ * Array holds static helper functions that allow you to create and
+ * manipulate arrays by reflection. Operations know how to perform widening
+ * conversions, but throw {@link IllegalArgumentException} if you attempt
+ * a narrowing conversion. Also, when accessing primitive arrays, this
+ * class performs object wrapping and unwrapping as necessary.<p>
+ *
+ * <B>Note:</B> This class returns and accepts types as Classes, even
+ * primitive types; there are Class types defined that represent each
+ * different primitive type. They are <code>java.lang.Boolean.TYPE,
+ * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
+ * byte.class</code>, etc. These are not to be confused with the
+ * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
+ * real classes. Note also that the shorthand <code>Object[].class</code>
+ * is a convenient way to get array Classes.<p>
+ *
+ * <B>Performance note:</B> This class performs best when it does not have
+ * to convert primitive types. The further along the chain it has to convert,
+ * the worse performance will be. You're best off using the array as whatever
+ * type it already is, and then converting the result. You will do even
+ * worse if you do this and use the generic set() function.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Per Bothner (bothner@cygnus.com)
+ * @see java.lang.Boolean#TYPE
+ * @see java.lang.Byte#TYPE
+ * @see java.lang.Short#TYPE
+ * @see java.lang.Character#TYPE
+ * @see java.lang.Integer#TYPE
+ * @see java.lang.Long#TYPE
+ * @see java.lang.Float#TYPE
+ * @see java.lang.Double#TYPE
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Array
+{
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("javalangreflect");
+ }
+ }
+
+ /**
+ * This class is uninstantiable.
+ */
+ private Array()
+ {
+ }
+
+ /**
+ * Creates a new single-dimensioned array.
+ * @param componentType the type of the array to create
+ * @param length the length of the array to create
+ * @return the created array, cast to an Object
+ * @throws NullPointerException if <code>componentType</code> is null
+ * @throws IllegalArgumentException if <code>componentType</code> is
+ * <code>Void.TYPE</code>
+ * @throws NegativeArraySizeException when length is less than 0
+ * @throws OutOfMemoryError if memory allocation fails
+ */
+ public static Object newInstance(Class componentType, int length)
+ {
+ if (! componentType.isPrimitive())
+ return createObjectArray(componentType, length);
+ if (componentType == boolean.class)
+ return new boolean[length];
+ if (componentType == byte.class)
+ return new byte[length];
+ if (componentType == char.class)
+ return new char[length];
+ if (componentType == short.class)
+ return new short[length];
+ if (componentType == int.class)
+ return new int[length];
+ if (componentType == long.class)
+ return new long[length];
+ if (componentType == float.class)
+ return new float[length];
+ if (componentType == double.class)
+ return new double[length];
+ // assert componentType == void.class
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Creates a new multi-dimensioned array. The new array has the same
+ * component type as the argument class, and the number of dimensions
+ * in the new array is the sum of the dimensions of the argument class
+ * and the length of the argument dimensions. Virtual Machine limitations
+ * forbid too many dimensions (usually 255 is the maximum); but even
+ * 50 dimensions of 2 elements in each dimension would exceed your memory
+ * long beforehand!
+ *
+ * @param componentType the type of the array to create.
+ * @param dimensions the dimensions of the array to create. Each element
+ * in <code>dimensions</code> makes another dimension of the new
+ * array. Thus, <code>Array.newInstance(java.lang.Boolean,
+ * new int[]{1,2,3})</code> is the same as
+ * <code>new java.lang.Boolean[1][2][3]</code>
+ * @return the created array, cast to an Object
+ * @throws NullPointerException if componentType or dimension is null
+ * @throws IllegalArgumentException if the the size of
+ * <code>dimensions</code> is 0 or exceeds the maximum number of
+ * array dimensions in the VM; or if componentType is Void.TYPE
+ * @throws NegativeArraySizeException when any of the dimensions is less
+ * than 0
+ * @throws OutOfMemoryError if memory allocation fails
+ */
+ public static Object newInstance(Class componentType, int[] dimensions)
+ {
+ if (dimensions.length <= 0)
+ throw new IllegalArgumentException ("Empty dimensions array.");
+ return createMultiArray(componentType, dimensions,
+ dimensions.length - 1);
+ }
+
+ /**
+ * Gets the array length.
+ * @param array the array
+ * @return the length of the array
+ * @throws IllegalArgumentException if <code>array</code> is not an array
+ * @throws NullPointerException if <code>array</code> is null
+ */
+ public static int getLength(Object array)
+ {
+ if (array instanceof Object[])
+ return ((Object[]) array).length;
+ if (array instanceof boolean[])
+ return ((boolean[]) array).length;
+ if (array instanceof byte[])
+ return ((byte[]) array). length;
+ if (array instanceof char[])
+ return ((char[]) array).length;
+ if (array instanceof short[])
+ return ((short[]) array).length;
+ if (array instanceof int[])
+ return ((int[]) array).length;
+ if (array instanceof long[])
+ return ((long[]) array).length;
+ if (array instanceof float[])
+ return ((float[]) array).length;
+ if (array instanceof double[])
+ return ((double[]) array).length;
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of an array. Primitive elements will be wrapped in
+ * the corresponding class type.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not an array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #getBoolean(Object, int)
+ * @see #getByte(Object, int)
+ * @see #getChar(Object, int)
+ * @see #getShort(Object, int)
+ * @see #getInt(Object, int)
+ * @see #getLong(Object, int)
+ * @see #getFloat(Object, int)
+ * @see #getDouble(Object, int)
+ */
+ public static Object get(Object array, int index)
+ {
+ if (array instanceof Object[])
+ return ((Object[]) array)[index];
+ if (array instanceof boolean[])
+ return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE;
+ if (array instanceof byte[])
+ return new Byte(((byte[]) array)[index]);
+ if (array instanceof char[])
+ return new Character(((char[]) array)[index]);
+ if (array instanceof short[])
+ return new Short(((short[]) array)[index]);
+ if (array instanceof int[])
+ return new Integer(((int[]) array)[index]);
+ if (array instanceof long[])
+ return new Long(((long[]) array)[index]);
+ if (array instanceof float[])
+ return new Float(((float[]) array)[index]);
+ if (array instanceof double[])
+ return new Double(((double[]) array)[index]);
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of a boolean array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the boolean element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a boolean
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static boolean getBoolean(Object array, int index)
+ {
+ if (array instanceof boolean[])
+ return ((boolean[]) array)[index];
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of a byte array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the byte element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static byte getByte(Object array, int index)
+ {
+ if (array instanceof byte[])
+ return ((byte[]) array)[index];
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of a char array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the char element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a char
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static char getChar(Object array, int index)
+ {
+ if (array instanceof char[])
+ return ((char[]) array)[index];
+ if (array == null)
+ throw new NullPointerException();
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Gets an element of a short array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the short element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte
+ * or char array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static short getShort(Object array, int index)
+ {
+ if (array instanceof short[])
+ return ((short[]) array)[index];
+ return getByte(array, index);
+ }
+
+ /**
+ * Gets an element of an int array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the int element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * char, short, or int array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static int getInt(Object array, int index)
+ {
+ if (array instanceof int[])
+ return ((int[]) array)[index];
+ if (array instanceof char[])
+ return ((char[]) array)[index];
+ return getShort(array, index);
+ }
+
+ /**
+ * Gets an element of a long array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the long element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * char, short, int, or long array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static long getLong(Object array, int index)
+ {
+ if (array instanceof long[])
+ return ((long[]) array)[index];
+ return getInt(array, index);
+ }
+
+ /**
+ * Gets an element of a float array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the float element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * char, short, int, long, or float array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static float getFloat(Object array, int index)
+ {
+ if (array instanceof float[])
+ return ((float[]) array)[index];
+ return getLong(array, index);
+ }
+
+ /**
+ * Gets an element of a double array.
+ *
+ * @param array the array to access
+ * @param index the array index to access
+ * @return the double element at <code>array[index]</code>
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * char, short, int, long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #get(Object, int)
+ */
+ public static double getDouble(Object array, int index)
+ {
+ if (array instanceof double[])
+ return ((double[]) array)[index];
+ return getFloat(array, index);
+ }
+
+ /**
+ * Sets an element of an array. If the array is primitive, then the new
+ * value is unwrapped and widened.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not an array,
+ * or the array is primitive and unwrapping value fails, or the
+ * value is not assignable to the array component type
+ * @throws NullPointerException if array is null, or if array is primitive
+ * and value is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #setBoolean(Object, int, boolean)
+ * @see #setByte(Object, int, byte)
+ * @see #setChar(Object, int, char)
+ * @see #setShort(Object, int, short)
+ * @see #setInt(Object, int, int)
+ * @see #setLong(Object, int, long)
+ * @see #setFloat(Object, int, float)
+ * @see #setDouble(Object, int, double)
+ */
+ public static void set(Object array, int index, Object value)
+ {
+ if (array instanceof Object[])
+ {
+ // Too bad the API won't let us throw the easier ArrayStoreException!
+ if (value != null
+ && ! array.getClass().getComponentType().isInstance(value))
+ throw new IllegalArgumentException();
+ ((Object[]) array)[index] = value;
+ }
+ else if (value instanceof Byte)
+ setByte(array, index, ((Byte) value).byteValue());
+ else if (value instanceof Short)
+ setShort(array, index, ((Short) value).shortValue());
+ else if (value instanceof Integer)
+ setInt(array, index, ((Integer) value).intValue());
+ else if (value instanceof Long)
+ setLong(array, index, ((Long) value).longValue());
+ else if (value instanceof Float)
+ setFloat(array, index, ((Float) value).floatValue());
+ else if (value instanceof Double)
+ setDouble(array, index, ((Double) value).doubleValue());
+ else if (value instanceof Character)
+ setChar(array, index, ((Character) value).charValue());
+ else if (value instanceof Boolean)
+ setBoolean(array, index, ((Boolean) value).booleanValue());
+ else if (array == null)
+ throw new NullPointerException();
+ else
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Sets an element of a boolean array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a boolean
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setBoolean(Object array, int index, boolean value)
+ {
+ if (array instanceof boolean[])
+ ((boolean[]) array)[index] = value;
+ else if (array == null)
+ throw new NullPointerException();
+ else
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Sets an element of a byte array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a byte,
+ * short, int, long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setByte(Object array, int index, byte value)
+ {
+ if (array instanceof byte[])
+ ((byte[]) array)[index] = value;
+ else
+ setShort(array, index, value);
+ }
+
+ /**
+ * Sets an element of a char array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a char,
+ * int, long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setChar(Object array, int index, char value)
+ {
+ if (array instanceof char[])
+ ((char[]) array)[index] = value;
+ else
+ setInt(array, index, value);
+ }
+
+ /**
+ * Sets an element of a short array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a short,
+ * int, long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setShort(Object array, int index, short value)
+ {
+ if (array instanceof short[])
+ ((short[]) array)[index] = value;
+ else
+ setInt(array, index, value);
+ }
+
+ /**
+ * Sets an element of an int array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not an int,
+ * long, float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setInt(Object array, int index, int value)
+ {
+ if (array instanceof int[])
+ ((int[]) array)[index] = value;
+ else
+ setLong(array, index, value);
+ }
+
+ /**
+ * Sets an element of a long array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a long,
+ * float, or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setLong(Object array, int index, long value)
+ {
+ if (array instanceof long[])
+ ((long[]) array)[index] = value;
+ else
+ setFloat(array, index, value);
+ }
+
+ /**
+ * Sets an element of a float array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a float
+ * or double array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setFloat(Object array, int index, float value)
+ {
+ if (array instanceof float[])
+ ((float[]) array)[index] = value;
+ else
+ setDouble(array, index, value);
+ }
+
+ /**
+ * Sets an element of a double array.
+ *
+ * @param array the array to set a value of
+ * @param index the array index to set the value to
+ * @param value the value to set
+ * @throws IllegalArgumentException if <code>array</code> is not a double
+ * array
+ * @throws NullPointerException if <code>array</code> is null
+ * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of
+ * bounds
+ * @see #set(Object, int, Object)
+ */
+ public static void setDouble(Object array, int index, double value)
+ {
+ if (array instanceof double[])
+ ((double[]) array)[index] = value;
+ else if (array == null)
+ throw new NullPointerException();
+ else
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Dynamically and recursively create a multi-dimensioned array of objects.
+ *
+ * @param type guaranteed to be a valid object type
+ * @param dimensions the dimensions of the array
+ * @param index index of the current dimension to build
+ * @return the new multi-dimensioned array
+ * @throws NegativeArraySizeException if any entry of dimensions is negative
+ * @throws OutOfMemoryError if memory allocation fails
+ */
+ // This would be faster if implemented natively, using the multianewarray
+ // bytecode instead of this recursive call
+ private static Object createMultiArray(Class type, int[] dimensions,
+ int index)
+ {
+ if (index == 0)
+ return newInstance(type, dimensions[0]);
+
+ Object toAdd = createMultiArray(type, dimensions, index - 1);
+ Class thisType = toAdd.getClass();
+ Object[] retval
+ = (Object[]) createObjectArray(thisType, dimensions[index]);
+ if (dimensions[index] > 0)
+ retval[0] = toAdd;
+ int i = dimensions[index];
+ while (--i > 0)
+ retval[i] = createMultiArray(type, dimensions, index - 1);
+ return retval;
+ }
+
+ /**
+ * Dynamically create an array of objects.
+ *
+ * @param type guaranteed to be a valid object type
+ * @param dim the length of the array
+ * @return the new array
+ * @throws NegativeArraySizeException if dim is negative
+ * @throws OutOfMemoryError if memory allocation fails
+ */
+ private static native Object createObjectArray(Class type, int dim);
+}
diff --git a/libjava/classpath/java/lang/reflect/GenericArrayType.java b/libjava/classpath/java/lang/reflect/GenericArrayType.java
new file mode 100644
index 00000000000..8dc33a796c5
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/GenericArrayType.java
@@ -0,0 +1,61 @@
+/* GenericArrayType.java - Represent an array type with a generic component
+ Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * Represents the type of an array's components, which may be
+ * either a parameterized type or a type variable.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface GenericArrayType
+ extends Type
+{
+
+ /**
+ * Returns the <code>Type</code> of the components within the array.
+ *
+ * @return a <code>Type</code> instance representing the type of
+ * the array's components.
+ */
+ Type getGenericComponentType();
+
+}
diff --git a/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java b/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java
new file mode 100644
index 00000000000..ab6928de6c0
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java
@@ -0,0 +1,62 @@
+/* GenericSignatureFormatError.java - Thrown when a signature is malformed.
+ Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * Thrown on encountering a syntactically malformed signature in
+ * a reflective method. During reflection, the generic type signature
+ * of a type, method or constructor may be interpreted by the virtual
+ * machine. This error is thrown if this operation fails.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class GenericSignatureFormatError
+ extends ClassFormatError
+{
+
+ /**
+ * Constructs a new <code>GenericSignatureFormatError</code>.
+ */
+ public GenericSignatureFormatError()
+ {
+ }
+
+}
diff --git a/libjava/classpath/java/lang/reflect/InvocationHandler.java b/libjava/classpath/java/lang/reflect/InvocationHandler.java
new file mode 100644
index 00000000000..208e621eedc
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/InvocationHandler.java
@@ -0,0 +1,137 @@
+/* java.lang.reflect.InvocationHandler - dynamically executes methods in
+ proxy instances
+ Copyright (C) 2001 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * This interface defines an invocation handler. Suppose you are using
+ * reflection, and found a method that requires that its parameter
+ * be an object of a given interface. You want to call this method,
+ * but have no idea what classes implement that interface. So, you can
+ * create a {@link Proxy} instance, a convenient way to dynamically
+ * generate a class that meets all the necessary properties of that
+ * interface. But in order for the proxy instance to do any good, it
+ * needs to know what to do when interface methods are invoked! So,
+ * this interface is basically a cool wrapper that provides runtime
+ * code generation needed by proxy instances.
+ *
+ * <p>While this interface was designed for use by Proxy, it will also
+ * work on any object in general.</p>
+ *
+ * <p>Hints for implementing this class:</p>
+ *
+ * <ul>
+ * <li>Don't forget that Object.equals, Object.hashCode, and
+ * Object.toString will call this handler. In particular,
+ * a naive call to proxy.equals, proxy.hashCode, or proxy.toString
+ * will put you in an infinite loop. And remember that string
+ * concatenation also invokes toString.</li>
+ * <li>Obey the contract of the Method object you are handling, or
+ * the proxy instance will be forced to throw a
+ * {@link NullPointerException}, {@link ClassCastException},
+ * or {@link UndeclaredThrowableException}.</li>
+ * <li>Be prepared to wrap/unwrap primitives as necessary.</li>
+ * <li>The Method object may be owned by a different interface than
+ * what was actually used as the qualifying type of the method
+ * invocation in the Java source code. This means that it might
+ * not always be safe to throw an exception listed as belonging
+ * to the method's throws clause.</li>
+ * </ul>
+ *
+ * <p><small>For a fun time, create an InvocationHandler that handles the
+ * methods of a proxy instance of the InvocationHandler interface!</small></p>
+ *
+ * @see Proxy
+ * @see UndeclaredThrowableException
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public interface InvocationHandler
+{
+ /**
+ * When a method is invoked on a proxy instance, it is wrapped and
+ * this method is called instead, so that you may decide at runtime
+ * how the original method should behave.
+ *
+ * @param proxy the instance that the wrapped method should be
+ * invoked on. When this method is called by a Proxy object,
+ * `proxy' will be an instance of {@link Proxy}, and oddly enough,
+ * <code>Proxy.getInvocationHandler(proxy)</code> will return
+ * <code>this</code>!
+ * @param method the reflected method to invoke on the proxy.
+ * When this method is called by a Proxy object, 'method'
+ * will be the reflection object owned by the declaring
+ * class or interface, which may be a supertype of the
+ * interfaces the proxy directly implements.
+ * @param args the arguments passed to the original method, or
+ * <code>null</code> if the method takes no arguments.
+ * (But also be prepared to handle a 0-length array).
+ * Arguments of primitive type, such as <code>boolean</code>
+ * or <code>int</code>, are wrapped in the appropriate
+ * class such as {@link Boolean} or {@link Integer}.
+ * @return whatever is necessary to return from the wrapped method.
+ * If the wrapped method is <code>void</code>, the proxy
+ * instance will ignore it. If the wrapped method returns
+ * a primitive, this must be the correct wrapper type whose value
+ * is exactly assignable to the appropriate type (no widening
+ * will be performed); a null object in this case causes a
+ * {@link NullPointerException}. In all remaining cases, if
+ * the returned object is not assignment compatible to the
+ * declared type of the original method, the proxy instance
+ * will generate a {@link ClassCastException}.
+ * @throws Throwable this interface is listed as throwing anything,
+ * but the implementation should only throw unchecked
+ * exceptions and exceptions listed in the throws clause of
+ * all methods being overridden by the proxy instance. If
+ * something is thrown that is not compatible with the throws
+ * clause of all overridden methods, the proxy instance will
+ * wrap the exception in an UndeclaredThrowableException.
+ * Note that an exception listed in the throws clause of the
+ * `method' parameter might not be declared in additional
+ * interfaces also implemented by the proxy object.
+ *
+ * @see Proxy
+ * @see UndeclaredThrowableException
+ */
+ Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable;
+
+}
diff --git a/libjava/classpath/java/lang/reflect/InvocationTargetException.java b/libjava/classpath/java/lang/reflect/InvocationTargetException.java
new file mode 100644
index 00000000000..af79d3a199d
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/InvocationTargetException.java
@@ -0,0 +1,123 @@
+/* InvocationTargetException.java -- Wrapper exception for reflection
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * InvocationTargetException is sort of a way to "wrap" whatever exception
+ * comes up when a method or constructor is called via Reflection. As of
+ * JDK 1.4, it was retrofitted to match the exception chaining of all other
+ * exceptions, but <code>getTargetException()</code> still works.
+ *
+ * @author John Keiser
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Method#invoke(Object,Object[])
+ * @see Constructor#newInstance(Object[])
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public class InvocationTargetException extends Exception
+{
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 4085088731926701167L;
+
+ /**
+ * The chained exception. This field is only around for serial compatibility.
+ *
+ * @serial the chained exception
+ */
+ private final Throwable target;
+
+ /**
+ * Construct an exception with null as the cause. The cause is initialized
+ * to null.
+ */
+ protected InvocationTargetException()
+ {
+ this(null, null);
+ }
+
+ /**
+ * Create an <code>InvocationTargetException</code> using another
+ * exception.
+ *
+ * @param targetException the exception to wrap
+ */
+ public InvocationTargetException(Throwable targetException)
+ {
+ this(targetException, null);
+ }
+
+ /**
+ * Create an <code>InvocationTargetException</code> using another
+ * exception and an error message.
+ *
+ * @param targetException the exception to wrap
+ * @param err an extra reason for the exception-throwing
+ */
+ public InvocationTargetException(Throwable targetException, String err)
+ {
+ super(err, targetException);
+ target = targetException;
+ }
+
+ /**
+ * Get the wrapped (targeted) exception.
+ *
+ * @return the targeted exception
+ * @see #getCause()
+ */
+ public Throwable getTargetException()
+ {
+ return target;
+ }
+
+ /**
+ * Returns the cause of this exception (which may be null).
+ *
+ * @return the cause
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return target;
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/Member.java b/libjava/classpath/java/lang/reflect/Member.java
new file mode 100644
index 00000000000..9983b275a94
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Member.java
@@ -0,0 +1,100 @@
+/* java.lang.reflect.Member - common query methods in reflection
+ Copyright (C) 1998, 1999, 2001, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * Member is an interface that represents any member of a class (field or
+ * method) or a constructor. You can get information about the declaring
+ * class, name or modifiers of the member with this interface.
+ *
+ * @author John Keiser
+ * @author Per Bothner (bothner@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Class
+ * @see Field
+ * @see Method
+ * @see Constructor
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public interface Member
+{
+ /**
+ * Represents all members, whether public, private, protected or
+ * package-protected, but only which are declared in this class.
+ * Used in SecurityManager.checkMemberAccess() to determine the
+ * type of members to access.
+ * @see SecurityManager#checkMemberAccess()
+ */
+ int DECLARED = 1;
+
+ /**
+ * Represents public members only, but includes all inherited members.
+ * Used in SecurityManager.checkMemberAccess() to determine the type of
+ * members to access.
+ * @see SecurityManager#checkMemberAccess()
+ */
+ int PUBLIC = 0;
+
+ /**
+ * Gets the class that declared this member. This is not the class where
+ * this method was called, or even the class where this Member object
+ * came to life, but the class that declares the member this represents.
+ *
+ * @return the class that declared this member
+ */
+ Class getDeclaringClass();
+
+ /**
+ * Gets the simple name of this member. This will be a valid Java
+ * identifier, with no qualification.
+ *
+ * @return the name of this member
+ */
+ String getName();
+
+ /**
+ * Gets the modifiers this member uses. Use the <code>Modifier</code>
+ * class to interpret the values.
+ *
+ * @return an integer representing the modifiers to this Member
+ * @see Modifier
+ */
+ int getModifiers();
+}
diff --git a/libjava/classpath/java/lang/reflect/Modifier.java b/libjava/classpath/java/lang/reflect/Modifier.java
new file mode 100644
index 00000000000..efc88c941db
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Modifier.java
@@ -0,0 +1,332 @@
+/* java.lang.reflect.Modifier
+ Copyright (C) 1998, 1999, 2001, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * Modifier is a helper class with static methods to determine whether an
+ * int returned from getModifiers() represents static, public, protected,
+ * native, final, etc... and provides an additional method to print
+ * out all of the modifiers in an int in order.
+ * <p>
+ * The methods in this class use the bitmask values in the VM spec to
+ * determine the modifiers of an int. This means that a VM must return a
+ * standard mask, conformant with the VM spec. I don't know if this is how
+ * Sun does it, but I'm willing to bet money that it is.
+ *
+ * @author John Keiser
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Member#getModifiers()
+ * @see Method#getModifiers()
+ * @see Field#getModifiers()
+ * @see Constructor#getModifiers()
+ * @see Class#getModifiers()
+ * @since 1.1
+ */
+public class Modifier
+{
+ /** <STRONG>This constructor really shouldn't be here ... there are no
+ * instance methods or variables of this class, so instantiation is
+ * worthless. However, this function is in the 1.1 spec, so it is added
+ * for completeness.</STRONG>
+ */
+ public Modifier()
+ {
+ }
+
+ /**
+ * Public: accessible from any other class.
+ */
+ public static final int PUBLIC = 0x0001;
+
+ /**
+ * Private: accessible only from the same enclosing class.
+ */
+ public static final int PRIVATE = 0x0002;
+
+ /**
+ * Protected: accessible only to subclasses, or within the package.
+ */
+ public static final int PROTECTED = 0x0004;
+
+ /**
+ * Static:<br><ul>
+ * <li>Class: no enclosing instance for nested class.</li>
+ * <li>Field or Method: can be accessed or invoked without an
+ * instance of the declaring class.</li>
+ * </ul>
+ */
+ public static final int STATIC = 0x0008;
+
+ /**
+ * Final:<br><ul>
+ * <li>Class: no subclasses allowed.</li>
+ * <li>Field: cannot be changed.</li>
+ * <li>Method: cannot be overriden.</li>
+ * </ul>
+ */
+ public static final int FINAL = 0x0010;
+
+ /**
+ * Synchronized: Method: lock the class while calling this method.
+ */
+ public static final int SYNCHRONIZED = 0x0020;
+
+ /**
+ * Volatile: Field: cannot be cached.
+ */
+ public static final int VOLATILE = 0x0040;
+
+ /**
+ * Transient: Field: not serialized or deserialized.
+ */
+ public static final int TRANSIENT = 0x0080;
+
+ /**
+ * Native: Method: use JNI to call this method.
+ */
+ public static final int NATIVE = 0x0100;
+
+ /**
+ * Interface: Class: is an interface.
+ */
+ public static final int INTERFACE = 0x0200;
+
+ /**
+ * Abstract:<br><ul>
+ * <li>Class: may not be instantiated.</li>
+ * <li>Method: may not be called.</li>
+ * </ul>
+ */
+ public static final int ABSTRACT = 0x0400;
+
+ /**
+ * Strictfp: Method: expressions are FP-strict.<p>
+ * Also used as a modifier for classes, to mean that all initializers
+ * and constructors are FP-strict, but does not show up in
+ * Class.getModifiers.
+ */
+ public static final int STRICT = 0x0800;
+
+
+ /**
+ * Super - treat invokespecial as polymorphic so that super.foo() works
+ * according to the JLS. This is a reuse of the synchronized constant
+ * to patch a hole in JDK 1.0. *shudder*.
+ */
+ static final int SUPER = 0x0020;
+
+ /**
+ * All the flags, only used by code in this package.
+ */
+ static final int ALL_FLAGS = 0xfff;
+
+ /**
+ * Check whether the given modifier is abstract.
+ * @param mod the modifier.
+ * @return <code>true</code> if abstract, <code>false</code> otherwise.
+ */
+ public static boolean isAbstract(int mod)
+ {
+ return (mod & ABSTRACT) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is final.
+ * @param mod the modifier.
+ * @return <code>true</code> if final, <code>false</code> otherwise.
+ */
+ public static boolean isFinal(int mod)
+ {
+ return (mod & FINAL) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is an interface.
+ * @param mod the modifier.
+ * @return <code>true</code> if an interface, <code>false</code> otherwise.
+ */
+ public static boolean isInterface(int mod)
+ {
+ return (mod & INTERFACE) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is native.
+ * @param mod the modifier.
+ * @return <code>true</code> if native, <code>false</code> otherwise.
+ */
+ public static boolean isNative(int mod)
+ {
+ return (mod & NATIVE) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is private.
+ * @param mod the modifier.
+ * @return <code>true</code> if private, <code>false</code> otherwise.
+ */
+ public static boolean isPrivate(int mod)
+ {
+ return (mod & PRIVATE) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is protected.
+ * @param mod the modifier.
+ * @return <code>true</code> if protected, <code>false</code> otherwise.
+ */
+ public static boolean isProtected(int mod)
+ {
+ return (mod & PROTECTED) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is public.
+ * @param mod the modifier.
+ * @return <code>true</code> if public, <code>false</code> otherwise.
+ */
+ public static boolean isPublic(int mod)
+ {
+ return (mod & PUBLIC) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is static.
+ * @param mod the modifier.
+ * @return <code>true</code> if static, <code>false</code> otherwise.
+ */
+ public static boolean isStatic(int mod)
+ {
+ return (mod & STATIC) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is strictfp.
+ * @param mod the modifier.
+ * @return <code>true</code> if strictfp, <code>false</code> otherwise.
+ */
+ public static boolean isStrict(int mod)
+ {
+ return (mod & STRICT) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is synchronized.
+ * @param mod the modifier.
+ * @return <code>true</code> if synchronized, <code>false</code> otherwise.
+ */
+ public static boolean isSynchronized(int mod)
+ {
+ return (mod & SYNCHRONIZED) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is transient.
+ * @param mod the modifier.
+ * @return <code>true</code> if transient, <code>false</code> otherwise.
+ */
+ public static boolean isTransient(int mod)
+ {
+ return (mod & TRANSIENT) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is volatile.
+ * @param mod the modifier.
+ * @return <code>true</code> if volatile, <code>false</code> otherwise.
+ */
+ public static boolean isVolatile(int mod)
+ {
+ return (mod & VOLATILE) != 0;
+ }
+
+ /**
+ * Get a string representation of all the modifiers represented by the
+ * given int. The keywords are printed in this order:
+ * <code>&lt;public|protected|private&gt; abstract static final transient
+ * volatile synchronized native strictfp interface</code>.
+ *
+ * @param mod the modifier.
+ * @return the String representing the modifiers.
+ */
+ public static String toString(int mod)
+ {
+ return toString(mod, new StringBuffer()).toString();
+ }
+
+ /**
+ * Package helper method that can take a StringBuffer.
+ * @param mod the modifier
+ * @param r the StringBuffer to which the String representation is appended
+ * @return r, with information appended
+ */
+ static StringBuffer toString(int mod, StringBuffer r)
+ {
+ if (isPublic(mod))
+ r.append("public ");
+ if (isProtected(mod))
+ r.append("protected ");
+ if (isPrivate(mod))
+ r.append("private ");
+ if (isAbstract(mod))
+ r.append("abstract ");
+ if (isStatic(mod))
+ r.append("static ");
+ if (isFinal(mod))
+ r.append("final ");
+ if (isTransient(mod))
+ r.append("transient ");
+ if (isVolatile(mod))
+ r.append("volatile ");
+ if (isSynchronized(mod))
+ r.append("synchronized ");
+ if (isNative(mod))
+ r.append("native ");
+ if (isStrict(mod))
+ r.append("strictfp ");
+ if (isInterface(mod))
+ r.append("interface ");
+
+ // Trim trailing space.
+ if ((mod & ALL_FLAGS) != 0)
+ r.setLength(r.length() - 1);
+ return r;
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/ParameterizedType.java b/libjava/classpath/java/lang/reflect/ParameterizedType.java
new file mode 100644
index 00000000000..61081c962db
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/ParameterizedType.java
@@ -0,0 +1,122 @@
+/* ParameterizedType.java -- Represents parameterized types e.g. List<String>
+ Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * <p>
+ * Represents a type which is parameterized over one or more other
+ * types. For example, <code>List&lt;Integer&gt;</code> is a parameterized
+ * type, with <code>List</code> parameterized over the type
+ * <code>Integer</code>.
+ * </p>
+ * <p>
+ * Instances of this classes are created as needed, during reflection.
+ * On creating a parameterized type, <code>p</code>, the
+ * <code>GenericTypeDeclaration</code> corresponding to <code>p</code>
+ * is created and resolved. Each type argument of <code>p</code>
+ * is then created recursively; details of this process are availble
+ * in the documentation of <code>TypeVariable</code>. This creation
+ * process only happens once; repetition has no effect.
+ * </p>
+ * <p>
+ * Implementors of this interface must implement an appropriate
+ * <code>equals()</code> method. This method should equate any
+ * two instances of the implementing class that have the same
+ * <code>GenericTypeDeclaration</code> and <code>Type</code>
+ * parameters.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @see GenericTypeDeclaration
+ * @see TypeVariable
+ * @since 1.5
+ */
+public interface ParameterizedType
+ extends Type
+{
+
+ /**
+ * <p>
+ * Returns an array of <code>Type</code> objects, which gives
+ * the parameters of this type.
+ * </p>
+ * <p>
+ * <strong>Note</code>: the returned array may be empty. This
+ * occurs if the supposed <code>ParameterizedType</code> is simply
+ * a normal type wrapped inside a parameterized type.
+ * </p>
+ *
+ * @return an array of <code>Type</code>s, representing the arguments
+ * of this type.
+ * @throws TypeNotPresentException if any of the types referred to by
+ * the parameters of this type do not actually exist.
+ * @throws MalformedParameterizedTypeException if any of the types
+ * refer to a type which can not be instantiated.
+ */
+ Type[] getActualTypeArguments();
+
+ /**
+ * Returns the type of which this type is a member. For example,
+ * in <code>Top&lt;String&gt;.Bottom&lt;Integer&gt;</code>,
+ * <code>Bottom&lt;Integer&gt;</code> is a member of
+ * <code>Top&lt;String&gt;</code>, and so the latter is returned
+ * by this method. Calling this method on top-level types (such as
+ * <code>Top&lt;String&gt;</code>) returns null.
+ *
+ * @return the type which owns this type.
+ * @throws TypeNotPresentException if the owner type referred to by
+ * this type do not actually exist.
+ * @throws MalformedParameterizedTypeException if the owner type
+ * referred to by this type can not be instantiated.
+ */
+ Type getOwnerType();
+
+ /**
+ * Returns a version of this type without parameters, which corresponds
+ * to the class or interface which declared the type. For example,
+ * the raw type corresponding to <code>List&lt;Double&gt;</code>
+ * is <code>List</code>, which was declared by the <code>List</code>
+ * class.
+ *
+ * @return the raw variant of this type (i.e. the type without
+ * parameters).
+ */
+ Type getRawType();
+
+}
diff --git a/libjava/classpath/java/lang/reflect/Proxy.java b/libjava/classpath/java/lang/reflect/Proxy.java
new file mode 100644
index 00000000000..dc1ac87e4e1
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Proxy.java
@@ -0,0 +1,1615 @@
+/* Proxy.java -- build a proxy class that implements reflected interfaces
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+import gnu.classpath.Configuration;
+import gnu.java.lang.reflect.TypeSignature;
+
+import java.io.Serializable;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This class allows you to dynamically create an instance of any (or
+ * even multiple) interfaces by reflection, and decide at runtime
+ * how that instance will behave by giving it an appropriate
+ * {@link InvocationHandler}. Proxy classes serialize specially, so
+ * that the proxy object can be reused between VMs, without requiring
+ * a persistent copy of the generated class code.
+ *
+ * <h3>Creation</h3>
+ * To create a proxy for some interface Foo:
+ *
+ * <pre>
+ * InvocationHandler handler = new MyInvocationHandler(...);
+ * Class proxyClass = Proxy.getProxyClass(
+ * Foo.class.getClassLoader(), new Class[] { Foo.class });
+ * Foo f = (Foo) proxyClass
+ * .getConstructor(new Class[] { InvocationHandler.class })
+ * .newInstance(new Object[] { handler });
+ * </pre>
+ * or more simply:
+ * <pre>
+ * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
+ * new Class[] { Foo.class },
+ * handler);
+ * </pre>
+ *
+ * <h3>Dynamic Proxy Classes</h3>
+ * A dynamic proxy class is created at runtime, and has the following
+ * properties:
+ * <ul>
+ * <li>The class is <code>public</code> and <code>final</code>,
+ * and is neither <code>abstract</code> nor an inner class.</li>
+ * <li>The class has no canonical name (there is no formula you can use
+ * to determine or generate its name), but begins with the
+ * sequence "$Proxy". Abuse this knowledge at your own peril.
+ * (For now, '$' in user identifiers is legal, but it may not
+ * be that way forever. You weren't using '$' in your
+ * identifiers, were you?)</li>
+ * <li>The class extends Proxy, and explicitly implements all the
+ * interfaces specified at creation, in order (this is important
+ * for determining how method invocation is resolved). Note that
+ * a proxy class implements {@link Serializable}, at least
+ * implicitly, since Proxy does, but true serial behavior
+ * depends on using a serializable invocation handler as well.</li>
+ * <li>If at least one interface is non-public, the proxy class
+ * will be in the same package. Otherwise, the package is
+ * unspecified. This will work even if the package is sealed
+ * from user-generated classes, because Proxy classes are
+ * generated by a trusted source. Meanwhile, the proxy class
+ * belongs to the classloader you designated.</li>
+ * <li>Reflection works as expected: {@link Class#getInterfaces()} and
+ * {@link Class#getMethods()} work as they do on normal classes.</li>
+ * <li>The method {@link #isProxyClass()} will distinguish between
+ * true proxy classes and user extensions of this class. It only
+ * returns true for classes created by {@link #getProxyClass}.</li>
+ * <li>The {@link ProtectionDomain} of a proxy class is the same as for
+ * bootstrap classes, such as Object or Proxy, since it is created by
+ * a trusted source. This protection domain will typically be granted
+ * {@link java.security.AllPermission}. But this is not a security
+ * risk, since there are adequate permissions on reflection, which is
+ * the only way to create an instance of the proxy class.</li>
+ * <li>The proxy class contains a single constructor, which takes as
+ * its only argument an {@link InvocationHandler}. The method
+ * {@link #newInstance} is shorthand to do the necessary
+ * reflection.</li>
+ * </ul>
+ *
+ * <h3>Proxy Instances</h3>
+ * A proxy instance is an instance of a proxy class. It has the
+ * following properties, many of which follow from the properties of a
+ * proxy class listed above:
+ * <ul>
+ * <li>For a proxy class with Foo listed as one of its interfaces, the
+ * expression <code>proxy instanceof Foo</code> will return true,
+ * and the expression <code>(Foo) proxy</code> will succeed without
+ * a {@link ClassCastException}.</li>
+ * <li>Each proxy instance has an invocation handler, which can be
+ * accessed by {@link #getInvocationHandler(Object)}. Any call
+ * to an interface method, including {@link Object#hashcode()},
+ * {@link Object#equals(Object)}, or {@link Object#toString()},
+ * but excluding the public final methods of Object, will be
+ * encoded and passed to the {@link InvocationHandler#invoke}
+ * method of this handler.</li>
+ * </ul>
+ *
+ * <h3>Inheritance Issues</h3>
+ * A proxy class may inherit a method from more than one interface.
+ * The order in which interfaces are listed matters, because it determines
+ * which reflected {@link Method} object will be passed to the invocation
+ * handler. This means that the dynamically generated class cannot
+ * determine through which interface a method is being invoked.<p>
+ *
+ * In short, if a method is declared in Object (namely, hashCode,
+ * equals, or toString), then Object will be used; otherwise, the
+ * leftmost interface that inherits or declares a method will be used,
+ * even if it has a more permissive throws clause than what the proxy
+ * class is allowed. Thus, in the invocation handler, it is not always
+ * safe to assume that every class listed in the throws clause of the
+ * passed Method object can safely be thrown; fortunately, the Proxy
+ * instance is robust enough to wrap all illegal checked exceptions in
+ * {@link UndeclaredThrowableException}.
+ *
+ * @see InvocationHandler
+ * @see UndeclaredThrowableException
+ * @see Class
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.3
+ * @status updated to 1.4, except for the use of ProtectionDomain
+ */
+public class Proxy implements Serializable
+{
+ /**
+ * Compatible with JDK 1.3+.
+ */
+ private static final long serialVersionUID = -2222568056686623797L;
+
+ /**
+ * Map of ProxyType to proxy class.
+ *
+ * @XXX This prevents proxy classes from being garbage collected.
+ * java.util.WeakHashSet is not appropriate, because that collects the
+ * keys, but we are interested in collecting the elements.
+ */
+ private static final Map proxyClasses = new HashMap();
+
+ /**
+ * The invocation handler for this proxy instance. For Proxy, this
+ * field is unused, but it appears here in order to be serialized in all
+ * proxy classes.
+ *
+ * <em>NOTE</em>: This implementation is more secure for proxy classes
+ * than what Sun specifies. Sun does not require h to be immutable, but
+ * this means you could change h after the fact by reflection. However,
+ * by making h immutable, we may break non-proxy classes which extend
+ * Proxy.
+ * @serial invocation handler associated with this proxy instance
+ */
+ protected InvocationHandler h;
+
+ /**
+ * Constructs a new Proxy from a subclass (usually a proxy class),
+ * with the specified invocation handler.
+ *
+ * <em>NOTE</em>: This throws a NullPointerException if you attempt
+ * to create a proxy instance with a null handler using reflection.
+ * This behavior is not yet specified by Sun; see Sun Bug 4487672.
+ *
+ * @param handler the invocation handler, may be null if the subclass
+ * is not a proxy class
+ * @throws NullPointerException if handler is null and this is a proxy
+ * instance
+ */
+ protected Proxy(InvocationHandler handler)
+ {
+ if (handler == null && isProxyClass(getClass()))
+ throw new NullPointerException("invalid handler");
+ h = handler;
+ }
+
+ /**
+ * Returns the proxy {@link Class} for the given ClassLoader and array
+ * of interfaces, dynamically generating it if necessary.
+ *
+ * <p>There are several restrictions on this method, the violation of
+ * which will result in an IllegalArgumentException or
+ * NullPointerException:</p>
+ *
+ * <ul>
+ * <li>All objects in `interfaces' must represent distinct interfaces.
+ * Classes, primitive types, null, and duplicates are forbidden.</li>
+ * <li>The interfaces must be visible in the specified ClassLoader.
+ * In other words, for each interface i:
+ * <code>Class.forName(i.getName(), false, loader) == i</code>
+ * must be true.</li>
+ * <li>All non-public interfaces (if any) must reside in the same
+ * package, or the proxy class would be non-instantiable. If
+ * there are no non-public interfaces, the package of the proxy
+ * class is unspecified.</li>
+ * <li>All interfaces must be compatible - if two declare a method
+ * with the same name and parameters, the return type must be
+ * the same and the throws clause of the proxy class will be
+ * the maximal subset of subclasses of the throws clauses for
+ * each method that is overridden.</li>
+ * <li>VM constraints limit the number of interfaces a proxy class
+ * may directly implement (however, the indirect inheritance
+ * of {@link Serializable} does not count against this limit).
+ * Even though most VMs can theoretically have 65535
+ * superinterfaces for a class, the actual limit is smaller
+ * because a class's constant pool is limited to 65535 entries,
+ * and not all entries can be interfaces.</li>
+ * </ul>
+ *
+ * <p>Note that different orders of interfaces produce distinct classes.</p>
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the array of interfaces the proxy class implements,
+ * may be empty, but not null
+ * @return the Class object of the proxy class
+ * @throws IllegalArgumentException if the constraints above were
+ * violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry
+ */
+ // synchronized so that we aren't trying to build the same class
+ // simultaneously in two threads
+ public static synchronized Class getProxyClass(ClassLoader loader,
+ Class[] interfaces)
+ {
+ interfaces = (Class[]) interfaces.clone();
+ ProxyType pt = new ProxyType(loader, interfaces);
+ Class clazz = (Class) proxyClasses.get(pt);
+ if (clazz == null)
+ {
+ if (Configuration.HAVE_NATIVE_GET_PROXY_CLASS)
+ clazz = getProxyClass0(loader, interfaces);
+ else
+ {
+ ProxyData data = (Configuration.HAVE_NATIVE_GET_PROXY_DATA
+ ? getProxyData0(loader, interfaces)
+ : ProxyData.getProxyData(pt));
+
+ clazz = (Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS
+ ? generateProxyClass0(loader, data)
+ : new ClassFactory(data).generate(loader));
+ }
+
+ Object check = proxyClasses.put(pt, clazz);
+ // assert check == null && clazz != null;
+ if (check != null || clazz == null)
+ throw new InternalError(/*"Fatal flaw in getProxyClass"*/);
+ }
+ return clazz;
+ }
+
+ /**
+ * Combines several methods into one. This is equivalent to:
+ * <pre>
+ * Proxy.getProxyClass(loader, interfaces)
+ * .getConstructor(new Class[] {InvocationHandler.class})
+ * .newInstance(new Object[] {handler});
+ * </pre>
+ * except that it will not fail with the normal problems caused
+ * by reflection. It can still fail for the same reasons documented
+ * in getProxyClass, or if handler is null.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the array of interfaces the proxy class implements,
+ * may be empty, but not null
+ * @param handler the invocation handler, may not be null
+ * @return a proxy instance implementing the specified interfaces
+ * @throws IllegalArgumentException if the constraints for getProxyClass
+ * were violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry, or if handler is null
+ * @see #getProxyClass(ClassLoader, Class[])
+ * @see Class#getConstructor(Class[])
+ * @see Constructor#newInstance(Object[])
+ */
+ public static Object newProxyInstance(ClassLoader loader,
+ Class[] interfaces,
+ InvocationHandler handler)
+ {
+ try
+ {
+ // getProxyClass() and Proxy() throw the necessary exceptions
+ return getProxyClass(loader, interfaces)
+ .getConstructor(new Class[] {InvocationHandler.class})
+ .newInstance(new Object[] {handler});
+ }
+ catch (RuntimeException e)
+ {
+ // Let IllegalArgumentException, NullPointerException escape.
+ // assert e instanceof IllegalArgumentException
+ // || e instanceof NullPointerException;
+ throw e;
+ }
+ catch (InvocationTargetException e)
+ {
+ // Let wrapped NullPointerException escape.
+ // assert e.getTargetException() instanceof NullPointerException
+ throw (NullPointerException) e.getCause();
+ }
+ catch (Exception e)
+ {
+ // Covers InstantiationException, IllegalAccessException,
+ // NoSuchMethodException, none of which should be generated
+ // if the proxy class was generated correctly.
+ // assert false;
+ throw (Error) new InternalError("Unexpected: " + e).initCause(e);
+ }
+ }
+
+ /**
+ * Returns true if and only if the Class object is a dynamically created
+ * proxy class (created by <code>getProxyClass</code> or by the
+ * syntactic sugar of <code>newProxyInstance</code>).
+ *
+ * <p>This check is secure (in other words, it is not simply
+ * <code>clazz.getSuperclass() == Proxy.class</code>), it will not
+ * be spoofed by non-proxy classes that extend Proxy.
+ *
+ * @param clazz the class to check, must not be null
+ * @return true if the class represents a proxy class
+ * @throws NullPointerException if clazz is null
+ */
+ // This is synchronized on the off chance that another thread is
+ // trying to add a class to the map at the same time we read it.
+ public static synchronized boolean isProxyClass(Class clazz)
+ {
+ if (! Proxy.class.isAssignableFrom(clazz))
+ return false;
+ // This is a linear search, even though we could do an O(1) search
+ // using new ProxyType(clazz.getClassLoader(), clazz.getInterfaces()).
+ return proxyClasses.containsValue(clazz);
+ }
+
+ /**
+ * Returns the invocation handler for the given proxy instance.<p>
+ *
+ * <em>NOTE</em>: We guarantee a non-null result if successful,
+ * but Sun allows the creation of a proxy instance with a null
+ * handler. See the comments for {@link #Proxy(InvocationHandler)}.
+ *
+ * @param proxy the proxy instance, must not be null
+ * @return the invocation handler, guaranteed non-null.
+ * @throws IllegalArgumentException if
+ * <code>Proxy.isProxyClass(proxy.getClass())</code> returns false.
+ * @throws NullPointerException if proxy is null
+ */
+ public static InvocationHandler getInvocationHandler(Object proxy)
+ {
+ if (! isProxyClass(proxy.getClass()))
+ throw new IllegalArgumentException("not a proxy instance");
+ return ((Proxy) proxy).h;
+ }
+
+ /**
+ * Optional native method to replace (and speed up) the pure Java
+ * implementation of getProxyClass. Only needed if
+ * Configuration.HAVE_NATIVE_GET_PROXY_CLASS is true, this does the
+ * work of both getProxyData0 and generateProxyClass0 with no
+ * intermediate form in Java. The native code may safely assume that
+ * this class must be created, and does not already exist.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the interfaces the class will extend
+ * @return the generated proxy class
+ * @throws IllegalArgumentException if the constraints for getProxyClass
+ * were violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry, or if handler is null
+ * @see Configuration#HAVE_NATIVE_GET_PROXY_CLASS
+ * @see #getProxyClass(ClassLoader, Class[])
+ * @see #getProxyData0(ClassLoader, Class[])
+ * @see #generateProxyClass0(ProxyData)
+ */
+ private static native Class getProxyClass0(ClassLoader loader,
+ Class[] interfaces);
+
+ /**
+ * Optional native method to replace (and speed up) the pure Java
+ * implementation of getProxyData. Only needed if
+ * Configuration.HAVE_NATIVE_GET_PROXY_DATA is true. The native code
+ * may safely assume that a new ProxyData object must be created which
+ * does not duplicate any existing ones.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces the interfaces the class will extend
+ * @return all data that is required to make this proxy class
+ * @throws IllegalArgumentException if the constraints for getProxyClass
+ * were violated, except for problems with null
+ * @throws NullPointerException if `interfaces' is null or contains
+ * a null entry, or if handler is null
+ * @see Configuration.HAVE_NATIVE_GET_PROXY_DATA
+ * @see #getProxyClass(ClassLoader, Class[])
+ * @see #getProxyClass0(ClassLoader, Class[])
+ * @see ProxyType#getProxyData()
+ */
+ private static native ProxyData getProxyData0(ClassLoader loader,
+ Class[] interfaces);
+
+ /**
+ * Optional native method to replace (and speed up) the pure Java
+ * implementation of generateProxyClass. Only needed if
+ * Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS is true. The native
+ * code may safely assume that a new Class must be created, and that
+ * the ProxyData object does not describe any existing class.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param data the struct of information to convert to a Class. This
+ * has already been verified for all problems except exceeding
+ * VM limitations
+ * @return the newly generated class
+ * @throws IllegalArgumentException if VM limitations are exceeded
+ * @see #getProxyClass(ClassLoader, Class[])
+ * @see #getProxyClass0(ClassLoader, Class[])
+ * @see ProxyData#generateProxyClass(ClassLoader)
+ */
+ private static native Class generateProxyClass0(ClassLoader loader,
+ ProxyData data);
+
+ /**
+ * Helper class for mapping unique ClassLoader and interface combinations
+ * to proxy classes.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class ProxyType
+ {
+ /**
+ * Store the class loader (may be null)
+ */
+ final ClassLoader loader;
+
+ /**
+ * Store the interfaces (never null, all elements are interfaces)
+ */
+ final Class[] interfaces;
+
+ /**
+ * Construct the helper object.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @param interfaces an array of interfaces
+ */
+ ProxyType(ClassLoader loader, Class[] interfaces)
+ {
+ if (loader == null)
+ loader = ClassLoader.getSystemClassLoader();
+ this.loader = loader;
+ this.interfaces = interfaces;
+ }
+
+ /**
+ * Calculates the hash code.
+ *
+ * @return a combination of the classloader and interfaces hashcodes.
+ */
+ public int hashCode()
+ {
+ //loader is always not null
+ int hash = loader.hashCode();
+ for (int i = 0; i < interfaces.length; i++)
+ hash = hash * 31 + interfaces[i].hashCode();
+ return hash;
+ }
+
+ // A more comprehensive comparison of two arrays,
+ // ignore array element order, and
+ // ignore redundant elements
+ private static boolean sameTypes(Class arr1[], Class arr2[]) {
+ if (arr1.length == 1 && arr2.length == 1) {
+ return arr1[0] == arr2[0];
+ }
+
+ // total occurrance of elements of arr1 in arr2
+ int total_occ_of_arr1_in_arr2 = 0;
+ each_type:
+ for (int i = arr1.length; --i >= 0; )
+ {
+ Class t = arr1[i];
+ for (int j = i; --j >= 0; )
+ {
+ if (t == arr1[j])
+ { //found duplicate type
+ continue each_type;
+ }
+ }
+
+ // count c(a unique element of arr1)'s
+ // occurrences in arr2
+ int occ_in_arr2 = 0;
+ for (int j = arr2.length; --j >= 0; )
+ {
+ if (t == arr2[j])
+ {
+ ++occ_in_arr2;
+ }
+ }
+ if (occ_in_arr2 == 0)
+ { // t does not occur in arr2
+ return false;
+ }
+
+ total_occ_of_arr1_in_arr2 += occ_in_arr2;
+ }
+ // now, each element of arr2 must have been visited
+ return total_occ_of_arr1_in_arr2 == arr2.length;
+ }
+
+ /**
+ * Calculates equality.
+ *
+ * @param the object to compare to
+ * @return true if it is a ProxyType with same data
+ */
+ public boolean equals(Object other)
+ {
+ ProxyType pt = (ProxyType) other;
+ if (loader != pt.loader || interfaces.length != pt.interfaces.length)
+ return false;
+ return sameTypes(interfaces, pt.interfaces);
+ }
+ } // class ProxyType
+
+ /**
+ * Helper class which allows hashing of a method name and signature
+ * without worrying about return type, declaring class, or throws clause,
+ * and which reduces the maximally common throws clause between two methods
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class ProxySignature
+ {
+ /**
+ * The core signatures which all Proxy instances handle.
+ */
+ static final HashMap coreMethods = new HashMap();
+ static
+ {
+ try
+ {
+ ProxySignature sig
+ = new ProxySignature(Object.class
+ .getMethod("equals",
+ new Class[] {Object.class}));
+ coreMethods.put(sig, sig);
+ sig = new ProxySignature(Object.class.getMethod("hashCode", null));
+ coreMethods.put(sig, sig);
+ sig = new ProxySignature(Object.class.getMethod("toString", null));
+ coreMethods.put(sig, sig);
+ }
+ catch (Exception e)
+ {
+ // assert false;
+ throw (Error) new InternalError("Unexpected: " + e).initCause(e);
+ }
+ }
+
+ /**
+ * The underlying Method object, never null
+ */
+ final Method method;
+
+ /**
+ * The set of compatible thrown exceptions, may be empty
+ */
+ final Set exceptions = new HashSet();
+
+ /**
+ * Construct a signature
+ *
+ * @param method the Method this signature is based on, never null
+ */
+ ProxySignature(Method method)
+ {
+ this.method = method;
+ Class[] exc = method.getExceptionTypes();
+ int i = exc.length;
+ while (--i >= 0)
+ {
+ // discard unchecked exceptions
+ if (Error.class.isAssignableFrom(exc[i])
+ || RuntimeException.class.isAssignableFrom(exc[i]))
+ continue;
+ exceptions.add(exc[i]);
+ }
+ }
+
+ /**
+ * Given a method, make sure it's return type is identical
+ * to this, and adjust this signature's throws clause appropriately
+ *
+ * @param other the signature to merge in
+ * @throws IllegalArgumentException if the return types conflict
+ */
+ void checkCompatibility(ProxySignature other)
+ {
+ if (method.getReturnType() != other.method.getReturnType())
+ throw new IllegalArgumentException("incompatible return types: "
+ + method + ", " + other.method);
+
+ // if you can think of a more efficient way than this O(n^2) search,
+ // implement it!
+ int size1 = exceptions.size();
+ int size2 = other.exceptions.size();
+ boolean[] valid1 = new boolean[size1];
+ boolean[] valid2 = new boolean[size2];
+ Iterator itr = exceptions.iterator();
+ int pos = size1;
+ while (--pos >= 0)
+ {
+ Class c1 = (Class) itr.next();
+ Iterator itr2 = other.exceptions.iterator();
+ int pos2 = size2;
+ while (--pos2 >= 0)
+ {
+ Class c2 = (Class) itr2.next();
+ if (c2.isAssignableFrom(c1))
+ valid1[pos] = true;
+ if (c1.isAssignableFrom(c2))
+ valid2[pos2] = true;
+ }
+ }
+ pos = size1;
+ itr = exceptions.iterator();
+ while (--pos >= 0)
+ {
+ itr.next();
+ if (! valid1[pos])
+ itr.remove();
+ }
+ pos = size2;
+ itr = other.exceptions.iterator();
+ while (--pos >= 0)
+ {
+ itr.next();
+ if (! valid2[pos])
+ itr.remove();
+ }
+ exceptions.addAll(other.exceptions);
+ }
+
+ /**
+ * Calculates the hash code.
+ *
+ * @return a combination of name and parameter types
+ */
+ public int hashCode()
+ {
+ int hash = method.getName().hashCode();
+ Class[] types = method.getParameterTypes();
+ for (int i = 0; i < types.length; i++)
+ hash = hash * 31 + types[i].hashCode();
+ return hash;
+ }
+
+ /**
+ * Calculates equality.
+ *
+ * @param the object to compare to
+ * @return true if it is a ProxySignature with same data
+ */
+ public boolean equals(Object other)
+ {
+ ProxySignature ps = (ProxySignature) other;
+ Class[] types1 = method.getParameterTypes();
+ Class[] types2 = ps.method.getParameterTypes();
+ if (! method.getName().equals(ps.method.getName())
+ || types1.length != types2.length)
+ return false;
+ int i = types1.length;
+ while (--i >= 0)
+ if (types1[i] != types2[i])
+ return false;
+ return true;
+ }
+ } // class ProxySignature
+
+ /**
+ * A flat representation of all data needed to generate bytecode/instantiate
+ * a proxy class. This is basically a struct.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class ProxyData
+ {
+ /**
+ * The package this class is in <b>including the trailing dot</b>
+ * or an empty string for the unnamed (aka default) package.
+ */
+ String pack;
+
+ /**
+ * The interfaces this class implements. Non-null, but possibly empty.
+ */
+ Class[] interfaces;
+
+ /**
+ * The Method objects this class must pass as the second argument to
+ * invoke (also useful for determining what methods this class has).
+ * Non-null, non-empty (includes at least Object.hashCode, Object.equals,
+ * and Object.toString).
+ */
+ Method[] methods;
+
+ /**
+ * The exceptions that do not need to be wrapped in
+ * UndeclaredThrowableException. exceptions[i] is the same as, or a
+ * subset of subclasses, of methods[i].getExceptionTypes(), depending on
+ * compatible throws clauses with multiple inheritance. It is unspecified
+ * if these lists include or exclude subclasses of Error and
+ * RuntimeException, but excluding them is harmless and generates a
+ * smaller class.
+ */
+ Class[][] exceptions;
+
+ /**
+ * For unique id's
+ */
+ private static int count;
+
+ /**
+ * The id of this proxy class
+ */
+ final int id = count++;
+
+ /**
+ * Construct a ProxyData with uninitialized data members.
+ */
+ ProxyData()
+ {
+ }
+
+ /**
+ * Return the name of a package (including the trailing dot)
+ * given the name of a class.
+ * Returns an empty string if no package. We use this in preference to
+ * using Class.getPackage() to avoid problems with ClassLoaders
+ * that don't set the package.
+ */
+ private static String getPackage(Class k)
+ {
+ String name = k.getName();
+ int idx = name.lastIndexOf('.');
+ return name.substring(0, idx + 1);
+ }
+
+ /**
+ * Verifies that the arguments are legal, and sets up remaining data
+ * This should only be called when a class must be generated, as
+ * it is expensive.
+ *
+ * @param pt the ProxyType to convert to ProxyData
+ * @return the flattened, verified ProxyData structure for use in
+ * class generation
+ * @throws IllegalArgumentException if `interfaces' contains
+ * non-interfaces or incompatible combinations, and verify is true
+ * @throws NullPointerException if interfaces is null or contains null
+ */
+ static ProxyData getProxyData(ProxyType pt)
+ {
+ Map method_set = (Map) ProxySignature.coreMethods.clone();
+ boolean in_package = false; // true if we encounter non-public interface
+
+ ProxyData data = new ProxyData();
+ data.interfaces = pt.interfaces;
+
+ // if interfaces is too large, we croak later on when the constant
+ // pool overflows
+ int i = data.interfaces.length;
+ while (--i >= 0)
+ {
+ Class inter = data.interfaces[i];
+ if (! inter.isInterface())
+ throw new IllegalArgumentException("not an interface: " + inter);
+ try
+ {
+ if (Class.forName(inter.getName(), false, pt.loader) != inter)
+ throw new IllegalArgumentException("not accessible in "
+ + "classloader: " + inter);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalArgumentException("not accessible in "
+ + "classloader: " + inter);
+ }
+ if (! Modifier.isPublic(inter.getModifiers()))
+ if (in_package)
+ {
+ String p = getPackage(inter);
+ if (! data.pack.equals(p))
+ throw new IllegalArgumentException("non-public interfaces "
+ + "from different "
+ + "packages");
+ }
+ else
+ {
+ in_package = true;
+ data.pack = getPackage(inter);
+ }
+ for (int j = i-1; j >= 0; j--)
+ if (data.interfaces[j] == inter)
+ throw new IllegalArgumentException("duplicate interface: "
+ + inter);
+ Method[] methods = inter.getMethods();
+ int j = methods.length;
+ while (--j >= 0)
+ {
+ ProxySignature sig = new ProxySignature(methods[j]);
+ ProxySignature old = (ProxySignature) method_set.put(sig, sig);
+ if (old != null)
+ sig.checkCompatibility(old);
+ }
+ }
+
+ i = method_set.size();
+ data.methods = new Method[i];
+ data.exceptions = new Class[i][];
+ Iterator itr = method_set.values().iterator();
+ while (--i >= 0)
+ {
+ ProxySignature sig = (ProxySignature) itr.next();
+ data.methods[i] = sig.method;
+ data.exceptions[i] = (Class[]) sig.exceptions
+ .toArray(new Class[sig.exceptions.size()]);
+ }
+ return data;
+ }
+ } // class ProxyData
+
+ /**
+ * Does all the work of building a class. By making this a nested class,
+ * this code is not loaded in memory if the VM has a native
+ * implementation instead.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+ private static final class ClassFactory
+ {
+ /** Constants for assisting the compilation */
+ private static final byte POOL = 0;
+ private static final byte FIELD = 1;
+ private static final byte METHOD = 2;
+ private static final byte INTERFACE = 3;
+ private static final String CTOR_SIG
+ = "(Ljava/lang/reflect/InvocationHandler;)V";
+ private static final String INVOKE_SIG = "(Ljava/lang/Object;"
+ + "Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";
+
+ /** Bytecodes for insertion in the class definition byte[] */
+ private static final char ACONST_NULL = 1;
+ private static final char ICONST_0 = 3;
+ private static final char BIPUSH = 16;
+ private static final char SIPUSH = 17;
+ private static final char ILOAD = 21;
+ private static final char ILOAD_0 = 26;
+ private static final char ALOAD_0 = 42;
+ private static final char ALOAD_1 = 43;
+ private static final char AALOAD = 50;
+ private static final char AASTORE = 83;
+ private static final char DUP = 89;
+ private static final char DUP_X1 = 90;
+ private static final char SWAP = 95;
+ private static final char IRETURN = 172;
+ private static final char LRETURN = 173;
+ private static final char FRETURN = 174;
+ private static final char DRETURN = 175;
+ private static final char ARETURN = 176;
+ private static final char RETURN = 177;
+ private static final char GETSTATIC = 178;
+ private static final char GETFIELD = 180;
+ private static final char INVOKEVIRTUAL = 182;
+ private static final char INVOKESPECIAL = 183;
+ private static final char INVOKESTATIC = 184;
+ private static final char INVOKEINTERFACE = 185;
+ private static final char NEW = 187;
+ private static final char ANEWARRAY = 189;
+ private static final char ATHROW = 191;
+ private static final char CHECKCAST = 192;
+
+ // Implementation note: we use StringBuffers to hold the byte data, since
+ // they automatically grow. However, we only use the low 8 bits of
+ // every char in the array, so we are using twice the necessary memory
+ // for the ease StringBuffer provides.
+
+ /** The constant pool. */
+ private final StringBuffer pool = new StringBuffer();
+ /** The rest of the class data. */
+ private final StringBuffer stream = new StringBuffer();
+
+ /** Map of strings to byte sequences, to minimize size of pool. */
+ private final Map poolEntries = new HashMap();
+
+ /** The VM name of this proxy class. */
+ private final String qualName;
+
+ /**
+ * The Method objects the proxy class refers to when calling the
+ * invocation handler.
+ */
+ private final Method[] methods;
+
+ /**
+ * Initializes the buffers with the bytecode contents for a proxy class.
+ *
+ * @param data the remainder of the class data
+ * @throws IllegalArgumentException if anything else goes wrong this
+ * late in the game; as far as I can tell, this will only happen
+ * if the constant pool overflows, which is possible even when
+ * the user doesn't exceed the 65535 interface limit
+ */
+ ClassFactory(ProxyData data)
+ {
+ methods = data.methods;
+
+ // magic = 0xcafebabe
+ // minor_version = 0
+ // major_version = 46
+ // constant_pool_count: place-holder for now
+ pool.append("\u00ca\u00fe\u00ba\u00be\0\0\0\56\0\0");
+ // constant_pool[], filled in as we go
+
+ // access_flags
+ putU2(Modifier.SUPER | Modifier.FINAL | Modifier.PUBLIC);
+ // this_class
+ qualName = (data.pack + "$Proxy" + data.id);
+ putU2(classInfo(TypeSignature.getEncodingOfClass(qualName, false)));
+ // super_class
+ putU2(classInfo("java/lang/reflect/Proxy"));
+
+ // interfaces_count
+ putU2(data.interfaces.length);
+ // interfaces[]
+ for (int i = 0; i < data.interfaces.length; i++)
+ putU2(classInfo(data.interfaces[i]));
+
+ // Recall that Proxy classes serialize specially, so we do not need
+ // to worry about a <clinit> method for this field. Instead, we
+ // just assign it by reflection after the class is successfully loaded.
+ // fields_count - private static Method[] m;
+ putU2(1);
+ // fields[]
+ // m.access_flags
+ putU2(Modifier.PRIVATE | Modifier.STATIC);
+ // m.name_index
+ putU2(utf8Info("m"));
+ // m.descriptor_index
+ putU2(utf8Info("[Ljava/lang/reflect/Method;"));
+ // m.attributes_count
+ putU2(0);
+ // m.attributes[]
+
+ // methods_count - # handler methods, plus <init>
+ putU2(methods.length + 1);
+ // methods[]
+ // <init>.access_flags
+ putU2(Modifier.PUBLIC);
+ // <init>.name_index
+ putU2(utf8Info("<init>"));
+ // <init>.descriptor_index
+ putU2(utf8Info(CTOR_SIG));
+ // <init>.attributes_count - only Code is needed
+ putU2(1);
+ // <init>.Code.attribute_name_index
+ putU2(utf8Info("Code"));
+ // <init>.Code.attribute_length = 18
+ // <init>.Code.info:
+ // $Proxynn(InvocationHandler h) { super(h); }
+ // <init>.Code.max_stack = 2
+ // <init>.Code.max_locals = 2
+ // <init>.Code.code_length = 6
+ // <init>.Code.code[]
+ stream.append("\0\0\0\22\0\2\0\2\0\0\0\6" + ALOAD_0 + ALOAD_1
+ + INVOKESPECIAL);
+ putU2(refInfo(METHOD, "java/lang/reflect/Proxy", "<init>", CTOR_SIG));
+ // <init>.Code.exception_table_length = 0
+ // <init>.Code.exception_table[]
+ // <init>.Code.attributes_count = 0
+ // <init>.Code.attributes[]
+ stream.append(RETURN + "\0\0\0\0");
+
+ for (int i = methods.length - 1; i >= 0; i--)
+ emitMethod(i, data.exceptions[i]);
+
+ // attributes_count
+ putU2(0);
+ // attributes[] - empty; omit SourceFile attribute
+ // XXX should we mark this with a Synthetic attribute?
+ }
+
+ /**
+ * Produce the bytecode for a single method.
+ *
+ * @param i the index of the method we are building
+ * @param e the exceptions possible for the method
+ */
+ private void emitMethod(int i, Class[] e)
+ {
+ // First, we precalculate the method length and other information.
+
+ Method m = methods[i];
+ Class[] paramtypes = m.getParameterTypes();
+ int wrap_overhead = 0; // max words taken by wrapped primitive
+ int param_count = 1; // 1 for this
+ int code_length = 16; // aload_0, getfield, aload_0, getstatic, const,
+ // aaload, const/aconst_null, invokeinterface
+ if (i > 5)
+ {
+ if (i > Byte.MAX_VALUE)
+ code_length += 2; // sipush
+ else
+ code_length++; // bipush
+ }
+ if (paramtypes.length > 0)
+ {
+ code_length += 3; // anewarray
+ if (paramtypes.length > Byte.MAX_VALUE)
+ code_length += 2; // sipush
+ else if (paramtypes.length > 5)
+ code_length++; // bipush
+ for (int j = 0; j < paramtypes.length; j++)
+ {
+ code_length += 4; // dup, const, load, store
+ Class type = paramtypes[j];
+ if (j > 5)
+ {
+ if (j > Byte.MAX_VALUE)
+ code_length += 2; // sipush
+ else
+ code_length++; // bipush
+ }
+ if (param_count >= 4)
+ code_length++; // 2-byte load
+ param_count++;
+ if (type.isPrimitive())
+ {
+ code_length += 7; // new, dup, invokespecial
+ if (type == long.class || type == double.class)
+ {
+ wrap_overhead = 3;
+ param_count++;
+ }
+ else if (wrap_overhead < 2)
+ wrap_overhead = 2;
+ }
+ }
+ }
+ int end_pc = code_length;
+ Class ret_type = m.getReturnType();
+ if (ret_type == void.class)
+ code_length++; // return
+ else if (ret_type.isPrimitive())
+ code_length += 7; // cast, invokevirtual, return
+ else
+ code_length += 4; // cast, return
+ int exception_count = 0;
+ boolean throws_throwable = false;
+ for (int j = 0; j < e.length; j++)
+ if (e[j] == Throwable.class)
+ {
+ throws_throwable = true;
+ break;
+ }
+ if (! throws_throwable)
+ {
+ exception_count = e.length + 3; // Throwable, Error, RuntimeException
+ code_length += 9; // new, dup_x1, swap, invokespecial, athrow
+ }
+ int handler_pc = code_length - 1;
+ StringBuffer signature = new StringBuffer("(");
+ for (int j = 0; j < paramtypes.length; j++)
+ signature.append(TypeSignature.getEncodingOfClass(paramtypes[j]));
+ signature.append(")").append(TypeSignature.getEncodingOfClass(ret_type));
+
+ // Now we have enough information to emit the method.
+
+ // handler.access_flags
+ putU2(Modifier.PUBLIC | Modifier.FINAL);
+ // handler.name_index
+ putU2(utf8Info(m.getName()));
+ // handler.descriptor_index
+ putU2(utf8Info(signature.toString()));
+ // handler.attributes_count - Code is necessary, Exceptions possible
+ putU2(e.length > 0 ? 2 : 1);
+
+ // handler.Code.info:
+ // type name(args) {
+ // try {
+ // return (type) h.invoke(this, methods[i], new Object[] {args});
+ // } catch (<declared Exceptions> e) {
+ // throw e;
+ // } catch (Throwable t) {
+ // throw new UndeclaredThrowableException(t);
+ // }
+ // }
+ // Special cases:
+ // if arg_n is primitive, wrap it
+ // if method throws Throwable, try-catch is not needed
+ // if method returns void, return statement not needed
+ // if method returns primitive, unwrap it
+ // save space by sharing code for all the declared handlers
+
+ // handler.Code.attribute_name_index
+ putU2(utf8Info("Code"));
+ // handler.Code.attribute_length
+ putU4(12 + code_length + 8 * exception_count);
+ // handler.Code.max_stack
+ putU2(param_count == 1 ? 4 : 7 + wrap_overhead);
+ // handler.Code.max_locals
+ putU2(param_count);
+ // handler.Code.code_length
+ putU4(code_length);
+ // handler.Code.code[]
+ putU1(ALOAD_0);
+ putU1(GETFIELD);
+ putU2(refInfo(FIELD, "java/lang/reflect/Proxy", "h",
+ "Ljava/lang/reflect/InvocationHandler;"));
+ putU1(ALOAD_0);
+ putU1(GETSTATIC);
+ putU2(refInfo(FIELD, TypeSignature.getEncodingOfClass(qualName, false),
+ "m", "[Ljava/lang/reflect/Method;"));
+ putConst(i);
+ putU1(AALOAD);
+ if (paramtypes.length > 0)
+ {
+ putConst(paramtypes.length);
+ putU1(ANEWARRAY);
+ putU2(classInfo("java/lang/Object"));
+ param_count = 1;
+ for (int j = 0; j < paramtypes.length; j++, param_count++)
+ {
+ putU1(DUP);
+ putConst(j);
+ if (paramtypes[j].isPrimitive())
+ {
+ putU1(NEW);
+ putU2(classInfo(wrapper(paramtypes[j])));
+ putU1(DUP);
+ }
+ putLoad(param_count, paramtypes[j]);
+ if (paramtypes[j].isPrimitive())
+ {
+ putU1(INVOKESPECIAL);
+ putU2(refInfo(METHOD, wrapper(paramtypes[j]), "<init>",
+ '(' + (TypeSignature
+ .getEncodingOfClass(paramtypes[j])
+ + ")V")));
+ if (paramtypes[j] == long.class
+ || paramtypes[j] == double.class)
+ param_count++;
+ }
+ putU1(AASTORE);
+ }
+ }
+ else
+ putU1(ACONST_NULL);
+ putU1(INVOKEINTERFACE);
+ putU2(refInfo(INTERFACE, "java/lang/reflect/InvocationHandler",
+ "invoke", INVOKE_SIG));
+ putU1(4); // InvocationHandler, this, Method, Object[]
+ putU1(0);
+ if (ret_type == void.class)
+ putU1(RETURN);
+ else if (ret_type.isPrimitive())
+ {
+ putU1(CHECKCAST);
+ putU2(classInfo(wrapper(ret_type)));
+ putU1(INVOKEVIRTUAL);
+ putU2(refInfo(METHOD, wrapper(ret_type),
+ ret_type.getName() + "Value",
+ "()" + TypeSignature.getEncodingOfClass(ret_type)));
+ if (ret_type == long.class)
+ putU1(LRETURN);
+ else if (ret_type == float.class)
+ putU1(FRETURN);
+ else if (ret_type == double.class)
+ putU1(DRETURN);
+ else
+ putU1(IRETURN);
+ }
+ else
+ {
+ putU1(CHECKCAST);
+ putU2(classInfo(ret_type));
+ putU1(ARETURN);
+ }
+ if (! throws_throwable)
+ {
+ putU1(NEW);
+ putU2(classInfo("java/lang/reflect/UndeclaredThrowableException"));
+ putU1(DUP_X1);
+ putU1(SWAP);
+ putU1(INVOKESPECIAL);
+ putU2(refInfo(METHOD,
+ "java/lang/reflect/UndeclaredThrowableException",
+ "<init>", "(Ljava/lang/Throwable;)V"));
+ putU1(ATHROW);
+ }
+
+ // handler.Code.exception_table_length
+ putU2(exception_count);
+ // handler.Code.exception_table[]
+ if (! throws_throwable)
+ {
+ // handler.Code.exception_table.start_pc
+ putU2(0);
+ // handler.Code.exception_table.end_pc
+ putU2(end_pc);
+ // handler.Code.exception_table.handler_pc
+ putU2(handler_pc);
+ // handler.Code.exception_table.catch_type
+ putU2(classInfo("java/lang/Error"));
+ // handler.Code.exception_table.start_pc
+ putU2(0);
+ // handler.Code.exception_table.end_pc
+ putU2(end_pc);
+ // handler.Code.exception_table.handler_pc
+ putU2(handler_pc);
+ // handler.Code.exception_table.catch_type
+ putU2(classInfo("java/lang/RuntimeException"));
+ for (int j = 0; j < e.length; j++)
+ {
+ // handler.Code.exception_table.start_pc
+ putU2(0);
+ // handler.Code.exception_table.end_pc
+ putU2(end_pc);
+ // handler.Code.exception_table.handler_pc
+ putU2(handler_pc);
+ // handler.Code.exception_table.catch_type
+ putU2(classInfo(e[j]));
+ }
+ // handler.Code.exception_table.start_pc
+ putU2(0);
+ // handler.Code.exception_table.end_pc
+ putU2(end_pc);
+ // handler.Code.exception_table.handler_pc -
+ // -8 for undeclared handler, which falls thru to normal one
+ putU2(handler_pc - 8);
+ // handler.Code.exception_table.catch_type
+ putU2(0);
+ }
+ // handler.Code.attributes_count
+ putU2(0);
+ // handler.Code.attributes[]
+
+ if (e.length > 0)
+ {
+ // handler.Exceptions.attribute_name_index
+ putU2(utf8Info("Exceptions"));
+ // handler.Exceptions.attribute_length
+ putU4(2 * e.length + 2);
+ // handler.Exceptions.number_of_exceptions
+ putU2(e.length);
+ // handler.Exceptions.exception_index_table[]
+ for (int j = 0; j < e.length; j++)
+ putU2(classInfo(e[j]));
+ }
+ }
+
+ /**
+ * Creates the Class object that corresponds to the bytecode buffers
+ * built when this object was constructed.
+ *
+ * @param loader the class loader to define the proxy class in; null
+ * implies the bootstrap class loader
+ * @return the proxy class Class object
+ */
+ Class generate(ClassLoader loader)
+ {
+ byte[] bytecode = new byte[pool.length() + stream.length()];
+ // More efficient to bypass calling charAt() repetitively.
+ char[] c = pool.toString().toCharArray();
+ int i = c.length;
+ while (--i >= 0)
+ bytecode[i] = (byte) c[i];
+ c = stream.toString().toCharArray();
+ i = c.length;
+ int j = bytecode.length;
+ while (i > 0)
+ bytecode[--j] = (byte) c[--i];
+
+ // Patch the constant pool size, which we left at 0 earlier.
+ int count = poolEntries.size() + 1;
+ bytecode[8] = (byte) (count >> 8);
+ bytecode[9] = (byte) count;
+
+ try
+ {
+ Class vmClassLoader = Class.forName("java.lang.VMClassLoader");
+ Class[] types = {ClassLoader.class, String.class,
+ byte[].class, int.class, int.class,
+ ProtectionDomain.class };
+ Method m = vmClassLoader.getDeclaredMethod("defineClass", types);
+ // We can bypass the security check of setAccessible(true), since
+ // we're in the same package.
+ m.flag = true;
+
+ Object[] args = {loader, qualName, bytecode, new Integer(0),
+ new Integer(bytecode.length),
+ Object.class.getProtectionDomain() };
+ Class clazz = (Class) m.invoke(null, args);
+
+ // Finally, initialize the m field of the proxy class, before
+ // returning it.
+ Field f = clazz.getDeclaredField("m");
+ f.flag = true;
+ // we can share the array, because it is not publicized
+ f.set(null, methods);
+
+ return clazz;
+ }
+ catch (Exception e)
+ {
+ // assert false;
+ throw (Error) new InternalError("Unexpected: " + e).initCause(e);
+ }
+ }
+
+ /**
+ * Put a single byte on the stream.
+ *
+ * @param i the information to add (only lowest 8 bits are used)
+ */
+ private void putU1(int i)
+ {
+ stream.append((char) i);
+ }
+
+ /**
+ * Put two bytes on the stream.
+ *
+ * @param i the information to add (only lowest 16 bits are used)
+ */
+ private void putU2(int i)
+ {
+ stream.append((char) (i >> 8)).append((char) i);
+ }
+
+ /**
+ * Put four bytes on the stream.
+ *
+ * @param i the information to add (treated as unsigned)
+ */
+ private void putU4(int i)
+ {
+ stream.append((char) (i >> 24)).append((char) (i >> 16));
+ stream.append((char) (i >> 8)).append((char) i);
+ }
+
+ /**
+ * Put bytecode to load a constant integer on the stream. This only
+ * needs to work for values less than Short.MAX_VALUE.
+ *
+ * @param i the int to add
+ */
+ private void putConst(int i)
+ {
+ if (i >= -1 && i <= 5)
+ putU1(ICONST_0 + i);
+ else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE)
+ {
+ putU1(BIPUSH);
+ putU1(i);
+ }
+ else
+ {
+ putU1(SIPUSH);
+ putU2(i);
+ }
+ }
+
+ /**
+ * Put bytecode to load a given local variable on the stream.
+ *
+ * @param i the slot to load
+ * @param type the base type of the load
+ */
+ private void putLoad(int i, Class type)
+ {
+ int offset = 0;
+ if (type == long.class)
+ offset = 1;
+ else if (type == float.class)
+ offset = 2;
+ else if (type == double.class)
+ offset = 3;
+ else if (! type.isPrimitive())
+ offset = 4;
+ if (i < 4)
+ putU1(ILOAD_0 + 4 * offset + i);
+ else
+ {
+ putU1(ILOAD + offset);
+ putU1(i);
+ }
+ }
+
+ /**
+ * Given a primitive type, return its wrapper class name.
+ *
+ * @param clazz the primitive type (but not void.class)
+ * @return the internal form of the wrapper class name
+ */
+ private String wrapper(Class clazz)
+ {
+ if (clazz == boolean.class)
+ return "java/lang/Boolean";
+ if (clazz == byte.class)
+ return "java/lang/Byte";
+ if (clazz == short.class)
+ return "java/lang/Short";
+ if (clazz == char.class)
+ return "java/lang/Character";
+ if (clazz == int.class)
+ return "java/lang/Integer";
+ if (clazz == long.class)
+ return "java/lang/Long";
+ if (clazz == float.class)
+ return "java/lang/Float";
+ if (clazz == double.class)
+ return "java/lang/Double";
+ // assert false;
+ return null;
+ }
+
+ /**
+ * Returns the entry of this String in the Constant pool, adding it
+ * if necessary.
+ *
+ * @param str the String to resolve
+ * @return the index of the String in the constant pool
+ */
+ private char utf8Info(String str)
+ {
+ String utf8 = toUtf8(str);
+ int len = utf8.length();
+ return poolIndex("\1" + (char) (len >> 8) + (char) (len & 0xff) + utf8);
+ }
+
+ /**
+ * Returns the entry of the appropriate class info structure in the
+ * Constant pool, adding it if necessary.
+ *
+ * @param name the class name, in internal form
+ * @return the index of the ClassInfo in the constant pool
+ */
+ private char classInfo(String name)
+ {
+ char index = utf8Info(name);
+ char[] c = {7, (char) (index >> 8), (char) (index & 0xff)};
+ return poolIndex(new String(c));
+ }
+
+ /**
+ * Returns the entry of the appropriate class info structure in the
+ * Constant pool, adding it if necessary.
+ *
+ * @param clazz the class type
+ * @return the index of the ClassInfo in the constant pool
+ */
+ private char classInfo(Class clazz)
+ {
+ return classInfo(TypeSignature.getEncodingOfClass(clazz.getName(),
+ false));
+ }
+
+ /**
+ * Returns the entry of the appropriate fieldref, methodref, or
+ * interfacemethodref info structure in the Constant pool, adding it
+ * if necessary.
+ *
+ * @param structure FIELD, METHOD, or INTERFACE
+ * @param clazz the class name, in internal form
+ * @param name the simple reference name
+ * @param type the type of the reference
+ * @return the index of the appropriate Info structure in the constant pool
+ */
+ private char refInfo(byte structure, String clazz, String name,
+ String type)
+ {
+ char cindex = classInfo(clazz);
+ char ntindex = nameAndTypeInfo(name, type);
+ // relies on FIELD == 1, METHOD == 2, INTERFACE == 3
+ char[] c = {(char) (structure + 8),
+ (char) (cindex >> 8), (char) (cindex & 0xff),
+ (char) (ntindex >> 8), (char) (ntindex & 0xff)};
+ return poolIndex(new String(c));
+ }
+
+ /**
+ * Returns the entry of the appropriate nameAndTyperef info structure
+ * in the Constant pool, adding it if necessary.
+ *
+ * @param name the simple name
+ * @param type the reference type
+ * @return the index of the NameAndTypeInfo structure in the constant pool
+ */
+ private char nameAndTypeInfo(String name, String type)
+ {
+ char nindex = utf8Info(name);
+ char tindex = utf8Info(type);
+ char[] c = {12, (char) (nindex >> 8), (char) (nindex & 0xff),
+ (char) (tindex >> 8), (char) (tindex & 0xff)};
+ return poolIndex(new String(c));
+ }
+
+ /**
+ * Converts a regular string to a UTF8 string, where the upper byte
+ * of every char is 0, and '\\u0000' is not in the string. This is
+ * basically to use a String as a fancy byte[], and while it is less
+ * efficient in memory use, it is easier for hashing.
+ *
+ * @param str the original, in straight unicode
+ * @return a modified string, in UTF8 format in the low bytes
+ */
+ private String toUtf8(String str)
+ {
+ final char[] ca = str.toCharArray();
+ final int len = ca.length;
+
+ // Avoid object creation, if str is already fits UTF8.
+ int i;
+ for (i = 0; i < len; i++)
+ if (ca[i] == 0 || ca[i] > '\u007f')
+ break;
+ if (i == len)
+ return str;
+
+ final StringBuffer sb = new StringBuffer(str);
+ sb.setLength(i);
+ for ( ; i < len; i++)
+ {
+ final char c = ca[i];
+ if (c > 0 && c <= '\u007f')
+ sb.append(c);
+ else if (c <= '\u07ff') // includes '\0'
+ {
+ sb.append((char) (0xc0 | (c >> 6)));
+ sb.append((char) (0x80 | (c & 0x6f)));
+ }
+ else
+ {
+ sb.append((char) (0xe0 | (c >> 12)));
+ sb.append((char) (0x80 | ((c >> 6) & 0x6f)));
+ sb.append((char) (0x80 | (c & 0x6f)));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Returns the location of a byte sequence (conveniently wrapped in
+ * a String with all characters between \u0001 and \u00ff inclusive)
+ * in the constant pool, adding it if necessary.
+ *
+ * @param sequence the byte sequence to look for
+ * @return the index of the sequence
+ * @throws IllegalArgumentException if this would make the constant
+ * pool overflow
+ */
+ private char poolIndex(String sequence)
+ {
+ Integer i = (Integer) poolEntries.get(sequence);
+ if (i == null)
+ {
+ // pool starts at index 1
+ int size = poolEntries.size() + 1;
+ if (size >= 65535)
+ throw new IllegalArgumentException("exceeds VM limitations");
+ i = new Integer(size);
+ poolEntries.put(sequence, i);
+ pool.append(sequence);
+ }
+ return (char) i.intValue();
+ }
+ } // class ClassFactory
+}
diff --git a/libjava/classpath/java/lang/reflect/README b/libjava/classpath/java/lang/reflect/README
new file mode 100644
index 00000000000..99ea224d7f6
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/README
@@ -0,0 +1,4 @@
+README for java.lang.reflect:
+
+java.lang.reflect is now mostly empty. We've carved out the classes that have
+to do with the VM and put them into the VM interface.
diff --git a/libjava/classpath/java/lang/reflect/ReflectPermission.java b/libjava/classpath/java/lang/reflect/ReflectPermission.java
new file mode 100644
index 00000000000..56eccf8130c
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/ReflectPermission.java
@@ -0,0 +1,102 @@
+/* ReflectPermission.java - named permission for reflaction
+ Copyright (C) 2000, 2001, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+import java.security.BasicPermission;
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
+ */
+
+/**
+ * This class implements permissions for reflection. This is a named
+ * permission, and the only defined name is suppressAccessChecks, which
+ * allows suppression of normal Java objects when using reflection.
+ *
+ * <table>
+ * <tr>
+ * <th>Permission Target Name</th>
+ * <th>What Permission Allows</th>
+ * <th>Risk of Allowing Permission</th>
+ * </tr>
+ * <tr>
+ * <td><code>suppressAccessChecks</code></td>
+ * <td>Ability to access fields, invoke methods, and construct objects
+ * via reflection, including non-public members in contexts where
+ * such access is not legal at compile-time.</td>
+ * <td>This is dangerous. It exposes possibly confidential information,
+ * and malicious code could interfere with the internals of the Virtual
+ * Machine by corrupting private data.</td>
+ * </tr>
+ * </table>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.2
+ * @status updated to 1.4
+ */
+public final class ReflectPermission
+ extends BasicPermission
+{
+ /**
+ * Compatible with JDK 1.2.
+ */
+ private static final long serialVersionUID = 7412737110241507485L;
+
+ /**
+ * Construct a ReflectPermission with the given name.
+ *
+ * @param name The permission name
+ */
+ public ReflectPermission(String name)
+ {
+ super(name);
+ }
+
+ /**
+ * Construct a ReflectPermission with the given name.
+ *
+ * @param name The permission name
+ * @param actions The actions; this is ignored and should be null
+ */
+ public ReflectPermission(String name, String actions)
+ {
+ super(name, actions);
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/TODO b/libjava/classpath/java/lang/reflect/TODO
new file mode 100755
index 00000000000..6514c760317
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/TODO
@@ -0,0 +1,4 @@
+TODO for java.lang.reflect Java side
+
+- more tests!
+- Java 2 support (waiting on java.lang Java 2 support)
diff --git a/libjava/classpath/java/lang/reflect/Type.java b/libjava/classpath/java/lang/reflect/Type.java
new file mode 100644
index 00000000000..c9ea5bfb9cb
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Type.java
@@ -0,0 +1,55 @@
+/* Type.java - Superinterface for all types.
+ Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * Represents any <code>Type</code> within the Java programming
+ * language. This may be a primitive type (e.g. <code>int</code>,
+ * an array type (e.g. <code>double[]>/code>), a raw type
+ * (e.g. <code>Calendar</code>), a parameterized type
+ * (e.g. <code>List&lt;Boolean&gt;</code>, or a type
+ * variable (e.g. <code>T extends String</code>).
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface Type
+{
+}
diff --git a/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java b/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java
new file mode 100644
index 00000000000..6d5a8008459
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java
@@ -0,0 +1,128 @@
+/* UndeclaredThrowableException.java -- wraps an undeclared checked exception
+ thrown by a Proxy invocation handler
+ Copyright (C) 2001, 2002, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * This exception class is thrown by a {@link Proxy} instance if
+ * the {@link InvocationHandler#invoke(Object, Method, Object[]) invoke}
+ * method of that instance's InvocationHandler attempts to throw an
+ * exception that not declared by the throws clauses of all of the
+ * interface methods that the proxy instance is implementing.
+ *
+ * <p>When thrown by Proxy, this class will always wrap a checked
+ * exception, never {@link Error} or {@link RuntimeException},
+ * which are unchecked.
+ *
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Proxy
+ * @see InvocationHandler
+ * @since 1.3
+ * @status updated to 1.4
+ */
+public class UndeclaredThrowableException extends RuntimeException
+{
+ /**
+ * Compatible with JDK 1.3+.
+ */
+ private static final long serialVersionUID = 330127114055056639L;
+
+ /**
+ * The immutable exception that this wraps. This field is redundant
+ * with {@link Throwable#cause}, but is necessary for serial compatibility.
+ *
+ * @serial the chained exception
+ */
+ private final Throwable undeclaredThrowable;
+
+ /**
+ * Wraps the given checked exception into a RuntimeException, with no
+ * detail message. {@link Throwable#initCause(Throwable)} will fail
+ * on this instance.
+ *
+ * @param cause the undeclared throwable that caused this exception,
+ * may be null
+ */
+ public UndeclaredThrowableException(Throwable cause)
+ {
+ this(cause, null);
+ }
+
+ /**
+ * Wraps the given checked exception into a RuntimeException, with the
+ * specified detail message. {@link Throwable#initCause(Throwable)} will
+ * fail on this instance.
+ *
+ * @param cause the undeclared throwable that caused this exception,
+ * may be null
+ * @param message the message, may be null
+ */
+ public UndeclaredThrowableException(Throwable cause, String message)
+ {
+ super(message, cause);
+ undeclaredThrowable = cause;
+ }
+
+ /**
+ * Returns the cause of this exception. If this exception was created
+ * by a {@link Proxy} instance, it will be a non-null checked
+ * exception. This method pre-dates exception chaining, and is now
+ * simply a longer way to call <code>getCause()</code>.
+ *
+ * @return the cause of this exception, may be null
+ * @see #getCause()
+ */
+ public Throwable getUndeclaredThrowable()
+ {
+ return undeclaredThrowable;
+ }
+
+ /**
+ * Returns the cause of this exception. If this exception was created
+ * by a {@link Proxy} instance, it will be a non-null checked
+ * exception.
+ *
+ * @return the cause of this exception, may be null
+ * @since 1.4
+ */
+ public Throwable getCause()
+ {
+ return undeclaredThrowable;
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/WildcardType.java b/libjava/classpath/java/lang/reflect/WildcardType.java
new file mode 100644
index 00000000000..4f789067cf0
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/WildcardType.java
@@ -0,0 +1,115 @@
+/* WildcardType.java -- A wildcard type expression e.g. ? extends String
+ Copyright (C) 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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.reflect;
+
+/**
+ * Represents a wildcard type expression, where the type variable
+ * is unnamed. The simplest example of this is <code>?</code>,
+ * which represents any unbounded type. Another example is
+ * <code>? extends Number</code>, which specifies any type
+ * which is a subclass of <code>Number</code> (<code>Number</code>
+ * is the upper bound).
+ * </p>
+ * <p>
+ * <code>? super String</code> gives the type a less common lower bound,
+ * which means that the type must be either a <code>String</code> or one
+ * of its superclasses. This can be useful in working with collections.
+ * You may want a method to add instances of a class to a collection
+ * with a more generic type (e.g. adding <code>String</code>s to
+ * a list of <code>Object</code>s), but don't want to allow users
+ * to pass in a collection with a more specific type.
+ * </p>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface WildcardType extends Type
+{
+
+ /**
+ * <p>
+ * Returns an array of <code>Type</code>s, which specify the
+ * lower bounds of this type. The default lower bound is
+ * <code>null</code>, which causes this method to return an
+ * empty array.
+ * </p>
+ * <p>
+ * In generating the array of <code>Type</code>s, each
+ * <code>ParameterizedType</code> or <code>TypeVariable</code> is
+ * created, (see the documentation for these classes for details of this
+ * process), if necessary, while all other types are simply
+ * resolved.
+ * </p>
+ *
+ * @return an array of <code>Type</code> objects, representing
+ * the wildcard type's lower bounds.
+ * @throws TypeNotPresentException if any of the types referred to by
+ * the lower bounds of this type do not actually exist.
+ * @throws MalformedParameterizedTypeException if any of the types
+ * refer to a type which can not be instantiated.
+ */
+ Type[] getLowerBounds();
+
+ /**
+ * <p>
+ * Returns an array of <code>Type</code>s, which specify the
+ * upper bounds of this type. The default upper bound is
+ * <code>Object</code>, which causes this method to return an
+ * array, containing just the <code>Type</code> instance for
+ * <code>Object</code>.
+ * </p>
+ * <p>
+ * In generating the array of <code>Type</code>s, each
+ * <code>ParameterizedType</code> or <code>TypeVariable</code> is
+ * created, (see the documentation for these classes for details of this
+ * process), if necessary, while all other types are simply
+ * resolved.
+ * </p>
+ *
+ * @return an array of <code>Type</code> objects, representing
+ * the wildcard type's upper bounds.
+ * @throws TypeNotPresentException if any of the types referred to by
+ * the upper bounds of this type do not actually exist.
+ * @throws MalformedParameterizedTypeException if any of the types
+ * refer to a type which can not be instantiated.
+ */
+ Type[] getUpperBounds();
+
+}
diff --git a/libjava/classpath/java/lang/reflect/package.html b/libjava/classpath/java/lang/reflect/package.html
new file mode 100644
index 00000000000..9f7ed632836
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/package.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in java.lang.reflect package.
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 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. -->
+
+<html>
+<head><title>GNU Classpath - java.lang.reflect</title></head>
+
+<body>
+<p>Runtime inspection and manipulation of object classes, methods, arguments
+and fields.</p>
+
+</body>
+</html>