diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/java/lang/reflect | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/java/lang/reflect')
37 files changed, 5711 insertions, 0 deletions
diff --git a/libjava/java/lang/reflect/AccessibleObject.h b/libjava/java/lang/reflect/AccessibleObject.h new file mode 100644 index 000000000..d140e300c --- /dev/null +++ b/libjava/java/lang/reflect/AccessibleObject.h @@ -0,0 +1,36 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_AccessibleObject__ +#define __java_lang_reflect_AccessibleObject__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::AccessibleObject : public ::java::lang::Object +{ + +public: // actually protected + AccessibleObject(); +public: + virtual jboolean isAccessible(); + static void setAccessible(JArray< ::java::lang::reflect::AccessibleObject * > *, jboolean); + virtual void setAccessible(jboolean); +private: + static void checkPermission(); + void secureSetAccessible(jboolean); +public: + virtual ::java::lang::annotation::Annotation * getAnnotation(::java::lang::Class *); + virtual JArray< ::java::lang::annotation::Annotation * > * getAnnotations(); + virtual JArray< ::java::lang::annotation::Annotation * > * getDeclaredAnnotations(); + virtual jboolean isAnnotationPresent(::java::lang::Class *); +public: // actually package-private + jboolean __attribute__((aligned(__alignof__( ::java::lang::Object)))) flag; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_AccessibleObject__ diff --git a/libjava/java/lang/reflect/AnnotatedElement.h b/libjava/java/lang/reflect/AnnotatedElement.h new file mode 100644 index 000000000..5792b75e0 --- /dev/null +++ b/libjava/java/lang/reflect/AnnotatedElement.h @@ -0,0 +1,24 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_AnnotatedElement__ +#define __java_lang_reflect_AnnotatedElement__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::AnnotatedElement : public ::java::lang::Object +{ + +public: + virtual ::java::lang::annotation::Annotation * getAnnotation(::java::lang::Class *) = 0; + virtual JArray< ::java::lang::annotation::Annotation * > * getAnnotations() = 0; + virtual JArray< ::java::lang::annotation::Annotation * > * getDeclaredAnnotations() = 0; + virtual jboolean isAnnotationPresent(::java::lang::Class *) = 0; + static ::java::lang::Class class$; +} __attribute__ ((java_interface)); + +#endif // __java_lang_reflect_AnnotatedElement__ diff --git a/libjava/java/lang/reflect/Array.h b/libjava/java/lang/reflect/Array.h new file mode 100644 index 000000000..48df7d3fa --- /dev/null +++ b/libjava/java/lang/reflect/Array.h @@ -0,0 +1,46 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Array__ +#define __java_lang_reflect_Array__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::Array : public ::java::lang::Object +{ + + Array(); +public: + static ::java::lang::Object * newInstance(::java::lang::Class *, jint); + static ::java::lang::Object * newInstance(::java::lang::Class *, JArray< jint > *); + static jint getLength(::java::lang::Object *); + static ::java::lang::Object * get(::java::lang::Object *, jint); + static jboolean getBoolean(::java::lang::Object *, jint); + static jbyte getByte(::java::lang::Object *, jint); + static jchar getChar(::java::lang::Object *, jint); + static jshort getShort(::java::lang::Object *, jint); + static jint getInt(::java::lang::Object *, jint); + static jlong getLong(::java::lang::Object *, jint); + static jfloat getFloat(::java::lang::Object *, jint); + static jdouble getDouble(::java::lang::Object *, jint); +private: + static ::java::lang::Class * getElementType(::java::lang::Object *, jint); + static void set(::java::lang::Object *, jint, ::java::lang::Object *, ::java::lang::Class *); +public: + static void set(::java::lang::Object *, jint, ::java::lang::Object *); + static void setBoolean(::java::lang::Object *, jint, jboolean); + static void setByte(::java::lang::Object *, jint, jbyte); + static void setChar(::java::lang::Object *, jint, jchar); + static void setShort(::java::lang::Object *, jint, jshort); + static void setInt(::java::lang::Object *, jint, jint); + static void setLong(::java::lang::Object *, jint, jlong); + static void setFloat(::java::lang::Object *, jint, jfloat); + static void setDouble(::java::lang::Object *, jint, jdouble); + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_Array__ diff --git a/libjava/java/lang/reflect/Array.java b/libjava/java/lang/reflect/Array.java new file mode 100644 index 000000000..639cc0e02 --- /dev/null +++ b/libjava/java/lang/reflect/Array.java @@ -0,0 +1,458 @@ +/* java.lang.reflect.Array - manipulate arrays by reflection + Copyright (C) 1998, 1999, 2001, 2003, 2005, 2007 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +import gnu.classpath.Configuration; + +/** + * Array holds static helper functions that allow you to create and + * manipulate arrays by reflection. Operations know how to perform widening + * conversions, but throw {@link IllegalArgumentException} if you attempt + * a narrowing conversion. Also, when accessing primitive arrays, this + * class performs object wrapping and unwrapping as necessary.<p> + * + * <B>Note:</B> This class returns and accepts types as Classes, even + * primitive types; there are Class types defined that represent each + * different primitive type. They are <code>java.lang.Boolean.TYPE, + * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class, + * byte.class</code>, etc. These are not to be confused with the + * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are + * real classes. Note also that the shorthand <code>Object[].class</code> + * is a convenient way to get array Classes.<p> + * + * <B>Performance note:</B> This class performs best when it does not have + * to convert primitive types. The further along the chain it has to convert, + * the worse performance will be. You're best off using the array as whatever + * type it already is, and then converting the result. You will do even + * worse if you do this and use the generic set() function. + * + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @author Per Bothner (bothner@cygnus.com) + * @see java.lang.Boolean#TYPE + * @see java.lang.Byte#TYPE + * @see java.lang.Short#TYPE + * @see java.lang.Character#TYPE + * @see java.lang.Integer#TYPE + * @see java.lang.Long#TYPE + * @see java.lang.Float#TYPE + * @see java.lang.Double#TYPE + * @since 1.1 + * @status updated to 1.4 + */ +public final class Array +{ + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("javalangreflect"); + } + } + + /** + * This class is uninstantiable. + */ + private Array() + { + } + + /** + * Creates a new single-dimensioned array. + * @param componentType the type of the array to create + * @param length the length of the array to create + * @return the created array, cast to an Object + * @throws NullPointerException if <code>componentType</code> is null + * @throws IllegalArgumentException if <code>componentType</code> is + * <code>Void.TYPE</code> + * @throws NegativeArraySizeException when length is less than 0 + * @throws OutOfMemoryError if memory allocation fails + */ + public static native Object newInstance(Class<?> componentType, int length); + + /** + * 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 native Object newInstance(Class<?> elementType, int[] dimensions); + + /** + * 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 native int getLength(Object array); + + /** + * 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 native Object get(Object array, int index); + + /** + * 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 native boolean getBoolean(Object array, int index); + + /** + * 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 native byte getByte(Object array, int index); + + /** + * 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 native char getChar(Object array, int index); + + /** + * 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 native short getShort(Object array, int 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 native int getInt(Object array, int 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 native long getLong(Object array, int 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 native float getFloat(Object array, int 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 native double getDouble(Object array, int index); + + private static native Class getElementType(Object array, int index); + + private static native void set(Object array, int index, + Object value, Class elType); + + /** + * 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) + { + Class elType = getElementType(array, index); + if (! elType.isPrimitive()) + set(array, index, value, elType); + 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 + 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 native void setBoolean(Object array, int index, boolean value); + + /** + * 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 native void setByte(Object array, int index, byte 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 native void setChar(Object array, int index, char 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 native void setShort(Object array, int index, short 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 native void setInt(Object array, int index, int 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 native void setLong(Object array, int index, long 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 native void setFloat(Object array, int index, float 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 native void setDouble(Object array, int index, double value); +} diff --git a/libjava/java/lang/reflect/Constructor.h b/libjava/java/lang/reflect/Constructor.h new file mode 100644 index 000000000..5a200bc11 --- /dev/null +++ b/libjava/java/lang/reflect/Constructor.h @@ -0,0 +1,65 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Constructor__ +#define __java_lang_reflect_Constructor__ + +#pragma interface + +#include <java/lang/reflect/AccessibleObject.h> +#include <gcj/array.h> + + +jmethodID _Jv_FromReflectedConstructor (java::lang::reflect::Constructor *); +jobject _Jv_JNI_ToReflectedMethod (_Jv_JNIEnv *, jclass, jmethodID, jboolean); + +class java::lang::reflect::Constructor : public ::java::lang::reflect::AccessibleObject +{ + + Constructor(); +public: + ::java::lang::Class * getDeclaringClass(); + ::java::lang::String * getName(); +private: + jint getModifiersInternal(); +public: + jint getModifiers(); + jboolean isSynthetic(); + jboolean isVarArgs(); + JArray< ::java::lang::Class * > * getParameterTypes(); + JArray< ::java::lang::Class * > * getExceptionTypes(); + jboolean equals(::java::lang::Object *); + jint hashCode(); + ::java::lang::String * toString(); +public: // actually package-private + static void addTypeParameters(::java::lang::StringBuilder *, JArray< ::java::lang::reflect::TypeVariable * > *); +public: + ::java::lang::String * toGenericString(); + ::java::lang::Object * newInstance(JArray< ::java::lang::Object * > *); + JArray< ::java::lang::reflect::TypeVariable * > * getTypeParameters(); +private: + ::java::lang::String * getSignature(); +public: + JArray< ::java::lang::reflect::Type * > * getGenericExceptionTypes(); + JArray< ::java::lang::reflect::Type * > * getGenericParameterTypes(); + ::java::lang::annotation::Annotation * getAnnotation(::java::lang::Class *); + JArray< ::java::lang::annotation::Annotation * > * getDeclaredAnnotations(); + JArray< JArray< ::java::lang::annotation::Annotation * > * > * getParameterAnnotations(); +private: + JArray< ::java::lang::annotation::Annotation * > * getDeclaredAnnotationsInternal(); + JArray< JArray< ::java::lang::annotation::Annotation * > * > * getParameterAnnotationsInternal(); + void getType(); + static const jint CONSTRUCTOR_MODIFIERS = 7; + ::java::lang::Class * __attribute__((aligned(__alignof__( ::java::lang::reflect::AccessibleObject)))) declaringClass; + JArray< ::java::lang::Class * > * exception_types; + JArray< ::java::lang::Class * > * parameter_types; + jint offset; +public: + static ::java::lang::Class class$; + + friend jmethodID (::_Jv_FromReflectedConstructor) (java::lang::reflect::Constructor *); + friend jobject (::_Jv_JNI_ToReflectedMethod) (_Jv_JNIEnv *, jclass, jmethodID, jboolean); + friend class java::lang::Class; +}; + +#endif // __java_lang_reflect_Constructor__ diff --git a/libjava/java/lang/reflect/Constructor.java b/libjava/java/lang/reflect/Constructor.java new file mode 100644 index 000000000..adebc600a --- /dev/null +++ b/libjava/java/lang/reflect/Constructor.java @@ -0,0 +1,424 @@ +/* java.lang.reflect.Constructor - reflection of Java constructors + Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 + 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.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> + * @author Tom Tromey <tromey@redhat.com> + * @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 Member, GenericDeclaration +{ + private static final int CONSTRUCTOR_MODIFIERS + = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC; + + /** + * This class is uninstantiable except from native code. + */ + private Constructor () + { + } + + /** + * Gets the class that declared this constructor. + * @return the class that declared this member + */ + public Class<T> getDeclaringClass () + { + return declaringClass; + } + + /** + * 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 declaringClass.getName(); + } + + /** + * Return the raw modifiers for this constructor. In particular + * this will include the synthetic and varargs bits. + * @return the constructor's modifiers + */ + private native int getModifiersInternal(); + + /** + * 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 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 (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 (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 () + { + if (parameter_types == null) + getType (); + return (Class<?>[]) parameter_types.clone(); + } + + /** + * 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 () + { + if (exception_types == null) + getType(); + return (Class<?>[]) exception_types.clone(); + } + + /** + * 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. + * + * @param o the object to compare to + * @return <code>true</code> if they are equal; <code>false</code> if not. + */ + public boolean equals (Object obj) + { + if (! (obj instanceof Constructor)) + return false; + Constructor c = (Constructor) obj; + return declaringClass == c.declaringClass && offset == c.offset; + } + + /** + * 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 declaringClass.getName().hashCode(); + } + + /** + * Get a String representation of the Constructor. A Constructor's String + * representation is "<modifier> <classname>(<paramtypes>) + * throws <exceptions>", 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() + { + if (parameter_types == null) + getType (); + StringBuffer b = new StringBuffer (); + int mods = getModifiers(); + if (mods != 0) + { + Modifier.toString(mods, b); + b.append(" "); + } + Method.appendClassName (b, declaringClass); + b.append("("); + for (int i = 0; i < parameter_types.length; ++i) + { + Method.appendClassName (b, parameter_types[i]); + if (i < parameter_types.length - 1) + b.append(","); + } + b.append(")"); + return b.toString(); + } + + static <X extends GenericDeclaration> + void addTypeParameters(StringBuilder 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() + { + StringBuilder sb = new StringBuilder(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 native T newInstance (Object... args) + throws InstantiationException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException; + + /** + * 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() + { + String sig = getSignature(); + if (sig == null) + return new TypeVariable[0]; + MethodSignatureParser p = new MethodSignatureParser(this, sig); + return p.getTypeParameters(); + } + + /** + * Return the String in the Signature attribute for this constructor. If there + * is no Signature attribute, return null. + */ + private native String getSignature(); + + /** + * 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() + { + String sig = getSignature(); + if (sig == null) + return getExceptionTypes(); + MethodSignatureParser 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() + { + String sig = getSignature(); + if (sig == null) + return getParameterTypes(); + MethodSignatureParser p = new MethodSignatureParser(this, sig); + return p.getGenericParameterTypes(); + } + + public <T extends Annotation> T getAnnotation(Class<T> annoClass) + { + Annotation[] annos = getDeclaredAnnotations(); + for (int i = 0; i < annos.length; ++i) + if (annos[i].annotationType() == annoClass) + return (T) annos[i]; + return null; + } + + public Annotation[] getDeclaredAnnotations() + { + Annotation[] result = getDeclaredAnnotationsInternal(); + if (result == null) + result = new Annotation[0]; + return result; + } + + public Annotation[][] getParameterAnnotations() + { + // FIXME: should check that we have the right number + // of parameters ...? + Annotation[][] result = getParameterAnnotationsInternal(); + if (result == null) + result = new Annotation[0][0]; + return result; + } + + private native Annotation[] getDeclaredAnnotationsInternal(); + private native Annotation[][] getParameterAnnotationsInternal(); + + // Update cached values from method descriptor in class. + private native void getType (); + + // Declaring class. + private Class<T> declaringClass; + + // Exception types. + private Class[] exception_types; + // Parameter types. + private Class[] parameter_types; + + // Offset in bytes from the start of declaringClass's methods array. + private int offset; +} diff --git a/libjava/java/lang/reflect/Field.h b/libjava/java/lang/reflect/Field.h new file mode 100644 index 000000000..0af95652d --- /dev/null +++ b/libjava/java/lang/reflect/Field.h @@ -0,0 +1,98 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Field__ +#define __java_lang_reflect_Field__ + +#pragma interface + +#include <java/lang/reflect/AccessibleObject.h> +#include <gcj/array.h> + + +jfieldID _Jv_FromReflectedField (java::lang::reflect::Field *); +jobject _Jv_JNI_ToReflectedField (_Jv_JNIEnv*, jclass, jfieldID, jboolean); +jobject _Jv_getFieldInternal (java::lang::reflect::Field *f, jclass c, jobject o); + +class java::lang::reflect::Field : public ::java::lang::reflect::AccessibleObject +{ + +public: // actually package-private + Field(); +public: + ::java::lang::Class * getDeclaringClass(); + ::java::lang::String * getName(); +private: + jint getModifiersInternal(); +public: + jint getModifiers(); + jboolean isSynthetic(); + jboolean isEnumConstant(); + ::java::lang::Class * getType(); + jboolean equals(::java::lang::Object *); + jint hashCode(); + ::java::lang::String * toString(); + ::java::lang::String * toGenericString(); + ::java::lang::Object * get(::java::lang::Object *); + jboolean getBoolean(::java::lang::Object *); + jbyte getByte(::java::lang::Object *); + jchar getChar(::java::lang::Object *); + jshort getShort(::java::lang::Object *); + jint getInt(::java::lang::Object *); + jlong getLong(::java::lang::Object *); + jfloat getFloat(::java::lang::Object *); + jdouble getDouble(::java::lang::Object *); +private: + jboolean getBoolean(::java::lang::Class *, ::java::lang::Object *); + jchar getChar(::java::lang::Class *, ::java::lang::Object *); + jbyte getByte(::java::lang::Class *, ::java::lang::Object *); + jshort getShort(::java::lang::Class *, ::java::lang::Object *); + jint getInt(::java::lang::Class *, ::java::lang::Object *); + jlong getLong(::java::lang::Class *, ::java::lang::Object *); + jfloat getFloat(::java::lang::Class *, ::java::lang::Object *); + jdouble getDouble(::java::lang::Class *, ::java::lang::Object *); + ::java::lang::Object * get(::java::lang::Class *, ::java::lang::Object *); +public: + void set(::java::lang::Object *, ::java::lang::Object *); + void setBoolean(::java::lang::Object *, jboolean); + void setByte(::java::lang::Object *, jbyte); + void setChar(::java::lang::Object *, jchar); + void setShort(::java::lang::Object *, jshort); + void setInt(::java::lang::Object *, jint); + void setLong(::java::lang::Object *, jlong); + void setFloat(::java::lang::Object *, jfloat); + void setDouble(::java::lang::Object *, jdouble); + ::java::lang::reflect::Type * getGenericType(); + ::java::lang::annotation::Annotation * getAnnotation(::java::lang::Class *); + JArray< ::java::lang::annotation::Annotation * > * getDeclaredAnnotations(); +private: + JArray< ::java::lang::annotation::Annotation * > * getDeclaredAnnotationsInternal(); + ::java::lang::String * getSignature(); +public: // actually package-private + void setByte(::java::lang::Class *, ::java::lang::Object *, jbyte, jboolean); + void setShort(::java::lang::Class *, ::java::lang::Object *, jshort, jboolean); + void setInt(::java::lang::Class *, ::java::lang::Object *, jint, jboolean); + void setLong(::java::lang::Class *, ::java::lang::Object *, jlong, jboolean); + void setFloat(::java::lang::Class *, ::java::lang::Object *, jfloat, jboolean); + void setDouble(::java::lang::Class *, ::java::lang::Object *, jdouble, jboolean); + void setChar(::java::lang::Class *, ::java::lang::Object *, jchar, jboolean); + void setBoolean(::java::lang::Class *, ::java::lang::Object *, jboolean, jboolean); + void set(::java::lang::Class *, ::java::lang::Object *, ::java::lang::Object *, ::java::lang::Class *, jboolean); +private: + void set(::java::lang::Class *, ::java::lang::Object *, ::java::lang::Object *); + ::java::lang::Class * __attribute__((aligned(__alignof__( ::java::lang::reflect::AccessibleObject)))) declaringClass; + ::java::lang::String * name; + jint offset; + ::java::lang::Class * type; +public: // actually package-private + static const jint FIELD_MODIFIERS = 223; +public: + static ::java::lang::Class class$; + + friend jfieldID (::_Jv_FromReflectedField) (java::lang::reflect::Field *); + friend jobject (::_Jv_JNI_ToReflectedField) (_Jv_JNIEnv*, jclass, jfieldID, jboolean); + friend class java::lang::Class; + friend jobject (::_Jv_getFieldInternal) (java::lang::reflect::Field *f, jclass c, jobject o); +}; + +#endif // __java_lang_reflect_Field__ diff --git a/libjava/java/lang/reflect/Field.java b/libjava/java/lang/reflect/Field.java new file mode 100644 index 000000000..61db14df5 --- /dev/null +++ b/libjava/java/lang/reflect/Field.java @@ -0,0 +1,817 @@ +/* java.lang.reflect.Field - reflection of Java fields + Copyright (C) 1998, 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 gnu.java.lang.ClassHelper; + +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> + * @author Per Bothner <bothner@cygnus.com> + * @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 +{ + private Class declaringClass; + private String name; + + // Offset in bytes from the start of declaringClass's fields array. + private int offset; + + // The Class (or primitive TYPE) of this field. + private Class type; + + static final int FIELD_MODIFIERS + = Modifier.FINAL | Modifier.PRIVATE | Modifier.PROTECTED + | Modifier.PUBLIC | Modifier.STATIC | Modifier.TRANSIENT + | Modifier.VOLATILE; + + // This is instantiated by Class sometimes, but it uses C++ and + // avoids the Java protection check. + Field () + { + } + + /** + * 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 declaringClass; + } + + /** + * Gets the name of this field. + * @return the name of this field + */ + public native String getName(); + + /** + * Return the raw modifiers for this field. + * @return the field's modifiers + */ + private native int getModifiersInternal(); + + /** + * 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 getModifiersInternal() & FIELD_MODIFIERS; + } + + /** + * Return true if this field is synthetic, false otherwise. + * @since 1.5 + */ + public boolean isSynthetic() + { + return (getModifiersInternal() & Modifier.SYNTHETIC) != 0; + } + + /** + * Return true if this field represents an enum constant, + * false otherwise. + * @since 1.5 + */ + public boolean isEnumConstant() + { + return (getModifiersInternal() & Modifier.ENUM) != 0; + } + + /** + * Gets the type of this field. + * @return the type of this field + */ + public native Class<?> 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 fld) + { + if (! (fld instanceof Field)) + return false; + Field f = (Field) fld; + return declaringClass == f.declaringClass && offset == f.offset; + } + + /** + * 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 getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Get a String representation of the Field. A Field's String + * representation is "<modifiers> <type> + * <class>.<fieldname>".<br> Example: + * <code>public transient boolean gnu.parse.Parser.parseComplete</code> + * + * @return the String representation of the Field + */ + public String toString () + { + StringBuffer sbuf = new StringBuffer (); + int mods = getModifiers(); + if (mods != 0) + { + Modifier.toString(mods, sbuf); + sbuf.append(' '); + } + Method.appendClassName (sbuf, getType ()); + sbuf.append(' '); + Method.appendClassName (sbuf, getDeclaringClass()); + sbuf.append('.'); + sbuf.append(getName()); + return sbuf.toString(); + } + + public String toGenericString() + { + StringBuilder sb = new StringBuilder(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 obj) + throws IllegalAccessException + { + return get(null, obj); + } + + /** + * 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 obj) + throws IllegalAccessException + { + return getBoolean(null, obj); + } + + /** + * 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 obj) + throws IllegalAccessException + { + return getByte(null, obj); + } + + /** + * 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 obj) + throws IllegalAccessException + { + return getChar(null, obj); + } + + /** + * 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 obj) + throws IllegalAccessException + { + return getShort(null, obj); + } + + /** + * 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 obj) + throws IllegalAccessException + { + return getInt(null, obj); + } + + /** + * 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 obj) + throws IllegalAccessException + { + return getLong(null, obj); + } + + /** + * 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 obj) + throws IllegalAccessException + { + return getFloat(null, obj); + } + + /** + * 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 obj) + throws IllegalAccessException + { + return getDouble(null, obj); + } + + private native boolean getBoolean (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + private native char getChar (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + private native byte getByte (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + private native short getShort (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + private native int getInt (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + private native long getLong (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + private native float getFloat (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + private native double getDouble (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + private native Object get (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + /** + * 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 object, Object value) + throws IllegalAccessException + { + set(null, object, 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 obj, boolean b) + throws IllegalAccessException + { + setBoolean(null, obj, b, true); + } + + /** + * 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 obj, byte b) + throws IllegalAccessException + { + setByte(null, obj, b, true); + } + + /** + * 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 obj, char c) + throws IllegalAccessException + { + setChar(null, obj, c, true); + } + + /** + * 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 obj, short s) + throws IllegalAccessException + { + setShort(null, obj, s, true); + } + + /** + * 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 obj, int i) + throws IllegalAccessException + { + setInt(null, obj, i, true); + } + + /** + * 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 obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setLong(null, obj, l, true); + } + + /** + * 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 obj, float f) + throws IllegalAccessException + { + setFloat(null, obj, f, true); + } + + /** + * 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 obj, double d) + throws IllegalAccessException + { + setDouble(null, obj, d, true); + } + + /** + * 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() + { + String signature = getSignature(); + if (signature == null) + return getType(); + FieldSignatureParser p = new FieldSignatureParser(getDeclaringClass(), + signature); + return p.getFieldType(); + } + + public <T extends Annotation> T getAnnotation(Class<T> annoClass) + { + Annotation[] annos = getDeclaredAnnotations(); + for (int i = 0; i < annos.length; ++i) + if (annos[i].annotationType() == annoClass) + return (T) annos[i]; + return null; + } + + public Annotation[] getDeclaredAnnotations() + { + Annotation[] result = getDeclaredAnnotationsInternal(); + if (result == null) + result = new Annotation[0]; + return result; + } + + private native Annotation[] getDeclaredAnnotationsInternal(); + + /** + * Return the String in the Signature attribute for this field. If there + * is no Signature attribute, return null. + */ + private native String getSignature(); + + native void setByte (Class caller, Object obj, byte b, boolean checkFinal) + throws IllegalArgumentException, IllegalAccessException; + + native void setShort (Class caller, Object obj, short s, boolean checkFinal) + throws IllegalArgumentException, IllegalAccessException; + + native void setInt (Class caller, Object obj, int i, boolean checkFinal) + throws IllegalArgumentException, IllegalAccessException; + + native void setLong (Class caller, Object obj, long l, boolean checkFinal) + throws IllegalArgumentException, IllegalAccessException; + + native void setFloat (Class caller, Object obj, float f, boolean checkFinal) + throws IllegalArgumentException, IllegalAccessException; + + native void setDouble (Class caller, Object obj, double d, + boolean checkFinal) + throws IllegalArgumentException, IllegalAccessException; + + native void setChar (Class caller, Object obj, char c, boolean checkFinal) + throws IllegalArgumentException, IllegalAccessException; + + native void setBoolean (Class caller, Object obj, boolean b, + boolean checkFinal) + throws IllegalArgumentException, IllegalAccessException; + + native void set (Class caller, Object obj, Object val, Class type, + boolean checkFinal) + throws IllegalArgumentException, IllegalAccessException; + + private void set (Class caller, Object object, Object value) + throws IllegalArgumentException, IllegalAccessException + { + Class type = getType(); + if (! type.isPrimitive()) + set(caller, object, value, type, true); + else if (value instanceof Byte) + setByte(caller, object, ((Byte) value).byteValue(), true); + else if (value instanceof Short) + setShort (caller, object, ((Short) value).shortValue(), true); + else if (value instanceof Integer) + setInt(caller, object, ((Integer) value).intValue(), true); + else if (value instanceof Long) + setLong(caller, object, ((Long) value).longValue(), true); + else if (value instanceof Float) + setFloat(caller, object, ((Float) value).floatValue(), true); + else if (value instanceof Double) + setDouble(caller, object, ((Double) value).doubleValue(), true); + else if (value instanceof Character) + setChar(caller, object, ((Character) value).charValue(), true); + else if (value instanceof Boolean) + setBoolean(caller, object, ((Boolean) value).booleanValue(), true); + else + throw new IllegalArgumentException(); + } +} diff --git a/libjava/java/lang/reflect/GenericArrayType.h b/libjava/java/lang/reflect/GenericArrayType.h new file mode 100644 index 000000000..cdeb0b2a3 --- /dev/null +++ b/libjava/java/lang/reflect/GenericArrayType.h @@ -0,0 +1,19 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_GenericArrayType__ +#define __java_lang_reflect_GenericArrayType__ + +#pragma interface + +#include <java/lang/Object.h> + +class java::lang::reflect::GenericArrayType : public ::java::lang::Object +{ + +public: + virtual ::java::lang::reflect::Type * getGenericComponentType() = 0; + static ::java::lang::Class class$; +} __attribute__ ((java_interface)); + +#endif // __java_lang_reflect_GenericArrayType__ diff --git a/libjava/java/lang/reflect/GenericDeclaration.h b/libjava/java/lang/reflect/GenericDeclaration.h new file mode 100644 index 000000000..5c484ea96 --- /dev/null +++ b/libjava/java/lang/reflect/GenericDeclaration.h @@ -0,0 +1,21 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_GenericDeclaration__ +#define __java_lang_reflect_GenericDeclaration__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::GenericDeclaration : public ::java::lang::Object +{ + +public: + virtual JArray< ::java::lang::reflect::TypeVariable * > * getTypeParameters() = 0; + static ::java::lang::Class class$; +} __attribute__ ((java_interface)); + +#endif // __java_lang_reflect_GenericDeclaration__ diff --git a/libjava/java/lang/reflect/GenericSignatureFormatError.h b/libjava/java/lang/reflect/GenericSignatureFormatError.h new file mode 100644 index 000000000..c46c9264a --- /dev/null +++ b/libjava/java/lang/reflect/GenericSignatureFormatError.h @@ -0,0 +1,22 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_GenericSignatureFormatError__ +#define __java_lang_reflect_GenericSignatureFormatError__ + +#pragma interface + +#include <java/lang/ClassFormatError.h> + +class java::lang::reflect::GenericSignatureFormatError : public ::java::lang::ClassFormatError +{ + +public: + GenericSignatureFormatError(); +private: + static const jlong serialVersionUID = 6709919147137911034LL; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_GenericSignatureFormatError__ diff --git a/libjava/java/lang/reflect/InvocationHandler.h b/libjava/java/lang/reflect/InvocationHandler.h new file mode 100644 index 000000000..722195321 --- /dev/null +++ b/libjava/java/lang/reflect/InvocationHandler.h @@ -0,0 +1,21 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_InvocationHandler__ +#define __java_lang_reflect_InvocationHandler__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::InvocationHandler : public ::java::lang::Object +{ + +public: + virtual ::java::lang::Object * invoke(::java::lang::Object *, ::java::lang::reflect::Method *, JArray< ::java::lang::Object * > *) = 0; + static ::java::lang::Class class$; +} __attribute__ ((java_interface)); + +#endif // __java_lang_reflect_InvocationHandler__ diff --git a/libjava/java/lang/reflect/InvocationTargetException.h b/libjava/java/lang/reflect/InvocationTargetException.h new file mode 100644 index 000000000..37e229c29 --- /dev/null +++ b/libjava/java/lang/reflect/InvocationTargetException.h @@ -0,0 +1,28 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_InvocationTargetException__ +#define __java_lang_reflect_InvocationTargetException__ + +#pragma interface + +#include <java/lang/Exception.h> + +class java::lang::reflect::InvocationTargetException : public ::java::lang::Exception +{ + +public: // actually protected + InvocationTargetException(); +public: + InvocationTargetException(::java::lang::Throwable *); + InvocationTargetException(::java::lang::Throwable *, ::java::lang::String *); + virtual ::java::lang::Throwable * getTargetException(); + virtual ::java::lang::Throwable * getCause(); +private: + static const jlong serialVersionUID = 4085088731926701167LL; + ::java::lang::Throwable * __attribute__((aligned(__alignof__( ::java::lang::Exception)))) target; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_InvocationTargetException__ diff --git a/libjava/java/lang/reflect/MalformedParameterizedTypeException.h b/libjava/java/lang/reflect/MalformedParameterizedTypeException.h new file mode 100644 index 000000000..a48f669c0 --- /dev/null +++ b/libjava/java/lang/reflect/MalformedParameterizedTypeException.h @@ -0,0 +1,22 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_MalformedParameterizedTypeException__ +#define __java_lang_reflect_MalformedParameterizedTypeException__ + +#pragma interface + +#include <java/lang/RuntimeException.h> + +class java::lang::reflect::MalformedParameterizedTypeException : public ::java::lang::RuntimeException +{ + +public: + MalformedParameterizedTypeException(); +private: + static const jlong serialVersionUID = -5696557788586220964LL; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_MalformedParameterizedTypeException__ diff --git a/libjava/java/lang/reflect/Member.h b/libjava/java/lang/reflect/Member.h new file mode 100644 index 000000000..9e3522be0 --- /dev/null +++ b/libjava/java/lang/reflect/Member.h @@ -0,0 +1,24 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Member__ +#define __java_lang_reflect_Member__ + +#pragma interface + +#include <java/lang/Object.h> + +class java::lang::reflect::Member : public ::java::lang::Object +{ + +public: + virtual ::java::lang::Class * getDeclaringClass() = 0; + virtual ::java::lang::String * getName() = 0; + virtual jint getModifiers() = 0; + virtual jboolean isSynthetic() = 0; + static const jint DECLARED = 1; + static const jint PUBLIC = 0; + static ::java::lang::Class class$; +} __attribute__ ((java_interface)); + +#endif // __java_lang_reflect_Member__ diff --git a/libjava/java/lang/reflect/Method.h b/libjava/java/lang/reflect/Method.h new file mode 100644 index 000000000..8a843d5d1 --- /dev/null +++ b/libjava/java/lang/reflect/Method.h @@ -0,0 +1,84 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Method__ +#define __java_lang_reflect_Method__ + +#pragma interface + +#include <java/lang/reflect/AccessibleObject.h> +#include <gcj/array.h> + + +jmethodID _Jv_FromReflectedMethod (java::lang::reflect::Method *); +jobject _Jv_JNI_ToReflectedMethod (_Jv_JNIEnv *, jclass, jmethodID, jboolean); +::java::lang::reflect::Method *_Jv_GetReflectedMethod (jclass, _Jv_Utf8Const*, _Jv_Utf8Const*); + +class java::lang::reflect::Method : public ::java::lang::reflect::AccessibleObject +{ + + Method(); +public: + ::java::lang::Class * getDeclaringClass(); + ::java::lang::String * getName(); +private: + jint getModifiersInternal(); +public: + jint getModifiers(); + jboolean isBridge(); + jboolean isSynthetic(); + jboolean isVarArgs(); + ::java::lang::Class * getReturnType(); + JArray< ::java::lang::Class * > * getParameterTypes(); +public: // actually package-private + JArray< ::java::lang::Class * > * internalGetParameterTypes(); +public: + JArray< ::java::lang::Class * > * getExceptionTypes(); +public: // actually package-private + JArray< ::java::lang::Class * > * internalGetExceptionTypes(); +public: + jboolean equals(::java::lang::Object *); + jint hashCode(); + ::java::lang::String * toString(); + ::java::lang::String * toGenericString(); + ::java::lang::Object * invoke(::java::lang::Object *, JArray< ::java::lang::Object * > *); + JArray< ::java::lang::reflect::TypeVariable * > * getTypeParameters(); +private: + ::java::lang::String * getSignature(); +public: + JArray< ::java::lang::reflect::Type * > * getGenericExceptionTypes(); + JArray< ::java::lang::reflect::Type * > * getGenericParameterTypes(); + ::java::lang::reflect::Type * getGenericReturnType(); + ::java::lang::Object * getDefaultValue(); + ::java::lang::annotation::Annotation * getAnnotation(::java::lang::Class *); + JArray< ::java::lang::annotation::Annotation * > * getDeclaredAnnotations(); + JArray< JArray< ::java::lang::annotation::Annotation * > * > * getParameterAnnotations(); +private: + JArray< ::java::lang::annotation::Annotation * > * getDeclaredAnnotationsInternal(); + JArray< JArray< ::java::lang::annotation::Annotation * > * > * getParameterAnnotationsInternal(); + void getType(); +public: // actually package-private + static void appendClassName(::java::lang::StringBuffer *, ::java::lang::Class *); + static const jint METHOD_MODIFIERS = 3391; +private: + ::java::lang::Class * __attribute__((aligned(__alignof__( ::java::lang::reflect::AccessibleObject)))) declaringClass; +public: // actually package-private + JArray< ::java::lang::Class * > * exception_types; +private: + ::java::lang::String * name; +public: // actually package-private + JArray< ::java::lang::Class * > * parameter_types; + ::java::lang::Class * return_type; +private: + jint offset; +public: + static ::java::lang::Class class$; + + friend jmethodID (::_Jv_FromReflectedMethod) (java::lang::reflect::Method *); + friend jobject (::_Jv_JNI_ToReflectedMethod) (_Jv_JNIEnv *, jclass, jmethodID, jboolean); + friend class java::lang::Class; + friend class java::io::ObjectInputStream; + friend java::lang::reflect::Method* ::_Jv_GetReflectedMethod (jclass, _Jv_Utf8Const*, _Jv_Utf8Const*); +}; + +#endif // __java_lang_reflect_Method__ diff --git a/libjava/java/lang/reflect/Method.java b/libjava/java/lang/reflect/Method.java new file mode 100644 index 000000000..878210abb --- /dev/null +++ b/libjava/java/lang/reflect/Method.java @@ -0,0 +1,501 @@ +// Method.java - Represent method of class or interface. + +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package java.lang.reflect; + +import gnu.gcj.RawData; +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> + * @author Tom Tromey <tromey@redhat.com> + * @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 +{ + static final int METHOD_MODIFIERS + = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE + | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC + | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED; + + /** + * This class is uninstantiable. + */ + private Method () + { + } + + /** + * 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 declaringClass; + } + + /** + * Gets the name of this method. + * @return the name of this method + */ + public native String getName (); + + /** + * Return the raw modifiers for this method. + * @return the method's modifiers + */ + private native int getModifiersInternal(); + + /** + * 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 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 (getModifiersInternal() & Modifier.BRIDGE) != 0; + } + + /** + * Return true if this method is synthetic, false otherwise. + * @since 1.5 + */ + public boolean isSynthetic() + { + return (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 (getModifiersInternal() & Modifier.VARARGS) != 0; + } + + /** + * Gets the return type of this method. + * @return the type of this method + */ + public Class<?> getReturnType () + { + if (return_type == null) + getType(); + return return_type; + } + + /** + * 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 () + { + if (parameter_types == null) + getType(); + return (Class<?>[]) parameter_types.clone(); + } + + // Just like getParameterTypes, but don't clone the array. + // Package private for use by VMProxy. + final Class<?>[] internalGetParameterTypes () + { + if (parameter_types == null) + getType(); + return (Class<?>[]) parameter_types; + } + + /** + * 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 () + { + if (exception_types == null) + getType(); + return (Class<?>[]) exception_types.clone(); + } + + // Just like getExceptionTypes, but don't clone the array. + // Package private for use by VMProxy. + final Class<?>[] internalGetExceptionTypes () + { + if (exception_types == null) + getType(); + return (Class<?>[]) exception_types; + } + + /** + * Compare two objects to see if they are semantically equivalent. + * Two Methods are semantically equivalent if they have the same declaring + * class, name, and parameter list. This ignores different exception + * clauses or return types. + * + * @param o the object to compare to + * @return <code>true</code> if they are equal; <code>false</code> if not + */ + public boolean equals (Object obj) + { + if (! (obj instanceof Method)) + return false; + Method m = (Method) obj; + return declaringClass == m.declaringClass && offset == m.offset; + } + + /** + * 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 getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Get a String representation of the Method. A Method's String + * representation is "<modifiers> <returntype> + * <methodname>(<paramtypes>) throws <exceptions>", 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() + { + if (parameter_types == null) + getType (); + + StringBuffer b = new StringBuffer (); + int mods = getModifiers(); + if (mods != 0) + { + Modifier.toString(mods, b); + b.append(" "); + } + appendClassName (b, return_type); + b.append(" "); + appendClassName (b, declaringClass); + b.append("."); + b.append(getName()); + b.append("("); + for (int i = 0; i < parameter_types.length; ++i) + { + appendClassName (b, parameter_types[i]); + if (i < parameter_types.length - 1) + b.append(","); + } + b.append(")"); + if (exception_types.length > 0) + { + b.append(" throws "); + for (int i = 0; i < exception_types.length; ++i) + { + appendClassName (b, exception_types[i]); + if (i < exception_types.length - 1) + b.append(","); + } + } + return b.toString(); + } + + public String toGenericString() + { + // 128 is a reasonable buffer initial size for constructor + StringBuilder sb = new StringBuilder(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 native Object invoke (Object obj, Object... args) + throws IllegalAccessException, IllegalArgumentException, + InvocationTargetException; + + /** + * 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() + { + String sig = getSignature(); + if (sig == null) + return new TypeVariable[0]; + MethodSignatureParser p = new MethodSignatureParser(this, sig); + return p.getTypeParameters(); + } + + /** + * Return the String in the Signature attribute for this method. If there + * is no Signature attribute, return null. + */ + private native String getSignature(); + + /** + * 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() + { + String sig = getSignature(); + if (sig == null) + return getExceptionTypes(); + MethodSignatureParser 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() + { + String sig = getSignature(); + if (sig == null) + return getParameterTypes(); + MethodSignatureParser 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() + { + String sig = getSignature(); + if (sig == null) + return getReturnType(); + MethodSignatureParser 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 native Object getDefaultValue(); + + public <T extends Annotation> T getAnnotation(Class<T> annoClass) + { + Annotation[] annos = getDeclaredAnnotations(); + for (int i = 0; i < annos.length; ++i) + if (annos[i].annotationType() == annoClass) + return (T) annos[i]; + return null; + } + + public Annotation[] getDeclaredAnnotations() + { + Annotation[] result = getDeclaredAnnotationsInternal(); + if (result == null) + result = new Annotation[0]; + return result; + } + + public Annotation[][] getParameterAnnotations() + { + // FIXME: should check that we have the right number + // of parameters ...? + Annotation[][] result = getParameterAnnotationsInternal(); + if (result == null) + result = new Annotation[0][0]; + return result; + } + + private native Annotation[] getDeclaredAnnotationsInternal(); + private native Annotation[][] getParameterAnnotationsInternal(); + + private native void getType (); + + // Append a class name to a string buffer. We try to print the + // fully-qualified name, the way that a Java programmer would expect + // it to be written. Weirdly, Class has no appropriate method for + // this. + static void appendClassName (StringBuffer buf, Class k) + { + if (k.isArray ()) + { + appendClassName (buf, k.getComponentType ()); + buf.append ("[]"); + } + else + { + // This is correct for primitive and reference types. Really + // we'd like `Main$Inner' to be printed as `Main.Inner', I + // think, but that is a pain. + buf.append (k.getName ()); + } + } + + // Declaring class. + private Class declaringClass; + + // Exception types. + Class[] exception_types; + // Name cache. (Initially null.) + private String name; + // Parameter types. + Class[] parameter_types; + // Return type. + Class return_type; + + // Offset in bytes from the start of declaringClass's methods array. + private int offset; +} diff --git a/libjava/java/lang/reflect/Modifier.h b/libjava/java/lang/reflect/Modifier.h new file mode 100644 index 000000000..4ee474a95 --- /dev/null +++ b/libjava/java/lang/reflect/Modifier.h @@ -0,0 +1,58 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Modifier__ +#define __java_lang_reflect_Modifier__ + +#pragma interface + +#include <java/lang/Object.h> + +class java::lang::reflect::Modifier : public ::java::lang::Object +{ + +public: + Modifier(); + static jboolean isAbstract(jint); + static jboolean isFinal(jint); + static jboolean isInterface(jint); + static jboolean isNative(jint); + static jboolean isPrivate(jint); + static jboolean isProtected(jint); + static jboolean isPublic(jint); + static jboolean isStatic(jint); + static jboolean isStrict(jint); + static jboolean isSynchronized(jint); + static jboolean isTransient(jint); + static jboolean isVolatile(jint); + static ::java::lang::String * toString(jint); +public: // actually package-private + static ::java::lang::StringBuilder * toString(jint, ::java::lang::StringBuilder *); + static ::java::lang::StringBuffer * toString(jint, ::java::lang::StringBuffer *); +public: + static const jint PUBLIC = 1; + static const jint PRIVATE = 2; + static const jint PROTECTED = 4; + static const jint STATIC = 8; + static const jint FINAL = 16; + static const jint SYNCHRONIZED = 32; + static const jint VOLATILE = 64; + static const jint TRANSIENT = 128; + static const jint NATIVE = 256; + static const jint INTERFACE = 512; + static const jint ABSTRACT = 1024; + static const jint STRICT = 2048; +public: // actually package-private + static const jint SUPER = 32; + static const jint ALL_FLAGS = 4095; + static const jint BRIDGE = 64; + static const jint VARARGS = 128; + static const jint SYNTHETIC = 4096; + static const jint ENUM = 16384; + static const jint INVISIBLE = 32768; + static const jint INTERPRETED = 4096; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_Modifier__ diff --git a/libjava/java/lang/reflect/Modifier.java b/libjava/java/lang/reflect/Modifier.java new file mode 100644 index 000000000..f9a9ca2c9 --- /dev/null +++ b/libjava/java/lang/reflect/Modifier.java @@ -0,0 +1,375 @@ +/* java.lang.reflect.Modifier + Copyright (C) 1998, 1999, 2001, 2002, 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; + +/** + * 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; + + /** + * GCJ-LOCAL: This access flag is set on methods we declare + * internally but which must not be visible to reflection. + */ + static final int INVISIBLE = 0x8000; + + /** + * GCJ-LOCAL: This access flag is set on interpreted classes. + */ + static final int INTERPRETED = 0x1000; + + /** + * 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><public|protected|private> abstract static final transient + * volatile synchronized native strictfp interface</code>. + * + * @param mod the modifier. + * @return the String representing the modifiers. + */ + public static String toString(int mod) + { + return toString(mod, new StringBuffer()).toString(); + } + + /** + * Package helper method that can take a StringBuilder. + * @param mod the modifier + * @param r the StringBuilder to which the String representation is appended + * @return r, with information appended + */ + static StringBuilder toString(int mod, StringBuilder r) + { + r.append(toString(mod, new StringBuffer())); + return r; + } + + /** + * Package helper method that can take a StringBuffer. + * @param mod the modifier + * @param r the StringBuffer to which the String representation is appended + * @return r, with information appended + */ + static StringBuffer toString(int mod, StringBuffer r) + { + if (isPublic(mod)) + r.append("public "); + if (isProtected(mod)) + r.append("protected "); + if (isPrivate(mod)) + r.append("private "); + if (isAbstract(mod)) + r.append("abstract "); + if (isStatic(mod)) + r.append("static "); + if (isFinal(mod)) + r.append("final "); + if (isTransient(mod)) + r.append("transient "); + if (isVolatile(mod)) + r.append("volatile "); + if (isSynchronized(mod)) + r.append("synchronized "); + if (isNative(mod)) + r.append("native "); + if (isStrict(mod)) + r.append("strictfp "); + if (isInterface(mod)) + r.append("interface "); + + // Trim trailing space. + if ((mod & ALL_FLAGS) != 0) + r.setLength(r.length() - 1); + return r; + } +} diff --git a/libjava/java/lang/reflect/ParameterizedType.h b/libjava/java/lang/reflect/ParameterizedType.h new file mode 100644 index 000000000..dab9ad953 --- /dev/null +++ b/libjava/java/lang/reflect/ParameterizedType.h @@ -0,0 +1,23 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_ParameterizedType__ +#define __java_lang_reflect_ParameterizedType__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::ParameterizedType : public ::java::lang::Object +{ + +public: + virtual JArray< ::java::lang::reflect::Type * > * getActualTypeArguments() = 0; + virtual ::java::lang::reflect::Type * getOwnerType() = 0; + virtual ::java::lang::reflect::Type * getRawType() = 0; + static ::java::lang::Class class$; +} __attribute__ ((java_interface)); + +#endif // __java_lang_reflect_ParameterizedType__ diff --git a/libjava/java/lang/reflect/Proxy$ClassFactory.h b/libjava/java/lang/reflect/Proxy$ClassFactory.h new file mode 100644 index 000000000..c4cfb883d --- /dev/null +++ b/libjava/java/lang/reflect/Proxy$ClassFactory.h @@ -0,0 +1,78 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Proxy$ClassFactory__ +#define __java_lang_reflect_Proxy$ClassFactory__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::Proxy$ClassFactory : public ::java::lang::Object +{ + +public: // actually package-private + Proxy$ClassFactory(::java::lang::reflect::Proxy$ProxyData *); +private: + void emitMethod(jint, JArray< ::java::lang::Class * > *); +public: // actually package-private + ::java::lang::Class * generate(::java::lang::ClassLoader *); +private: + void putU1(jint); + void putU2(jint); + void putU4(jint); + void putConst(jint); + void putLoad(jint, ::java::lang::Class *); + ::java::lang::String * wrapper(::java::lang::Class *); + jchar utf8Info(::java::lang::String *); + jchar classInfo(::java::lang::String *); + jchar classInfo(::java::lang::Class *); + jchar refInfo(jbyte, ::java::lang::String *, ::java::lang::String *, ::java::lang::String *); + jchar nameAndTypeInfo(::java::lang::String *, ::java::lang::String *); + ::java::lang::String * toUtf8(::java::lang::String *); + jchar poolIndex(::java::lang::String *); + static const jbyte FIELD = 1; + static const jbyte METHOD = 2; + static const jbyte INTERFACE = 3; + static ::java::lang::String * CTOR_SIG; + static ::java::lang::String * INVOKE_SIG; + static const jchar ACONST_NULL = 1; + static const jchar ICONST_0 = 3; + static const jchar BIPUSH = 16; + static const jchar SIPUSH = 17; + static const jchar ILOAD = 21; + static const jchar ILOAD_0 = 26; + static const jchar ALOAD_0 = 42; + static const jchar ALOAD_1 = 43; + static const jchar AALOAD = 50; + static const jchar AASTORE = 83; + static const jchar DUP = 89; + static const jchar DUP_X1 = 90; + static const jchar SWAP = 95; + static const jchar IRETURN = 172; + static const jchar LRETURN = 173; + static const jchar FRETURN = 174; + static const jchar DRETURN = 175; + static const jchar ARETURN = 176; + static const jchar RETURN = 177; + static const jchar GETSTATIC = 178; + static const jchar GETFIELD = 180; + static const jchar INVOKEVIRTUAL = 182; + static const jchar INVOKESPECIAL = 183; + static const jchar INVOKEINTERFACE = 185; + static const jchar NEW = 187; + static const jchar ANEWARRAY = 189; + static const jchar ATHROW = 191; + static const jchar CHECKCAST = 192; + ::java::lang::StringBuffer * __attribute__((aligned(__alignof__( ::java::lang::Object)))) pool; + ::java::lang::StringBuffer * stream; + ::java::util::Map * poolEntries; + ::java::lang::String * qualName; + JArray< ::java::lang::reflect::Method * > * methods; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_Proxy$ClassFactory__ diff --git a/libjava/java/lang/reflect/Proxy$ProxyData.h b/libjava/java/lang/reflect/Proxy$ProxyData.h new file mode 100644 index 000000000..2c0d91e5e --- /dev/null +++ b/libjava/java/lang/reflect/Proxy$ProxyData.h @@ -0,0 +1,37 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Proxy$ProxyData__ +#define __java_lang_reflect_Proxy$ProxyData__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::Proxy$ProxyData : public ::java::lang::Object +{ + +public: // actually package-private + Proxy$ProxyData(); +private: + static ::java::lang::String * getPackage(::java::lang::Class *); +public: // actually package-private + static ::java::lang::reflect::Proxy$ProxyData * getProxyData(::java::lang::reflect::Proxy$ProxyType *); +private: + static jboolean isCoreObjectMethod(::java::lang::reflect::Method *); +public: // actually package-private + ::java::lang::String * __attribute__((aligned(__alignof__( ::java::lang::Object)))) pack; + JArray< ::java::lang::Class * > * interfaces; + JArray< ::java::lang::reflect::Method * > * methods; + JArray< JArray< ::java::lang::Class * > * > * exceptions; +private: + static jint count; +public: // actually package-private + jint id; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_Proxy$ProxyData__ diff --git a/libjava/java/lang/reflect/Proxy$ProxySignature.h b/libjava/java/lang/reflect/Proxy$ProxySignature.h new file mode 100644 index 000000000..ae0f028de --- /dev/null +++ b/libjava/java/lang/reflect/Proxy$ProxySignature.h @@ -0,0 +1,28 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Proxy$ProxySignature__ +#define __java_lang_reflect_Proxy$ProxySignature__ + +#pragma interface + +#include <java/lang/Object.h> + +class java::lang::reflect::Proxy$ProxySignature : public ::java::lang::Object +{ + +public: // actually package-private + Proxy$ProxySignature(::java::lang::reflect::Method *); + void checkCompatibility(::java::lang::reflect::Proxy$ProxySignature *); +public: + jint hashCode(); + jboolean equals(::java::lang::Object *); +public: // actually package-private + static ::java::util::HashMap * coreMethods; + ::java::lang::reflect::Method * __attribute__((aligned(__alignof__( ::java::lang::Object)))) method; + ::java::util::Set * exceptions; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_Proxy$ProxySignature__ diff --git a/libjava/java/lang/reflect/Proxy$ProxyType.h b/libjava/java/lang/reflect/Proxy$ProxyType.h new file mode 100644 index 000000000..da7653539 --- /dev/null +++ b/libjava/java/lang/reflect/Proxy$ProxyType.h @@ -0,0 +1,28 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Proxy$ProxyType__ +#define __java_lang_reflect_Proxy$ProxyType__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::Proxy$ProxyType : public ::java::lang::Object +{ + +public: // actually package-private + Proxy$ProxyType(::java::lang::ClassLoader *, JArray< ::java::lang::Class * > *); +public: + jint hashCode(); + jboolean equals(::java::lang::Object *); +public: // actually package-private + ::java::lang::ClassLoader * __attribute__((aligned(__alignof__( ::java::lang::Object)))) loader; + JArray< ::java::lang::Class * > * interfaces; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_Proxy$ProxyType__ diff --git a/libjava/java/lang/reflect/Proxy.h b/libjava/java/lang/reflect/Proxy.h new file mode 100644 index 000000000..4dad2cffd --- /dev/null +++ b/libjava/java/lang/reflect/Proxy.h @@ -0,0 +1,32 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Proxy__ +#define __java_lang_reflect_Proxy__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::Proxy : public ::java::lang::Object +{ + +public: // actually protected + Proxy(::java::lang::reflect::InvocationHandler *); +public: + static ::java::lang::Class * getProxyClass(::java::lang::ClassLoader *, JArray< ::java::lang::Class * > *); + static ::java::lang::Object * newProxyInstance(::java::lang::ClassLoader *, JArray< ::java::lang::Class * > *, ::java::lang::reflect::InvocationHandler *); + static jboolean isProxyClass(::java::lang::Class *); + static ::java::lang::reflect::InvocationHandler * getInvocationHandler(::java::lang::Object *); +private: + static const jlong serialVersionUID = -2222568056686623797LL; + static ::java::util::Map * proxyClasses; +public: // actually protected + ::java::lang::reflect::InvocationHandler * __attribute__((aligned(__alignof__( ::java::lang::Object)))) h; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_Proxy__ diff --git a/libjava/java/lang/reflect/ReflectPermission.h b/libjava/java/lang/reflect/ReflectPermission.h new file mode 100644 index 000000000..0e6a7c32e --- /dev/null +++ b/libjava/java/lang/reflect/ReflectPermission.h @@ -0,0 +1,23 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_ReflectPermission__ +#define __java_lang_reflect_ReflectPermission__ + +#pragma interface + +#include <java/security/BasicPermission.h> + +class java::lang::reflect::ReflectPermission : public ::java::security::BasicPermission +{ + +public: + ReflectPermission(::java::lang::String *); + ReflectPermission(::java::lang::String *, ::java::lang::String *); +private: + static const jlong serialVersionUID = 7412737110241507485LL; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_ReflectPermission__ diff --git a/libjava/java/lang/reflect/Type.h b/libjava/java/lang/reflect/Type.h new file mode 100644 index 000000000..55c317fa4 --- /dev/null +++ b/libjava/java/lang/reflect/Type.h @@ -0,0 +1,18 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_Type__ +#define __java_lang_reflect_Type__ + +#pragma interface + +#include <java/lang/Object.h> + +class java::lang::reflect::Type : public ::java::lang::Object +{ + +public: + static ::java::lang::Class class$; +} __attribute__ ((java_interface)); + +#endif // __java_lang_reflect_Type__ diff --git a/libjava/java/lang/reflect/TypeVariable.h b/libjava/java/lang/reflect/TypeVariable.h new file mode 100644 index 000000000..6029c0190 --- /dev/null +++ b/libjava/java/lang/reflect/TypeVariable.h @@ -0,0 +1,23 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_TypeVariable__ +#define __java_lang_reflect_TypeVariable__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::TypeVariable : public ::java::lang::Object +{ + +public: + virtual JArray< ::java::lang::reflect::Type * > * getBounds() = 0; + virtual ::java::lang::reflect::GenericDeclaration * getGenericDeclaration() = 0; + virtual ::java::lang::String * getName() = 0; + static ::java::lang::Class class$; +} __attribute__ ((java_interface)); + +#endif // __java_lang_reflect_TypeVariable__ diff --git a/libjava/java/lang/reflect/UndeclaredThrowableException.h b/libjava/java/lang/reflect/UndeclaredThrowableException.h new file mode 100644 index 000000000..01b969b0e --- /dev/null +++ b/libjava/java/lang/reflect/UndeclaredThrowableException.h @@ -0,0 +1,26 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_UndeclaredThrowableException__ +#define __java_lang_reflect_UndeclaredThrowableException__ + +#pragma interface + +#include <java/lang/RuntimeException.h> + +class java::lang::reflect::UndeclaredThrowableException : public ::java::lang::RuntimeException +{ + +public: + UndeclaredThrowableException(::java::lang::Throwable *); + UndeclaredThrowableException(::java::lang::Throwable *, ::java::lang::String *); + virtual ::java::lang::Throwable * getUndeclaredThrowable(); + virtual ::java::lang::Throwable * getCause(); +private: + static const jlong serialVersionUID = 330127114055056639LL; + ::java::lang::Throwable * __attribute__((aligned(__alignof__( ::java::lang::RuntimeException)))) undeclaredThrowable; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_UndeclaredThrowableException__ diff --git a/libjava/java/lang/reflect/VMProxy.h b/libjava/java/lang/reflect/VMProxy.h new file mode 100644 index 000000000..e48e8e4e8 --- /dev/null +++ b/libjava/java/lang/reflect/VMProxy.h @@ -0,0 +1,28 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_VMProxy__ +#define __java_lang_reflect_VMProxy__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::VMProxy : public ::java::lang::Object +{ + +public: // actually package-private + VMProxy(); + static ::java::lang::Class * getProxyClass(::java::lang::ClassLoader *, JArray< ::java::lang::Class * > *); + static ::java::lang::reflect::Proxy$ProxyData * getProxyData(::java::lang::ClassLoader *, JArray< ::java::lang::Class * > *); + static ::java::lang::Class * generateProxyClass(::java::lang::ClassLoader *, ::java::lang::reflect::Proxy$ProxyData *); + static jboolean HAVE_NATIVE_GET_PROXY_CLASS; + static jboolean HAVE_NATIVE_GET_PROXY_DATA; + static jboolean HAVE_NATIVE_GENERATE_PROXY_CLASS; +public: + static ::java::lang::Class class$; +}; + +#endif // __java_lang_reflect_VMProxy__ diff --git a/libjava/java/lang/reflect/VMProxy.java b/libjava/java/lang/reflect/VMProxy.java new file mode 100644 index 000000000..ea1c88506 --- /dev/null +++ b/libjava/java/lang/reflect/VMProxy.java @@ -0,0 +1,140 @@ +/* VMProxy.java -- VM interface for proxy class + 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; + +final class VMProxy +{ + /** + * Set to true if the VM provides a native method to implement + * Proxy.getProxyClass completely, including argument verification. + * If this is true, HAVE_NATIVE_GET_PROXY_DATA and + * HAVE_NATIVE_GENERATE_PROXY_CLASS should be false. + * @see java.lang.reflect.Proxy + */ + static boolean HAVE_NATIVE_GET_PROXY_CLASS = false; + + /** + * Set to true if the VM provides a native method to implement + * the first part of Proxy.getProxyClass: generation of the array + * of methods to convert, and verification of the arguments. + * If this is true, HAVE_NATIVE_GET_PROXY_CLASS should be false. + * @see java.lang.reflect.Proxy + */ + static boolean HAVE_NATIVE_GET_PROXY_DATA = false; + + /** + * Set to true if the VM provides a native method to implement + * the second part of Proxy.getProxyClass: conversion of an array of + * methods into an actual proxy class. + * If this is true, HAVE_NATIVE_GET_PROXY_CLASS should be false. + * @see java.lang.reflect.Proxy + */ + static boolean HAVE_NATIVE_GENERATE_PROXY_CLASS = true; + + /** + * Optional native method to replace (and speed up) the pure Java + * implementation of getProxyClass. Only needed if + * VMProxy.HAVE_NATIVE_GET_PROXY_CLASS is true, this does the + * work of both getProxyData and generateProxyClass with no + * intermediate form in Java. The native code may safely assume that + * this class must be created, and does not already exist. + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @param interfaces the interfaces the class will extend + * @return the generated proxy class + * @throws IllegalArgumentException if the constraints for getProxyClass + * were violated, except for problems with null + * @throws NullPointerException if `interfaces' is null or contains + * a null entry, or if handler is null + * @see Configuration#HAVE_NATIVE_GET_PROXY_CLASS + * @see #getProxyClass(ClassLoader, Class[]) + * @see #getProxyData(ClassLoader, Class[]) + * @see #generateProxyClass(ProxyData) + */ + static Class getProxyClass(ClassLoader loader, Class[] interfaces) + { + return null; + } + + /** + * Optional native method to replace (and speed up) the pure Java + * implementation of getProxyData. Only needed if + * Configuration.HAVE_NATIVE_GET_PROXY_DATA is true. The native code + * may safely assume that a new ProxyData object must be created which + * does not duplicate any existing ones. + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @param interfaces the interfaces the class will extend + * @return all data that is required to make this proxy class + * @throws IllegalArgumentException if the constraints for getProxyClass + * were violated, except for problems with null + * @throws NullPointerException if `interfaces' is null or contains + * a null entry, or if handler is null + * @see Configuration.HAVE_NATIVE_GET_PROXY_DATA + * @see #getProxyClass(ClassLoader, Class[]) + * @see #getProxyClass(ClassLoader, Class[]) + * @see ProxyType#getProxyData() + */ + static Proxy.ProxyData getProxyData(ClassLoader loader, Class[] interfaces) + { + return null; + } + + /** + * Optional native method to replace (and speed up) the pure Java + * implementation of generateProxyClass. Only needed if + * Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS is true. The native + * code may safely assume that a new Class must be created, and that + * the ProxyData object does not describe any existing class. + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @param data the struct of information to convert to a Class. This + * has already been verified for all problems except exceeding + * VM limitations + * @return the newly generated class + * @throws IllegalArgumentException if VM limitations are exceeded + * @see #getProxyClass(ClassLoader, Class[]) + * @see #getProxyClass(ClassLoader, Class[]) + * @see ProxyData#generateProxyClass(ClassLoader) + */ + static native Class generateProxyClass(ClassLoader loader, Proxy.ProxyData data); +} diff --git a/libjava/java/lang/reflect/WildcardType.h b/libjava/java/lang/reflect/WildcardType.h new file mode 100644 index 000000000..2c5b93d65 --- /dev/null +++ b/libjava/java/lang/reflect/WildcardType.h @@ -0,0 +1,22 @@ + +// DO NOT EDIT THIS FILE - it is machine generated -*- c++ -*- + +#ifndef __java_lang_reflect_WildcardType__ +#define __java_lang_reflect_WildcardType__ + +#pragma interface + +#include <java/lang/Object.h> +#include <gcj/array.h> + + +class java::lang::reflect::WildcardType : public ::java::lang::Object +{ + +public: + virtual JArray< ::java::lang::reflect::Type * > * getLowerBounds() = 0; + virtual JArray< ::java::lang::reflect::Type * > * getUpperBounds() = 0; + static ::java::lang::Class class$; +} __attribute__ ((java_interface)); + +#endif // __java_lang_reflect_WildcardType__ diff --git a/libjava/java/lang/reflect/natArray.cc b/libjava/java/lang/reflect/natArray.cc new file mode 100644 index 000000000..b7bc8beff --- /dev/null +++ b/libjava/java/lang/reflect/natArray.cc @@ -0,0 +1,360 @@ +// natField.cc - Implementation of java.lang.reflect.Field native methods. + +/* Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> + +#include <stdlib.h> + +#include <jvm.h> +#include <gcj/cni.h> +#include <java-stack.h> +#include <java/lang/reflect/Array.h> +#include <java/lang/ArrayIndexOutOfBoundsException.h> +#include <java/lang/IllegalArgumentException.h> +#include <java/lang/Byte.h> +#include <java/lang/Short.h> +#include <java/lang/Integer.h> +#include <java/lang/Long.h> +#include <java/lang/Float.h> +#include <java/lang/Double.h> +#include <java/lang/Boolean.h> +#include <java/lang/Character.h> + +jobject +java::lang::reflect::Array::newInstance (jclass componentType, jint length) +{ + if (componentType->isPrimitive()) + { + // We could check for this in _Jv_NewPrimArray, but that seems + // like needless overhead when the only real route to this + // problem is here. + if (componentType == JvPrimClass (void)) + throw new java::lang::IllegalArgumentException (); + return _Jv_NewPrimArray (componentType, length); + } + else + // FIXME: class loader? + return JvNewObjectArray (length, componentType, NULL); +} + +jobject +java::lang::reflect::Array::newInstance (jclass componentType, + jintArray dimensions) +{ + jint ndims = dimensions->length; + if (ndims == 0) + throw new java::lang::IllegalArgumentException (); + jint* dims = elements (dimensions); + if (ndims == 1) + return newInstance (componentType, dims[0]); + + Class *caller = _Jv_StackTrace::GetCallingClass (&Array::class$); + ClassLoader *caller_loader = NULL; + if (caller) + caller_loader = caller->getClassLoaderInternal(); + + jclass arrayType = componentType; + for (int i = 0; i < ndims; i++) + arrayType = _Jv_GetArrayClass (arrayType, caller_loader); + + return _Jv_NewMultiArray (arrayType, ndims, dims); +} + +jint +java::lang::reflect::Array::getLength (jobject array) +{ + jclass arrayType = array->getClass(); + if (! arrayType->isArray ()) + throw new java::lang::IllegalArgumentException; + return ((__JArray*) array)->length; +} + +jclass +java::lang::reflect::Array::getElementType (jobject array, jint index) +{ + jclass arrayType = array->getClass(); + if (! arrayType->isArray ()) + throw new java::lang::IllegalArgumentException; + jint length = ((__JArray*) array)->length; + if ((_Jv_uint) index >= (_Jv_uint) length) + _Jv_ThrowBadArrayIndex(index); + return arrayType->getComponentType (); +} + +jboolean +java::lang::reflect::Array::getBoolean (jobject array, jint index) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (boolean)) + return elements ((jbooleanArray) array) [index]; + throw new java::lang::IllegalArgumentException; +} + +jchar +java::lang::reflect::Array::getChar (jobject array, jint index) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (char)) + return elements ((jcharArray) array) [index]; + throw new java::lang::IllegalArgumentException; +} + +jbyte +java::lang::reflect::Array::getByte (jobject array, jint index) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (byte)) + return elements ((jbyteArray) array) [index]; + throw new java::lang::IllegalArgumentException; +} + +jshort +java::lang::reflect::Array::getShort (jobject array, jint index) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (short)) + return elements ((jshortArray) array) [index]; + if (elementType == JvPrimClass (byte)) + return elements ((jbyteArray) array) [index]; + throw new java::lang::IllegalArgumentException; +} + +jint +java::lang::reflect::Array::getInt (jobject array, jint index) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (int)) + return elements ((jintArray) array) [index]; + if (elementType == JvPrimClass (short)) + return elements ((jshortArray) array) [index]; + if (elementType == JvPrimClass (byte)) + return elements ((jbyteArray) array) [index]; + if (elementType == JvPrimClass (char)) + return elements ((jcharArray) array) [index]; + throw new java::lang::IllegalArgumentException; +} + +jlong +java::lang::reflect::Array::getLong (jobject array, jint index) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (long)) + return elements ((jlongArray) array) [index]; + if (elementType == JvPrimClass (int)) + return elements ((jintArray) array) [index]; + if (elementType == JvPrimClass (short)) + return elements ((jshortArray) array) [index]; + if (elementType == JvPrimClass (byte)) + return elements ((jbyteArray) array) [index]; + if (elementType == JvPrimClass (char)) + return elements ((jcharArray) array) [index]; + throw new java::lang::IllegalArgumentException; +} + +jfloat +java::lang::reflect::Array::getFloat (jobject array, jint index) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (float)) + return elements ((jfloatArray) array) [index]; + if (elementType == JvPrimClass (long)) + return elements ((jlongArray) array) [index]; + if (elementType == JvPrimClass (int)) + return elements ((jintArray) array) [index]; + if (elementType == JvPrimClass (short)) + return elements ((jshortArray) array) [index]; + if (elementType == JvPrimClass (byte)) + return elements ((jbyteArray) array) [index]; + if (elementType == JvPrimClass (char)) + return elements ((jcharArray) array) [index]; + throw new java::lang::IllegalArgumentException; +} + +jdouble +java::lang::reflect::Array::getDouble (jobject array, jint index) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (double)) + return elements ((jdoubleArray) array) [index]; + if (elementType == JvPrimClass (float)) + return elements ((jfloatArray) array) [index]; + if (elementType == JvPrimClass (long)) + return elements ((jlongArray) array) [index]; + if (elementType == JvPrimClass (int)) + return elements ((jintArray) array) [index]; + if (elementType == JvPrimClass (short)) + return elements ((jshortArray) array) [index]; + if (elementType == JvPrimClass (byte)) + return elements ((jbyteArray) array) [index]; + if (elementType == JvPrimClass (char)) + return elements ((jcharArray) array) [index]; + throw new java::lang::IllegalArgumentException; +} + +jobject +java::lang::reflect::Array::get (jobject array, jint index) +{ + jclass elementType = getElementType (array, index); + if (! elementType->isPrimitive ()) + return elements ((jobjectArray) array) [index]; + if (elementType == JvPrimClass (double)) + return new java::lang::Double (elements ((jdoubleArray) array) [index]); + if (elementType == JvPrimClass (float)) + return new java::lang::Float (elements ((jfloatArray) array) [index]); + if (elementType == JvPrimClass (long)) + return new java::lang::Long (elements ((jlongArray) array) [index]); + if (elementType == JvPrimClass (int)) + return new java::lang::Integer (elements ((jintArray) array) [index]); + if (elementType == JvPrimClass (short)) + return new java::lang::Short (elements ((jshortArray) array) [index]); + if (elementType == JvPrimClass (byte)) + return new java::lang::Byte (elements ((jbyteArray) array) [index]); + if (elementType == JvPrimClass (char)) + return new java::lang::Character (elements ((jcharArray) array) [index]); + if (elementType == JvPrimClass (boolean)) + { + _Jv_InitClass (&java::lang::Boolean::class$); + if (elements ((jbooleanArray) array) [index]) + return java::lang::Boolean::TRUE; + else + return java::lang::Boolean::FALSE; + } + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Array::setChar (jobject array, jint index, jchar value) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (char)) + elements ((jcharArray) array) [index] = value; + else if (elementType == JvPrimClass (int)) + elements ((jintArray) array) [index] = value; + else if (elementType == JvPrimClass (long)) + elements ((jlongArray) array) [index] = value; + else if (elementType == JvPrimClass (float)) + elements ((jfloatArray) array) [index] = value; + else if (elementType == JvPrimClass (double)) + elements ((jdoubleArray) array) [index] = value; + else + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Array::setByte (jobject array, jint index, jbyte value) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (byte)) + elements ((jbyteArray) array) [index] = value; + else if (elementType == JvPrimClass (short)) + elements ((jshortArray) array) [index] = value; + else if (elementType == JvPrimClass (int)) + elements ((jintArray) array) [index] = value; + else if (elementType == JvPrimClass (long)) + elements ((jlongArray) array) [index] = value; + else if (elementType == JvPrimClass (float)) + elements ((jfloatArray) array) [index] = value; + else if (elementType == JvPrimClass (double)) + elements ((jdoubleArray) array) [index] = value; + else + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Array::setShort (jobject array, jint index, jshort value) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (short)) + elements ((jshortArray) array) [index] = value; + else if (elementType == JvPrimClass (int)) + elements ((jintArray) array) [index] = value; + else if (elementType == JvPrimClass (long)) + elements ((jlongArray) array) [index] = value; + else if (elementType == JvPrimClass (float)) + elements ((jfloatArray) array) [index] = value; + else if (elementType == JvPrimClass (double)) + elements ((jdoubleArray) array) [index] = value; + else + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Array::setInt (jobject array, jint index, jint value) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (int)) + elements ((jintArray) array) [index] = value; + else if (elementType == JvPrimClass (long)) + elements ((jlongArray) array) [index] = value; + else if (elementType == JvPrimClass (float)) + elements ((jfloatArray) array) [index] = value; + else if (elementType == JvPrimClass (double)) + elements ((jdoubleArray) array) [index] = value; + else + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Array::setLong (jobject array, jint index, jlong value) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (long)) + elements ((jlongArray) array) [index] = value; + else if (elementType == JvPrimClass (float)) + elements ((jfloatArray) array) [index] = value; + else if (elementType == JvPrimClass (double)) + elements ((jdoubleArray) array) [index] = value; + else + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Array::setFloat (jobject array, jint index, jfloat value) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (float)) + elements ((jfloatArray) array) [index] = value; + else if (elementType == JvPrimClass (double)) + elements ((jdoubleArray) array) [index] = value; + else + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Array::setDouble (jobject array, jint index, jdouble value) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (double)) + elements ((jdoubleArray) array) [index] = value; + else + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Array::setBoolean (jobject array, + jint index, jboolean value) +{ + jclass elementType = getElementType (array, index); + if (elementType == JvPrimClass (boolean)) + elements ((jbooleanArray) array) [index] = value; + else + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Array::set (jobject array, jint index, + jobject value, jclass elType) +{ + // We don't have to call getElementType here, or check INDEX, + // because it was already done in the Java wrapper. + if (value != NULL && ! _Jv_IsInstanceOf (value, elType)) + throw new java::lang::IllegalArgumentException; + elements ((jobjectArray) array) [index] = value; +} diff --git a/libjava/java/lang/reflect/natConstructor.cc b/libjava/java/lang/reflect/natConstructor.cc new file mode 100644 index 000000000..953d86dd4 --- /dev/null +++ b/libjava/java/lang/reflect/natConstructor.cc @@ -0,0 +1,93 @@ +// natConstructor.cc - Native code for Constructor class. + +/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2006 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> + +#include <gcj/cni.h> +#include <jvm.h> +#include <java-stack.h> + +#include <java/lang/ArrayIndexOutOfBoundsException.h> +#include <java/lang/IllegalAccessException.h> +#include <java/lang/reflect/Constructor.h> +#include <java/lang/reflect/Method.h> +#include <java/lang/reflect/InvocationTargetException.h> +#include <java/lang/reflect/Modifier.h> +#include <java/lang/InstantiationException.h> +#include <gcj/method.h> + +typedef JArray< ::java::lang::annotation::Annotation * > * anno_a_t; +typedef JArray< JArray< ::java::lang::annotation::Annotation * > *> * anno_aa_t; + +jint +java::lang::reflect::Constructor::getModifiersInternal () +{ + return _Jv_FromReflectedConstructor (this)->accflags; +} + +jstring +java::lang::reflect::Constructor::getSignature() +{ + return declaringClass->getReflectionSignature (this); +} + +anno_a_t +java::lang::reflect::Constructor::getDeclaredAnnotationsInternal() +{ + return (anno_a_t) declaringClass->getDeclaredAnnotations(this, false); +} + +anno_aa_t +java::lang::reflect::Constructor::getParameterAnnotationsInternal() +{ + return (anno_aa_t) declaringClass->getDeclaredAnnotations(this, true); +} + +void +java::lang::reflect::Constructor::getType () +{ + _Jv_GetTypesFromSignature (_Jv_FromReflectedConstructor (this), + declaringClass, + ¶meter_types, + NULL); + + // FIXME: for now we have no way to get exception information. + exception_types = + (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$, NULL); +} + +jobject +java::lang::reflect::Constructor::newInstance (jobjectArray args) +{ + using namespace java::lang::reflect; + + if (parameter_types == NULL) + getType (); + + jmethodID meth = _Jv_FromReflectedConstructor (this); + + // Check accessibility, if required. + if (! (Modifier::isPublic (meth->accflags) || this->isAccessible())) + { + Class *caller = _Jv_StackTrace::GetCallingClass (&Constructor::class$); + if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags)) + throw new IllegalAccessException; + } + + if (Modifier::isAbstract (declaringClass->getModifiers())) + throw new InstantiationException; + + _Jv_InitClass (declaringClass); + + // In the constructor case the return type is the type of the + // constructor. + return _Jv_CallAnyMethodA (NULL, declaringClass, meth, true, + parameter_types, args); +} diff --git a/libjava/java/lang/reflect/natField.cc b/libjava/java/lang/reflect/natField.cc new file mode 100644 index 000000000..734f65316 --- /dev/null +++ b/libjava/java/lang/reflect/natField.cc @@ -0,0 +1,449 @@ +// natField.cc - Implementation of java.lang.reflect.Field native methods. + +/* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> + +#include <stdlib.h> + +#include <jvm.h> +#include <java-stack.h> +#include <java/lang/reflect/Field.h> +#include <java/lang/reflect/Modifier.h> +#include <java/lang/ArrayIndexOutOfBoundsException.h> +#include <java/lang/IllegalArgumentException.h> +#include <java/lang/IllegalAccessException.h> +#include <java/lang/NullPointerException.h> +#include <java/lang/Byte.h> +#include <java/lang/Short.h> +#include <java/lang/Integer.h> +#include <java/lang/Long.h> +#include <java/lang/Float.h> +#include <java/lang/Double.h> +#include <java/lang/Boolean.h> +#include <java/lang/Character.h> + +typedef JArray< ::java::lang::annotation::Annotation * > * anno_a_t; + +jint +java::lang::reflect::Field::getModifiersInternal () +{ + return _Jv_FromReflectedField (this)->flags; +} + +jstring +java::lang::reflect::Field::getSignature() +{ + return declaringClass->getReflectionSignature (this); +} + +anno_a_t +java::lang::reflect::Field::getDeclaredAnnotationsInternal() +{ + return (anno_a_t) declaringClass->getDeclaredAnnotations(this); +} + +jstring +java::lang::reflect::Field::getName () +{ + if (name == NULL) + name = _Jv_NewStringUtf8Const (_Jv_FromReflectedField (this)->name); + return name; +} + +jclass +java::lang::reflect::Field::getType () +{ + if (type == NULL) + { + jfieldID fld = _Jv_FromReflectedField (this); + JvSynchronize sync (declaringClass); + _Jv_Linker::resolve_field (fld, declaringClass->getClassLoaderInternal ()); + type = fld->type; + } + return type; +} + +static void* +getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj, + jboolean checkFinal) +{ + using namespace java::lang::reflect; + + jfieldID fld = _Jv_FromReflectedField (field); + _Jv_ushort flags = fld->getModifiers(); + + // Setting a final field is usually not allowed. + if (checkFinal + // As of 1.5, you can set a non-static final field if it is + // accessible. + && (! field->isAccessible() + || (field->getModifiers() & java::lang::reflect::Modifier::STATIC)) + && (field->getModifiers() & java::lang::reflect::Modifier::FINAL)) + throw new java::lang::IllegalAccessException(JvNewStringUTF + ("Field is final")); + + // Check accessibility, if required. + if (! (Modifier::isPublic (flags) || field->isAccessible())) + { + if (! caller) + caller = _Jv_StackTrace::GetCallingClass (&Field::class$); + if (! _Jv_CheckAccess (caller, field->getDeclaringClass(), flags)) + throw new java::lang::IllegalAccessException; + } + + if (flags & Modifier::STATIC) + { + jclass fldClass = field->getDeclaringClass (); + JvInitClass(fldClass); + return fld->u.addr; + } + else + { + if (obj == NULL) + throw new java::lang::NullPointerException; + if (! _Jv_IsInstanceOf (obj, field->getDeclaringClass())) + throw new java::lang::IllegalArgumentException; + return (void*) ((char*) obj + fld->getOffset ()); + } +} + +static jboolean +getBoolean (jclass cls, void* addr) +{ + if (cls == JvPrimClass (boolean)) + return * (jboolean *) addr; + throw new java::lang::IllegalArgumentException; +} + +static jchar +getChar (jclass cls, void* addr) +{ + if (cls == JvPrimClass (char)) + return * (jchar *) addr; + throw new java::lang::IllegalArgumentException; +} + +static jbyte +getByte (jclass cls, void* addr) +{ + if (cls == JvPrimClass (byte)) + return * (jbyte *) addr; + throw new java::lang::IllegalArgumentException; +} + +static jshort +getShort (jclass cls, void* addr) +{ + if (cls == JvPrimClass (short)) + return * (jshort *) addr; + if (cls == JvPrimClass (byte)) + return * (jbyte *) addr; + throw new java::lang::IllegalArgumentException; +} + +static jint +getInt (jclass cls, void* addr) +{ + if (cls == JvPrimClass (int)) + return * (jint *) addr; + if (cls == JvPrimClass (short)) + return * (jshort *) addr; + if (cls == JvPrimClass (char)) + return * (jchar *) addr; + if (cls == JvPrimClass (byte)) + return * (jbyte *) addr; + throw new java::lang::IllegalArgumentException; +} + +static jlong +getLong (jclass cls, void* addr) +{ + if (cls == JvPrimClass (long)) + return * (jlong *) addr; + return ::getInt(cls, addr); +} + +static jfloat +getFloat (jclass cls, void* addr) +{ + if (cls == JvPrimClass (float)) + return * (jfloat *) addr; + if (cls == JvPrimClass (long)) + return * (jlong *) addr; + return ::getInt(cls, addr); +} + +static jdouble +getDouble (jclass cls, void* addr) +{ + if (cls == JvPrimClass (double)) + return * (jdouble *) addr; + if (cls == JvPrimClass (float)) + return * (jfloat *) addr; + if (cls == JvPrimClass (long)) + return * (jlong *) addr; + return ::getInt(cls, addr); +} + +jboolean +java::lang::reflect::Field::getBoolean (jclass caller, jobject obj) +{ + return ::getBoolean (this->getType(), getAddr (this, caller, obj, false)); +} + +jchar +java::lang::reflect::Field::getChar (jclass caller, jobject obj) +{ + return ::getChar (this->getType(), getAddr (this, caller, obj, false)); +} + +jbyte +java::lang::reflect::Field::getByte (jclass caller, jobject obj) +{ + return ::getByte (this->getType(), getAddr (this, caller, obj, false)); +} + +jshort +java::lang::reflect::Field::getShort (jclass caller, jobject obj) +{ + return ::getShort (this->getType(), getAddr (this, caller, obj, false)); +} + +jint +java::lang::reflect::Field::getInt (jclass caller, jobject obj) +{ + return ::getInt (this->getType(), getAddr (this, caller, obj, false)); +} + +jlong +java::lang::reflect::Field::getLong (jclass caller, jobject obj) +{ + return ::getLong (this->getType(), getAddr (this, caller, obj, false)); +} + +jfloat +java::lang::reflect::Field::getFloat (jclass caller, jobject obj) +{ + return ::getFloat (this->getType(), getAddr (this, caller, obj, false)); +} + +jdouble +java::lang::reflect::Field::getDouble (jclass caller, jobject obj) +{ + return ::getDouble (this->getType(), getAddr (this, caller, obj, false)); +} + +jobject +java::lang::reflect::Field::get (jclass caller, jobject obj) +{ + jclass type = this->getType(); + void* addr = getAddr (this, caller, obj, false); + if (! type->isPrimitive ()) + return * (jobject*) addr; + if (type == JvPrimClass (double)) + return new java::lang::Double (* (jdouble*) addr); + if (type == JvPrimClass (float)) + return new java::lang::Float (* (jfloat*) addr); + if (type == JvPrimClass (long)) + return new java::lang::Long (* (jlong*) addr); + if (type == JvPrimClass (int)) + return new java::lang::Integer (* (jint*) addr); + if (type == JvPrimClass (short)) + return new java::lang::Short (* (jshort*) addr); + if (type == JvPrimClass (byte)) + return new java::lang::Byte (* (jbyte*) addr); + if (type == JvPrimClass (char)) + return new java::lang::Character (* (jchar*) addr); + if (type == JvPrimClass (boolean)) + { + _Jv_InitClass (&java::lang::Boolean::class$); + if (* (jboolean*) addr) + return java::lang::Boolean::TRUE; + else + return java::lang::Boolean::FALSE; + } + throw new java::lang::IllegalArgumentException; +} + +static void +setBoolean (jclass type, void *addr, jboolean value) +{ + if (type == JvPrimClass (boolean)) + * (jboolean *) addr = value; + else + throw new java::lang::IllegalArgumentException; +} + +static void +setChar (jclass type, void *addr, jchar value) +{ + if (type == JvPrimClass (char)) + * (jchar *) addr = value; + else if (type == JvPrimClass (int)) + * (jint *) addr = value; + else if (type == JvPrimClass (long)) + * (jlong *) addr = value; + else if (type == JvPrimClass (float)) + * (jfloat *) addr = value; + else if (type == JvPrimClass (double)) + * (jdouble *) addr = value; + else + throw new java::lang::IllegalArgumentException; +} + +static void +setByte (jclass type, void *addr, jbyte value) +{ + if (type == JvPrimClass (byte)) + * (jbyte *) addr = value; + else if (type == JvPrimClass (short)) + * (jshort *) addr = value; + else if (type == JvPrimClass (int)) + * (jint *) addr = value; + else if (type == JvPrimClass (long)) + * (jlong *) addr = value; + else if (type == JvPrimClass (float)) + * (jfloat *) addr = value; + else if (type == JvPrimClass (double)) + * (jdouble *) addr = value; + else + throw new java::lang::IllegalArgumentException; +} + +static void +setShort (jclass type, void *addr, jshort value) +{ + if (type == JvPrimClass (short)) + * (jshort *) addr = value; + else if (type == JvPrimClass (int)) + * (jint *) addr = value; + else if (type == JvPrimClass (long)) + * (jlong *) addr = value; + else if (type == JvPrimClass (float)) + * (jfloat *) addr = value; + else if (type == JvPrimClass (double)) + * (jdouble *) addr = value; + else + throw new java::lang::IllegalArgumentException; +} + +static void +setInt (jclass type, void *addr, jint value) +{ + if (type == JvPrimClass (int)) + * (jint *) addr = value; + else if (type == JvPrimClass (long)) + * (jlong *) addr = value; + else if (type == JvPrimClass (float)) + * (jfloat *) addr = value; + else if (type == JvPrimClass (double)) + * (jdouble *) addr = value; + else + throw new java::lang::IllegalArgumentException; +} + +static void +setLong (jclass type, void *addr, jlong value) +{ + if (type == JvPrimClass (long)) + * (jlong *) addr = value; + else if (type == JvPrimClass (float)) + * (jfloat *) addr = value; + else if (type == JvPrimClass (double)) + * (jdouble *) addr = value; + else + throw new java::lang::IllegalArgumentException; +} + +static void +setFloat (jclass type, void *addr, jfloat value) +{ + if (type == JvPrimClass (float)) + * (jfloat *) addr = value; + else if (type == JvPrimClass (double)) + * (jdouble *) addr = value; + else + throw new java::lang::IllegalArgumentException; +} + +static void +setDouble (jclass type, void *addr, jdouble value) +{ + if (type == JvPrimClass (double)) + * (jdouble *) addr = value; + else + throw new java::lang::IllegalArgumentException; +} + +void +java::lang::reflect::Field::setBoolean (jclass caller, jobject obj, jboolean b, + jboolean checkFinal) +{ + ::setBoolean (this->getType(), getAddr (this, caller, obj, checkFinal), b); +} + +void +java::lang::reflect::Field::setChar (jclass caller, jobject obj, jchar c, + jboolean checkFinal) +{ + ::setChar (this->getType(), getAddr (this, caller, obj, checkFinal), c); +} + +void +java::lang::reflect::Field::setByte (jclass caller, jobject obj, jbyte b, + jboolean checkFinal) +{ + ::setByte (this->getType(), getAddr (this, caller, obj, checkFinal), b); +} + +void +java::lang::reflect::Field::setShort (jclass caller, jobject obj, jshort s, + jboolean checkFinal) +{ + ::setShort (this->getType(), getAddr (this, caller, obj, checkFinal), s); +} + +void +java::lang::reflect::Field::setInt (jclass caller, jobject obj, jint i, + jboolean checkFinal) +{ + ::setInt (this->getType(), getAddr (this, caller, obj, checkFinal), i); +} + +void +java::lang::reflect::Field::setLong (jclass caller, jobject obj, jlong l, + jboolean checkFinal) +{ + ::setLong (this->getType(), getAddr (this, caller, obj, checkFinal), l); +} + +void +java::lang::reflect::Field::setFloat (jclass caller, jobject obj, jfloat f, + jboolean checkFinal) +{ + ::setFloat (this->getType(), getAddr (this, caller, obj, checkFinal), f); +} + +void +java::lang::reflect::Field::setDouble (jclass caller, jobject obj, jdouble d, + jboolean checkFinal) +{ + ::setDouble (this->getType(), getAddr (this, caller, obj, checkFinal), d); +} + +void +java::lang::reflect::Field::set (jclass caller, jobject object, jobject value, + jclass type, jboolean checkFinal) +{ + void* addr = getAddr (this, caller, object, checkFinal); + if (value != NULL && ! _Jv_IsInstanceOf (value, type)) + throw new java::lang::IllegalArgumentException; + * (jobject*) addr = value; +} diff --git a/libjava/java/lang/reflect/natMethod.cc b/libjava/java/lang/reflect/natMethod.cc new file mode 100644 index 000000000..d95c92f84 --- /dev/null +++ b/libjava/java/lang/reflect/natMethod.cc @@ -0,0 +1,701 @@ +// natMethod.cc - Native code for Method class. + +/* Copyright (C) 1998, 1999, 2000, 2001 , 2002, 2003, 2004, 2005, 2006 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> + +#include <gcj/cni.h> +#include <jvm.h> +#include <jni.h> +#include <java-stack.h> + +#include <java/lang/reflect/Method.h> +#include <java/lang/reflect/Constructor.h> +#include <java/lang/reflect/InvocationTargetException.h> +#include <java/lang/reflect/Modifier.h> + +#include <java/lang/Void.h> +#include <java/lang/Byte.h> +#include <java/lang/Boolean.h> +#include <java/lang/Character.h> +#include <java/lang/Short.h> +#include <java/lang/Integer.h> +#include <java/lang/Long.h> +#include <java/lang/Float.h> +#include <java/lang/Double.h> +#include <java/lang/IllegalAccessException.h> +#include <java/lang/IllegalArgumentException.h> +#include <java/lang/IncompatibleClassChangeError.h> +#include <java/lang/NullPointerException.h> +#include <java/lang/ArrayIndexOutOfBoundsException.h> +#include <java/lang/VirtualMachineError.h> +#include <java/lang/Class.h> +#include <gcj/method.h> +#include <gnu/gcj/RawData.h> +#include <java/lang/NoClassDefFoundError.h> + +#include <stdlib.h> + +#if USE_LIBFFI +#include <ffi.h> +#else +#include <java/lang/UnsupportedOperationException.h> +#endif + +typedef JArray< ::java::lang::annotation::Annotation * > * anno_a_t; +typedef JArray< JArray< ::java::lang::annotation::Annotation * > *> * anno_aa_t; + + + +struct cpair +{ + jclass prim; + jclass wrap; +}; + +// This is used to determine when a primitive widening conversion is +// allowed. +static cpair primitives[] = +{ +#define BOOLEAN 0 + { JvPrimClass (boolean), &java::lang::Boolean::class$ }, + { JvPrimClass (byte), &java::lang::Byte::class$ }, +#define SHORT 2 + { JvPrimClass (short), &java::lang::Short::class$ }, +#define CHAR 3 + { JvPrimClass (char), &java::lang::Character::class$ }, + { JvPrimClass (int), &java::lang::Integer::class$ }, + { JvPrimClass (long), &java::lang::Long::class$ }, + { JvPrimClass (float), &java::lang::Float::class$ }, + { JvPrimClass (double), &java::lang::Double::class$ }, + { NULL, NULL } +}; + +static inline jboolean +can_widen (jclass from, jclass to) +{ + int fromx = -1, tox = -1; + + for (int i = 0; primitives[i].prim; ++i) + { + if (primitives[i].wrap == from) + fromx = i; + if (primitives[i].prim == to) + tox = i; + } + + // Can't handle a miss. + if (fromx == -1 || tox == -1) + return false; + // Boolean arguments may not be widened. + if (fromx == BOOLEAN && tox != BOOLEAN) + return false; + // Nothing promotes to char. + if (tox == CHAR && fromx != CHAR) + return false; + + return fromx <= tox; +} + +#ifdef USE_LIBFFI +static inline ffi_type * +get_ffi_type (jclass klass) +{ + // A special case. + if (klass == NULL) + return &ffi_type_pointer; + + ffi_type *r; + if (klass == JvPrimClass (byte)) + r = &ffi_type_sint8; + else if (klass == JvPrimClass (short)) + r = &ffi_type_sint16; + else if (klass == JvPrimClass (int)) + r = &ffi_type_sint32; + else if (klass == JvPrimClass (long)) + r = &ffi_type_sint64; + else if (klass == JvPrimClass (float)) + r = &ffi_type_float; + else if (klass == JvPrimClass (double)) + r = &ffi_type_double; + else if (klass == JvPrimClass (boolean)) + { + // On some platforms a bool is a byte, on others an int. + if (sizeof (jboolean) == sizeof (jbyte)) + r = &ffi_type_sint8; + else + { + JvAssert (sizeof (jboolean) == sizeof (jint)); + r = &ffi_type_sint32; + } + } + else if (klass == JvPrimClass (char)) + r = &ffi_type_uint16; + else + { + JvAssert (! klass->isPrimitive()); + r = &ffi_type_pointer; + } + + return r; +} +#endif // USE_LIBFFI + +jobject +java::lang::reflect::Method::invoke (jobject obj, jobjectArray args) +{ + using namespace java::lang::reflect; + jclass iface = NULL; + + if (parameter_types == NULL) + getType (); + + jmethodID meth = _Jv_FromReflectedMethod (this); + + if (Modifier::isStatic(meth->accflags)) + { + // We have to initialize a static class. It is safe to do this + // here and not in _Jv_CallAnyMethodA because JNI initializes a + // class whenever a method lookup is done. + _Jv_InitClass (declaringClass); + } + else + { + jclass objClass = JV_CLASS (obj); + if (! _Jv_IsAssignableFrom (objClass, declaringClass)) + throw new java::lang::IllegalArgumentException; + } + + // Check accessibility, if required. + if (! this->isAccessible()) + { + if (! (Modifier::isPublic (meth->accflags))) + { + Class *caller = _Jv_StackTrace::GetCallingClass (&Method::class$); + if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags)) + throw new IllegalAccessException; + } + else + // Method is public, check to see if class is accessible. + { + jint flags = (declaringClass->accflags + & (Modifier::PUBLIC + | Modifier::PROTECTED + | Modifier::PRIVATE)); + if (flags == 0) // i.e. class is package private + { + Class *caller = _Jv_StackTrace::GetCallingClass (&Method::class$); + if (! _Jv_ClassNameSamePackage (caller->name, + declaringClass->name)) + throw new IllegalAccessException; + } + } + } + + if (declaringClass->isInterface()) + iface = declaringClass; + + return _Jv_CallAnyMethodA (obj, return_type, meth, false, + parameter_types, args, iface); +} + +jint +java::lang::reflect::Method::getModifiersInternal () +{ + return _Jv_FromReflectedMethod (this)->accflags; +} + +jstring +java::lang::reflect::Method::getSignature() +{ + return declaringClass->getReflectionSignature (this); +} + +jobject +java::lang::reflect::Method::getDefaultValue() +{ + return declaringClass->getMethodDefaultValue(this); +} + +anno_a_t +java::lang::reflect::Method::getDeclaredAnnotationsInternal() +{ + return (anno_a_t) declaringClass->getDeclaredAnnotations(this, false); +} + +anno_aa_t +java::lang::reflect::Method::getParameterAnnotationsInternal() +{ + return (anno_aa_t) declaringClass->getDeclaredAnnotations(this, true); +} + +jstring +java::lang::reflect::Method::getName () +{ + if (name == NULL) + name = _Jv_NewStringUtf8Const (_Jv_FromReflectedMethod (this)->name); + return name; +} + +/* Internal method to set return_type and parameter_types fields. */ + +void +java::lang::reflect::Method::getType () +{ + _Jv_Method *method = _Jv_FromReflectedMethod (this); + _Jv_GetTypesFromSignature (method, + declaringClass, + ¶meter_types, + &return_type); + + int count = 0; + if (method->throws != NULL) + { + while (method->throws[count] != NULL) + ++count; + } + + exception_types + = (JArray<jclass> *) JvNewObjectArray (count, &java::lang::Class::class$, + NULL); + jclass *elts = elements (exception_types); + for (int i = 0; i < count; ++i) + elts[i] = _Jv_FindClass (method->throws[i], + declaringClass->getClassLoaderInternal ()); +} + +void +_Jv_GetTypesFromSignature (jmethodID method, + jclass declaringClass, + JArray<jclass> **arg_types_out, + jclass *return_type_out) +{ + + _Jv_Utf8Const* sig = method->signature; + java::lang::ClassLoader *loader = declaringClass->getClassLoaderInternal(); + char *ptr = sig->chars(); + int numArgs = 0; + /* First just count the number of parameters. */ + // FIXME: should do some validation here, e.g., that there is only + // one return type. + for (; ; ptr++) + { + switch (*ptr) + { + case 0: + case ')': + case 'V': + break; + case '[': + case '(': + continue; + case 'B': + case 'C': + case 'D': + case 'F': + case 'S': + case 'I': + case 'J': + case 'Z': + numArgs++; + continue; + case 'L': + numArgs++; + do + ptr++; + while (*ptr != ';' && ptr[1] != '\0'); + continue; + } + break; + } + + JArray<jclass> *args = (JArray<jclass> *) + JvNewObjectArray (numArgs, &java::lang::Class::class$, NULL); + jclass* argPtr = elements (args); + for (ptr = sig->chars(); *ptr != '\0'; ptr++) + { + if (*ptr == '(') + continue; + if (*ptr == ')') + { + argPtr = return_type_out; + continue; + } + + char *end_ptr; + jclass type = _Jv_FindClassFromSignature (ptr, loader, &end_ptr); + if (type == NULL) + // FIXME: This isn't ideal. + throw new java::lang::NoClassDefFoundError (sig->toString()); + + // ARGPTR can be NULL if we are processing the return value of a + // call from Constructor. + if (argPtr) + *argPtr++ = type; + + ptr = end_ptr; + } + *arg_types_out = args; +} + +// This is a very rough analog of the JNI CallNonvirtual<type>MethodA +// functions. It handles both Methods and Constructors, and it can +// handle any return type. In the Constructor case, the `obj' +// argument is unused and should be NULL; also, the `return_type' is +// the class that the constructor will construct. RESULT is a pointer +// to a `jvalue' (see jni.h); for a void method this should be NULL. +// This function returns an exception (if one was thrown), or NULL if +// the call went ok. +void +_Jv_CallAnyMethodA (jobject obj, + jclass return_type, + jmethodID meth, + jboolean is_constructor, + jboolean is_virtual_call, + JArray<jclass> *parameter_types, + const jvalue *args, + jvalue *result, + jboolean is_jni_call, + jclass iface) +{ + using namespace java::lang::reflect; + +#ifdef USE_LIBFFI + JvAssert (! is_constructor || ! obj); + JvAssert (! is_constructor || return_type); + + // See whether call needs an object as the first argument. A + // constructor does need a `this' argument, but it is one we create. + jboolean needs_this = false; + if (is_constructor + || ! Modifier::isStatic(meth->accflags)) + needs_this = true; + + int param_count = parameter_types->length; + if (needs_this) + ++param_count; + + ffi_type *rtype; + // A constructor itself always returns void. + if (is_constructor || return_type == JvPrimClass (void)) + rtype = &ffi_type_void; + else + rtype = get_ffi_type (return_type); + ffi_type **argtypes = (ffi_type **) __builtin_alloca (param_count + * sizeof (ffi_type *)); + + jclass *paramelts = elements (parameter_types); + + // Special case for the `this' argument of a constructor. Note that + // the JDK 1.2 docs specify that the new object must be allocated + // before argument conversions are done. + if (is_constructor) + obj = _Jv_AllocObject (return_type); + + const int size_per_arg = sizeof(jvalue); + ffi_cif cif; + + char *p = (char *) __builtin_alloca (param_count * size_per_arg); + // Overallocate to get correct alignment. + void **values = (void **) + __builtin_alloca (param_count * sizeof (void *)); + + int i = 0; + if (needs_this) + { + // The `NULL' type is `Object'. + argtypes[i] = get_ffi_type (NULL); + values[i] = p; + memcpy (p, &obj, sizeof (jobject)); + p += size_per_arg; + ++i; + } + + for (int arg = 0; i < param_count; ++i, ++arg) + { + int tsize; + + argtypes[i] = get_ffi_type (paramelts[arg]); + if (paramelts[arg]->isPrimitive()) + tsize = paramelts[arg]->size(); + else + tsize = sizeof (jobject); + + // Copy appropriate bits from the jvalue into the ffi array. + // FIXME: we could do this copying all in one loop, above, by + // over-allocating a bit. + // How do we do this without breaking big-endian platforms? + values[i] = p; + memcpy (p, &args[arg], tsize); + p += size_per_arg; + } + + if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, param_count, + rtype, argtypes) != FFI_OK) + throw new java::lang::VirtualMachineError(JvNewStringLatin1("internal error: ffi_prep_cif failed")); + + using namespace java::lang; + using namespace java::lang::reflect; + + union + { + ffi_arg i; + jobject o; + jlong l; + jfloat f; + jdouble d; + } ffi_result; + + switch (rtype->type) + { + case FFI_TYPE_VOID: + break; + case FFI_TYPE_SINT8: + result->b = 0; + break; + case FFI_TYPE_SINT16: + result->s = 0; + break; + case FFI_TYPE_UINT16: + result->c = 0; + break; + case FFI_TYPE_SINT32: + result->i = 0; + break; + case FFI_TYPE_SINT64: + result->j = 0; + break; + case FFI_TYPE_FLOAT: + result->f = 0; + break; + case FFI_TYPE_DOUBLE: + result->d = 0; + break; + case FFI_TYPE_POINTER: + result->l = 0; + break; + default: + JvFail ("Unknown ffi_call return type"); + break; + } + + void *ncode; + + // FIXME: If a vtable index is -1 at this point it is invalid, so we + // have to use the ncode. + // + // This can happen because methods in final classes don't have + // vtable entries, but _Jv_isVirtualMethod() doesn't know that. We + // could solve this problem by allocating a vtable index for methods + // in final classes. + if (is_virtual_call + && ! Modifier::isFinal (meth->accflags) + && (_Jv_ushort)-1 != meth->index) + { + _Jv_VTable *vtable = *(_Jv_VTable **) obj; + if (iface == NULL) + { + if (is_jni_call && Modifier::isAbstract (meth->accflags)) + { + // With JNI we don't know if this is an interface call + // or a call to an abstract method. Look up the method + // by name, the slow way. + _Jv_Method *concrete_meth + = _Jv_LookupDeclaredMethod (vtable->clas, + meth->name, + meth->signature, + NULL); + if (concrete_meth == NULL + || concrete_meth->ncode == NULL + || Modifier::isAbstract(concrete_meth->accflags)) + throw new java::lang::IncompatibleClassChangeError + (_Jv_GetMethodString (vtable->clas, meth)); + ncode = concrete_meth->ncode; + } + else + ncode = vtable->get_method (meth->index); + } + else + ncode = _Jv_LookupInterfaceMethodIdx (vtable->clas, iface, + meth->index); + } + else + { + ncode = meth->ncode; + } + + try + { + ffi_call (&cif, (void (*)()) ncode, &ffi_result, values); + } + catch (Throwable *ex) + { + // For JNI we just throw the real error. For reflection, we + // wrap the underlying method's exception in an + // InvocationTargetException. + if (! is_jni_call) + ex = new InvocationTargetException (ex); + throw ex; + } + + // Since ffi_call returns integer values promoted to a word, use + // a narrowing conversion for jbyte, jchar, etc. results. + // Note that boolean is handled either by the FFI_TYPE_SINT8 or + // FFI_TYPE_SINT32 case. + if (is_constructor) + result->l = obj; + else + { + switch (rtype->type) + { + case FFI_TYPE_VOID: + break; + case FFI_TYPE_SINT8: + result->b = (jbyte)ffi_result.i; + break; + case FFI_TYPE_SINT16: + result->s = (jshort)ffi_result.i; + break; + case FFI_TYPE_UINT16: + result->c = (jchar)ffi_result.i; + break; + case FFI_TYPE_SINT32: + result->i = (jint)ffi_result.i; + break; + case FFI_TYPE_SINT64: + result->j = (jlong)ffi_result.l; + break; + case FFI_TYPE_FLOAT: + result->f = (jfloat)ffi_result.f; + break; + case FFI_TYPE_DOUBLE: + result->d = (jdouble)ffi_result.d; + break; + case FFI_TYPE_POINTER: + result->l = (jobject)ffi_result.o; + break; + default: + JvFail ("Unknown ffi_call return type"); + break; + } + } +#else + throw new java::lang::UnsupportedOperationException(JvNewStringLatin1("reflection not available in this build")); +#endif // USE_LIBFFI +} + +// This is another version of _Jv_CallAnyMethodA, but this one does +// more checking and is used by the reflection (and not JNI) code. +jobject +_Jv_CallAnyMethodA (jobject obj, + jclass return_type, + jmethodID meth, + jboolean is_constructor, + JArray<jclass> *parameter_types, + jobjectArray args, + jclass iface) +{ + if (parameter_types->length == 0 && args == NULL) + { + // The JDK accepts this, so we do too. + } + else if (parameter_types->length != args->length) + throw new java::lang::IllegalArgumentException; + + int param_count = parameter_types->length; + + jclass *paramelts = elements (parameter_types); + jobject *argelts = args == NULL ? NULL : elements (args); + jvalue argvals[param_count]; + +#define COPY(Where, What, Type) \ + do { \ + Type val = (What); \ + memcpy ((Where), &val, sizeof (Type)); \ + } while (0) + + for (int i = 0; i < param_count; ++i) + { + jclass k = argelts[i] ? argelts[i]->getClass() : NULL; + if (paramelts[i]->isPrimitive()) + { + if (! argelts[i] + || ! k + || ! can_widen (k, paramelts[i])) + throw new java::lang::IllegalArgumentException; + + if (paramelts[i] == JvPrimClass (boolean)) + COPY (&argvals[i], + ((java::lang::Boolean *) argelts[i])->booleanValue(), + jboolean); + else if (paramelts[i] == JvPrimClass (char)) + COPY (&argvals[i], + ((java::lang::Character *) argelts[i])->charValue(), + jchar); + else + { + java::lang::Number *num = (java::lang::Number *) argelts[i]; + if (paramelts[i] == JvPrimClass (byte)) + COPY (&argvals[i], num->byteValue(), jbyte); + else if (paramelts[i] == JvPrimClass (short)) + COPY (&argvals[i], num->shortValue(), jshort); + else if (paramelts[i] == JvPrimClass (int)) + COPY (&argvals[i], num->intValue(), jint); + else if (paramelts[i] == JvPrimClass (long)) + COPY (&argvals[i], num->longValue(), jlong); + else if (paramelts[i] == JvPrimClass (float)) + COPY (&argvals[i], num->floatValue(), jfloat); + else if (paramelts[i] == JvPrimClass (double)) + COPY (&argvals[i], num->doubleValue(), jdouble); + } + } + else + { + if (argelts[i] && ! paramelts[i]->isAssignableFrom (k)) + throw new java::lang::IllegalArgumentException; + COPY (&argvals[i], argelts[i], jobject); + } + } + + jvalue ret_value; + _Jv_CallAnyMethodA (obj, return_type, meth, is_constructor, + _Jv_isVirtualMethod (meth), + parameter_types, argvals, &ret_value, + false, iface); + + jobject r; +#define VAL(Wrapper, Field) (new Wrapper (ret_value.Field)) + if (is_constructor) + r = ret_value.l; + else if (return_type == JvPrimClass (byte)) + r = VAL (java::lang::Byte, b); + else if (return_type == JvPrimClass (short)) + r = VAL (java::lang::Short, s); + else if (return_type == JvPrimClass (int)) + r = VAL (java::lang::Integer, i); + else if (return_type == JvPrimClass (long)) + r = VAL (java::lang::Long, j); + else if (return_type == JvPrimClass (float)) + r = VAL (java::lang::Float, f); + else if (return_type == JvPrimClass (double)) + r = VAL (java::lang::Double, d); + else if (return_type == JvPrimClass (boolean)) + r = VAL (java::lang::Boolean, z); + else if (return_type == JvPrimClass (char)) + r = VAL (java::lang::Character, c); + else if (return_type == JvPrimClass (void)) + r = NULL; + else + { + JvAssert (return_type == NULL || ! return_type->isPrimitive()); + r = ret_value.l; + } + + return r; +} diff --git a/libjava/java/lang/reflect/natVMProxy.cc b/libjava/java/lang/reflect/natVMProxy.cc new file mode 100644 index 000000000..4c3fd74f9 --- /dev/null +++ b/libjava/java/lang/reflect/natVMProxy.cc @@ -0,0 +1,459 @@ +// natVMProxy.cc -- Implementation of VMProxy methods. + +/* Copyright (C) 2006, 2007 + Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +// The idea of behind this code is to utilize libffi's ability to +// create closures to provide a fast "cut-through" way to generate +// proxy classes. Instead of generating bytecode and then +// interpreting that, we copy the method definitions for each of the +// methods we're supposed to be prxying and generate a libffi closure +// for each one. + +#include <config.h> +#include <platform.h> +#include <sysdep/descriptor.h> + +#include <limits.h> +#include <string.h> +#include <stddef.h> +#include <stdio.h> + +#include <gcj/cni.h> +#include <gcj/javaprims.h> +#include <jvm.h> +#include <jni.h> +#include <java-threads.h> +#include <java-interp.h> +#include <ffi.h> +#include <execution.h> +#include <gcj/method.h> + +#include <gnu/gcj/runtime/BootClassLoader.h> +#include <java/lang/Class.h> +#include <java/lang/ClassCastException.h> +#include <java/lang/Error.h> +#include <java/lang/IllegalArgumentException.h> +#include <java/lang/Integer.h> +#include <java/lang/StringBuffer.h> +#include <java/lang/UnsupportedOperationException.h> +#include <java/lang/VMClassLoader.h> +#include <java/lang/VMCompiler.h> +#include <java/lang/reflect/InvocationHandler.h> +#include <java/lang/reflect/Method.h> +#include <java/lang/reflect/Proxy$ClassFactory.h> +#include <java/lang/reflect/Proxy$ProxyData.h> +#include <java/lang/reflect/Proxy.h> +#include <java/lang/reflect/UndeclaredThrowableException.h> +#include <java/lang/reflect/VMProxy.h> + +#include <java/lang/Byte.h> +#include <java/lang/Short.h> +#include <java/lang/Integer.h> +#include <java/lang/Long.h> +#include <java/lang/Float.h> +#include <java/lang/Double.h> +#include <java/lang/Boolean.h> +#include <java/lang/Character.h> + + +using namespace java::lang::reflect; +using namespace java::lang; + +#ifndef INTERPRETER +jclass +java::lang::reflect::VMProxy::generateProxyClass + (ClassLoader *, Proxy$ProxyData *) +{ + throw new UnsupportedOperationException ( + JvNewStringLatin1 ("Interpreter not available")); +} +#else +typedef void (*closure_fun) (ffi_cif*, void*, void**, void*); +static void *ncode (int method_index, jclass klass, _Jv_Method *self, closure_fun fun); +static void run_proxy (ffi_cif*, void*, void**, void*); + +typedef jobject invoke_t (jobject, Proxy *, Method *, JArray< jobject > *); + +// True if pc points to a proxy frame. + +bool +_Jv_is_proxy (void *pc) +{ + return pc == UNWRAP_FUNCTION_DESCRIPTOR ((void*)&run_proxy); +} + +// Generate a proxy class by using libffi closures for each entry +// point. + +jclass +java::lang::reflect::VMProxy::generateProxyClass + (ClassLoader *loader, Proxy$ProxyData *d) +{ + // If we're precompiling, generate bytecode and allow VMCompiler to + // precompile it. + if (VMCompiler::precompiles ()) + return (new Proxy$ClassFactory(d))->generate(loader); + + jclass klass = new Class (); + + // Synchronize on the class, so that it is not attempted initialized + // until we're done. + JvSynchronize sync (klass); + + klass->superclass = &Proxy::class$; + klass->engine = &_Jv_soleIndirectCompiledEngine; + klass->size_in_bytes = -1; + klass->vtable_method_count = -1; + + // Declare private static transient java.lang.reflect.Method[] $Proxy0.m + klass->field_count = klass->static_field_count = 1; + klass->fields = (_Jv_Field*)_Jv_AllocRawObj (sizeof (_Jv_Field)); + klass->fields[0].name = _Jv_makeUtf8Const ("m"); + klass->fields[0].type = d->methods->getClass(); + klass->fields[0].flags = (Modifier::PRIVATE | Modifier::STATIC + | Modifier::TRANSIENT); + + // Record the defining loader. For the bootstrap class loader, + // we record NULL. + if (loader != VMClassLoader::bootLoader) + klass->loader = loader; + + { + StringBuffer *sb = new StringBuffer(); + sb->append(JvNewStringLatin1 ("$Proxy")); + sb->append(Integer::toString (d->id)); + klass->name = _Jv_makeUtf8Const (sb->toString()); + } + + // Allocate space for the interfaces. + klass->interface_count = d->interfaces->length; + klass->interfaces = (jclass*) _Jv_AllocRawObj (klass->interface_count + *sizeof (jclass)); + for (int i = 0; i < klass->interface_count; i++) + klass->interfaces[i] = elements(d->interfaces)[i]; + + size_t count = d->methods->length; + + { + size_t total_count = count + Proxy::class$.method_count + 1; + if (total_count >= 65536) + throw new IllegalArgumentException (); + // Allocate space for the methods. This is a worst case + // estimate. + klass->methods + = (_Jv_Method *) _Jv_AllocRawObj (sizeof (_Jv_Method) + * total_count); + } + + jshort &method_count = klass->method_count; + + // Copy all reachable methods from Proxy. + for (int i = 0; i < Proxy::class$.method_count; i++) + { + if (_Jv_CheckAccess (klass, &Proxy::class$, + Proxy::class$.methods[i].accflags)) + { + klass->methods[method_count] = Proxy::class$.methods[i]; + method_count++; + } + } + + _Jv_Method *init_method + = (_Jv_Linker::search_method_in_class + (klass, klass, + _Jv_makeUtf8Const ("<init>"), + _Jv_makeUtf8Const ("(Ljava.lang.reflect.InvocationHandler;)V"), + false)); + init_method->accflags |= Modifier::PUBLIC; + + // Create the methods for all of the interfaces. + for (size_t i = 0; i < count; i++) + { + _Jv_Method &method = klass->methods[method_count++]; + const _Jv_Method &imethod + = *_Jv_FromReflectedMethod (elements(d->methods)[i]); + // We use a shallow copy of IMETHOD rather than a deep copy; + // this means that the pointer fields of METHOD point into the + // interface. As long as this subclass of Proxy is reachable, + // the interfaces of which it is a proxy will also be reachable, + // so this is safe. + method = imethod; + method.ncode = ncode (i, klass, &method, run_proxy); + method.accflags &= ~Modifier::ABSTRACT; + } + + _Jv_Linker::layout_vtable_methods (klass); + _Jv_RegisterInitiatingLoader (klass, klass->loader); + + // Set $Proxy0.m to point to the methods arrray + java::lang::reflect::Field *f + = klass->getDeclaredField (JvNewStringLatin1 ("m")); + f->flag = true; + f->set(NULL, d->methods); + + return klass; +} + + +// Box things with primitive types. +static inline jobject +box (void *thing, jclass klass, FFI_TYPE type) +{ + jobject o; + + switch (type) + { + case FFI_TYPE_VOID: + return NULL; + + case FFI_TYPE_POINTER: + o = *(jobject*)thing; + return o; + + default: + ; + } + + if (klass == JvPrimClass (byte)) + o = new Byte (*(jbyte*)thing); + else if (klass == JvPrimClass (short)) + o = new Short (*(jshort*)thing); + else if (klass == JvPrimClass (int)) + o = new Integer (*(jint*)thing); + else if (klass == JvPrimClass (long)) + o = new Long (*(jlong*)thing); + else if (klass == JvPrimClass (float)) + o = new Float (*(jfloat*)thing); + else if (klass == JvPrimClass (double)) + o = new Double (*(jdouble*)thing); + else if (klass == JvPrimClass (boolean)) + o = new Boolean (*(jboolean*)thing); + else if (klass == JvPrimClass (char)) + o = new Character (*(jchar*)thing); + else + JvFail ("Bad ffi type in proxy"); + + return o; +} + + +// Unbox things with primitive types. +static inline void +unbox (jobject o, jclass klass, void *rvalue, FFI_TYPE type) +{ + switch (type) + { + case FFI_TYPE_VOID: + return; + + case FFI_TYPE_POINTER: + _Jv_CheckCast (klass, o); + *(jobject*)rvalue = o; + return; + + default: + ; + } + + // If the value returned ... is null and the interface method's + // return type is primitive, then a NullPointerException will be + // thrown ... + if (klass == JvPrimClass (byte)) + { + _Jv_CheckCast (&Byte::class$, o); + *(jbyte*)rvalue = ((Byte*)o)->byteValue(); + } + else if (klass == JvPrimClass (short)) + { + _Jv_CheckCast (&Short::class$, o); + *(jshort*)rvalue = ((Short*)o)->shortValue(); + } + else if (klass == JvPrimClass (int)) + { + _Jv_CheckCast (&Integer::class$, o); + *(jint*)rvalue = ((Integer*)o)->intValue(); + } + else if (klass == JvPrimClass (long)) + { + _Jv_CheckCast (&Long::class$, o); + *(jlong*)rvalue = ((Long*)o)->longValue(); + } + else if (klass == JvPrimClass (float)) + { + _Jv_CheckCast (&Float::class$, o); + *(jfloat*)rvalue = ((Float*)o)->floatValue(); + } + else if (klass == JvPrimClass (double)) + { + _Jv_CheckCast (&Double::class$, o); + *(jdouble*)rvalue = ((Double*)o)->doubleValue(); + } + else if (klass == JvPrimClass (boolean)) + { + _Jv_CheckCast (&Boolean::class$, o); + *(jboolean*)rvalue = ((Boolean*)o)->booleanValue(); + } + else if (klass == JvPrimClass (char)) + { + _Jv_CheckCast (&Character::class$, o); + *(jchar*)rvalue = ((Character*)o)->charValue(); + } + else + JvFail ("Bad ffi type in proxy"); +} + +// _Jv_getFieldInternal is declared as a friend of reflect.Field in +// libjava/headers.txt. This gives us a way to call the private +// method Field.get (Class caller, Object obj). +extern inline jobject +_Jv_getFieldInternal (java::lang::reflect::Field *f, jclass c, jobject o) +{ + return f->get(c, o); +} + +// run_proxy is the entry point for all proxy methods. It boxes up +// all the arguments and then invokes the invocation handler's invoke() +// method. Exceptions are caught and propagated. + +typedef struct { + ffi_closure closure; + _Jv_ClosureList list; + ffi_cif cif; + _Jv_Method *self; + int method_index; + ffi_type *arg_types[0]; +} ncode_closure; + +static void +run_proxy (ffi_cif *cif, + void *rvalue, + void **args, + void*user_data) +{ + using namespace java::lang::reflect; + + Proxy *proxy = *(Proxy**)args[0]; + ncode_closure *self = (ncode_closure *) user_data; + + jclass proxyClass = proxy->getClass(); + + // FRAME_DESC registers this particular invocation as the top-most + // interpreter frame. This lets the stack tracing code (for + // Throwable) print information about the Proxy being run rather + // than about Proxy.class itself. FRAME_DESC has a destructor so it + // cleans up automatically when this proxy invocation returns. + Thread *thread = Thread::currentThread(); + _Jv_InterpFrame frame_desc (self->self, thread, proxyClass, + NULL, frame_proxy); + + // The method to invoke is saved in $Proxy0.m[method_index]. + // FIXME: We could somewhat improve efficiency by storing a pointer + // to the method (rather than its index) in ncode_closure. This + // would avoid the lookup, but it probably wouldn't make a huge + // difference. We'd still have to save the method array because + // ncode structs are not scanned by the gc. + Field *f = proxyClass->getDeclaredField (JvNewStringLatin1 ("m")); + JArray<Method*> *methods + = (JArray<Method*>*)_Jv_getFieldInternal (f, proxyClass, NULL); + Method *meth = elements(methods)[self->method_index]; + + JArray<jclass> *parameter_types = meth->internalGetParameterTypes (); + JArray<jclass> *exception_types = meth->internalGetExceptionTypes (); + + InvocationHandler *handler = proxy->h; + JArray<jobject> *argsArray = NULL; + jobject *jargs = NULL; + if (parameter_types->length) + { + void *poo + = _Jv_NewObjectArray (parameter_types->length, &Object::class$, NULL); + argsArray = (JArray<jobject> *) poo; + jargs = elements(argsArray); + } + + // FIXME: It must be possible to use fast interface dispatch here, + // but I've not quite figured out how to do it. + invoke_t *invoke + = (invoke_t *)(_Jv_LookupInterfaceMethod + (handler->getClass (), + _Jv_makeUtf8Const ("invoke"), + (_Jv_makeUtf8Const + ("(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)" + "Ljava.lang.Object;")))); + + // Copy and box all the args. + int index = 1; + for (int i = 0; i < parameter_types->length; i++, index++) + jargs[i] = box (args[index], elements(parameter_types)[i], + cif->arg_types[index]->type); + + jobject ret; + try + { + ret = invoke (handler, proxy, meth, argsArray); + } + catch (Throwable *t) + { + if (_Jv_IsInstanceOf (t, &RuntimeException::class$) + || _Jv_IsInstanceOf (t, &Error::class$)) + throw t; + + Class **throwables = elements (exception_types); + for (int i = 0; i < exception_types->length; i++) + if (_Jv_IsInstanceOf (t, throwables[i])) + throw t; + + throw new UndeclaredThrowableException (t); + } + + unbox (ret, meth->return_type, rvalue, cif->rtype->type); +} + + +// Given a method and a closure function, create libffi CIF and return +// the address of its closure. + +static void * +ncode (int method_index, jclass klass, _Jv_Method *self, closure_fun fun) +{ + using namespace java::lang::reflect; + + jboolean staticp = (self->accflags & Modifier::STATIC) != 0; + int arg_count = _Jv_count_arguments (self->signature, staticp); + + void *code; + ncode_closure *closure = + (ncode_closure*)ffi_closure_alloc (sizeof (ncode_closure) + + arg_count * sizeof (ffi_type*), + &code); + closure->method_index = method_index; + closure->list.registerClosure (klass, closure); + + _Jv_init_cif (self->signature, + arg_count, + staticp, + &closure->cif, + &closure->arg_types[0], + NULL); + closure->self = self; + + JvAssert ((self->accflags & Modifier::NATIVE) == 0); + + ffi_prep_closure_loc (&closure->closure, + &closure->cif, + fun, + code, + code); + + self->ncode = code; + return self->ncode; +} + +#endif // INTERPRETER |