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