diff options
Diffstat (limited to 'libjava/java/lang/reflect')
-rw-r--r-- | libjava/java/lang/reflect/AccessibleObject.java | 53 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Array.java | 78 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Constructor.java | 106 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Field.java | 264 | ||||
-rw-r--r-- | libjava/java/lang/reflect/InvocationTargetException.java | 73 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Member.java | 26 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Method.java | 123 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Modifier.java | 130 | ||||
-rw-r--r-- | libjava/java/lang/reflect/natArray.cc | 339 | ||||
-rw-r--r-- | libjava/java/lang/reflect/natField.cc | 435 | ||||
-rw-r--r-- | libjava/java/lang/reflect/natMethod.cc | 386 |
11 files changed, 2013 insertions, 0 deletions
diff --git a/libjava/java/lang/reflect/AccessibleObject.java b/libjava/java/lang/reflect/AccessibleObject.java new file mode 100644 index 00000000000..8c869e167b0 --- /dev/null +++ b/libjava/java/lang/reflect/AccessibleObject.java @@ -0,0 +1,53 @@ +// AccessibleObject.java - Base for reflection objects. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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; + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date December 12, 1998 + */ +/* Written using JDK 1.2 beta docs. + * Status: Believed complete and correct. + */ + +public class AccessibleObject +{ + protected AccessibleObject () + { + flag = false; + } + + boolean isAccessible () + { + return flag; + } + + static void setAccessible (AccessibleObject[] array, boolean flag) + { + checkPermission (); + for (int i = 0; i < array.length; ++i) + array[i].flag = flag; + } + + void setAccessible (boolean flag) + { + checkPermission (); + this.flag = flag; + } + + private static final void checkPermission () + { + SecurityManager sm = System.getSecurityManager(); + // FIXME: sm.checkPermission(ReflectPermission ("suppressAccessChecks")) + } + + private boolean flag; +} diff --git a/libjava/java/lang/reflect/Array.java b/libjava/java/lang/reflect/Array.java new file mode 100644 index 00000000000..398f80d5643 --- /dev/null +++ b/libjava/java/lang/reflect/Array.java @@ -0,0 +1,78 @@ +// FileDescriptor.java - Open file or device + +/* Copyright (C) 1999 Cygnus Solutions + + 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; + +/** + * @author Per Bothner <bothner@cygnus.com> + * @date january 12, 1999 + */ + +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3. + * Status: Believe complete and correct. + */ + +public final class Array +{ + Array () { } + + public static native Object newInstance(Class componentType, int length); + public static native Object newInstance(Class elementType, int[] dimensions); + public static native int getLength (Object array); + + public static native Object get (Object array, int index); + public static native char getChar (Object array, int index); + public static native byte getByte (Object array, int index); + public static native short getShort (Object array, int index); + public static native int getInt (Object array, int index); + public static native long getLong (Object array, int index); + public static native float getFloat (Object array, int index); + public static native double getDouble (Object array, int index); + public static native boolean getBoolean (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); + + 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(); + } + + public static native void setByte (Object array, int index, byte value); + public static native void setShort (Object array, int index, short value); + public static native void setInt (Object array, int index, int value); + public static native void setLong (Object array, int index, long value); + public static native void setFloat (Object array, int index, float value); + public static native void setDouble (Object array, int index, double value); + public static native void setChar (Object array, int index, char value); + public static native void setBoolean(Object array, int index, boolean value); +} diff --git a/libjava/java/lang/reflect/Constructor.java b/libjava/java/lang/reflect/Constructor.java new file mode 100644 index 00000000000..466c1204bae --- /dev/null +++ b/libjava/java/lang/reflect/Constructor.java @@ -0,0 +1,106 @@ +// Constructor.java - Represents a constructor for a class. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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; + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date December 12, 1998 + */ +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 + * "The Java Language Specification", ISBN 0-201-63451-1 + * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. + * Status: Incomplete: needs a private constructor, and + * newInstance() needs to be written. + */ + +public final class Constructor extends AccessibleObject implements Member +{ + public boolean equals (Object obj) + { + if (! (obj instanceof Constructor)) + return false; + Constructor c = (Constructor) obj; + return decl_class == c.decl_class && index == c.index; + } + + public Class getDeclaringClass () + { + return decl_class; + } + + public Class[] getExceptionTypes () + { + return (Class[]) exception_types.clone(); + } + + public int getModifiers () + { + return modifiers; + } + + public String getName () + { + return decl_class.getName(); + } + + public Class[] getParameterTypes () + { + return (Class[]) parameter_types.clone(); + } + + public int hashCode () + { + // FIXME. + return getName().hashCode(); + } + + // FIXME: this must be native. Should share implementation with + // Method.invoke. + public Object newInstance (Object[] args) + throws InstantiationException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException + { + return null; + } + + public String toString () + { + StringBuffer b = new StringBuffer (); + b.append(Modifier.toString(modifiers)); + b.append(" "); + b.append(getName()); + b.append("("); + for (int i = 0; i < parameter_types.length; ++i) + { + b.append(parameter_types[i].toString()); + if (i < parameter_types.length - 1) + b.append(","); + } + b.append(")"); + return b.toString(); + } + + // Can't create these. FIXME. + private Constructor () + { + } + + // Declaring class. + private Class decl_class; + // Exception types. + private Class[] exception_types; + // Modifiers. + private int modifiers; + // Parameter types. + private Class[] parameter_types; + // Index of this method in declaring class' method table. + private int index; +} diff --git a/libjava/java/lang/reflect/Field.java b/libjava/java/lang/reflect/Field.java new file mode 100644 index 00000000000..7c7e690926a --- /dev/null +++ b/libjava/java/lang/reflect/Field.java @@ -0,0 +1,264 @@ +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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; + +/** + * @author Per Bothner <bothner@cygnus.com> + * @date September 1998; February 1999. + */ +/* Status: Mostly implemented. + * However, access checks are not implemented. See natField.cc for + * _Jv_CheckFieldAccessibility as well as the missing getCaller. + * Note that the idea is to have to compiler convert calls to + * setXXX(...) and getXXX(...) to setXXX(CALLER, ...) and getXXX(CALLER, ...), + * where CALLER is reference to the class that contains the calls to + * setXXX or getXXX. This is easy for the compiler, and replaces + * expensive stack and table searching with a constant. + */ + +public final class Field extends AccessibleObject implements Member +{ + private Class declaringClass; + + // This is filled in by getName. + private String name; + + // Offset in bytes from the start of declaringClass's fields array. + private int offset; + + public boolean equals (Object fld) + { + if (! (fld instanceof Field)) + return false; + Field f = (Field) fld; + return declaringClass == f.declaringClass && offset == f.offset; + } + + public Class getDeclaringClass () + { + return declaringClass; + } + + public native String getName (); + + public native Class getType (); + + public native int getModifiers (); + + public int hashCode() + { + return (declaringClass.hashCode() ^ offset); + } + + // The idea is that the compiler will magically translate + // fld.getShort(obj) to fld.getShort(THISCLASS, obj). + // This makes checking assessiblity more efficient, + // since we don't have to do any stack-walking. + + public boolean getBoolean (Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getBoolean(null, obj); + } + public char getChar (Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getChar(null, obj); + } + + public byte getByte (Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getByte(null, obj); + } + + public short getShort (Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getShort(null, obj); + } + + public int getInt (Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getInt(null, obj); + } + + public long getLong (Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getLong(null, obj); + } + + public float getFloat (Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFloat(null, obj); + } + + public double getDouble (Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getDouble(null, obj); + } + + public Object get (Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return get(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; + + public native Object get (Class caller, Object obj) + throws IllegalArgumentException, IllegalAccessException; + + public void setByte (Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + setByte(null, obj, b); + } + + public void setShort (Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + setShort(null, obj, s); + } + + public void setInt (Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + setInt(null, obj, i); + } + + public void setLong (Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + setLong(null, obj, l); + } + + public void setFloat (Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + setFloat(null, obj, f); + } + + public void setDouble (Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + setDouble(null, obj, d); + } + + public void setChar (Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + setChar(null, obj, c); + } + + public void setBoolean (Object obj, boolean b) + throws IllegalArgumentException, IllegalAccessException + { + setBoolean(null, obj, b); + } + + public native void setByte (Class caller, Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException; + + public native void setShort (Class caller, Object obj, short s) + throws IllegalArgumentException, IllegalAccessException; + + public native void setInt (Class caller, Object obj, int i) + throws IllegalArgumentException, IllegalAccessException; + + public native void setLong (Class caller, Object obj, long l) + throws IllegalArgumentException, IllegalAccessException; + + public native void setFloat (Class caller, Object obj, float f) + throws IllegalArgumentException, IllegalAccessException; + + public native void setDouble (Class caller, Object obj, double d) + throws IllegalArgumentException, IllegalAccessException; + + public native void setChar (Class caller, Object obj, char c) + throws IllegalArgumentException, IllegalAccessException; + + public native void setBoolean (Class caller, Object obj, boolean b) + throws IllegalArgumentException, IllegalAccessException; + + private native void set (Class caller, Object obj, Object val, Class type) + throws IllegalArgumentException, IllegalAccessException; + + public void set (Object object, Object value) + throws IllegalArgumentException, IllegalAccessException + { + set(null, object, value); + } + + public void set (Class caller, Object object, Object value) + throws IllegalArgumentException, IllegalAccessException + { + Class type = getType(); + if (! type.isPrimitive()) + set(caller, object, value, type); + else if (value instanceof Byte) + setByte(caller, object, ((Byte) value).byteValue()); + else if (value instanceof Short) + setShort (caller, object, ((Short) value).shortValue()); + else if (value instanceof Integer) + setInt(caller, object, ((Integer) value).intValue()); + else if (value instanceof Long) + setLong(caller, object, ((Long) value).longValue()); + else if (value instanceof Float) + setFloat(caller, object, ((Float) value).floatValue()); + else if (value instanceof Double) + setDouble(caller, object, ((Double) value).doubleValue()); + else if (value instanceof Character) + setChar(caller, object, ((Character) value).charValue()); + else if (value instanceof Boolean) + setBoolean(caller, object, ((Boolean) value).booleanValue()); + else + throw new IllegalArgumentException(); + } + + public String toString () + { + StringBuffer sbuf = new StringBuffer (); + int mods = getModifiers(); + if (mods != 0) + Modifier.toString(mods, sbuf); + sbuf.append(getType()); + sbuf.append(' '); + sbuf.append(getDeclaringClass()); + sbuf.append('.'); + sbuf.append(getName()); + return sbuf.toString(); + } +} diff --git a/libjava/java/lang/reflect/InvocationTargetException.java b/libjava/java/lang/reflect/InvocationTargetException.java new file mode 100644 index 00000000000..eccd5f7daed --- /dev/null +++ b/libjava/java/lang/reflect/InvocationTargetException.java @@ -0,0 +1,73 @@ +// InvocationTargetException.java - Wrapper exception for reflection. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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 java.io.PrintStream; +import java.io.PrintWriter; + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date December 12, 1998 + */ +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 + * "The Java Language Specification", ISBN 0-201-63451-1 + * Status: Believed complete and correct. + */ + +public class InvocationTargetException extends Exception +{ + public Throwable getTargetException () + { + return target; + } + + protected InvocationTargetException () + { + super (); + target = null; + } + + public InvocationTargetException (Throwable exception) + { + super (); + target = exception; + } + + public InvocationTargetException (Throwable exception, String msg) + { + super (msg); + target = exception; + } + + // This is from JDK 1.2. + public void printStackTrace () + { + if (target != null) + target.printStackTrace(); + } + + // This is from JDK 1.2. + public void printStackTrace (PrintStream s) + { + if (target != null) + target.printStackTrace(s); + } + + // This is from JDK 1.2. + public void printStackTrace (PrintWriter wr) + { + if (target != null) + target.printStackTrace(wr); + } + + // The wrapped exception. The name is specified by the + // serialization spec. + private Throwable target; +} diff --git a/libjava/java/lang/reflect/Member.java b/libjava/java/lang/reflect/Member.java new file mode 100644 index 00000000000..a54f05f689e --- /dev/null +++ b/libjava/java/lang/reflect/Member.java @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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; + +/** + * @author Per Bothner <bothner@cygnus.com> + * @date September 27, 1998. + */ +/* Written using "Java Class Libraries", 2nd edition. + * Status: Believed complete and correct. + */ + +public interface Member +{ + public static final int PUBLIC = 0; + public static final int DECLARED = 1; + public Class getDeclaringClass (); + public int getModifiers (); + public String getName(); +} diff --git a/libjava/java/lang/reflect/Method.java b/libjava/java/lang/reflect/Method.java new file mode 100644 index 00000000000..01e830876e5 --- /dev/null +++ b/libjava/java/lang/reflect/Method.java @@ -0,0 +1,123 @@ +// Method.java - Represent method of class or interface. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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; + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date December 12, 1998 + */ +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 + * "The Java Language Specification", ISBN 0-201-63451-1 + * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. + * Status: Incomplete: needs a private constructor, and + * invoke() needs to be finished. + */ + +public final class Method extends AccessibleObject implements Member +{ + public boolean equals (Object obj) + { + if (! (obj instanceof Method)) + return false; + Method m = (Method) obj; + return declaringClass == m.declaringClass && offset == m.offset; + } + + public Class getDeclaringClass () + { + return declaringClass; + } + + public Class[] getExceptionTypes () + { + return (Class[]) exception_types.clone(); + } + + public native int getModifiers (); + + public native String getName (); + + private native void getType (); + + public Class[] getParameterTypes () + { + if (parameter_types == null) + getType(); + return (Class[]) parameter_types.clone(); + } + + public Class getReturnType () + { + if (return_type == null) + getType(); + return return_type; + } + + public int hashCode () + { + // FIXME. + return name.hashCode() + declaringClass.getName().hashCode(); + } + + public native Object invoke (Object obj, Object[] args) + throws IllegalAccessException, IllegalArgumentException, + InvocationTargetException; + + public String toString () + { + StringBuffer b = new StringBuffer (); + b.append(Modifier.toString(getModifiers())); + b.append(" "); + b.append(return_type.toString()); + b.append(" "); + b.append(declaringClass.toString()); + b.append("."); + b.append(name); + b.append("("); + for (int i = 0; i < parameter_types.length; ++i) + { + b.append(parameter_types[i].toString()); + 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) + { + b.append(exception_types[i].toString()); + if (i < exception_types.length - 1) + b.append(","); + } + } + return b.toString(); + } + + private Method () + { + } + + // Declaring class. + private Class declaringClass; + + // Exception types. + private Class[] exception_types; + // Name cache. (Initially null.) + private String name; + // Parameter types. + private Class[] parameter_types; + // Return type. + private 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.java b/libjava/java/lang/reflect/Modifier.java new file mode 100644 index 00000000000..f9df49e80ee --- /dev/null +++ b/libjava/java/lang/reflect/Modifier.java @@ -0,0 +1,130 @@ +// Modifier.java - Process modifier values. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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. */ + +/** + * @author Tom Tromey <tromey@cygnus.com> + * @date October 1, 1998 + */ + +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 + * "The Java Language Specification", ISBN 0-201-63451-1 + * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. + * Status: Believed complete and correct to version 1.1 + */ + +package java.lang.reflect; + +public class Modifier +{ + public static final int PUBLIC = 0x001; + public static final int PRIVATE = 0x002; + public static final int PROTECTED = 0x004; + public static final int STATIC = 0x008; + public static final int FINAL = 0x010; + public static final int SYNCHRONIZED = 0x020; + public static final int VOLATILE = 0x040; + public static final int TRANSIENT = 0x080; + public static final int NATIVE = 0x100; + public static final int INTERFACE = 0x200; + public static final int ABSTRACT = 0x400; + + public static boolean isAbstract (int mod) + { + return (mod & ABSTRACT) != 0; + } + + public static boolean isFinal (int mod) + { + return (mod & FINAL) != 0; + } + + public static boolean isInterface (int mod) + { + return (mod & INTERFACE) != 0; + } + + public static boolean isNative (int mod) + { + return (mod & NATIVE) != 0; + } + + public static boolean isPrivate (int mod) + { + return (mod & PRIVATE) != 0; + } + + public static boolean isProtected (int mod) + { + return (mod & PROTECTED) != 0; + } + + public static boolean isPublic (int mod) + { + return (mod & PUBLIC) != 0; + } + + public static boolean isStatic (int mod) + { + return (mod & STATIC) != 0; + } + + public static boolean isSynchronized (int mod) + { + return (mod & SYNCHRONIZED) != 0; + } + + public static boolean isTransient (int mod) + { + return (mod & TRANSIENT) != 0; + } + + public static boolean isVolatile (int mod) + { + return (mod & VOLATILE) != 0; + } + + public static String toString (int mod) + { + StringBuffer r = new StringBuffer (); + toString(mod, r); + return r.toString(); + } + + static void 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 (isNative (mod)) + r.append("native "); + if (isSynchronized (mod)) + r.append("synchronized "); + if (isInterface (mod)) + r.append("interface "); + + // Trim trailing space. + int l = r.length(); + if (l > 0) + r.setLength(l - 1); + } +} diff --git a/libjava/java/lang/reflect/natArray.cc b/libjava/java/lang/reflect/natArray.cc new file mode 100644 index 00000000000..3da8b5c01ce --- /dev/null +++ b/libjava/java/lang/reflect/natArray.cc @@ -0,0 +1,339 @@ +// natField.cc - Implementation of java.lang.reflect.Field native methods. + +/* Copyright (C) 1999 Cygnus Solutions + + 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 <cni.h> +#include <java/lang/reflect/Array.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()) + return _Jv_NewPrimArray (componentType, length); + else + return JvNewObjectArray (length, componentType, NULL); + +} + +jobject +java::lang::reflect::Array::newInstance (jclass componentType, jintArray dimensions) +{ + jint ndims = dimensions->length; + if (ndims == 0) + return componentType->newInstance (); + jint* dims = elements (dimensions); + if (ndims == 1) + return newInstance (componentType, dims[0]); + jclass arrayType = componentType; + for (int i = 0; i < ndims; i++) + arrayType = _Jv_FindArrayClass (arrayType); + return _Jv_NewMultiArray (arrayType, ndims, dims); + +} + +jint +java::lang::reflect::Array::getLength (jobject array) +{ + jclass arrayType = array->getClass(); + if (! arrayType->isArray ()) + JvThrow (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 ()) + JvThrow (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]; + JvThrow (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]; + JvThrow (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]; + JvThrow (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]; + JvThrow (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]; + JvThrow (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]; + JvThrow (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]; + JvThrow (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]; + JvThrow (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)) + if (elements ((jbooleanArray) array) [index]) + return java::lang::Boolean::TRUE; + else + return java::lang::Boolean::FALSE; + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (new java::lang::IllegalArgumentException()); +} + +void +java::lang::reflect::Array::set (jobject array, jint index, + jobject value, jclass elType) +{ + if (! _Jv_IsInstanceOf (value, elType)) + JvThrow (new java::lang::IllegalArgumentException ()); + elements ((jobjectArray) array) [index] = value; +} diff --git a/libjava/java/lang/reflect/natField.cc b/libjava/java/lang/reflect/natField.cc new file mode 100644 index 00000000000..2449b42545c --- /dev/null +++ b/libjava/java/lang/reflect/natField.cc @@ -0,0 +1,435 @@ +// natField.cc - Implementation of java.lang.reflect.Field native methods. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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 <cni.h> +#include <jvm.h> +#include <java/lang/reflect/Field.h> +#include <java/lang/reflect/Modifier.h> +#include <java/lang/IllegalArgumentException.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> +#include <java-field.h> + +jint +java::lang::reflect::Field::getModifiers () +{ + return _Jv_FromReflectedField (this)->getModifiers (); +} + +jstring +java::lang::reflect::Field::getName () +{ + if (name == NULL) + name = _Jv_NewStringUtf8Const (_Jv_FromReflectedField (this)->name); + return name; +} + +jclass +java::lang::reflect::Field::getType () +{ + jfieldID fld = _Jv_FromReflectedField (this); + if (! fld->isResolved()) + { + JvSynchronize sync (declaringClass); + if (! fld->isResolved()) + { + fld->type + = _Jv_FindClassFromSignature(((Utf8Const*) (fld->type))->data, + declaringClass->getClassLoader()); + fld->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG; + } + } + return fld->type; +} + +static void +_Jv_CheckFieldAccessibility (jfieldID /*fld*/, jclass /*caller*/) +{ +#if 0 + if (caller == NULL) + caller = getCaller(); +#endif +#if 0 + _Jv_ushort flags = fld->getModifiers(); + check accesss; +#endif +} + +static void* +getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj) +{ + jfieldID fld = _Jv_FromReflectedField (field); + _Jv_ushort flags = fld->getModifiers(); + if (! (flags & java::lang::reflect::Modifier::PUBLIC) + && ! field->isAccessible ()) + _Jv_CheckFieldAccessibility (fld, caller); + if (flags & java::lang::reflect::Modifier::STATIC) + { + jclass fldClass = field->getDeclaringClass (); + JvInitClass(fldClass); + return fld->u.addr; + } + else + { + if (obj == NULL) + _Jv_Throw (new java::lang::NullPointerException ()); + if (! _Jv_IsInstanceOf (obj, field->getDeclaringClass())) + JvThrow (new java::lang::IllegalArgumentException ()); + return (void*) ((char*) obj + fld->getOffset ()); + } +} + +static jboolean +getBoolean (jclass cls, void* addr) +{ + if (cls == JvPrimClass (boolean)) + return * (jboolean *) addr; + _Jv_Throw (new java::lang::IllegalArgumentException()); +} + +static jchar +getChar (jclass cls, void* addr) +{ + if (cls == JvPrimClass (char)) + return * (jchar *) addr; + _Jv_Throw (new java::lang::IllegalArgumentException()); +} + +static jbyte +getByte (jclass cls, void* addr) +{ + if (cls == JvPrimClass (byte)) + return * (jbyte *) addr; + _Jv_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; + _Jv_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; + _Jv_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) +{ + jfieldID fld = _Jv_FromReflectedField (this); + return ::getBoolean (fld->type, getAddr (this, caller, obj)); +} + +jchar +java::lang::reflect::Field::getChar (jclass caller, jobject obj) +{ + jfieldID fld = _Jv_FromReflectedField (this); + return ::getChar (fld->type, getAddr (this, caller, obj)); +} + +jbyte +java::lang::reflect::Field::getByte (jclass caller, jobject obj) +{ + jfieldID fld = _Jv_FromReflectedField (this); + return ::getByte (fld->type, getAddr (this, caller, obj)); +} + +jshort +java::lang::reflect::Field::getShort (jclass caller, jobject obj) +{ + jfieldID fld = _Jv_FromReflectedField (this); + return ::getShort (fld->type, getAddr (this, caller, obj)); +} + +jint +java::lang::reflect::Field::getInt (jclass caller, jobject obj) +{ + jfieldID fld = _Jv_FromReflectedField (this); + return ::getInt (fld->type, getAddr (this, caller, obj)); +} + +jlong +java::lang::reflect::Field::getLong (jclass caller, jobject obj) +{ + jfieldID fld = _Jv_FromReflectedField (this); + return ::getLong (fld->type, getAddr (this, caller, obj)); +} + +jfloat +java::lang::reflect::Field::getFloat (jclass caller, jobject obj) +{ + jfieldID fld = _Jv_FromReflectedField (this); + return ::getFloat (fld->type, getAddr (this, caller, obj)); +} + +jdouble +java::lang::reflect::Field::getDouble (jclass caller, jobject obj) +{ + jfieldID fld = _Jv_FromReflectedField (this); + return ::getDouble (fld->type, getAddr (this, caller, obj)); +} + +jobject +java::lang::reflect::Field::get (jclass caller, jobject obj) +{ + jfieldID fld = _Jv_FromReflectedField (this); + void* addr = getAddr (this, caller, obj); + if (! fld->type->isPrimitive ()) + return * (jobject*) addr; + if (fld->type == JvPrimClass (double)) + return new java::lang::Double (* (jdouble*) addr); + if (fld->type == JvPrimClass (float)) + return new java::lang::Float (* (jfloat*) addr); + if (fld->type == JvPrimClass (long)) + return new java::lang::Long (* (jlong*) addr); + if (fld->type == JvPrimClass (int)) + return new java::lang::Integer (* (jint*) addr); + if (fld->type == JvPrimClass (short)) + return new java::lang::Short (* (jshort*) addr); + if (fld->type == JvPrimClass (byte)) + return new java::lang::Byte (* (jbyte*) addr); + if (fld->type == JvPrimClass (char)) + return new java::lang::Character (* (jchar*) addr); + if (fld->type == JvPrimClass (boolean)) + if (* (jboolean*) addr) + return java::lang::Boolean::TRUE; + else + return java::lang::Boolean::FALSE; + JvThrow (new java::lang::IllegalArgumentException()); +} + +static void +setBoolean (jclass type, void *addr, jboolean value) +{ + if (type == JvPrimClass (boolean)) + * (jboolean *) addr = value; + else + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (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 + JvThrow (new java::lang::IllegalArgumentException()); +} + +static void +setDouble (jclass type, void *addr, jdouble value) +{ + if (type == JvPrimClass (double)) + * (jdouble *) addr = value; + else + JvThrow (new java::lang::IllegalArgumentException()); +} + +void +java::lang::reflect::Field::setBoolean (jclass caller, jobject obj, jboolean b) +{ + jfieldID fld = _Jv_FromReflectedField (this); + ::setBoolean (fld->type, getAddr (this, caller, obj), b); +} + +void +java::lang::reflect::Field::setChar (jclass caller, jobject obj, jchar c) +{ + jfieldID fld = _Jv_FromReflectedField (this); + ::setChar (fld->type, getAddr (this, caller, obj), c); +} + +void +java::lang::reflect::Field::setByte (jclass caller, jobject obj, jbyte b) +{ + jfieldID fld = _Jv_FromReflectedField (this); + ::setByte (fld->type, getAddr (this, caller, obj), b); +} + +void +java::lang::reflect::Field::setShort (jclass caller, jobject obj, jshort s) +{ + jfieldID fld = _Jv_FromReflectedField (this); + ::setShort (fld->type, getAddr (this, caller, obj), s); +} + +void +java::lang::reflect::Field::setInt (jclass caller, jobject obj, jint i) +{ + jfieldID fld = _Jv_FromReflectedField (this); + ::setInt (fld->type, getAddr (this, caller, obj), i); +} + +void +java::lang::reflect::Field::setLong (jclass caller, jobject obj, jlong l) +{ + jfieldID fld = _Jv_FromReflectedField (this); + ::setLong (fld->type, getAddr (this, caller, obj), l); +} +void +java::lang::reflect::Field::setFloat (jclass caller, jobject obj, jfloat f) +{ + jfieldID fld = _Jv_FromReflectedField (this); + ::setFloat (fld->type, getAddr (this, caller, obj), f); +} + +void +java::lang::reflect::Field::setDouble (jclass caller, jobject obj, jdouble d) +{ + jfieldID fld = _Jv_FromReflectedField (this); + ::setDouble (fld->type, getAddr (this, caller, obj), d); +} + +void +java::lang::reflect::Field::set (jclass caller, jobject object, jobject value, jclass type) +{ + if (! _Jv_IsInstanceOf (value, type)) + JvThrow (new java::lang::IllegalArgumentException ()); + void* addr = getAddr (this, caller, object); + * (jobject*) addr = value; +} diff --git a/libjava/java/lang/reflect/natMethod.cc b/libjava/java/lang/reflect/natMethod.cc new file mode 100644 index 00000000000..720bbc3d74e --- /dev/null +++ b/libjava/java/lang/reflect/natMethod.cc @@ -0,0 +1,386 @@ +// natMethod.cc - Native code for Method class. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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. */ + +// This is about 90% done. Search for FIXME to see what remains. + +#include <config.h> + +#include <cni.h> +#include <jvm.h> +#include <java-array.h> + +#include <java/lang/reflect/Method.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/IllegalArgumentException.h> +#include <java/lang/NullPointerException.h> +#include <java/lang/Class.h> +#include <java-method.h> + +#define ClassClass _CL_Q34java4lang5Class +extern java::lang::Class ClassClass; + +#include <stdlib.h> + +#if 0 + +#include <ffi.h> + +#define VoidClass _CL_Q34java4lang4Void +extern java::lang::Class VoidClass; +#define ByteClass _CL_Q34java4lang4Byte +extern java::lang::Class ByteClass; +#define ShortClass _CL_Q34java4lang5Short +extern java::lang::Class ShortClass; +#define CharacterClass _CL_Q34java4lang9Character +extern java::lang::Class CharacterClass; +#define IntegerClass _CL_Q34java4lang7Integer +extern java::lang::Class IntegerClass; +#define LongClass _CL_Q34java4lang4Long +extern java::lang::Class LongClass; +#define FloatClass _CL_Q34java4lang5Float +extern java::lang::Class FloatClass; +#define DoubleClass _CL_Q34java4lang6Double +extern java::lang::Class DoubleClass; + +struct cpair +{ + jclass prim; + jclass wrap; +}; + +// This is used to determine when a primitive widening conversion is +// allowed. +static cpair primitives[] = +{ +#define VOID 0 + { JvPrimClass (void), &VoidClass }, + { JvPrimClass (byte), &ByteClass }, +#define SHORT 2 + { JvPrimClass (short), &ShortClass }, +#define CHAR 3 + { JvPrimClass (char), &CharacterClass }, + { JvPrimClass (int), &IntegerClass }, + { JvPrimClass (long), &LongClass }, + { JvPrimClass (float), &FloatClass }, + { JvPrimClass (double), &DoubleClass }, + { NULL, NULL } +}; + +static 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; + // Can't handle Void arguments. + if (fromx == VOID || tox == VOID) + return false; + // Special-case short/char conversions. + if ((fromx == SHORT && tox == CHAR) || (fromx == CHAR && tox == SHORT)) + return false; + + return fromx <= tox; +} + +static 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)) + { + // FIXME. + r = &ffi_type_sint8; + } + else if (klass == JvPrimClass (char)) + r = &ffi_type_uint16; + else + { + JvAssert (! klass->isPrimitive()); + r = &ffi_type_pointer; + } + + return r; +} + +// FIXME: the body of this method should be a separate function so +// that Constructor can use it too. +jobject +java::lang::reflect::Method::invoke (jobject obj, + jobjectArray args) +{ + // FIXME: we need to be a friend of Class here. + _Jv_Method *meth = decl_class->methods[index]; + if (! java::lang::reflect::Modifier::isStatic(modifiers)) + { + jclass k = obj ? obj->getClass() : NULL; + if (! obj || ! decl_class->isAssignableFrom(k)) + JvThrow (new java::lang::NullPointerException); + // FIXME: access checks. + meth = _Jv_LookupMethod (k, meth->name, meth->signature); + } + + // FIXME: access checks. + + if (parameter_types->length != args->length) + JvThrow (new java::lang::IllegalArgumentException); + + ffi_type *rtype = get_ffi_type (return_type); + ffi_type **argtypes = (ffi_type **) alloca (parameter_types->length + * sizeof (ffi_type *)); + + jobject *paramelts = elements (parameter_types); + jobject *argelts = elements (args); + + int size = 0; + for (int i = 0; i < parameter_types->length; ++i) + { + jclass k = argelts[i] ? argelts[i]->getClass() : NULL; + argtypes[i] = get_ffi_type (k); + if (paramelts[i]->isPrimitive()) + { + if (! argelts[i] + || ! k->isPrimitive () + || ! can_widen (k, paramelts[i])) + JvThrow (new java::lang::IllegalArgumentException); + size += paramelts[i]->size(); + } + else + { + if (argelts[i] && ! paramelts[i]->isAssignableFrom (k)) + JvThrow (new java::lang::IllegalArgumentException); + size += sizeof (jobject); + } + } + + ffi_cif cif; + if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, parameter_types->length, + rtype, argtypes) != FFI_OK) + { + // FIXME: throw some kind of VirtualMachineError here. + } + + char *values = (char *) alloca (size); + char *p = values; + +#define COPY(Where, What, Type) \ + do { \ + Type val = (What); \ + memcpy ((Where), &val, sizeof (Type)); \ + Where += sizeof (Type); \ + } while (0) + + for (int i = 0; i < parameter_types->length; ++i) + { + java::lang::Number *num = (java::lang::Number *) paramelts[i]; + if (paramelts[i] == JvPrimClass (byte)) + COPY (p, num->byteValue(), jbyte); + else if (paramelts[i] == JvPrimClass (short)) + COPY (p, num->shortValue(), jshort); + else if (paramelts[i] == JvPrimClass (int)) + COPY (p, num->intValue(), jint); + else if (paramelts[i] == JvPrimClass (long)) + COPY (p, num->longValue(), jlong); + else if (paramelts[i] == JvPrimClass (float)) + COPY (p, num->floatValue(), jfloat); + else if (paramelts[i] == JvPrimClass (double)) + COPY (p, num->doubleValue(), jdouble); + else if (paramelts[i] == JvPrimClass (boolean)) + COPY (p, ((java::lang::Boolean *) argelts[i])->booleanValue(), jboolean); + else if (paramelts[i] == JvPrimClass (char)) + COPY (p, ((java::lang::Character *) argelts[i])->charValue(), jchar); + else + { + JvAssert (! paramelts[i]->isPrimitive()); + COPY (p, argelts[i], jobject); + } + } + + // FIXME: exception handling. + java::lang::Throwable *ex; + jdouble ret_value; // Largest possible value. Hopefully + // it is aligned! + ex = TRAMP_CALL (ffi_call (&cif, meth->ncode, &ret_value, (void *) values)); + + if (ex) + JvThrow (new InvocationTargetException (ex)); + + jobject r; +#define VAL(Wrapper, Type) (new Wrapper (* (Type *) &ret_value)) + if (return_type == JvPrimClass (byte)) + r = VAL (java::lang::Byte, jbyte); + else if (return_type == JvPrimClass (short)) + r = VAL (java::lang::Short, jshort); + else if (return_type == JvPrimClass (int)) + r = VAL (java::lang::Integer, jint); + else if (return_type == JvPrimClass (long)) + r = VAL (java::lang::Long, jlong); + else if (return_type == JvPrimClass (float)) + r = VAL (java::lang::Float, jfloat); + else if (return_type == JvPrimClass (double)) + r = VAL (java::lang::Double, jdouble); + else if (return_type == JvPrimClass (boolean)) + r = VAL (java::lang::Boolean, jboolean); + else if (return_type == JvPrimClass (char)) + r = VAL (java::lang::Character, jchar); + else if (return_type == JvPrimClass (void)) + r = NULL; + else + { + JvAssert (! return_type->isPrimitive()); + r = VAL (java::lang::Object, jobject); + } + + return r; +} + +#else /* 0 */ + +jobject +java::lang::reflect::Method::invoke (jobject, jobjectArray) +{ + JvFail ("not enabled yet"); +} + +#endif /* 0 */ + +jint +java::lang::reflect::Method::getModifiers () +{ + return _Jv_FromReflectedMethod (this)->accflags; +} + +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_Utf8Const* sig = _Jv_FromReflectedMethod (this)->signature; + java::lang::ClassLoader *loader = declaringClass->getClassLoader(); + char *ptr = sig->data; + int numArgs = 0; + /* First just count the number of parameters. */ + 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, &ClassClass, NULL); + jclass* argPtr = elements (args); + for (ptr = sig->data; *ptr != '\0'; ptr++) + { + int num_arrays = 0; + jclass type; + for (; *ptr == '['; ptr++) + num_arrays++; + switch (*ptr) + { + default: + return; + case ')': + argPtr = &return_type; + continue; + case '(': + continue; + case 'V': + case 'B': + case 'C': + case 'D': + case 'F': + case 'S': + case 'I': + case 'J': + case 'Z': + type = _Jv_FindClassFromSignature(ptr, loader); + break; + case 'L': + type = _Jv_FindClassFromSignature(ptr, loader); + do + ptr++; + while (*ptr != ';' && ptr[1] != '\0'); + break; + } + while (--num_arrays >= 0) + type = _Jv_FindArrayClass (type); + *argPtr++ = type; + } + parameter_types = args; +} |