getMethod/getConstructor native implementation
Artur Biesiadowski
abies at pg.gda.pl
Mon Nov 10 13:18:18 PST 1997
I think that I have implemented missing reflection native methods
for java.lang.Class.
getMethods0, getMethod0, getConstructors0 and getConstructor0
For now no implementation of Method.invoke and Constructor.newInstance,
as I don't know how to convert array to varargs needed for execute_java_*
Bugs:
- no exception info - kaffe omits this special attribute on class load
- null pointer exception on getDeclaredMethods(),
getDeclaredConstructors(); this have to be something simple, if I
find it out, I'll send a patch
Artur
-------------- next part --------------
/*
* java.lang.Class.c
*
* Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
*
* See the file "lib-license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* Written by Tim Wilkinson <tim at tjwassoc.demon.co.uk>, 1996.
*/
#include "config.h"
#include "config-std.h"
#include "config-mem.h"
#include "../../../../kaffe/kaffevm/gtypes.h"
#include "../../../../kaffe/kaffevm/access.h"
#include "../../../../kaffe/kaffevm/constants.h"
#include "../../../../kaffe/kaffevm/object.h"
#include "../../../../kaffe/kaffevm/classMethod.h"
#include "../../../../kaffe/kaffevm/itypes.h"
#include "../../../../kaffe/kaffevm/support.h"
#include "../../../../kaffe/kaffevm/soft.h"
#include "java.io.stubs/InputStream.h"
#include "java.io.stubs/PrintStream.h"
#include "java.lang.stubs/System.h"
#include "java.lang.reflect.stubs/Field.h"
#include "java.lang.reflect.stubs/Method.h"
#include "java.lang.reflect.stubs/Constructor.h"
#include <native.h>
#include "defs.h"
/*
* Convert string name to class object.
*/
struct Hjava_lang_Class*
java_lang_Class_forName(struct Hjava_lang_String* str)
{
Hjava_lang_Class* clazz;
char buf[MAXNAMELEN];
/* Get string and convert '.' to '/' */
javaString2CString(str, buf, sizeof(buf));
classname2pathname(buf, buf);
clazz = loadClass(makeUtf8Const (buf, strlen(buf)), 0);
processClass(clazz, CSTATE_OK);
return (clazz);
}
/*
* Convert class to string name.
*/
struct Hjava_lang_String*
java_lang_Class_getName(struct Hjava_lang_Class* c)
{
char buffer[100];
struct Hjava_lang_String* str;
int len;
char* name;
int i;
char* ptr;
char ch;
len = c->name->length;
name = len > 100 ? (char*)malloc(len) : buffer;
ptr = c->name->data;
for (i = 0; i < len; i++) {
ch = *ptr++;
if (ch == '/') {
ch = '.';
}
name[i] = ch;
}
str = makeJavaString(name, len);
if (name != buffer) {
free (name);
}
return (str);
}
/*
* Create a new instance of the derived class.
*/
struct Hjava_lang_Object*
java_lang_Class_newInstance(struct Hjava_lang_Class* this)
{
return (execute_java_constructor(0, 0, this, "()V"));
}
/*
* Return super class.
*/
struct Hjava_lang_Class*
java_lang_Class_getSuperclass(struct Hjava_lang_Class* this)
{
return (this->superclass);
}
HArrayOfObject* /* [Ljava.lang.Class; */
java_lang_Class_getInterfaces(struct Hjava_lang_Class* this)
{
HArrayOfObject* obj;
struct Hjava_lang_Class** ifaces;
int i;
obj = (HArrayOfObject*)AllocObjectArray(this->interface_len, "Ljava/lang/Class");
ifaces = (struct Hjava_lang_Class**)unhand(obj)->body;
for (i = 0; i < this->interface_len; i++) {
ifaces[i] = this->interfaces[i];
}
return (obj);
}
/*
* Return the class loader which loaded me.
*/
struct Hjava_lang_ClassLoader*
java_lang_Class_getClassLoader(struct Hjava_lang_Class* this)
{
return (this->loader);
}
/*
* Is the class an interface?
*/
jbool
java_lang_Class_isInterface(struct Hjava_lang_Class* this)
{
return ((this->accflags & ACC_INTERFACE) ? 1 : 0);
}
jbool
java_lang_Class_isPrimitive(struct Hjava_lang_Class* this)
{
return (CLASS_IS_PRIMITIVE(this));
}
jbool
java_lang_Class_isArray(struct Hjava_lang_Class* this)
{
return (CLASS_IS_ARRAY(this));
}
Hjava_lang_Class*
java_lang_Class_getComponentType(struct Hjava_lang_Class* this)
{
Hjava_lang_Class* type;
if (CLASS_IS_ARRAY(this)) {
return (CLASS_ELEMENT_TYPE(this));
}
else {
return ((Hjava_lang_Class*)0);
}
}
jbool
java_lang_Class_isAssignableFrom(struct Hjava_lang_Class* this, struct Hjava_lang_Class* cls)
{
return (instanceof(this, cls));
}
/*
* Get primitive class from class name (JDK 1.1)
*/
struct Hjava_lang_Class*
java_lang_Class_getPrimitiveClass(struct Hjava_lang_String* name)
{
jchar* chrs;
chrs = &unhand(unhand(name)->value)->body[unhand(name)->offset];
switch (chrs[0]) {
case 'b':
if (chrs[1] == 'y') {
return (&byteClass);
}
if (chrs[1] == 'o') {
return (&booleanClass);
}
break;
case 'c':
return (&charClass);
case 'd':
return (&doubleClass);
case 'f':
return (&floatClass);
case 'i':
return (&intClass);
case 'l':
return (&longClass);
case 's':
return (&shortClass);
case 'v':
return (&voidClass);
}
return(NULL);
}
/*
* Is object instance of this class?
*/
jbool
java_lang_Class_isInstance(struct Hjava_lang_Class* this, struct Hjava_lang_Object* obj)
{
return (soft_instanceof(this, obj));
}
jint
java_lang_Class_getModifiers(struct Hjava_lang_Class* this)
{
return (this->accflags);
}
jint
java_lang_Class_getSigners()
{
unimp("java.lang.Class:getSigners unimplemented");
}
jint
java_lang_Class_setSigners()
{
unimp("java.lang.Class:setSigners unimplemented");
}
int
arrayEquals( HArrayOfObject * first, HArrayOfObject * second )
{
int i;
if ( ARRAY_SIZE(first) != ARRAY_SIZE(second) )
return 0;
for ( i = ARRAY_SIZE(first) -1; i >= 0; i-- )
{
if ( OBJARRAY_DATA(first)[i] != OBJARRAY_DATA(second)[i] )
return 0;
}
return 1;
}
static HArrayOfObject*
parseSignature2Classes( char * signature, struct Hjava_lang_Class** returnType_holder )
{
HArrayOfObject * array;
Hjava_lang_Class ** adata;
Hjava_lang_Class * tclass;
const char * ptr;
char buf[CLASSMAXSIG]; /* FIXME - size of buffer? */
char * bufptr;
int ins =0;
int i = 0;
int arraynest =0;
ptr = signature;
while(1)
{
switch( *ptr )
{
case '(':
ptr++;
break;
case ')':
goto knowlength;
case 'L':
ins++;
while( *ptr != ';' )
ptr++;
ptr++;
break;
case '[':
ptr++;
break;
default:
ins++;
ptr++;
break;
}
}
knowlength:
array = (HArrayOfObject*)AllocObjectArray(ins, "Ljava/lang/Class;");
ptr = signature;
adata = (Hjava_lang_Class** ) ARRAY_DATA(array);
while(1)
{
switch( *ptr )
{
case '(':
ptr++;
continue;
case ')':
ptr++;
goto checkreturn;
case 'I':
tclass = &intClass;
ptr++;
break;
case 'Z':
tclass = &booleanClass;
ptr++;
break;
case 'S':
tclass = &shortClass;
ptr++;
break;
case 'B':
tclass = &byteClass;
ptr++;
break;
case 'C':
tclass = &charClass;
ptr++;
break;
case 'F':
tclass = &floatClass;
ptr++;
break;
case 'D':
tclass = &doubleClass;
ptr++;
break;
case 'J':
tclass = &longClass;
ptr++;
break;
case '[':
while ( *ptr == '[' )
{
ptr++;
arraynest++;
}
continue;
case 'L':
ptr++;
bufptr = buf;
while ( *ptr != ';' )
*bufptr++ = *ptr++;
*bufptr = '\0';
tclass = lookupClass( buf );
ptr++;
break;
default:
abort();
}
while ( arraynest )
{
tclass = lookupArray(tclass);
arraynest--;
}
*(adata +i) = tclass;
i++;
}
checkreturn:
assert(arraynest == 0);
if (returnType_holder)
{
arrayback:
switch( *ptr )
{
case 'I':
*returnType_holder = &intClass;
break;
case 'Z':
*returnType_holder = &booleanClass;
break;
case 'S':
*returnType_holder = &shortClass;
break;
case 'B':
*returnType_holder= &byteClass;
break;
case 'C':
*returnType_holder = &charClass;
break;
case 'F':
*returnType_holder = &floatClass;
break;
case 'D':
*returnType_holder = &doubleClass;
break;
case 'J':
*returnType_holder = &longClass;
break;
case 'V':
*returnType_holder = &voidClass;
break;
case '[':
while ( *ptr == '[' )
{
arraynest++;
ptr++;
}
goto arrayback;
case 'L':
ptr++;
bufptr = buf;
while ( *ptr != ';' )
*bufptr++ = *ptr++;
*bufptr = '\0';
*returnType_holder = lookupClass( buf );
break;
default:
abort();
}
while ( arraynest )
{
*returnType_holder = lookupArray(*returnType_holder);
arraynest--;
}
}
return array;
}
static struct Hjava_lang_reflect_Method*
makeMethod(struct Hjava_lang_Class* clazz, int slot, HArrayOfObject* parameters,
struct Hjava_lang_Class * returnType )
{
Hjava_lang_reflect_Method* method;
Method* met;
met = CLASS_METHODS((Hjava_lang_Class*)clazz) + slot;
method = (Hjava_lang_reflect_Method*)AllocObject("java/lang/reflect/Method");
unhand(method)->clazz = (struct Hjava_lang_Class*) clazz;
unhand(method)->slot = slot;
unhand(method)->name = Utf8Const2JavaString(met->name);
unhand(method)->returnType = returnType;
unhand(method)->parameterTypes = parameters;
unhand(method)->exceptionTypes = (HArrayOfObject*) AllocObjectArray(0,"Ljava/lang/Class");
/* FIXME - check real exceptions for method - need to change main kaffe */
return (method);
}
#define IS_CONSTRUCTOR( met ) equalUtf8Consts(met->name, constructor_name)
HArrayOfObject*
java_lang_Class_getMethods0(struct Hjava_lang_Class* this , jint declared)
{
int count =0;
Hjava_lang_Class* clas;
Hjava_lang_Class* returnType;
Method* met;
Hjava_lang_reflect_Method** ptr;
HArrayOfObject* array;
HArrayOfObject* params;
int i,nsize;
if (declared) {
i = CLASS_NMETHODS((Hjava_lang_Class*)this);
met = CLASS_METHODS(clas);
for ( ; --i >= 0; ++met) {
if (!IS_CONSTRUCTOR(met))
count++;
}
}
else {
clas = (Hjava_lang_Class*) this;
for (; clas != NULL; clas = clas->superclass) {
met = CLASS_METHODS(clas);
i = CLASS_NMETHODS(clas);
for ( ; --i >= 0; ++met) {
if ( (met->accflags & ACC_PUBLIC) &&
( !IS_CONSTRUCTOR(met) ) )
{
count++;
}
}
}
}
array = (HArrayOfObject*)AllocObjectArray(count, "Ljava/lang/reflect/Method;");
ptr = (Hjava_lang_reflect_Method**) ARRAY_DATA(array) + count;
clas = (Hjava_lang_Class*) this;
do {
met = CLASS_METHODS(clas);
nsize = CLASS_NMETHODS(clas);
for ( i=0; i < nsize; met++,i++) {
if (! (met->accflags & ACC_PUBLIC) && ! declared) {
continue;
}
if ( IS_CONSTRUCTOR(met) )
continue;
params = parseSignature2Classes(met->signature->data, &returnType);
*--ptr = makeMethod(clas, i,params,returnType);
}
clas = clas->superclass;
} while (!declared && clas != NULL);
return (array);
}
struct Hjava_lang_reflect_Method*
java_lang_Class_getMethod0(struct Hjava_lang_Class* this, struct Hjava_lang_String* name, HArrayOfObject* parameters, jint declared)
{
Hjava_lang_Class* clas;
HArrayOfObject* mparams;
Hjava_lang_Class* returnType;
clas = (Hjava_lang_Class*) this;
if ( !equalUtf8JavaStrings( constructor_name, name ) )
{
do {
Method* met = CLASS_METHODS(clas);
int n = CLASS_NMETHODS(clas);
int i;
for (i = 0; i < n; ++met, ++i) {
if (((met->accflags & ACC_PUBLIC) || declared)
&& equalUtf8JavaStrings (met->name, name)) {
mparams = parseSignature2Classes(met->signature->data,
&returnType);
if ( arrayEquals( parameters, mparams ) )
return makeMethod(clas, i,mparams,returnType);
}
}
clas = clas->superclass;
} while (!declared && clas != NULL);
}
SignalError(0, "java.lang.NoSuchMethodException", ""); /* FIXME */
}
static struct Hjava_lang_reflect_Constructor*
makeConstructor(struct Hjava_lang_Class* clazz, int slot, HArrayOfObject* parameters )
{
Hjava_lang_reflect_Constructor* constructor;
Method* met;
met = CLASS_METHODS((Hjava_lang_Class*)clazz) + slot;
constructor = (Hjava_lang_reflect_Constructor*)AllocObject("java/lang/reflect/Constructor");
unhand(constructor)->clazz = (struct Hjava_lang_Class*) clazz;
unhand(constructor)->slot = slot;
unhand(constructor)->parameterTypes = parameters;
unhand(constructor)->exceptionTypes = (HArrayOfObject*) AllocObjectArray(0,"Ljava/lang/Class");
/* FIXME - check real exceptions for method - need to change main kaffe */
return (constructor);
}
HArrayOfObject*
java_lang_Class_getConstructors0(struct Hjava_lang_Class* this , jint declared)
{
int count =0;
Hjava_lang_Class* clas;
Hjava_lang_Class* returnType;
Method* met;
Hjava_lang_reflect_Constructor** ptr;
HArrayOfObject* array;
HArrayOfObject* params;
int i,nsize;
if (declared) {
i = CLASS_NMETHODS((Hjava_lang_Class*)this);
met = CLASS_METHODS(clas);
for ( ; --i >= 0; ++met) {
if (IS_CONSTRUCTOR(met))
count++;
}
}
else {
clas = (Hjava_lang_Class*) this;
for (; clas != NULL; clas = clas->superclass) {
met = CLASS_METHODS(clas);
i = CLASS_NMETHODS(clas);
for ( ; --i >= 0; ++met) {
if ( (met->accflags & ACC_PUBLIC) &&
( IS_CONSTRUCTOR(met)) )
{
count++;
}
}
}
}
array = (HArrayOfObject*)AllocObjectArray(count, "Ljava/lang/reflect/Constructor;");
ptr = (Hjava_lang_reflect_Constructor**) ARRAY_DATA(array) + count;
clas = (Hjava_lang_Class*) this;
do {
met = CLASS_METHODS(clas);
nsize = CLASS_NMETHODS(clas);
for ( i=0; i < nsize; met++,i++) {
if (! (met->accflags & ACC_PUBLIC) && ! declared) {
continue;
}
if ( !IS_CONSTRUCTOR(met) )
continue;
params = parseSignature2Classes(met->signature->data, &returnType);
*--ptr = makeConstructor(clas, i,params);
}
clas = clas->superclass;
} while (!declared && clas != NULL);
return (array);
}
struct Hjava_lang_reflect_Constructor*
java_lang_Class_getConstructor0(struct Hjava_lang_Class* this, HArrayOfObject* parameters, jint declared)
{
Hjava_lang_Class* clas;
HArrayOfObject* mparams;
Hjava_lang_Class* returnType;
clas = (Hjava_lang_Class*) this;
do {
Method* met = CLASS_METHODS(clas);
int n = CLASS_NMETHODS(clas);
int i;
for (i = 0; i < n; ++met, ++i) {
if (((met->accflags & ACC_PUBLIC) || declared)
&& IS_CONSTRUCTOR(met)) {
mparams = parseSignature2Classes(met->signature->data,
&returnType);
if ( arrayEquals( parameters, mparams ) )
return makeConstructor(clas, i,mparams);
}
}
clas = clas->superclass;
} while (!declared && clas != NULL);
SignalError(0, "java.lang.NoSuchMethodException", ""); /* FIXME */
}
static
Hjava_lang_reflect_Field*
makeField(struct Hjava_lang_Class* clazz, int slot)
{
Hjava_lang_reflect_Field* field;
Field* fld;
fld = CLASS_FIELDS((Hjava_lang_Class*)clazz) + slot;
field = (Hjava_lang_reflect_Field*)AllocObject("java/lang/reflect/Field");
unhand(field)->clazz = (struct Hjava_lang_Class*) clazz;
unhand(field)->slot = slot;
unhand(field)->type = (struct Hjava_lang_Class*) fld->type;
unhand(field)->name = Utf8Const2JavaString(fld->name);
return (field);
}
HArrayOfObject*
java_lang_Class_getFields0(struct Hjava_lang_Class* clazz, int declared)
{
int count;
Hjava_lang_Class* clas;
Field* fld;
Hjava_lang_reflect_Field** ptr;
HArrayOfObject* array;
int i,nsize;
if (declared) {
count = CLASS_NFIELDS((Hjava_lang_Class*)clazz);
}
else {
count = 0;
clas = (Hjava_lang_Class*) clazz;
for (; clas != NULL; clas = clas->superclass) {
fld = CLASS_FIELDS(clas);
i = CLASS_NFIELDS(clas);
for ( ; --i >= 0; ++fld) {
if (fld->accflags & ACC_PUBLIC) {
count++;
}
}
}
}
array = (HArrayOfObject*)AllocObjectArray(count, "Ljava/lang/reflect/Field;");
ptr = (Hjava_lang_reflect_Field**) ARRAY_DATA(array) + count;
clas = (Hjava_lang_Class*) clazz;
do {
fld = CLASS_FIELDS(clas);
nsize = CLASS_NFIELDS(clas);
for ( i=0; i < nsize; fld++,i++) {
if (! (fld->accflags & ACC_PUBLIC) && ! declared) {
continue;
}
*--ptr = makeField(clas, i);
}
clas = clas->superclass;
} while (!declared && clas != NULL);
return (array);
}
Hjava_lang_reflect_Field*
java_lang_Class_getField0(struct Hjava_lang_Class* clazz, struct Hjava_lang_String* name, int declared)
{
Hjava_lang_Class* clas;
clas = (Hjava_lang_Class*) clazz;
do {
Field* fld = CLASS_FIELDS(clas);
int n = CLASS_NFIELDS(clas);
int i;
for (i = 0; i < n; ++fld, ++i) {
if (((fld->accflags & ACC_PUBLIC) || declared)
&& equalUtf8JavaStrings (fld->name, name)) {
return makeField(clas, i);
}
}
clas = clas->superclass;
} while (!declared && clas != NULL);
SignalError(0, "java.lang.NoSuchFieldException", ""); /* FIXME */
}
More information about the kaffe
mailing list