* src/native/vm/reflect.c (reflect_field_new): Fixed compilation.
[cacao.git] / src / native / vm / reflect.c
1 /* src/native/vm/reflect.c - helper functions for java/lang/reflect
2
3    Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: reflect.c 8289 2007-08-10 15:18:05Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <stdint.h>
33
34 #if defined(ENABLE_ANNOTATIONS)
35 #include "mm/memory.h"
36
37 #if defined(WITH_CLASSPATH_GNU)
38 #include "vm/vm.h"
39
40 #include "native/include/sun_reflect_ConstantPool.h"
41 #endif
42 #endif
43
44 #include "native/jni.h"
45 #include "native/llni.h"
46 #include "native/native.h"
47
48 /* keep this order of the native includes */
49
50 #include "native/include/java_lang_String.h"
51
52 #if defined(WITH_CLASSPATH_SUN)
53 # include "native/include/java_nio_ByteBuffer.h"        /* required by j.l.CL */
54 #endif
55 #include "native/include/java_lang_ClassLoader.h"
56
57 #include "native/include/java_lang_Object.h"
58 #include "native/include/java_lang_Class.h"
59 #include "native/include/java_lang_reflect_Constructor.h"
60 #include "native/include/java_lang_reflect_Field.h"
61 #include "native/include/java_lang_reflect_Method.h"
62
63 #include "native/vm/java_lang_String.h"
64 #include "native/vm/reflect.h"
65
66 #include "vm/builtin.h"
67 #include "vm/global.h"
68 #include "vm/stringlocal.h"
69
70 #include "vmcore/method.h"
71
72
73 /* reflect_constructor_new *****************************************************
74
75    Allocates a new java.lang.reflect.Constructor object and
76    initializes the fields with the method passed.
77
78 *******************************************************************************/
79
80 java_lang_reflect_Constructor *reflect_constructor_new(methodinfo *m)
81 {
82         classinfo                     *c;
83         java_objectheader             *o;
84         java_lang_reflect_Constructor *rc;
85         int32_t                        slot;
86         java_bytearray                *annotations          = NULL;
87         java_bytearray                *parameterAnnotations = NULL;
88         annotation_bytearray_t        *ba                   = NULL;
89
90 #if defined(ENABLE_ANNOTATIONS)
91         /* get annotations */
92         ba = method_get_annotations(m);
93
94         if (ba != NULL) {
95                 annotations = builtin_newarray_byte(ba->size);
96
97                 if (annotations == NULL)
98                         return NULL;
99                 
100                 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
101         }
102         
103         /* get parameter annotations */
104         ba = method_get_parameterannotations(m);
105
106         if (ba != NULL) {
107                 parameterAnnotations = builtin_newarray_byte(ba->size);
108
109                 if (parameterAnnotations == NULL)
110                         return NULL;
111                 
112                 MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
113         }
114 #endif
115
116         /* get declaring class */
117
118         c = (classinfo *) m->class;
119
120         /* allocate a new object */
121
122         o = builtin_new(class_java_lang_reflect_Constructor);
123
124         if (o == NULL)
125                 return NULL;
126
127         /* initialize instance fields */
128
129         rc = (java_lang_reflect_Constructor *) o;
130
131         /* calculate the slot */
132
133         slot = m - c->methods;
134
135 #if defined(WITH_CLASSPATH_GNU)
136
137         LLNI_field_set_cls(rc, clazz               , c);
138         LLNI_field_set_val(rc, slot                , slot);
139
140         /* TODO: add these private fields to java.lang.reflect.Constructor
141         LLNI_field_set_ref(rc, annotations         , annotations);
142         LLNI_field_set_ref(rc, parameterAnnotations, parameterAnnotations);
143         */
144
145 #elif defined(WITH_CLASSPATH_SUN)
146
147         LLNI_field_set_cls(rc, clazz               , c);
148         LLNI_field_set_ref(rc, parameterTypes      , method_get_parametertypearray(m));
149         LLNI_field_set_ref(rc, exceptionTypes      , method_get_exceptionarray(m));
150         LLNI_field_set_val(rc, modifiers           , m->flags & ACC_CLASS_REFLECT_MASK);
151         LLNI_field_set_val(rc, slot                , slot);
152         LLNI_field_set_ref(rc, signature           , m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL);
153         LLNI_field_set_ref(rc, annotations         , annotations);
154         LLNI_field_set_ref(rc, parameterAnnotations, parameterAnnotations);
155
156 #else
157 # error unknown classpath configuration
158 #endif
159
160         return rc;
161 }
162
163
164 /* reflect_field_new ***********************************************************
165
166    Allocates a new java.lang.reflect.Field object and initializes the
167    fields with the field passed.
168
169 *******************************************************************************/
170
171 java_lang_reflect_Field *reflect_field_new(fieldinfo *f)
172 {
173         classinfo               *c;
174         java_objectheader       *o;
175         java_lang_reflect_Field *rf;
176         int32_t                  slot;
177         java_bytearray          *annotations = NULL;
178         annotation_bytearray_t  *ba          = NULL;
179
180 #if defined(ENABLE_ANNOTATIONS)
181         /* get annotations */
182         ba = field_get_annotations(f);
183
184         if (ba != NULL) {
185                 annotations = builtin_newarray_byte(ba->size);
186
187                 if (annotations == NULL)
188                         return NULL;
189                 
190                 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
191         }
192 #endif
193
194         /* get declaring class */
195
196         c = (classinfo *) f->class;
197
198         /* allocate a new object */
199
200         o = builtin_new(class_java_lang_reflect_Field);
201
202         if (o == NULL)
203                 return NULL;
204
205         /* initialize instance fields */
206
207         rf = (java_lang_reflect_Field *) o;
208
209         /* calculate the slot */
210
211         slot = f - c->fields;
212
213 #if defined(WITH_CLASSPATH_GNU)
214
215         LLNI_field_set_cls(rf, clazz         , c);
216
217         /* The name needs to be interned */
218         /* XXX implement me better! */
219
220         LLNI_field_set_ref(rf, name          , _Jv_java_lang_String_intern((java_lang_String *) javastring_new(f->name)));
221         LLNI_field_set_val(rf, slot          , slot);
222         LLNI_field_set_ref(rf, annotations   , annotations);
223
224 #elif defined(WITH_CLASSPATH_SUN)
225
226         LLNI_field_set_cls(rf, clazz         , c);
227
228         /* The name needs to be interned */
229         /* XXX implement me better! */
230
231         LLNI_field_set_ref(rf, name          , _Jv_java_lang_String_intern((java_lang_String *) javastring_new(f->name)));
232         LLNI_field_set_cls(rf, type          , (java_lang_Class *) field_get_type(f));
233         LLNI_field_set_val(rf, modifiers     , f->flags);
234         LLNI_field_set_val(rf, slot          , slot);
235         LLNI_field_set_ref(rf, signature     , f->signature ? (java_lang_String *) javastring_new(f->signature) : NULL);
236         LLNI_field_set_ref(rf, annotations   , annotations);
237
238 #else
239 # error unknown classpath configuration
240 #endif
241
242         return rf;
243 }
244
245
246 /* reflect_method_new **********************************************************
247
248    Allocates a new java.lang.reflect.Method object and initializes the
249    fields with the method passed.
250
251 *******************************************************************************/
252
253 java_lang_reflect_Method *reflect_method_new(methodinfo *m)
254 {
255         classinfo                *c;
256         java_objectheader        *o;
257         java_lang_reflect_Method *rm;
258         int32_t                   slot;
259         java_bytearray           *annotations          = NULL;
260         java_bytearray           *parameterAnnotations = NULL;
261         java_bytearray           *annotationDefault    = NULL;
262         annotation_bytearray_t   *ba                   = NULL;
263
264 #if defined(ENABLE_ANNOTATIONS)
265         /* get annotations */
266         ba = method_get_annotations(m);
267
268         if (ba != NULL) {
269                 annotations = builtin_newarray_byte(ba->size);
270
271                 if (annotations == NULL)
272                         return NULL;
273                 
274                 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
275         }
276         
277         /* get parameter annotations */
278         ba = method_get_parameterannotations(m);
279
280         if (ba != NULL) {
281                 parameterAnnotations = builtin_newarray_byte(ba->size);
282
283                 if (parameterAnnotations == NULL)
284                         return NULL;
285                 
286                 MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
287         }
288
289         /* get annotation default value */
290         ba = method_get_annotationdefault(m);
291
292         if (ba != NULL) {
293                 annotationDefault = builtin_newarray_byte(ba->size);
294
295                 if (annotationDefault == NULL)
296                         return NULL;
297                 
298                 MCOPY(annotationDefault->data, ba->data, uint8_t, ba->size);
299         }
300 #endif
301
302         /* get declaring class */
303
304         c = (classinfo *) m->class;
305
306         /* allocate a new object */
307
308         o = builtin_new(class_java_lang_reflect_Method);
309
310         if (o == NULL)
311                 return NULL;
312
313         /* initialize instance fields */
314
315         rm = (java_lang_reflect_Method *) o;
316
317         /* calculate the slot */
318
319         slot = m - c->methods;
320
321 #if defined(WITH_CLASSPATH_GNU)
322
323         LLNI_field_set_cls(rm, clazz               , m->class);
324
325         /* The name needs to be interned */
326         /* XXX implement me better! */
327
328         LLNI_field_set_ref(rm, name                , _Jv_java_lang_String_intern((java_lang_String *) javastring_new(m->name)));
329         LLNI_field_set_val(rm, slot                , slot);
330         LLNI_field_set_ref(rm, annotations         , annotations);
331         LLNI_field_set_ref(rm, parameterAnnotations, parameterAnnotations);
332         LLNI_field_set_ref(rm, annotationDefault   , annotationDefault);
333
334 #elif defined(WITH_CLASSPATH_SUN)
335
336         LLNI_field_set_cls(rm, clazz               , (java_lang_Class *) m->class);
337
338         /* The name needs to be interned */
339         /* XXX implement me better! */
340
341         rm->name                 = _Jv_java_lang_String_intern((java_lang_String *) javastring_new(m->name));
342         rm->parameterTypes       = method_get_parametertypearray(m);
343         rm->returnType           = (java_lang_Class *) method_returntype_get(m);
344         rm->exceptionTypes       = method_get_exceptionarray(m);
345         rm->modifiers            = m->flags & ACC_CLASS_REFLECT_MASK;
346         rm->slot                 = slot;
347         rm->signature            = m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL;
348         rm->annotations          = annotations;
349         rm->parameterAnnotations = parameterAnnotations;
350         rm->annotationDefault    = annotationDefault;
351
352 #else
353 # error unknown classpath configuration
354 #endif
355
356         return rm;
357 }
358
359
360 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
361 /* reflect_get_declaredannotatios *********************************************
362
363    Returnes a java.util.Map<Class, Annotation> of the declared
364    annotations. Only calls the AnnotationParser if the declared
365    annotations are not yet parsed.
366
367 *******************************************************************************/
368
369 struct java_util_Map* reflect_get_declaredannotatios(
370         struct java_util_Map **declaredAnnotations,
371         java_bytearray        *annotations,
372         java_lang_Class       *declaringClass,
373         classinfo             *referer)
374 {
375         static methodinfo        *m_parseAnnotations   = NULL;
376         utf                      *utf_parseAnnotations = NULL;
377         utf                      *utf_desc             = NULL;
378         sun_reflect_ConstantPool *constantPool         = NULL;
379
380         if (*declaredAnnotations == NULL) {
381                 constantPool = 
382                         (sun_reflect_ConstantPool*)native_new_and_init(
383                                 class_sun_reflect_ConstantPool);
384                 
385                 if(constantPool == NULL) {
386                         /* out of memory */
387                         return NULL;
388                 }
389                 
390                 constantPool->constantPoolOop = (java_lang_Object*)declaringClass;
391                 
392                 /* only resolve the method the first time */
393                 if (m_parseAnnotations == NULL) {
394                         utf_parseAnnotations = utf_new_char("parseAnnotations");
395                         utf_desc = utf_new_char(
396                                 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
397                                 "Ljava/util/Map;");
398         
399                         if (utf_parseAnnotations == NULL || utf_desc == NULL) {
400                                 /* out of memory */
401                                 return NULL;
402                         }
403                 
404                         m_parseAnnotations = class_resolveclassmethod(
405                                 class_sun_reflect_annotation_AnnotationParser,
406                                 utf_parseAnnotations,
407                                 utf_desc,
408                                 referer,
409                                 true);
410         
411                         if (m_parseAnnotations == NULL) {
412                                 /* method not found */
413                                 return NULL;
414                         }
415                 }
416         
417                 *declaredAnnotations =
418                         (struct java_util_Map*)vm_call_method(
419                                 m_parseAnnotations, NULL, annotations,
420                                 constantPool, declaringClass);
421         }
422         
423         return *declaredAnnotations;
424 }
425
426
427 /* reflect_get_parameterannotations *******************************************
428
429    Parses and returns the parameter annotations of a method.
430
431 *******************************************************************************/
432
433 java_objectarray* reflect_get_parameterannotations(
434         java_objectheader *parameterAnnotations,
435         int32_t            slot,
436         java_lang_Class   *declaringClass,
437         classinfo         *referer)
438 {
439         /* This method in java would be basically the following.
440          * We don't do it in java because we don't want to make a
441          * public method with wich you can get a ConstantPool, because
442          * with that you could read any kind of constants (even private
443          * ones).
444          *
445          * ConstantPool constPool = new ConstantPool();
446          * constPool.constantPoolOop = getDeclaringClass();
447          * return sun.reflect.AnnotationParser.parseParameterAnnotations(
448          *      parameterAnnotations,
449          *      constPool,
450          *      getDeclaringClass(),
451          *      getParameterTypes().length);
452          */
453         static methodinfo        *m_parseParameterAnnotations   = NULL;
454         utf                      *utf_parseParameterAnnotations = NULL;
455         utf                      *utf_desc      = NULL;
456         sun_reflect_ConstantPool *constantPool  = NULL;
457         classinfo                *c             = NULL;
458         methodinfo               *m             = NULL;
459         int32_t                   numParameters = -1;
460
461         /* get parameter count */
462
463         c = (classinfo *)declaringClass;
464         m = &(c->methods[slot]);
465
466         numParameters = method_get_parametercount(m);
467
468         if (numParameters < 0) {
469                 /* error parsing descriptor */
470                 return NULL;
471         }
472
473         /* get ConstantPool */
474
475         constantPool = 
476                 (sun_reflect_ConstantPool*)native_new_and_init(
477                         class_sun_reflect_ConstantPool);
478         
479         if(constantPool == NULL) {
480                 /* out of memory */
481                 return NULL;
482         }
483
484         constantPool->constantPoolOop = (java_lang_Object*)declaringClass;
485
486         /* only resolve the method the first time */
487         if (m_parseParameterAnnotations == NULL) {
488                 utf_parseParameterAnnotations = utf_new_char("parseParameterAnnotations");
489                 utf_desc = utf_new_char(
490                         "([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)"
491                         "[[Ljava/lang/annotation/Annotation;");
492
493                 if (utf_parseParameterAnnotations == NULL || utf_desc == NULL) {
494                         /* out of memory */
495                         return NULL;
496                 }
497
498                 /* get parser method */
499
500                 m_parseParameterAnnotations = class_resolveclassmethod(
501                         class_sun_reflect_annotation_AnnotationParser,
502                         utf_parseParameterAnnotations,
503                         utf_desc,
504                         referer,
505                         true);
506
507                 if (m_parseParameterAnnotations == NULL)
508                 {
509                         /* method not found */
510                         return NULL;
511                 }
512         }
513
514         return (java_objectarray*)vm_call_method(
515                 m_parseParameterAnnotations, NULL, parameterAnnotations,
516                 constantPool, declaringClass, numParameters);
517 }
518 #endif
519
520
521 /*
522  * These are local overrides for various environment variables in Emacs.
523  * Please do not remove this and leave it at the end of the file, where
524  * Emacs will automagically detect them.
525  * ---------------------------------------------------------------------
526  * Local variables:
527  * mode: c
528  * indent-tabs-mode: t
529  * c-basic-offset: 4
530  * tab-width: 4
531  * End:
532  * vim:noexpandtab:sw=4:ts=4:
533  */