more statistics, less crashing
[cacao.git] / src / native / vm / Field.c
1 /* src/native/vm/Field.c - java/lang/reflect/Field
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Roman Obermaiser
28
29    Changes: Joseph Wenninger
30             Christian Thalinger
31
32    $Id: Field.c 2424 2005-04-30 13:45:06Z jowenn $
33
34 */
35
36
37 #include "native/jni.h"
38 #include "native/native.h"
39 #include "native/include/java_lang_Object.h"
40 #include "native/include/java_lang_Class.h"
41 #include "native/include/java_lang_reflect_Field.h"
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/global.h"
45 #include "vm/initialize.h"
46 #include "vm/loader.h"
47 #include "vm/stringlocal.h"
48 #include "vm/tables.h"
49 #include "vm/resolve.h"
50 #include "vm/jit/stacktrace.h"
51
52 #undef DEBUG
53
54 #ifdef __GNUC__
55 #warning        FIXE SET NATIVES
56 #endif
57
58 #if (defined(__ALPHA__) || defined(__I386__))
59 /*this = java_lang_reflect_Field, fi=fieldinfo, c=declaredClass (classinfo)*/
60 #define CHECKFIELDACCESS(this,fi,c,doret)       \
61         /*log_text("Checking access rights");*/ \
62         if (!(getField(this,jboolean,getFieldID_critical(env,this->header.vftbl->class,"flag","Z")))) { \
63                 int throwAccess=0;      \
64                 struct methodinfo *callingMethod;       \
65         \
66                 if ((fi->flags & ACC_PUBLIC)==0) {      \
67                         callingMethod=cacao_callingMethod();    \
68         \
69                         if ((fi->flags & ACC_PRIVATE)!=0) {     \
70                                 if (c!=callingMethod->class) {  \
71                                         throwAccess=1;  \
72                                 }       \
73                         } else {        \
74                                 if ((fi->flags & ACC_PROTECTED)!=0) {   \
75                                         if (!builtin_isanysubclass(callingMethod->class, c)) {  \
76                                                 throwAccess=1;  \
77                                         }       \
78                                 } else {        \
79                                         /* default visibility*/ \
80                                         if (c->packagename!=callingMethod->class->packagename) {        \
81                                                 throwAccess=1;  \
82                                         }       \
83                                 }       \
84                         }       \
85                 }       \
86                 if (throwAccess) {      \
87                         *exceptionptr=0;        \
88                         *exceptionptr = new_exception(string_java_lang_IllegalAccessException); \
89                         doret;  \
90                 }       \
91         }       
92 #else
93 #define CHECKFIELDACCESS(this,fi,c,doret)
94 #endif
95
96
97
98
99
100
101
102 /*
103  * Class:     java/lang/reflect/Field
104  * Method:    get
105  * Signature: (Ljava/lang/Object;)Ljava/lang/Object;
106  */
107 JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_Field_get(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj)
108 {
109         jfieldID target_fid;   /* the JNI-fieldid of the wrapping object */
110         jfieldID fid;          /* the JNI-fieldid of the field containing the value */
111         jobject o;               /* the object for wrapping the primitive type */
112         classinfo *c = (classinfo *) this->declaringClass;
113         int st;
114
115         /* get the fieldid of the field represented by this Field-object */
116         fid=&((classinfo*)this->declaringClass)->fields[this->slot]; /*get field*/
117         /*fid = class_findfield_approx((classinfo *) this->declaringClass,javastring_toutf(this->name, false));*/
118         st = (fid->flags & ACC_STATIC); /* true if field is static */
119
120
121         CHECKFIELDACCESS(this,fid,c,return 0);
122
123         /* The fieldid is used to retrieve the value, for primitive types a new 
124            object for wrapping the primitive type is created.  */
125         if (st || obj)
126                 switch ((((classinfo *) this->declaringClass)->fields[this->slot]).descriptor->text[0]) {
127                 case 'I':
128                         /* create wrapping class */
129                         c = class_java_lang_Integer;
130                         o = builtin_new(c);
131                         /* get fieldid to store the value */
132                         target_fid = (*env)->GetFieldID(env, c, "value", "I");
133                         if (!target_fid)
134                                 break;
135                                    
136                         if (st)
137                         /* static field */
138                                 SetIntField(env,o,target_fid, (*env)->GetStaticIntField(env, c, fid));
139                         else
140                                 /* instance field */
141                                 SetIntField(env,o,target_fid, (*env)->GetIntField(env,(jobject) obj, fid));
142
143                         /* return the wrapped object */            
144                         return (java_lang_Object *) o;
145
146                 case 'J':
147                         c = class_java_lang_Long;
148                         o = builtin_new(c);
149                         target_fid = (*env)->GetFieldID(env, c, "value", "J");
150                         if (!target_fid)
151                                 break;
152                                    
153                         if (st)
154                                 SetLongField(env,o,target_fid, (*env)->GetStaticLongField(env, c, fid));
155                         else
156                                 SetLongField(env,o,target_fid, (*env)->GetLongField(env,(jobject)  obj, fid));
157
158                         return (java_lang_Object *) o;
159
160                 case 'F':
161                         c = class_java_lang_Float;
162                         o = builtin_new(c);
163                         target_fid = (*env)->GetFieldID(env, c, "value", "F");
164                         if (!target_fid)
165                                 break;
166                                    
167                         if (st)
168                                 SetFloatField(env,o,target_fid, (*env)->GetStaticFloatField(env, c, fid));
169                         else
170                                 SetFloatField(env,o,target_fid, (*env)->GetFloatField(env, (jobject) obj, fid));
171
172                         return (java_lang_Object *) o;
173
174                 case 'D':
175                         c = class_java_lang_Double;
176                         o = builtin_new(c);
177                         target_fid = (*env)->GetFieldID(env, c, "value", "D");
178                         if (!target_fid)
179                                 break;
180                                    
181                         if (st)
182                                 SetDoubleField(env,o,target_fid, (*env)->GetStaticDoubleField(env, c, fid));
183                         else
184                                 SetDoubleField(env,o,target_fid, (*env)->GetDoubleField(env, (jobject) obj, fid));
185
186                         return (java_lang_Object *) o;
187
188                 case 'B':
189                         c = class_java_lang_Byte;
190                         o = builtin_new(c);
191                         target_fid = (*env)->GetFieldID(env, c, "value", "B");
192                         if (!target_fid)
193                                 break;
194                                    
195                         if (st)
196                                 SetByteField(env,o,target_fid, (*env)->GetStaticByteField(env, c, fid));
197                         else
198                                 SetByteField(env,o,target_fid, (*env)->GetByteField(env, (jobject) obj, fid));
199
200                         return (java_lang_Object *) o;
201
202                 case 'C':
203                         c = class_java_lang_Character;
204                         o = builtin_new(c);
205                         target_fid = (*env)->GetFieldID(env, c, "value", "C");
206                         if (!target_fid)
207                                 break;
208                                    
209                         if (st)
210                                 SetCharField(env,o,target_fid, (*env)->GetStaticCharField(env, c, fid));
211                         else
212                                 SetCharField(env,o,target_fid, (*env)->GetCharField(env, (jobject) obj, fid));
213
214                         return (java_lang_Object *) o;
215
216                 case 'S':
217                         c = class_java_lang_Short;
218                         o = builtin_new(c);
219                         target_fid = (*env)->GetFieldID(env, c, "value", "S");
220                         if (!target_fid)
221                                 break;
222                                    
223                         if (st)
224                                 SetShortField(env,o,target_fid, (*env)->GetStaticShortField(env, c, fid));
225                         else
226                                 SetShortField(env,o,target_fid, (*env)->GetShortField(env, (jobject) obj, fid));
227
228                         return (java_lang_Object *) o;
229
230                 case 'Z':
231                         c = class_java_lang_Boolean;
232                         o = builtin_new(c);
233                         target_fid = (*env)->GetFieldID(env, c, "value", "Z");
234                         if (!target_fid)
235                                 break;
236                                    
237                         if (st)
238                                 SetBooleanField(env,o,target_fid, (*env)->GetStaticBooleanField(env, c, fid));
239                         else
240                                 SetBooleanField(env,o,target_fid, (*env)->GetBooleanField(env, (jobject) obj, fid));
241
242                         return (java_lang_Object *) o;
243
244                 case '[':
245                 case 'L':
246                         if (st)
247                         /* static field */
248                                 return (java_lang_Object*) (*env)->GetStaticObjectField(env, c, fid);
249                         else
250                                 /* instance field */
251                                 return (java_lang_Object*) (*env)->GetObjectField(env, (jobject) obj, fid);
252                 }
253
254         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
255
256         return NULL;
257 }
258
259
260 /*
261  * Class:     java/lang/reflect/Field
262  * Method:    getBoolean
263  * Signature: (Ljava/lang/Object;)Z
264  */
265 JNIEXPORT s4 JNICALL Java_java_lang_reflect_Field_getBoolean(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj)
266 {
267         jfieldID fid;
268         char *utf_ptr;
269         classinfo *c = (classinfo *) this->declaringClass;
270
271 #ifdef DEBUG
272         /* check if the specified slot could be a valid field of this class*/
273         if (this->slot>((classinfo*)this->declaringClass)->fieldscount) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
274                                                                           "declaring class: fieldscount mismatch");
275 #endif
276         fid=&((classinfo*)this->declaringClass)->fields[this->slot]; /*get field*/
277         CHECKFIELDACCESS(this,fid,c,return 0);
278 #ifdef DEBUG
279         /* check if the field really has the same name and check if the type descriptor is not empty*/
280         if (fid->name!=javastring_toutf(this->name,false)) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
281                                                                           "declaring class: field name mismatch");
282         if (fid->descriptor->blength<1) panic("Type-Descriptor is empty");
283 #endif
284         /* check if obj would be needed (not static field), but is 0)*/
285         if ((!(fid->flags & ACC_STATIC)) && (obj==0)) {
286                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
287                 return 0;
288         }
289         
290         /*if (!(fid->flags & ACC_PUBLIC)) {
291                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
292                 return 0;
293
294         } */
295
296         if (fid->flags & ACC_STATIC) {
297                 /* initialize class if needed*/
298                 fprintf("calling initialize_class %s\n",((classinfo*) this->declaringClass)->name->text);
299                 initialize_class((classinfo *) this->declaringClass);
300                 if (*exceptionptr) return 0;
301                 /*return value*/
302                 utf_ptr = fid->descriptor->text;
303                 switch (*utf_ptr) {
304                         case 'Z': return fid->value.i;
305                         default:
306                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
307                                 return 0;
308                 }
309         } else {
310                 if (!builtin_instanceof((java_objectheader*)obj,(classinfo*)this->declaringClass)) {
311                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
312                                 return 0;
313                 }
314                 utf_ptr = fid->descriptor->text;
315                 switch (*utf_ptr) {
316                         case 'Z':return getField(obj,jboolean,fid);
317                         default:
318                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
319                                 return 0;
320                 }
321         }
322 }
323
324
325 /*
326  * Class:     java/lang/reflect/Field
327  * Method:    getByte
328  * Signature: (Ljava/lang/Object;)B
329  */
330 JNIEXPORT s4 JNICALL Java_java_lang_reflect_Field_getByte(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj)
331 {
332         jfieldID fid;
333         char *utf_ptr;
334         classinfo *c = (classinfo *) this->declaringClass;
335
336 #ifdef DEBUG
337         /* check if the specified slot could be a valid field of this class*/
338         if (this->slot>((classinfo*)this->declaringClass)->fieldscount) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
339                                                                           "declaring class: fieldscount mismatch");
340 #endif
341         fid=&((classinfo*)this->declaringClass)->fields[this->slot]; /*get field*/
342
343         CHECKFIELDACCESS(this,fid,c,return 0);
344 #ifdef DEBUG
345         /* check if the field really has the same name and check if the type descriptor is not empty*/
346         if (fid->name!=javastring_toutf(this->name,false)) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
347                                                                           "declaring class: field name mismatch");
348         if (fid->descriptor->blength<1) panic("Type-Descriptor is empty");
349 #endif
350         /* check if obj would be needed (not static field), but is 0)*/
351         if ((!(fid->flags & ACC_STATIC)) && (obj==0)) {
352                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
353                 return 0;
354         }
355         
356         /* if (!(fid->flags & ACC_PUBLIC)) {
357                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
358                 return 0;
359
360         }*/
361
362         if (fid->flags & ACC_STATIC) {
363                 /* initialize class if needed*/
364                 fprintf("calling initialize_class %s\n",((classinfo*) this->declaringClass)->name->text);
365                 initialize_class((classinfo *) this->declaringClass);
366                 if (*exceptionptr) return 0;
367                 /*return value*/
368                 utf_ptr = fid->descriptor->text;
369                 switch (*utf_ptr) {
370                         case 'B': return fid->value.i;
371                         default:
372                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
373                                 return 0;
374                 }
375         } else {
376                 if (!builtin_instanceof((java_objectheader*)obj,(classinfo*)this->declaringClass)) {
377                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
378                                 return 0;
379                 }
380                 utf_ptr = fid->descriptor->text;
381                 switch (*utf_ptr) {
382                         case 'B':return getField(obj,jbyte,fid);
383                         default:
384                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
385                                 return 0;
386                 }
387         }
388 }
389
390
391 /*
392  * Class:     java/lang/reflect/Field
393  * Method:    getChar
394  * Signature: (Ljava/lang/Object;)C
395  */
396 JNIEXPORT s4 JNICALL Java_java_lang_reflect_Field_getChar(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj)
397 {
398         jfieldID fid;
399         char *utf_ptr;
400         classinfo *c = (classinfo *) this->declaringClass;
401
402 #ifdef DEBUG
403         /* check if the specified slot could be a valid field of this class*/
404         if (this->slot>((classinfo*)this->declaringClass)->fieldscount) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
405                                                                           "declaring class: fieldscount mismatch");
406 #endif
407         fid=&((classinfo*)this->declaringClass)->fields[this->slot]; /*get field*/
408         CHECKFIELDACCESS(this,fid,c,return 0);
409
410 #ifdef DEBUG
411         /* check if the field really has the same name and check if the type descriptor is not empty*/
412         if (fid->name!=javastring_toutf(this->name,false)) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
413                                                                           "declaring class: field name mismatch");
414         if (fid->descriptor->blength<1) panic("Type-Descriptor is empty");
415 #endif
416         /* check if obj would be needed (not static field), but is 0)*/
417         if ((!(fid->flags & ACC_STATIC)) && (obj==0)) {
418                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
419                 return 0;
420         }
421         
422         /*if (!(fid->flags & ACC_PUBLIC)) {
423                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
424                 return 0;
425
426         }*/
427
428         if (fid->flags & ACC_STATIC) {
429                 /* initialize class if needed*/
430                 fprintf("calling initialize_class %s\n",((classinfo*) this->declaringClass)->name->text);
431                 initialize_class((classinfo *) this->declaringClass);
432                 if (*exceptionptr) return 0;
433                 /*return value*/
434                 utf_ptr = fid->descriptor->text;
435                 switch (*utf_ptr) { 
436                         case 'C': return fid->value.i;
437                         default:
438                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
439                                 return 0;
440                 }
441         } else {
442                 if (!builtin_instanceof((java_objectheader*)obj,(classinfo*)this->declaringClass)) {
443                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
444                                 return 0;
445                 }
446                 utf_ptr = fid->descriptor->text;
447                 switch (*utf_ptr) {
448                         case 'C':return getField(obj,jchar,fid);
449                         default:
450                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
451                                 return 0;
452                 }
453         }
454 }
455
456
457 /*
458  * Class:     java/lang/reflect/Field
459  * Method:    getDouble
460  * Signature: (Ljava/lang/Object;)D
461  */
462 JNIEXPORT double JNICALL Java_java_lang_reflect_Field_getDouble(JNIEnv *env , java_lang_reflect_Field *this, java_lang_Object *obj)
463 {
464         jfieldID fid;
465         char *utf_ptr;
466         classinfo *c = (classinfo *) this->declaringClass;
467
468 #ifdef DEBUG
469         /* check if the specified slot could be a valid field of this class*/
470         if (this->slot>((classinfo*)this->declaringClass)->fieldscount) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
471                                                                           "declaring class: fieldscount mismatch");
472 #endif
473         fid=&((classinfo*)this->declaringClass)->fields[this->slot]; /*get field*/
474         CHECKFIELDACCESS(this,fid,c,return 0);
475
476 #ifdef DEBUG
477         /* check if the field really has the same name and check if the type descriptor is not empty*/
478         if (fid->name!=javastring_toutf(this->name,false)) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
479                                                                           "declaring class: field name mismatch");
480         if (fid->descriptor->blength<1) panic("Type-Descriptor is empty");
481 #endif
482         /* check if obj would be needed (not static field), but is 0)*/
483         if ((!(fid->flags & ACC_STATIC)) && (obj==0)) {
484                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
485                 return 0;
486         }
487         
488         /*if (!(fid->flags & ACC_PUBLIC)) {
489                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
490                 return 0;
491
492         }*/
493
494         if (fid->flags & ACC_STATIC) {
495                 /* initialize class if needed*/
496                 fprintf("calling initialize_class %s\n",((classinfo*) this->declaringClass)->name->text);
497                 initialize_class((classinfo *) this->declaringClass);
498                 if (*exceptionptr) return 0;
499                 /*return value*/
500                 utf_ptr = fid->descriptor->text;
501                 switch (*utf_ptr) {
502                         case 'B':
503                         case 'S': 
504                         case 'C': 
505                         case 'I': return fid->value.i;
506                         case 'F': return fid->value.f;
507                         case 'D': return fid->value.d;
508                         default:
509                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
510                                 return 0;
511                 }
512         } else {
513                 if (!builtin_instanceof((java_objectheader*)obj,(classinfo*)this->declaringClass)) {
514                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
515                                 return 0;
516                 }
517                 utf_ptr = fid->descriptor->text;
518                 switch (*utf_ptr) {
519                         case 'B':return getField(obj,jbyte,fid);
520                         case 'S':return getField(obj,jshort,fid);
521                         case 'C':return getField(obj,jchar,fid);
522                         case 'I':return getField(obj,jint,fid);
523                         case 'D':return getField(obj,jdouble,fid);
524                         default:
525                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
526                                 return 0;
527                 }
528         }
529 }
530
531
532 /*
533  * Class:     java/lang/reflect/Field
534  * Method:    getFloat
535  * Signature: (Ljava/lang/Object;)F
536  */
537 JNIEXPORT float JNICALL Java_java_lang_reflect_Field_getFloat(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj)
538 {
539         jfieldID fid;
540         char *utf_ptr;
541         classinfo *c = (classinfo *) this->declaringClass;
542
543 #ifdef DEBUG
544         /* check if the specified slot could be a valid field of this class*/
545         if (this->slot>((classinfo*)this->declaringClass)->fieldscount) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
546                                                                           "declaring class: fieldscount mismatch");
547 #endif
548         fid=&((classinfo*)this->declaringClass)->fields[this->slot]; /*get field*/
549         CHECKFIELDACCESS(this,fid,c,return 0);
550
551 #ifdef DEBUG
552         /* check if the field really has the same name and check if the type descriptor is not empty*/
553         if (fid->name!=javastring_toutf(this->name,false)) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
554                                                                           "declaring class: field name mismatch");
555         if (fid->descriptor->blength<1) panic("Type-Descriptor is empty");
556 #endif
557         /* check if obj would be needed (not static field), but is 0)*/
558         if ((!(fid->flags & ACC_STATIC)) && (obj==0)) {
559                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
560                 return 0;
561         }
562         
563         /*if (!(fid->flags & ACC_PUBLIC)) {
564                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
565                 return 0;
566
567         }*/
568
569         if (fid->flags & ACC_STATIC) {
570                 /* initialize class if needed*/
571                 fprintf("calling initialize_class %s\n",((classinfo*) this->declaringClass)->name->text);
572                 initialize_class((classinfo *) this->declaringClass);
573                 if (*exceptionptr) return 0;
574                 /*return value*/
575                 utf_ptr = fid->descriptor->text;
576                 switch (*utf_ptr) {
577                         case 'B':
578                         case 'S': 
579                         case 'C': 
580                         case 'I': return fid->value.i;
581                         case 'F': return fid->value.f;
582                         default:
583                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
584                                 return 0;
585                 }
586         } else {
587                 if (!builtin_instanceof((java_objectheader*)obj,(classinfo*)this->declaringClass)) {
588                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
589                                 return 0;
590                 }
591                 utf_ptr = fid->descriptor->text;
592                 switch (*utf_ptr) {
593                         case 'B':return getField(obj,jbyte,fid);
594                         case 'S':return getField(obj,jshort,fid);
595                         case 'C':return getField(obj,jchar,fid);
596                         case 'I':return getField(obj,jint,fid);
597                         case 'F':return getField(obj,jfloat,fid);
598                         default:
599                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
600                                 return 0;
601                 }
602         }
603 }
604
605
606 /*
607  * Class:     java/lang/reflect/Field
608  * Method:    getInt
609  * Signature: (Ljava/lang/Object;)I
610  */
611 JNIEXPORT s4 JNICALL Java_java_lang_reflect_Field_getInt(JNIEnv *env , java_lang_reflect_Field *this, java_lang_Object *obj)
612 {
613         jfieldID fid;
614         char *utf_ptr;
615         classinfo *c = (classinfo *) this->declaringClass;
616
617 #ifdef DEBUG
618         /* check if the specified slot could be a valid field of this class*/
619         if (this->slot>((classinfo*)this->declaringClass)->fieldscount) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
620                                                                           "declaring class: fieldscount mismatch");
621 #endif
622         fid=&((classinfo*)this->declaringClass)->fields[this->slot]; /*get field*/
623         CHECKFIELDACCESS(this,fid,c,return 0);
624 #ifdef DEBUG
625         /* check if the field really has the same name and check if the type descriptor is not empty*/
626         if (fid->name!=javastring_toutf(this->name,false)) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
627                                                                           "declaring class: field name mismatch");
628         if (fid->descriptor->blength<1) panic("Type-Descriptor is empty");
629 #endif
630         /* check if obj would be needed (not static field), but is 0)*/
631         if ((!(fid->flags & ACC_STATIC)) && (obj==0)) {
632                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
633                 return 0;
634         }
635         
636         /*if (!(fid->flags & ACC_PUBLIC)) {
637                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
638                 return 0;
639
640         } */
641
642         if (fid->flags & ACC_STATIC) {
643                 /* initialize class if needed*/
644                 fprintf("calling initialize_class %s\n",((classinfo*) this->declaringClass)->name->text);
645                 initialize_class((classinfo *) this->declaringClass);
646                 if (*exceptionptr) return 0;
647                 /*return value*/
648                 utf_ptr = fid->descriptor->text;
649                 switch (*utf_ptr) {
650                         case 'B':
651                         case 'S': 
652                         case 'C': 
653                         case 'I': return fid->value.i;
654                         default:
655                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
656                                 return 0;
657                 }
658         } else {
659                 if (!builtin_instanceof((java_objectheader*)obj,(classinfo*)this->declaringClass)) {
660                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
661                                 return 0;
662                 }
663                 utf_ptr = fid->descriptor->text;
664                 switch (*utf_ptr) {
665                         case 'B':return getField(obj,jbyte,fid);
666                         case 'S':return getField(obj,jshort,fid);
667                         case 'C':return getField(obj,jchar,fid);
668                         case 'I':return getField(obj,jint,fid);
669                         default:
670                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
671                                 return 0;
672                 }
673         }
674 }
675
676
677 /*
678  * Class:     java/lang/reflect/Field
679  * Method:    getLong
680  * Signature: (Ljava/lang/Object;)J
681  */
682 JNIEXPORT s8 JNICALL Java_java_lang_reflect_Field_getLong(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj)
683 {
684         jfieldID fid;
685         char *utf_ptr;
686         classinfo *c = (classinfo *) this->declaringClass;
687
688 #ifdef DEBUG
689         /* check if the specified slot could be a valid field of this class*/
690         if (this->slot>((classinfo*)this->declaringClass)->fieldscount) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
691                                                                           "declaring class: fieldscount mismatch");
692 #endif
693         fid=&((classinfo*)this->declaringClass)->fields[this->slot]; /*get field*/
694         CHECKFIELDACCESS(this,fid,c,return 0);
695
696 #ifdef DEBUG
697         /* check if the field really has the same name and check if the type descriptor is not empty*/
698         if (fid->name!=javastring_toutf(this->name,false)) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
699                                                                           "declaring class: field name mismatch");
700         if (fid->descriptor->blength<1) panic("Type-Descriptor is empty");
701 #endif
702         /* check if obj would be needed (not static field), but is 0)*/
703         if ((!(fid->flags & ACC_STATIC)) && (obj==0)) {
704                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
705                 return 0;
706         }
707         
708         /*if (!(fid->flags & ACC_PUBLIC)) {
709                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
710                 return 0;
711
712         }*/
713
714         if (fid->flags & ACC_STATIC) {
715                 /* initialize class if needed*/
716                 fprintf("calling initialize_class %s\n",((classinfo*) this->declaringClass)->name->text);
717                 initialize_class((classinfo *) this->declaringClass);
718                 if (*exceptionptr) return 0;
719                 /*return value*/
720                 utf_ptr = fid->descriptor->text;
721                 switch (*utf_ptr) {
722                         case 'B':
723                         case 'S': 
724                         case 'C': 
725                         case 'I': return fid->value.i;
726                         case 'J': return fid->value.l;
727                         default:
728                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
729                                 return 0;
730                 }
731         } else {
732                 if (!builtin_instanceof((java_objectheader*)obj,(classinfo*)this->declaringClass)) {
733                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
734                                 return 0;
735                 }
736                 utf_ptr = fid->descriptor->text;
737                 switch (*utf_ptr) {
738                         case 'B':return getField(obj,jbyte,fid);
739                         case 'S':return getField(obj,jshort,fid);
740                         case 'C':return getField(obj,jchar,fid);
741                         case 'I':return getField(obj,jint,fid);
742                         case 'J':return getField(obj,jlong,fid);
743                         default:
744                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
745                                 return 0;
746                 }
747         }
748 }
749
750
751 /*
752  * Class:     java/lang/reflect/Field
753  * Method:    getShort
754  * Signature: (Ljava/lang/Object;)S
755  */
756 JNIEXPORT s4 JNICALL Java_java_lang_reflect_Field_getShort(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj)
757 {
758         jfieldID fid;
759         char *utf_ptr;
760         classinfo *c = (classinfo *) this->declaringClass;
761
762 #ifdef DEBUG
763         /* check if the specified slot could be a valid field of this class*/
764         if (this->slot>((classinfo*)this->declaringClass)->fieldscount) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
765                                                                           "declaring class: fieldscount mismatch");
766 #endif
767         fid=&((classinfo*)this->declaringClass)->fields[this->slot]; /*get field*/
768         CHECKFIELDACCESS(this,fid,c,return 0);
769
770 #ifdef DEBUG
771         /* check if the field really has the same name and check if the type descriptor is not empty*/
772         if (fid->name!=javastring_toutf(this->name,false)) throw_cacao_exception_exit(string_java_lang_IncompatibleClassChangeError,
773                                                                           "declaring class: field name mismatch");
774         if (fid->descriptor->blength<1) panic("Type-Descriptor is empty");
775 #endif
776         /* check if obj would be needed (not static field), but is 0)*/
777         if ((!(fid->flags & ACC_STATIC)) && (obj==0)) {
778                 *exceptionptr = new_exception(string_java_lang_NullPointerException);
779                 return 0;
780         }
781         
782         /*if (!(fid->flags & ACC_PUBLIC)) {
783                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
784                 return 0;
785
786         }*/
787
788         if (fid->flags & ACC_STATIC) {
789                 /* initialize class if needed*/
790                 fprintf("calling initialize_class %s\n",((classinfo*) this->declaringClass)->name->text);
791                 initialize_class((classinfo *) this->declaringClass);
792                 if (*exceptionptr) return 0;
793                 /*return value*/
794                 utf_ptr = fid->descriptor->text;
795                 switch (*utf_ptr) {
796                         case 'B':
797                         case 'S': return fid->value.i;
798                         default:
799                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
800                                 return 0;
801                 }
802         } else {
803                 if (!builtin_instanceof((java_objectheader*)obj,(classinfo*)this->declaringClass)) {
804                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
805                                 return 0;
806                 }
807                 utf_ptr = fid->descriptor->text;
808                 switch (*utf_ptr) {
809                         case 'B':return getField(obj,jbyte,fid);
810                         case 'S':return getField(obj,jshort,fid);
811                         default:
812                                 *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
813                                 return 0;
814                 }
815         }
816 }
817
818
819 /*
820  * Class:     java/lang/reflect/Field
821  * Method:    set
822  * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V
823  */
824 JNIEXPORT void JNICALL Java_java_lang_reflect_Field_set(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj, java_lang_Object *val)
825 {
826         jfieldID source_fid;  /* the field containing the value to be written */
827         jfieldID fid;         /* the field to be written */
828         classinfo *c;
829         int st;
830
831         fid = class_findfield_approx((classinfo *) this->declaringClass,
832                                                                  javastring_toutf(this->name, false));
833         st = (fid->flags & ACC_STATIC); /* true if the field is static */
834         CHECKFIELDACCESS(this,fid,((classinfo *) this->declaringClass),return);
835
836         if (val && (st || obj)) {
837
838                 c = val->header.vftbl->class;
839
840                 /* The fieldid is used to set the new value, for primitive types the value
841                    has to be retrieved from the wrapping object */  
842                 switch ((((classinfo *) this->declaringClass)->fields[this->slot]).descriptor->text[0]) {
843                 case 'I':
844                         /* illegal argument specified */
845                         if (c != class_java_lang_Integer)
846                                 break;
847                         /* determine the field to read the value */
848                         source_fid = (*env)->GetFieldID(env, c, "value", "I");
849                         if (!source_fid)
850                                 break;
851                                    
852                         /* set the new value */
853                         if (st)
854                         /* static field */
855                                 (*env)->SetStaticIntField(env, c, fid, GetIntField(env, (jobject) val, source_fid));
856                         else
857                                 /* instance field */
858                                 (*env)->SetIntField(env, (jobject) obj, fid, GetIntField(env, (jobject) val, source_fid));
859
860                         return;
861
862                 case 'J':
863                         if (c != class_java_lang_Long)
864                                 break;
865                         source_fid = (*env)->GetFieldID(env, c, "value", "J");
866                         if (!source_fid)
867                                 break;
868                                    
869                         if (st)
870                                 (*env)->SetStaticLongField(env, c, fid, GetLongField(env, (jobject) val, source_fid));
871                         else
872                                 (*env)->SetLongField(env, (jobject) obj, fid, GetLongField(env, (jobject) val, source_fid));
873
874                         return;
875
876                 case 'F':
877                         if (c != class_java_lang_Float)
878                                 break;
879                         source_fid = (*env)->GetFieldID(env, c, "value", "F");
880                         if (!source_fid)
881                                 break;
882                                    
883                         if (st)
884                                 (*env)->SetStaticFloatField(env, c, fid, GetFloatField(env, (jobject) val, source_fid));
885                         else
886                                 (*env)->SetFloatField(env, (jobject) obj, fid, GetFloatField(env, (jobject) val, source_fid));
887
888                         return;
889
890                 case 'D':
891                         if (c != class_java_lang_Double)
892                                 break;
893                         source_fid = (*env)->GetFieldID(env, c, "value", "D");
894                         if (!source_fid) break;
895                                    
896                         if (st)
897                                 (*env)->SetStaticDoubleField(env, c, fid, GetDoubleField(env,(jobject) val,source_fid));
898                         else
899                                 (*env)->SetDoubleField(env, (jobject) obj, fid, GetDoubleField(env,(jobject) val,source_fid));
900
901                         return;
902
903                 case 'B':
904                         if (c != class_java_lang_Byte)
905                                 break;
906                         source_fid = (*env)->GetFieldID(env, c, "value", "B");
907                         if (!source_fid)
908                                 break;
909                                    
910                         if (st)
911                                 (*env)->SetStaticByteField(env, c, fid, GetByteField(env, (jobject) val, source_fid));
912                         else
913                                 (*env)->SetByteField(env, (jobject) obj, fid, GetByteField(env, (jobject) val, source_fid));
914
915                         return;
916
917                 case 'C':
918                         if (c != class_java_lang_Character)
919                                 break;
920                         source_fid = (*env)->GetFieldID(env, c, "value", "C");
921                         if (!source_fid)
922                                 break;
923                                    
924                         if (st)
925                                 (*env)->SetStaticCharField(env, c, fid, GetCharField(env, (jobject) val, source_fid));
926                         else
927                                 (*env)->SetCharField(env, (jobject) obj, fid, GetCharField(env, (jobject) val, source_fid));
928
929                         return;
930
931                 case 'S':
932                         if (c != class_java_lang_Short)
933                                 break;
934                         source_fid = (*env)->GetFieldID(env, c, "value", "S");
935                         if (!source_fid)
936                                 break;
937                                    
938                         if (st)
939                                 (*env)->SetStaticShortField(env, c, fid, GetShortField(env, (jobject) val, source_fid));
940                         else
941                                 (*env)->SetShortField(env, (jobject) obj, fid, GetShortField(env, (jobject) val, source_fid));
942
943                         return;
944
945                 case 'Z':
946                         if (c != class_java_lang_Boolean)
947                                 break;
948                         source_fid = (*env)->GetFieldID(env, c, "value", "Z");
949                         if (!source_fid)
950                                 break;
951                                    
952                         if (st)
953                                 (*env)->SetStaticBooleanField(env, c, fid, GetBooleanField(env, (jobject) val, source_fid));
954                         else
955                                 (*env)->SetBooleanField(env, (jobject) obj, fid, GetBooleanField(env, (jobject) val, source_fid));
956
957                         return;
958
959                 case '[':
960                 case 'L':
961                         if (st)
962                                 (*env)->SetStaticObjectField(env, c, fid, (jobject) val);
963                         else
964                                 (*env)->SetObjectField(env, (jobject) obj, fid, (jobject) val);
965
966                         return;
967                 }
968         }
969
970         /* raise exception */
971         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
972 }
973
974
975 /*
976  * Class:     java/lang/reflect/Field
977  * Method:    setBoolean
978  * Signature: (Ljava/lang/Object;Z)V
979  */
980 JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setBoolean(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj, s4 val)
981 {
982         jfieldID fid;
983
984         if (this->declaringClass && obj) {
985                 fid = class_findfield_approx((classinfo *) this->declaringClass,
986                                                                          javastring_toutf(this->name, false));
987
988                 if (fid) {
989                         (*env)->SetBooleanField(env, (jobject) obj, fid, val);
990                         return;
991                 }
992         }
993
994         /* raise exception */
995         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
996 }
997
998
999 /*
1000  * Class:     java/lang/reflect/Field
1001  * Method:    setByte
1002  * Signature: (Ljava/lang/Object;B)V
1003  */
1004 JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setByte(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj, s4 val)
1005 {
1006         jfieldID fid;
1007
1008         if (this->declaringClass && obj) {
1009                 fid = class_findfield_approx((classinfo *) this->declaringClass,
1010                                                                          javastring_toutf(this->name, false));
1011
1012                 if (fid) {
1013                         (*env)->SetByteField(env, (jobject) obj, fid, val);
1014                         return;
1015                 }
1016         }
1017
1018         /* raise exception */
1019         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
1020 }
1021
1022
1023 /*
1024  * Class:     java/lang/reflect/Field
1025  * Method:    setChar
1026  * Signature: (Ljava/lang/Object;C)V
1027  */
1028 JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setChar(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj, s4 val)
1029 {
1030         jfieldID fid;
1031
1032         if (this->declaringClass && obj) {
1033                 fid = class_findfield_approx((classinfo *) this->declaringClass,
1034                                                                          javastring_toutf(this->name, false));
1035
1036                 if (fid) {
1037                         (*env)->SetCharField(env, (jobject) obj, fid, val);
1038                         return;
1039                 }
1040         }
1041
1042         /* raise exception */
1043         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
1044 }
1045
1046
1047 /*
1048  * Class:     java/lang/reflect/Field
1049  * Method:    setDouble
1050  * Signature: (Ljava/lang/Object;D)V
1051  */
1052 JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setDouble(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj, double val)
1053 {
1054         jfieldID fid;
1055
1056         if (this->declaringClass && obj) {
1057                 fid = class_findfield_approx((classinfo *) this->declaringClass,
1058                                                                          javastring_toutf(this->name, false));
1059
1060                 if (fid) {
1061                         (*env)->SetDoubleField(env, (jobject) obj, fid, val);
1062                         return;
1063                 } 
1064         }
1065
1066         /* raise exception */
1067         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
1068 }
1069
1070
1071 /*
1072  * Class:     java/lang/reflect/Field
1073  * Method:    setFloat
1074  * Signature: (Ljava/lang/Object;F)V
1075  */
1076 JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setFloat(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj, float val)
1077 {
1078         jfieldID fid;
1079
1080         if (this->declaringClass && obj) {
1081                 fid = class_findfield_approx((classinfo *) this->declaringClass,
1082                                                                          javastring_toutf(this->name, false));
1083
1084                 if (fid) {
1085                         (*env)->SetFloatField(env, (jobject) obj, fid, val);
1086                         return;
1087                 }
1088         }
1089
1090         /* raise exception */
1091         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
1092 }
1093
1094
1095 /*
1096  * Class:     java/lang/reflect/Field
1097  * Method:    setInt
1098  * Signature: (Ljava/lang/Object;I)V
1099  */
1100 JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setInt(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj, s4 val)
1101 {
1102         jfieldID fid;
1103
1104         if (this->declaringClass && obj) {
1105                 fid = class_findfield_approx((classinfo *) this->declaringClass,
1106                                                                          javastring_toutf(this->name, false));
1107
1108                 if (fid) {
1109                         (*env)->SetIntField(env, (jobject) obj, fid, val);
1110                         return;
1111                 }
1112         }
1113
1114         /* raise exception */
1115         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
1116 }
1117
1118
1119 /*
1120  * Class:     java/lang/reflect/Field
1121  * Method:    setLong
1122  * Signature: (Ljava/lang/Object;J)V
1123  */
1124 JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setLong(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj, s8 val)
1125 {
1126         jfieldID fid;
1127
1128         if (this->declaringClass && obj) {
1129                 fid = class_findfield_approx((classinfo *) this->declaringClass,
1130                                                                          javastring_toutf(this->name, false));
1131
1132                 if (fid) {
1133                         (*env)->SetLongField(env, (jobject) obj, fid, val);
1134                         return;
1135                 }
1136         }
1137
1138         /* raise exception */
1139         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
1140 }
1141
1142
1143 /*
1144  * Class:     java/lang/reflect/Field
1145  * Method:    setShort
1146  * Signature: (Ljava/lang/Object;S)V
1147  */
1148 JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setShort(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *obj, s4 val)
1149 {
1150         jfieldID fid;
1151
1152         if (this->declaringClass && obj) {
1153                 fid = class_findfield_approx((classinfo *) this->declaringClass,
1154                                                                          javastring_toutf(this->name, false));
1155
1156                 if (fid) {
1157                         (*env)->SetShortField(env, (jobject) obj, fid, val);
1158                         return;
1159                 }
1160         }
1161
1162         /* raise exception */
1163         *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
1164 }
1165
1166
1167 /*
1168  * Class:     java_lang_reflect_Field
1169  * Method:    getType
1170  * Signature: ()Ljava/lang/Class;
1171  */
1172 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_reflect_Field_getType(JNIEnv *env, java_lang_reflect_Field *this)
1173 {
1174         typedesc *desc = (((classinfo *) this->declaringClass)->fields[this->slot]).parseddesc;
1175         java_lang_Class *ret;
1176         if (!desc)
1177                 return NULL;
1178
1179         if (!resolve_class_from_typedesc(desc,false,(classinfo **)&ret))
1180                 return NULL; /* exception */
1181         
1182         use_class_as_object((classinfo*)ret);
1183         return ret;
1184 }
1185
1186
1187 /*
1188  * Class:     java_lang_reflect_Field
1189  * Method:    getModifiers
1190  * Signature: ()I
1191  */
1192 JNIEXPORT s4 JNICALL Java_java_lang_reflect_Field_getModifiers(JNIEnv *env, java_lang_reflect_Field *this)
1193 {
1194         return (((classinfo *) this->declaringClass)->fields[this->slot]).flags;
1195 }
1196
1197
1198 /*
1199  * These are local overrides for various environment variables in Emacs.
1200  * Please do not remove this and leave it at the end of the file, where
1201  * Emacs will automagically detect them.
1202  * ---------------------------------------------------------------------
1203  * Local variables:
1204  * mode: c
1205  * indent-tabs-mode: t
1206  * c-basic-offset: 4
1207  * tab-width: 4
1208  * End:
1209  */