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