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