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.java233
-rw-r--r--libjava/classpath/java/lang/reflect/AnnotatedElement.java115
-rw-r--r--libjava/classpath/java/lang/reflect/Array.java655
-rw-r--r--libjava/classpath/java/lang/reflect/Constructor.java453
-rw-r--r--libjava/classpath/java/lang/reflect/Field.java735
-rw-r--r--libjava/classpath/java/lang/reflect/GenericArrayType.java61
-rw-r--r--libjava/classpath/java/lang/reflect/GenericDeclaration.java62
-rw-r--r--libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java63
-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/MalformedParameterizedTypeException.java60
-rw-r--r--libjava/classpath/java/lang/reflect/Member.java109
-rw-r--r--libjava/classpath/java/lang/reflect/Method.java497
-rw-r--r--libjava/classpath/java/lang/reflect/Modifier.java354
-rw-r--r--libjava/classpath/java/lang/reflect/ParameterizedType.java122
-rw-r--r--libjava/classpath/java/lang/reflect/Proxy.java1545
-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/TypeVariable.java96
-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
24 files changed, 5875 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 000000000..75676913d
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/AccessibleObject.java
@@ -0,0 +1,233 @@
+/* java.lang.reflect.AccessibleObject
+ Copyright (C) 2001, 2005, 2006 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.lang.annotation.Annotation;
+
+/**
+ * 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.5
+ */
+public class AccessibleObject
+ implements AnnotatedElement
+{
+ /**
+ * 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;
+ }
+
+ /**
+ * <p>
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ * </p>
+ * <p>
+ * <strong>This method must be overridden by subclasses to provide
+ * appropriate behaviour.</strong>
+ * </p>
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+ {
+ throw new AssertionError("Subclass must override this method");
+ }
+
+ /**
+ * Returns all annotations associated with the element. If there are
+ * no annotations associated with the element, then a zero-length array
+ * will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of the
+ * element, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return this element's annotations.
+ */
+ public Annotation[] getAnnotations()
+ {
+ return getDeclaredAnnotations();
+ }
+
+ /**
+ * <p>
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ * </p>
+ * <p>
+ * <strong>This method must be overridden by subclasses to provide
+ * appropriate behaviour.</strong>
+ * </p>
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations()
+ {
+ throw new AssertionError("Subclass must override this method");
+ }
+
+ /**
+ * Returns true if an annotation for the specified type is associated
+ * with the element. This is primarily a short-hand for using marker
+ * annotations.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return true if an annotation exists for the specified type.
+ * @since 1.5
+ */
+ public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
+ {
+ return getAnnotation(annotationClass) != null;
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/AnnotatedElement.java b/libjava/classpath/java/lang/reflect/AnnotatedElement.java
new file mode 100644
index 000000000..0179a0f4c
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/AnnotatedElement.java
@@ -0,0 +1,115 @@
+/* AnnotatedElement.java
+ 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;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * <p>
+ * Represents an element that can be annotated. The methods of this interface
+ * provide reflection-based access to the annotations associated with a
+ * particular element, such as a class, field, method or package. Each
+ * annotation returned by these methods is both immutable and serializable.
+ * The returned arrays may be freely modified, without any effect on the
+ * arrays returned to future callers.
+ * </p>
+ * <p>
+ * If an annotation refers to a type or enumeration constant that is
+ * inaccessible, then a <code>TypeNotPresentException</code> or
+ * <code>EnumConstantNotPresentException</code> will be thrown. Likewise,
+ * invalid annotations will produce either a
+ * <code>AnnotationTypeMismatchException</code> or
+ * <code>IncompleteAnnotationException</code>.
+ * </p>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface AnnotatedElement
+{
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+ <T extends Annotation> T getAnnotation(Class<T> annotationClass);
+
+ /**
+ * Returns all annotations associated with the element. If there are
+ * no annotations associated with the element, then a zero-length array
+ * will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of the
+ * element, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return this element's annotations.
+ */
+ Annotation[] getAnnotations();
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+ Annotation[] getDeclaredAnnotations();
+
+ /**
+ * Returns true if an annotation for the specified type is associated
+ * with the element. This is primarily a short-hand for using marker
+ * annotations.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return true if an annotation exists for the specified type.
+ * @since 1.5
+ */
+ boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
+
+}
diff --git a/libjava/classpath/java/lang/reflect/Array.java b/libjava/classpath/java/lang/reflect/Array.java
new file mode 100644
index 000000000..a31e48ea6
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Array.java
@@ -0,0 +1,655 @@
+/* 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;
+
+/**
+ * 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
+{
+
+ /**
+ * 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 VMArray.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, 0);
+ }
+
+ /**
+ * 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 Byte.valueOf(((byte[]) array)[index]);
+ if (array instanceof char[])
+ return Character.valueOf(((char[]) array)[index]);
+ if (array instanceof short[])
+ return Short.valueOf(((short[]) array)[index]);
+ if (array instanceof int[])
+ return Integer.valueOf(((int[]) array)[index]);
+ if (array instanceof long[])
+ return Long.valueOf(((long[]) array)[index]);
+ if (array instanceof float[])
+ return Float.valueOf(((float[]) array)[index]);
+ if (array instanceof double[])
+ return Double.valueOf(((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 == dimensions.length - 1)
+ return newInstance(type, dimensions[index]);
+
+ Object toAdd = createMultiArray(type, dimensions, index + 1);
+ Class thisType = toAdd.getClass();
+ Object[] retval
+ = (Object[]) VMArray.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;
+ }
+
+}
diff --git a/libjava/classpath/java/lang/reflect/Constructor.java b/libjava/classpath/java/lang/reflect/Constructor.java
new file mode 100644
index 000000000..d6c8d7934
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Constructor.java
@@ -0,0 +1,453 @@
+/* java.lang.reflect.Constructor - reflection of Java constructors
+ Copyright (C) 1998, 2001, 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.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
+
+import gnu.java.lang.reflect.MethodSignatureParser;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * The Constructor class represents a constructor of a class. It also allows
+ * dynamic creation of an object, via reflection. Invocation on Constructor
+ * objects knows how to do widening conversions, but throws
+ * {@link IllegalArgumentException} if a narrowing conversion would be
+ * necessary. You can query for information on this Constructor regardless
+ * of location, but construction access may be limited by Java language
+ * access controls. If you can't do it in the compiler, you can't normally
+ * do it here either.<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.<p>
+ *
+ * Also note that this is not a serializable class. It is entirely feasible
+ * to make it serializable using the Externalizable interface, but this is
+ * on Sun, not me.
+ *
+ * @author John Keiser
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @see Member
+ * @see Class
+ * @see java.lang.Class#getConstructor(Class[])
+ * @see java.lang.Class#getDeclaredConstructor(Class[])
+ * @see java.lang.Class#getConstructors()
+ * @see java.lang.Class#getDeclaredConstructors()
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Constructor<T>
+ extends AccessibleObject
+ implements GenericDeclaration, Member
+{
+ private static final int CONSTRUCTOR_MODIFIERS
+ = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
+
+ private MethodSignatureParser p;
+
+ VMConstructor cons;
+
+ /**
+ * This class is uninstantiable outside this package.
+ */
+ Constructor(VMConstructor cons)
+ {
+ this.cons = cons;
+ cons.cons = this;
+ }
+
+ private Constructor()
+ {
+ }
+
+ /**
+ * Gets the class that declared this constructor.
+ * @return the class that declared this member
+ */
+ public Class<T> getDeclaringClass()
+ {
+ // Inescapable as the VM layer is 1.4 based.
+ @SuppressWarnings("unchecked")
+ Class<T> declClass = (Class<T>) cons.getDeclaringClass();
+ return declClass;
+ }
+
+ /**
+ * Gets the name of this constructor (the non-qualified name of the class
+ * it was declared in).
+ * @return the name of this constructor
+ */
+ public String getName()
+ {
+ return cons.getDeclaringClass().getName();
+ }
+
+ /**
+ * Gets the modifiers this constructor uses. Use the <code>Modifier</code>
+ * class to interpret the values. A constructor can only have a subset of the
+ * following modifiers: public, private, protected.
+ *
+ * @return an integer representing the modifiers to this Member
+ * @see Modifier
+ */
+ public int getModifiers()
+ {
+ return cons.getModifiersInternal() & CONSTRUCTOR_MODIFIERS;
+ }
+
+ /**
+ * Return true if this constructor is synthetic, false otherwise.
+ * A synthetic member is one which is created by the compiler,
+ * and which does not appear in the user's source code.
+ * @since 1.5
+ */
+ public boolean isSynthetic()
+ {
+ return (cons.getModifiersInternal() & Modifier.SYNTHETIC) != 0;
+ }
+
+ /**
+ * Return true if this is a varargs constructor, that is if
+ * the constructor takes a variable number of arguments.
+ * @since 1.5
+ */
+ public boolean isVarArgs()
+ {
+ return (cons.getModifiersInternal() & Modifier.VARARGS) != 0;
+ }
+
+ /**
+ * Get the parameter list for this constructor, in declaration order. If the
+ * constructor takes no parameters, returns a 0-length array (not null).
+ *
+ * @return a list of the types of the constructor's parameters
+ */
+ public Class<?>[] getParameterTypes()
+ {
+ return (Class<?>[]) cons.getParameterTypes();
+ }
+
+ /**
+ * Get the exception types this constructor says it throws, in no particular
+ * order. If the constructor has no throws clause, returns a 0-length array
+ * (not null).
+ *
+ * @return a list of the types in the constructor's throws clause
+ */
+ public Class<?>[] getExceptionTypes()
+ {
+ return (Class<?>[]) cons.getExceptionTypes();
+ }
+
+ /**
+ * Compare two objects to see if they are semantically equivalent.
+ * Two Constructors are semantically equivalent if they have the same
+ * declaring class and the same parameter list. This ignores different
+ * exception clauses, but since you can't create a Method except through the
+ * VM, this is just the == relation.
+ *
+ * @param o the object to compare to
+ * @return <code>true</code> if they are equal; <code>false</code> if not.
+ */
+ public boolean equals(Object o)
+ {
+ return cons.equals(o);
+ }
+
+ /**
+ * Get the hash code for the Constructor. The Constructor hash code is the
+ * hash code of the declaring class's name.
+ *
+ * @return the hash code for the object
+ */
+ public int hashCode()
+ {
+ return getName().hashCode();
+ }
+
+ /**
+ * Get a String representation of the Constructor. A Constructor's String
+ * representation is "&lt;modifier&gt; &lt;classname&gt;(&lt;paramtypes&gt;)
+ * throws &lt;exceptions&gt;", where everything after ')' is omitted if
+ * there are no exceptions.<br> Example:
+ * <code>public java.io.FileInputStream(java.lang.Runnable)
+ * throws java.io.FileNotFoundException</code>
+ *
+ * @return the String representation of the Constructor
+ */
+ public String toString()
+ {
+ // 128 is a reasonable buffer initial size for constructor
+ CPStringBuilder sb = new CPStringBuilder(128);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ sb.append(getDeclaringClass().getName()).append('(');
+ Class[] c = getParameterTypes();
+ if (c.length > 0)
+ {
+ sb.append(ClassHelper.getUserName(c[0]));
+ for (int i = 1; i < c.length; i++)
+ sb.append(',').append(ClassHelper.getUserName(c[i]));
+ }
+ sb.append(')');
+ c = getExceptionTypes();
+ if (c.length > 0)
+ {
+ sb.append(" throws ").append(c[0].getName());
+ for (int i = 1; i < c.length; i++)
+ sb.append(',').append(c[i].getName());
+ }
+ return sb.toString();
+ }
+
+ static <X extends GenericDeclaration>
+ void addTypeParameters(CPStringBuilder sb, TypeVariable<X>[] typeArgs)
+ {
+ if (typeArgs.length == 0)
+ return;
+ sb.append('<');
+ for (int i = 0; i < typeArgs.length; ++i)
+ {
+ if (i > 0)
+ sb.append(',');
+ sb.append(typeArgs[i]);
+ }
+ sb.append("> ");
+ }
+
+ public String toGenericString()
+ {
+ CPStringBuilder sb = new CPStringBuilder(128);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ addTypeParameters(sb, getTypeParameters());
+ sb.append(getDeclaringClass().getName()).append('(');
+ Type[] types = getGenericParameterTypes();
+ if (types.length > 0)
+ {
+ sb.append(types[0]);
+ for (int i = 1; i < types.length; ++i)
+ sb.append(',').append(types[i]);
+ }
+ sb.append(')');
+ types = getGenericExceptionTypes();
+ if (types.length > 0)
+ {
+ sb.append(" throws ").append(types[0]);
+ for (int i = 1; i < types.length; i++)
+ sb.append(',').append(types[i]);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Create a new instance by invoking the constructor. Arguments are
+ * automatically unwrapped and widened, if needed.<p>
+ *
+ * If this class is abstract, you will get an
+ * <code>InstantiationException</code>. If the constructor takes 0
+ * arguments, you may use null or a 0-length array for <code>args</code>.<p>
+ *
+ * If this Constructor enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not create this object in similar compiled code. If the class
+ * is uninitialized, you trigger class initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Then, the constructor is invoked. If it completes normally, the return
+ * value will be the new object. If it completes abruptly, the exception is
+ * wrapped in an <code>InvocationTargetException</code>.
+ *
+ * @param args the arguments to the constructor
+ * @return the newly created object
+ * @throws IllegalAccessException if the constructor could not normally be
+ * called by the Java code (i.e. it is not public)
+ * @throws IllegalArgumentException if the number of arguments is incorrect;
+ * or if the arguments types are wrong even with a widening
+ * conversion
+ * @throws InstantiationException if the class is abstract
+ * @throws InvocationTargetException if the constructor throws an exception
+ * @throws ExceptionInInitializerError if construction triggered class
+ * initialization, which then failed
+ */
+ public T newInstance(Object... args)
+ throws InstantiationException, IllegalAccessException,
+ InvocationTargetException
+ {
+ // Inescapable as the VM layer is 1.4 based.
+ @SuppressWarnings("unchecked")
+ T ins = (T) cons.construct(args);
+ return ins;
+ }
+
+ /**
+ * Returns an array of <code>TypeVariable</code> objects that represents
+ * the type variables declared by this constructor, in declaration order.
+ * An array of size zero is returned if this constructor has no type
+ * variables.
+ *
+ * @return the type variables associated with this constructor.
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public TypeVariable<Constructor<T>>[] getTypeParameters()
+ {
+ if (p == null)
+ {
+ String sig = cons.getSignature();
+ if (sig == null)
+ return new TypeVariable[0];
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getTypeParameters();
+ }
+
+ /**
+ * Returns an array of <code>Type</code> objects that represents
+ * the exception types declared by this constructor, in declaration order.
+ * An array of size zero is returned if this constructor declares no
+ * exceptions.
+ *
+ * @return the exception types declared by this constructor.
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type[] getGenericExceptionTypes()
+ {
+ if (p == null)
+ {
+ String sig = cons.getSignature();
+ if (sig == null)
+ return getExceptionTypes();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericExceptionTypes();
+ }
+
+ /**
+ * Returns an array of <code>Type</code> objects that represents
+ * the parameter list for this constructor, in declaration order.
+ * An array of size zero is returned if this constructor takes no
+ * parameters.
+ *
+ * @return a list of the types of the constructor's parameters
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type[] getGenericParameterTypes()
+ {
+ if (p == null)
+ {
+ String sig = cons.getSignature();
+ if (sig == null)
+ return getParameterTypes();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericParameterTypes();
+ }
+
+ /**
+ * <p>
+ * Return an array of arrays representing the annotations on each
+ * of the constructor's parameters. The outer array is aligned against
+ * the parameters of the constructors and is thus equal in length to
+ * the number of parameters (thus having a length zero if there are none).
+ * Each array element in the outer array contains an inner array which
+ * holds the annotations. This array has a length of zero if the parameter
+ * has no annotations.
+ * </p>
+ * <p>
+ * The returned annotations are serialized. Changing the annotations has
+ * no affect on the return value of future calls to this method.
+ * </p>
+ *
+ * @return an array of arrays which represents the annotations used on the
+ * parameters of this constructor. The order of the array elements
+ * matches the declaration order of the parameters.
+ * @since 1.5
+ */
+ public Annotation[][] getParameterAnnotations()
+ {
+ return cons.getParameterAnnotations();
+ }
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+ {
+ // Inescapable as the VM layer is 1.4 based.
+ @SuppressWarnings("unchecked")
+ T ann = (T) cons.getAnnotation(annotationClass);
+ return ann;
+ }
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations()
+ {
+ return cons.getDeclaredAnnotations();
+ }
+
+}
diff --git a/libjava/classpath/java/lang/reflect/Field.java b/libjava/classpath/java/lang/reflect/Field.java
new file mode 100644
index 000000000..29ca795b8
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Field.java
@@ -0,0 +1,735 @@
+/* java.lang.reflect.Field - reflection of Java fields
+ Copyright (C) 1998, 2001, 2005, 2008 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.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
+
+import gnu.java.lang.reflect.FieldSignatureParser;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * The Field class represents a member variable of a class. It also allows
+ * dynamic access to a member, via reflection. This works for both
+ * static and instance fields. Operations on Field objects know how to
+ * do widening conversions, but throw {@link IllegalArgumentException} if
+ * a narrowing conversion would be necessary. You can query for information
+ * on this Field regardless of location, but get and set access may be limited
+ * by Java language access controls. If you can't do it in the compiler, you
+ * can't normally do it here either.<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.<p>
+ *
+ * Also note that this is not a serializable class. It is entirely feasible
+ * to make it serializable using the Externalizable interface, but this is
+ * on Sun, not me.
+ *
+ * @author John Keiser
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @see Member
+ * @see Class
+ * @see Class#getField(String)
+ * @see Class#getDeclaredField(String)
+ * @see Class#getFields()
+ * @see Class#getDeclaredFields()
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Field
+extends AccessibleObject implements Member
+{
+ static final int FIELD_MODIFIERS
+ = Modifier.FINAL | Modifier.PRIVATE | Modifier.PROTECTED
+ | Modifier.PUBLIC | Modifier.STATIC | Modifier.TRANSIENT
+ | Modifier.VOLATILE;
+
+ private FieldSignatureParser p;
+
+ VMField f;
+
+ /**
+ * This class is uninstantiable outside the package.
+ */
+ Field(VMField f)
+ {
+ this.f = f;
+ f.f = this;
+ }
+
+ /**
+ * Gets the class that declared this field, or the class where this field
+ * is a non-inherited member.
+ * @return the class that declared this member
+ */
+ public Class<?> getDeclaringClass()
+ {
+ return (Class<?>) f.getDeclaringClass();
+ }
+
+ /**
+ * Gets the name of this field.
+ * @return the name of this field
+ */
+ public String getName()
+ {
+ return f.getName();
+ }
+
+ /**
+ * Gets the modifiers this field uses. Use the <code>Modifier</code>
+ * class to interpret the values. A field can only have a subset of the
+ * following modifiers: public, private, protected, static, final,
+ * transient, and volatile.
+ *
+ * @return an integer representing the modifiers to this Member
+ * @see Modifier
+ */
+ public int getModifiers()
+ {
+ return f.getModifiersInternal() & FIELD_MODIFIERS;
+ }
+
+ /**
+ * Return true if this field is synthetic, false otherwise.
+ * @since 1.5
+ */
+ public boolean isSynthetic()
+ {
+ return (f.getModifiersInternal() & Modifier.SYNTHETIC) != 0;
+ }
+
+ /**
+ * Return true if this field represents an enum constant,
+ * false otherwise.
+ * @since 1.5
+ */
+ public boolean isEnumConstant()
+ {
+ return (f.getModifiersInternal() & Modifier.ENUM) != 0;
+ }
+
+ /**
+ * Gets the type of this field.
+ * @return the type of this field
+ */
+ public Class<?> getType()
+ {
+ return f.getType();
+ }
+
+ /**
+ * Compare two objects to see if they are semantically equivalent.
+ * Two Fields are semantically equivalent if they have the same declaring
+ * class, name, and type. Since you can't creat a Field except through
+ * the VM, this is just the == relation.
+ *
+ * @param o the object to compare to
+ * @return <code>true</code> if they are equal; <code>false</code> if not
+ */
+ public boolean equals(Object o)
+ {
+ return f.equals(o);
+ }
+
+ /**
+ * Get the hash code for the Field. The Field hash code is the hash code
+ * of its name XOR'd with the hash code of its class name.
+ *
+ * @return the hash code for the object.
+ */
+ public int hashCode()
+ {
+ return f.getDeclaringClass().getName().hashCode() ^ f.getName().hashCode();
+ }
+
+ /**
+ * Get a String representation of the Field. A Field's String
+ * representation is "&lt;modifiers&gt; &lt;type&gt;
+ * &lt;class&gt;.&lt;fieldname&gt;".<br> Example:
+ * <code>public transient boolean gnu.parse.Parser.parseComplete</code>
+ *
+ * @return the String representation of the Field
+ */
+ public String toString()
+ {
+ // 64 is a reasonable buffer initial size for field
+ CPStringBuilder sb = new CPStringBuilder(64);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ sb.append(ClassHelper.getUserName(getType())).append(' ');
+ sb.append(getDeclaringClass().getName()).append('.');
+ sb.append(getName());
+ return sb.toString();
+ }
+
+ public String toGenericString()
+ {
+ CPStringBuilder sb = new CPStringBuilder(64);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ sb.append(getGenericType()).append(' ');
+ sb.append(getDeclaringClass().getName()).append('.');
+ sb.append(getName());
+ return sb.toString();
+ }
+
+ /**
+ * Get the value of this Field. If it is primitive, it will be wrapped
+ * in the appropriate wrapper type (boolean = java.lang.Boolean).<p>
+ *
+ * If the field is static, <code>o</code> will be ignored. Otherwise, if
+ * <code>o</code> is null, you get a <code>NullPointerException</code>,
+ * and if it is incompatible with the declaring class of the field, you
+ * get an <code>IllegalArgumentException</code>.<p>
+ *
+ * Next, if this Field enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not access this field in similar compiled code. If the field
+ * is static, and its class is uninitialized, you trigger class
+ * initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Finally, the field is accessed, and primitives are wrapped (but not
+ * necessarily in new objects). This method accesses the field of the
+ * declaring class, even if the instance passed in belongs to a subclass
+ * which declares another field to hide this one.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if <code>o</code> is not an instance of
+ * the class or interface declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #getBoolean(Object)
+ * @see #getByte(Object)
+ * @see #getChar(Object)
+ * @see #getShort(Object)
+ * @see #getInt(Object)
+ * @see #getLong(Object)
+ * @see #getFloat(Object)
+ * @see #getDouble(Object)
+ */
+ public Object get(Object o)
+ throws IllegalAccessException
+ {
+ return f.get(o);
+ }
+
+ /**
+ * Get the value of this boolean Field. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a boolean field of
+ * <code>o</code>, or if <code>o</code> is not an instance of the
+ * declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public boolean getBoolean(Object o)
+ throws IllegalAccessException
+ {
+ return f.getBoolean(o);
+ }
+
+ /**
+ * Get the value of this byte Field. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte field of
+ * <code>o</code>, or if <code>o</code> is not an instance of the
+ * declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public byte getByte(Object o)
+ throws IllegalAccessException
+ {
+ return f.getByte(o);
+ }
+
+ /**
+ * Get the value of this Field as a char. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a char field of
+ * <code>o</code>, or if <code>o</code> is not an instance
+ * of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public char getChar(Object o)
+ throws IllegalAccessException
+ {
+ return f.getChar(o);
+ }
+
+ /**
+ * Get the value of this Field as a short. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte or short
+ * field of <code>o</code>, or if <code>o</code> is not an instance
+ * of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public short getShort(Object o)
+ throws IllegalAccessException
+ {
+ return f.getShort(o);
+ }
+
+ /**
+ * Get the value of this Field as an int. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, or
+ * int field of <code>o</code>, or if <code>o</code> is not an
+ * instance of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public int getInt(Object o)
+ throws IllegalAccessException
+ {
+ return f.getInt(o);
+ }
+
+ /**
+ * Get the value of this Field as a long. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, int,
+ * or long field of <code>o</code>, or if <code>o</code> is not an
+ * instance of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public long getLong(Object o)
+ throws IllegalAccessException
+ {
+ return f.getLong(o);
+ }
+
+ /**
+ * Get the value of this Field as a float. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, int,
+ * long, or float field of <code>o</code>, or if <code>o</code> is
+ * not an instance of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public float getFloat(Object o)
+ throws IllegalAccessException
+ {
+ return f.getFloat(o);
+ }
+
+ /**
+ * Get the value of this Field as a double. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, int,
+ * long, float, or double field of <code>o</code>, or if
+ * <code>o</code> is not an instance of the declaring class of this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public double getDouble(Object o)
+ throws IllegalAccessException
+ {
+ return f.getDouble(o);
+ }
+
+ /**
+ * Set the value of this Field. If it is a primitive field, the value
+ * will be unwrapped from the passed object (boolean = java.lang.Boolean).<p>
+ *
+ * If the field is static, <code>o</code> will be ignored. Otherwise, if
+ * <code>o</code> is null, you get a <code>NullPointerException</code>,
+ * and if it is incompatible with the declaring class of the field, you
+ * get an <code>IllegalArgumentException</code>.<p>
+ *
+ * Next, if this Field enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not access this field in similar compiled code. This also
+ * occurs whether or not there is access control if the field is final.
+ * If the field is primitive, and unwrapping your argument fails, you will
+ * get an <code>IllegalArgumentException</code>; likewise, this error
+ * happens if <code>value</code> cannot be cast to the correct object type.
+ * If the field is static, and its class is uninitialized, you trigger class
+ * initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Finally, the field is set with the widened value. This method accesses
+ * the field of the declaring class, even if the instance passed in belongs
+ * to a subclass which declares another field to hide this one.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if <code>value</code> cannot be
+ * converted by a widening conversion to the underlying type of
+ * the Field, or if <code>o</code> is not an instance of the class
+ * declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #setBoolean(Object, boolean)
+ * @see #setByte(Object, byte)
+ * @see #setChar(Object, char)
+ * @see #setShort(Object, short)
+ * @see #setInt(Object, int)
+ * @see #setLong(Object, long)
+ * @see #setFloat(Object, float)
+ * @see #setDouble(Object, double)
+ */
+ public void set(Object o, Object value)
+ throws IllegalAccessException
+ {
+ f.set(o, value);
+ }
+
+ /**
+ * Set this boolean Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a boolean field, or if
+ * <code>o</code> is not an instance of the class declaring this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setBoolean(Object o, boolean value)
+ throws IllegalAccessException
+ {
+ f.setBoolean(o, value);
+ }
+
+ /**
+ * Set this byte Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, int, long,
+ * float, or double field, or if <code>o</code> is not an instance
+ * of the class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setByte(Object o, byte value)
+ throws IllegalAccessException
+ {
+ f.setByte(o, value);
+ }
+
+ /**
+ * Set this char Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a char, int, long,
+ * float, or double field, or if <code>o</code> is not an instance
+ * of the class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setChar(Object o, char value)
+ throws IllegalAccessException
+ {
+ f.setChar(o, value);
+ }
+
+ /**
+ * Set this short Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a short, int, long,
+ * float, or double field, or if <code>o</code> is not an instance
+ * of the class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setShort(Object o, short value)
+ throws IllegalAccessException
+ {
+ f.setShort(o, value);
+ }
+
+ /**
+ * Set this int Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not an int, long, float, or
+ * double field, or if <code>o</code> is not an instance of the
+ * class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setInt(Object o, int value)
+ throws IllegalAccessException
+ {
+ f.setInt(o, value);
+ }
+
+ /**
+ * Set this long Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a long, float, or double
+ * field, or if <code>o</code> is not an instance of the class
+ * declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setLong(Object o, long value)
+ throws IllegalAccessException
+ {
+ f.setLong(o, value);
+ }
+
+ /**
+ * Set this float Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a float or long field, or
+ * if <code>o</code> is not an instance of the class declaring this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setFloat(Object o, float value)
+ throws IllegalAccessException
+ {
+ f.setFloat(o, value);
+ }
+
+ /**
+ * Set this double Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a double field, or if
+ * <code>o</code> is not an instance of the class declaring this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setDouble(Object o, double value)
+ throws IllegalAccessException
+ {
+ f.setDouble(o, value);
+ }
+
+ /**
+ * Return the generic type of the field. If the field type is not a generic
+ * type, the method returns the same as <code>getType()</code>.
+ *
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type getGenericType()
+ {
+ if (p == null)
+ {
+ String signature = f.getSignature();
+ if (signature == null)
+ return getType();
+ p = new FieldSignatureParser(getDeclaringClass(),
+ signature);
+ }
+ return p.getFieldType();
+ }
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+ {
+ // Inescapable as the VM layer is 1.4 based. T will erase to Annotation anyway.
+ @SuppressWarnings("unchecked") T ann = (T) f.getAnnotation(annotationClass);
+ return ann;
+ }
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations()
+ {
+ return f.getDeclaredAnnotations();
+ }
+
+}
diff --git a/libjava/classpath/java/lang/reflect/GenericArrayType.java b/libjava/classpath/java/lang/reflect/GenericArrayType.java
new file mode 100644
index 000000000..2e080247c
--- /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/GenericDeclaration.java b/libjava/classpath/java/lang/reflect/GenericDeclaration.java
new file mode 100644
index 000000000..d78aba913
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/GenericDeclaration.java
@@ -0,0 +1,62 @@
+/* GenericDeclaration.java
+ Copyright (C) 2004 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 an entity that declares one or more type parameters.
+ * This includes classes and methods (including constructors).
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface GenericDeclaration
+{
+ /**
+ * Returns a <code>TypeVariable</code> object for each type variable
+ * declared by this entity, in order of declaration. An empty array
+ * is returned if no type variables are declared.
+ *
+ * @return an array of <code>TypeVariable</code> objects.
+ * @throws GenericSignatureFormatError if the signature format within the
+ * class file does not conform to that specified in the 3rd edition
+ * of the Java Virtual Machine Specification.
+ */
+ TypeVariable<?>[] getTypeParameters();
+}
diff --git a/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java b/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java
new file mode 100644
index 000000000..0f09522bc
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java
@@ -0,0 +1,63 @@
+/* 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
+{
+ private static final long serialVersionUID = 6709919147137911034L;
+
+ /**
+ * 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 000000000..3d30afd93
--- /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 000000000..af79d3a19
--- /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/MalformedParameterizedTypeException.java b/libjava/classpath/java/lang/reflect/MalformedParameterizedTypeException.java
new file mode 100644
index 000000000..bfbe3bc89
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/MalformedParameterizedTypeException.java
@@ -0,0 +1,60 @@
+/* MalformedParameterizedTypeException.java
+ Copyright (C) 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 when one of the reflection
+ * methods encountered an invalid parameterized type within
+ * the metadata of a class. One possible reason for this
+ * exception being thrown is the specification of too few or
+ * too many type variables.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MalformedParameterizedTypeException
+ extends RuntimeException
+{
+ private static final long serialVersionUID = -5696557788586220964L;
+
+ public MalformedParameterizedTypeException()
+ {
+ }
+}
diff --git a/libjava/classpath/java/lang/reflect/Member.java b/libjava/classpath/java/lang/reflect/Member.java
new file mode 100644
index 000000000..fed962cf9
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Member.java
@@ -0,0 +1,109 @@
+/* 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(Class, int)
+ */
+ 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(Class, int)
+ */
+ 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();
+
+ /**
+ * Return true if this member is synthetic, meaning that it was
+ * created by the compiler and does not appear in the user's
+ * source code.
+ * @return true if the member is synthetic
+ * @since 1.5
+ */
+ boolean isSynthetic();
+}
diff --git a/libjava/classpath/java/lang/reflect/Method.java b/libjava/classpath/java/lang/reflect/Method.java
new file mode 100644
index 000000000..fe4b2eb1f
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Method.java
@@ -0,0 +1,497 @@
+/* java.lang.reflect.Method - reflection of Java methods
+ Copyright (C) 1998, 2001, 2002, 2005, 2007, 2008 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.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
+
+import gnu.java.lang.reflect.MethodSignatureParser;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * The Method class represents a member method of a class. It also allows
+ * dynamic invocation, via reflection. This works for both static and
+ * instance methods. Invocation on Method objects knows how to do
+ * widening conversions, but throws {@link IllegalArgumentException} if
+ * a narrowing conversion would be necessary. You can query for information
+ * on this Method regardless of location, but invocation access may be limited
+ * by Java language access controls. If you can't do it in the compiler, you
+ * can't normally do it here either.<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.<p>
+ *
+ * Also note that this is not a serializable class. It is entirely feasible
+ * to make it serializable using the Externalizable interface, but this is
+ * on Sun, not me.
+ *
+ * @author John Keiser
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @see Member
+ * @see Class
+ * @see java.lang.Class#getMethod(String,Class[])
+ * @see java.lang.Class#getDeclaredMethod(String,Class[])
+ * @see java.lang.Class#getMethods()
+ * @see java.lang.Class#getDeclaredMethods()
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Method
+extends AccessibleObject implements Member, GenericDeclaration
+{
+ private static final int METHOD_MODIFIERS
+ = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE
+ | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC
+ | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED;
+
+ private MethodSignatureParser p;
+
+ VMMethod m;
+
+ /**
+ * This class is uninstantiable outside this package.
+ */
+ Method(VMMethod m)
+ {
+ this.m = m;
+ m.m = this;
+ }
+
+ /**
+ * Gets the class that declared this method, or the class where this method
+ * is a non-inherited member.
+ * @return the class that declared this member
+ */
+ public Class<?> getDeclaringClass()
+ {
+ return (Class<?>) m.getDeclaringClass();
+ }
+
+ /**
+ * Gets the name of this method.
+ * @return the name of this method
+ */
+ public String getName()
+ {
+ return m.getName();
+ }
+
+ /**
+ * Gets the modifiers this method uses. Use the <code>Modifier</code>
+ * class to interpret the values. A method can only have a subset of the
+ * following modifiers: public, private, protected, abstract, static,
+ * final, synchronized, native, and strictfp.
+ *
+ * @return an integer representing the modifiers to this Member
+ * @see Modifier
+ */
+ public int getModifiers()
+ {
+ return m.getModifiersInternal() & METHOD_MODIFIERS;
+ }
+
+ /**
+ * Return true if this method is a bridge method. A bridge method
+ * is generated by the compiler in some situations involving
+ * generics and inheritance.
+ * @since 1.5
+ */
+ public boolean isBridge()
+ {
+ return (m.getModifiersInternal() & Modifier.BRIDGE) != 0;
+ }
+
+ /**
+ * Return true if this method is synthetic, false otherwise.
+ * @since 1.5
+ */
+ public boolean isSynthetic()
+ {
+ return (m.getModifiersInternal() & Modifier.SYNTHETIC) != 0;
+ }
+
+ /**
+ * Return true if this is a varargs method, that is if
+ * the method takes a variable number of arguments.
+ * @since 1.5
+ */
+ public boolean isVarArgs()
+ {
+ return (m.getModifiersInternal() & Modifier.VARARGS) != 0;
+ }
+
+ /**
+ * Gets the return type of this method.
+ * @return the type of this method
+ */
+ public Class<?> getReturnType()
+ {
+ return (Class<?>) m.getReturnType();
+ }
+
+ /**
+ * Get the parameter list for this method, in declaration order. If the
+ * method takes no parameters, returns a 0-length array (not null).
+ *
+ * @return a list of the types of the method's parameters
+ */
+ public Class<?>[] getParameterTypes()
+ {
+ return (Class<?>[]) m.getParameterTypes();
+ }
+
+ /**
+ * Get the exception types this method says it throws, in no particular
+ * order. If the method has no throws clause, returns a 0-length array
+ * (not null).
+ *
+ * @return a list of the types in the method's throws clause
+ */
+ public Class<?>[] getExceptionTypes()
+ {
+ return (Class<?>[]) m.getExceptionTypes();
+ }
+
+ /**
+ * Compare two objects to see if they are semantically equivalent.
+ * Two Methods are semantically equivalent if they have the same declaring
+ * class, name, parameter list, and return type.
+ *
+ * @param o the object to compare to
+ * @return <code>true</code> if they are equal; <code>false</code> if not
+ */
+ public boolean equals(Object o)
+ {
+ return m.equals(o);
+ }
+
+ /**
+ * Get the hash code for the Method. The Method hash code is the hash code
+ * of its name XOR'd with the hash code of its class name.
+ *
+ * @return the hash code for the object
+ */
+ public int hashCode()
+ {
+ return m.getDeclaringClass().getName().hashCode() ^ m.getName().hashCode();
+ }
+
+ /**
+ * Get a String representation of the Method. A Method's String
+ * representation is "&lt;modifiers&gt; &lt;returntype&gt;
+ * &lt;methodname&gt;(&lt;paramtypes&gt;) throws &lt;exceptions&gt;", where
+ * everything after ')' is omitted if there are no exceptions.<br> Example:
+ * <code>public static int run(java.lang.Runnable,int)</code>
+ *
+ * @return the String representation of the Method
+ */
+ public String toString()
+ {
+ // 128 is a reasonable buffer initial size for constructor
+ CPStringBuilder sb = new CPStringBuilder(128);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ sb.append(ClassHelper.getUserName(getReturnType())).append(' ');
+ sb.append(getDeclaringClass().getName()).append('.');
+ sb.append(getName()).append('(');
+ Class[] c = getParameterTypes();
+ if (c.length > 0)
+ {
+ sb.append(ClassHelper.getUserName(c[0]));
+ for (int i = 1; i < c.length; i++)
+ sb.append(',').append(ClassHelper.getUserName(c[i]));
+ }
+ sb.append(')');
+ c = getExceptionTypes();
+ if (c.length > 0)
+ {
+ sb.append(" throws ").append(c[0].getName());
+ for (int i = 1; i < c.length; i++)
+ sb.append(',').append(c[i].getName());
+ }
+ return sb.toString();
+ }
+
+ public String toGenericString()
+ {
+ // 128 is a reasonable buffer initial size for constructor
+ CPStringBuilder sb = new CPStringBuilder(128);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ Constructor.addTypeParameters(sb, getTypeParameters());
+ sb.append(getGenericReturnType()).append(' ');
+ sb.append(getDeclaringClass().getName()).append('.');
+ sb.append(getName()).append('(');
+ Type[] types = getGenericParameterTypes();
+ if (types.length > 0)
+ {
+ sb.append(types[0]);
+ for (int i = 1; i < types.length; i++)
+ sb.append(',').append(types[i]);
+ }
+ sb.append(')');
+ types = getGenericExceptionTypes();
+ if (types.length > 0)
+ {
+ sb.append(" throws ").append(types[0]);
+ for (int i = 1; i < types.length; i++)
+ sb.append(',').append(types[i]);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Invoke the method. Arguments are automatically unwrapped and widened,
+ * and the result is automatically wrapped, if needed.<p>
+ *
+ * If the method is static, <code>o</code> will be ignored. Otherwise,
+ * the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot
+ * mimic the behavior of nonvirtual lookup (as in super.foo()). This means
+ * you will get a <code>NullPointerException</code> if <code>o</code> is
+ * null, and an <code>IllegalArgumentException</code> if it is incompatible
+ * with the declaring class of the method. If the method takes 0 arguments,
+ * you may use null or a 0-length array for <code>args</code>.<p>
+ *
+ * Next, if this Method enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not acces this method in similar compiled code. If the method
+ * is static, and its class is uninitialized, you trigger class
+ * initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Finally, the method is invoked. If it completes normally, the return value
+ * will be null for a void method, a wrapped object for a primitive return
+ * method, or the actual return of an Object method. If it completes
+ * abruptly, the exception is wrapped in an
+ * <code>InvocationTargetException</code>.
+ *
+ * @param o the object to invoke the method on
+ * @param args the arguments to the method
+ * @return the return value of the method, wrapped in the appropriate
+ * wrapper if it is primitive
+ * @throws IllegalAccessException if the method could not normally be called
+ * by the Java code (i.e. it is not public)
+ * @throws IllegalArgumentException if the number of arguments is incorrect;
+ * if the arguments types are wrong even with a widening conversion;
+ * or if <code>o</code> is not an instance of the class or interface
+ * declaring this method
+ * @throws InvocationTargetException if the method throws an exception
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static method triggered
+ * class initialization, which then failed
+ */
+ public Object invoke(Object o, Object... args)
+ throws IllegalAccessException, InvocationTargetException
+ {
+ return m.invoke(o, args);
+ }
+
+ /**
+ * Returns an array of <code>TypeVariable</code> objects that represents
+ * the type variables declared by this constructor, in declaration order.
+ * An array of size zero is returned if this class has no type
+ * variables.
+ *
+ * @return the type variables associated with this class.
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public TypeVariable<Method>[] getTypeParameters()
+ {
+ if (p == null)
+ {
+ String sig = m.getSignature();
+ if (sig == null)
+ return (TypeVariable<Method>[]) new TypeVariable[0];
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getTypeParameters();
+ }
+
+ /**
+ * Returns an array of <code>Type</code> objects that represents
+ * the exception types declared by this method, in declaration order.
+ * An array of size zero is returned if this method declares no
+ * exceptions.
+ *
+ * @return the exception types declared by this method.
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type[] getGenericExceptionTypes()
+ {
+ if (p == null)
+ {
+ String sig = m.getSignature();
+ if (sig == null)
+ return getExceptionTypes();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericExceptionTypes();
+ }
+
+ /**
+ * Returns an array of <code>Type</code> objects that represents
+ * the parameter list for this method, in declaration order.
+ * An array of size zero is returned if this method takes no
+ * parameters.
+ *
+ * @return a list of the types of the method's parameters
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type[] getGenericParameterTypes()
+ {
+ if (p == null)
+ {
+ String sig = m.getSignature();
+ if (sig == null)
+ return getParameterTypes();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericParameterTypes();
+ }
+
+ /**
+ * Returns the return type of this method.
+ *
+ * @return the return type of this method
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type getGenericReturnType()
+ {
+ if (p == null)
+ {
+ String sig = m.getSignature();
+ if (sig == null)
+ return getReturnType();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericReturnType();
+ }
+
+ /**
+ * If this method is an annotation method, returns the default
+ * value for the method. If there is no default value, or if the
+ * method is not a member of an annotation type, returns null.
+ * Primitive types are wrapped.
+ *
+ * @throws TypeNotPresentException if the method returns a Class,
+ * and the class cannot be found
+ *
+ * @since 1.5
+ */
+ public Object getDefaultValue()
+ {
+ return m.getDefaultValue();
+ }
+
+ /**
+ * <p>
+ * Return an array of arrays representing the annotations on each
+ * of the method's parameters. The outer array is aligned against
+ * the parameters of the method and is thus equal in length to
+ * the number of parameters (thus having a length zero if there are none).
+ * Each array element in the outer array contains an inner array which
+ * holds the annotations. This array has a length of zero if the parameter
+ * has no annotations.
+ * </p>
+ * <p>
+ * The returned annotations are serialized. Changing the annotations has
+ * no affect on the return value of future calls to this method.
+ * </p>
+ *
+ * @return an array of arrays which represents the annotations used on the
+ * parameters of this method. The order of the array elements
+ * matches the declaration order of the parameters.
+ * @since 1.5
+ */
+ public Annotation[][] getParameterAnnotations()
+ {
+ return m.getParameterAnnotations();
+ }
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+ {
+ // Inescapable as the VM layer is 1.4 based. T will erase to Annotation anyway.
+ @SuppressWarnings("unchecked")
+ T ann = (T) m.getAnnotation(annotationClass);
+ return ann;
+ }
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations()
+ {
+ return m.getDeclaredAnnotations();
+ }
+
+}
diff --git a/libjava/classpath/java/lang/reflect/Modifier.java b/libjava/classpath/java/lang/reflect/Modifier.java
new file mode 100644
index 000000000..15bad05e7
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Modifier.java
@@ -0,0 +1,354 @@
+/* java.lang.reflect.Modifier
+ Copyright (C) 1998, 1999, 2001, 2002, 2005, 2008 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.java.lang.CPStringBuilder;
+
+/**
+ * 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;
+
+ /**
+ * Flag indicating a bridge method.
+ */
+ static final int BRIDGE = 0x40;
+
+ /**
+ * Flag indicating a varargs method.
+ */
+ static final int VARARGS = 0x80;
+
+ /**
+ * Flag indicating a synthetic member.
+ */
+ static final int SYNTHETIC = 0x1000;
+
+ /**
+ * Flag indicating an enum constant or an enum class.
+ */
+ static final int ENUM = 0x4000;
+
+ /**
+ * 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 CPStringBuilder()).toString();
+ }
+
+ /**
+ * Package helper method that can take a CPStringBuilder.
+ * @param mod the modifier
+ * @param r the CPStringBuilder to which the String representation is appended
+ * @return r, with information appended
+ */
+ static CPStringBuilder toString(int mod, CPStringBuilder 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 000000000..7a8a7b4e7
--- /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 GenericDeclaration
+ * @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 000000000..0e76124df
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/Proxy.java
@@ -0,0 +1,1545 @@
+/* Proxy.java -- build a proxy class that implements reflected interfaces
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 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.java.lang.CPStringBuilder;
+
+import gnu.java.lang.reflect.TypeSignature;
+
+import java.io.Serializable;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+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(Class)} 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 #newProxyInstance(ClassLoader, Class[], InvocationHandler)}
+ * 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.5, 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 (VMProxy.HAVE_NATIVE_GET_PROXY_CLASS)
+ clazz = VMProxy.getProxyClass(loader, interfaces);
+ else
+ {
+ ProxyData data = (VMProxy.HAVE_NATIVE_GET_PROXY_DATA
+ ? VMProxy.getProxyData(loader, interfaces)
+ : ProxyData.getProxyData(pt));
+
+ clazz = (VMProxy.HAVE_NATIVE_GENERATE_PROXY_CLASS
+ ? VMProxy.generateProxyClass(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;
+ }
+
+ /**
+ * 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)
+ {
+ this.loader = loader;
+ this.interfaces = interfaces;
+ }
+
+ /**
+ * Calculates the hash code.
+ *
+ * @return a combination of the classloader and interfaces hashcodes.
+ */
+ public int hashCode()
+ {
+ int hash = loader == null ? 0 : loader.hashCode();
+ for (int i = 0; i < interfaces.length; i++)
+ hash = hash * 31 + interfaces[i].hashCode();
+ return hash;
+ }
+
+ /**
+ * Calculates equality.
+ *
+ * @param other 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;
+ for (int i = 0; i < interfaces.length; i++)
+ if (interfaces[i] != pt.interfaces[i])
+ return false;
+ return true;
+ }
+ } // 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"));
+ coreMethods.put(sig, sig);
+ sig = new ProxySignature(Object.class.getMethod("toString"));
+ 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 other 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)
+ */
+ 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)
+ {
+ if (isCoreObjectMethod(methods[j]))
+ {
+ // In the case of an attempt to redefine a public non-final
+ // method of Object, we must skip it
+ continue;
+ }
+ 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;
+ }
+
+ /**
+ * Checks whether the method is similar to a public non-final method of
+ * Object or not (i.e. with the same name and parameter types). Note that we
+ * can't rely, directly or indirectly (via Collection.contains) on
+ * Method.equals as it would also check the declaring class, what we do not
+ * want. We only want to check that the given method have the same signature
+ * as a core method (same name and parameter types)
+ *
+ * @param method the method to check
+ * @return whether the method has the same name and parameter types as
+ * Object.equals, Object.hashCode or Object.toString
+ * @see java.lang.Object#equals(Object)
+ * @see java.lang.Object#hashCode()
+ * @see java.lang.Object#toString()
+ */
+ private static boolean isCoreObjectMethod(Method method)
+ {
+ String methodName = method.getName();
+ if (methodName.equals("equals"))
+ {
+ return Arrays.equals(method.getParameterTypes(),
+ new Class[] { Object.class });
+ }
+ if (methodName.equals("hashCode"))
+ {
+ return method.getParameterTypes().length == 0;
+ }
+ if (methodName.equals("toString"))
+ {
+ return method.getParameterTypes().length == 0;
+ }
+ return false;
+ }
+
+ } // 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 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 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;
+ CPStringBuilder signature = new CPStringBuilder("(");
+ 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, Integer.valueOf(0),
+ Integer.valueOf(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 CPStringBuilder sb = new CPStringBuilder(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 = Integer.valueOf(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 000000000..99ea224d7
--- /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 000000000..56eccf813
--- /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 000000000..6514c7603
--- /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 000000000..41b0a9ca9
--- /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/TypeVariable.java b/libjava/classpath/java/lang/reflect/TypeVariable.java
new file mode 100644
index 000000000..671c290ba
--- /dev/null
+++ b/libjava/classpath/java/lang/reflect/TypeVariable.java
@@ -0,0 +1,96 @@
+/* TypeVariable.java
+ Copyright (C) 2004 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>
+ * This is a common interface for all type variables provided by
+ * the Java language. Instances are created the first time a type
+ * variable is needed by one of the reflective methods declared in
+ * this package.
+ * </p>
+ * <p>
+ * Creating a type variable requires resolving the appropriate type.
+ * This may involve resolving other classes as a side effect (e.g.
+ * if the type is nested inside other classes). Creation should not
+ * involve resolving the bounds. Repeated creation has no effect; an
+ * equivalent instance is returned. Caching is not required, but all
+ * instances must be <code>equal()</code> to each other.
+ * </p>
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public interface TypeVariable<T extends GenericDeclaration> extends Type
+{
+
+ /**
+ * Returns an array of <code>Type</code> objects which represent the upper
+ * bounds of this type variable. There is always a default bound of
+ * <code>Object</code>. Any <code>ParameterizedType</code>s will be
+ * created as necessary, and other types resolved.
+ *
+ * @return an array of <code>Type</code> objects representing the upper
+ * bounds.
+ * @throws TypeNotPresentException if any of the bounds refer to a
+ * non-existant type.
+ * @throws MalformedParameterizedTypeException if the creation of a
+ * <code>ParameterizedType</code> fails.
+ */
+ Type[] getBounds();
+
+
+ /**
+ * Returns a representation of the declaration used to declare this
+ * type variable.
+ *
+ * @return the <code>GenericDeclaration</code> object for this type
+ * variable.
+ */
+ T getGenericDeclaration();
+
+ /**
+ * Returns the name of the type variable, as written in the source
+ * code.
+ *
+ * @return the name of the type variable.
+ */
+ String getName();
+}
diff --git a/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java b/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java
new file mode 100644
index 000000000..ea574ad7c
--- /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#getCause()}, 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 000000000..43b5d0a40
--- /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 000000000..9f7ed6328
--- /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>