9281c70d1303b28ced37226e7bc3e5d72af70e31
[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 8305 2007-08-15 13:49:26Z panzi $
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_handle_t                 *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         LLNI_field_set_ref(rc, annotations         , annotations);
140         LLNI_field_set_ref(rc, parameterAnnotations, parameterAnnotations);
141
142 #elif defined(WITH_CLASSPATH_SUN)
143
144         LLNI_field_set_cls(rc, clazz               , c);
145         LLNI_field_set_ref(rc, parameterTypes      , method_get_parametertypearray(m));
146         LLNI_field_set_ref(rc, exceptionTypes      , method_get_exceptionarray(m));
147         LLNI_field_set_val(rc, modifiers           , m->flags & ACC_CLASS_REFLECT_MASK);
148         LLNI_field_set_val(rc, slot                , slot);
149         LLNI_field_set_ref(rc, signature           , m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL);
150         LLNI_field_set_ref(rc, annotations         , annotations);
151         LLNI_field_set_ref(rc, parameterAnnotations, parameterAnnotations);
152
153 #else
154 # error unknown classpath configuration
155 #endif
156
157         return rc;
158 }
159
160
161 /* reflect_field_new ***********************************************************
162
163    Allocates a new java.lang.reflect.Field object and initializes the
164    fields with the field passed.
165
166 *******************************************************************************/
167
168 java_lang_reflect_Field *reflect_field_new(fieldinfo *f)
169 {
170         classinfo               *c;
171         java_handle_t           *o;
172         java_lang_reflect_Field *rf;
173         int32_t                  slot;
174         java_bytearray          *annotations = NULL;
175         annotation_bytearray_t  *ba          = NULL;
176
177 #if defined(ENABLE_ANNOTATIONS)
178         /* get annotations */
179         ba = field_get_annotations(f);
180
181         if (ba != NULL) {
182                 annotations = builtin_newarray_byte(ba->size);
183
184                 if (annotations == NULL)
185                         return NULL;
186                 
187                 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
188         }
189 #endif
190
191         /* get declaring class */
192
193         c = (classinfo *) f->class;
194
195         /* allocate a new object */
196
197         o = builtin_new(class_java_lang_reflect_Field);
198
199         if (o == NULL)
200                 return NULL;
201
202         /* initialize instance fields */
203
204         rf = (java_lang_reflect_Field *) o;
205
206         /* calculate the slot */
207
208         slot = f - c->fields;
209
210 #if defined(WITH_CLASSPATH_GNU)
211
212         LLNI_field_set_cls(rf, clazz         , c);
213
214         /* The name needs to be interned */
215         /* XXX implement me better! */
216
217         LLNI_field_set_ref(rf, name          , _Jv_java_lang_String_intern((java_lang_String *) javastring_new(f->name)));
218         LLNI_field_set_val(rf, slot          , slot);
219         LLNI_field_set_ref(rf, annotations   , annotations);
220
221 #elif defined(WITH_CLASSPATH_SUN)
222
223         LLNI_field_set_cls(rf, clazz         , c);
224
225         /* The name needs to be interned */
226         /* XXX implement me better! */
227
228         LLNI_field_set_ref(rf, name          , _Jv_java_lang_String_intern((java_lang_String *) javastring_new(f->name)));
229         LLNI_field_set_cls(rf, type          , (java_lang_Class *) field_get_type(f));
230         LLNI_field_set_val(rf, modifiers     , f->flags);
231         LLNI_field_set_val(rf, slot          , slot);
232         LLNI_field_set_ref(rf, signature     , f->signature ? (java_lang_String *) javastring_new(f->signature) : NULL);
233         LLNI_field_set_ref(rf, annotations   , annotations);
234
235 #else
236 # error unknown classpath configuration
237 #endif
238
239         return rf;
240 }
241
242
243 /* reflect_method_new **********************************************************
244
245    Allocates a new java.lang.reflect.Method object and initializes the
246    fields with the method passed.
247
248 *******************************************************************************/
249
250 java_lang_reflect_Method *reflect_method_new(methodinfo *m)
251 {
252         classinfo                *c;
253         java_handle_t            *o;
254         java_lang_reflect_Method *rm;
255         int32_t                   slot;
256         java_bytearray           *annotations          = NULL;
257         java_bytearray           *parameterAnnotations = NULL;
258         java_bytearray           *annotationDefault    = NULL;
259         annotation_bytearray_t   *ba                   = NULL;
260
261 #if defined(ENABLE_ANNOTATIONS)
262         /* get annotations */
263         ba = method_get_annotations(m);
264
265         if (ba != NULL) {
266                 annotations = builtin_newarray_byte(ba->size);
267
268                 if (annotations == NULL)
269                         return NULL;
270                 
271                 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
272         }
273         
274         /* get parameter annotations */
275         ba = method_get_parameterannotations(m);
276
277         if (ba != NULL) {
278                 parameterAnnotations = builtin_newarray_byte(ba->size);
279
280                 if (parameterAnnotations == NULL)
281                         return NULL;
282                 
283                 MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
284         }
285
286         /* get annotation default value */
287         ba = method_get_annotationdefault(m);
288
289         if (ba != NULL) {
290                 annotationDefault = builtin_newarray_byte(ba->size);
291
292                 if (annotationDefault == NULL)
293                         return NULL;
294                 
295                 MCOPY(annotationDefault->data, ba->data, uint8_t, ba->size);
296         }
297 #endif
298
299         /* get declaring class */
300
301         c = (classinfo *) m->class;
302
303         /* allocate a new object */
304
305         o = builtin_new(class_java_lang_reflect_Method);
306
307         if (o == NULL)
308                 return NULL;
309
310         /* initialize instance fields */
311
312         rm = (java_lang_reflect_Method *) o;
313
314         /* calculate the slot */
315
316         slot = m - c->methods;
317
318 #if defined(WITH_CLASSPATH_GNU)
319
320         LLNI_field_set_cls(rm, clazz               , m->class);
321
322         /* The name needs to be interned */
323         /* XXX implement me better! */
324
325         LLNI_field_set_ref(rm, name                , _Jv_java_lang_String_intern((java_lang_String *) javastring_new(m->name)));
326         LLNI_field_set_val(rm, slot                , slot);
327         LLNI_field_set_ref(rm, annotations         , annotations);
328         LLNI_field_set_ref(rm, parameterAnnotations, parameterAnnotations);
329         LLNI_field_set_ref(rm, annotationDefault   , annotationDefault);
330
331 #elif defined(WITH_CLASSPATH_SUN)
332
333         LLNI_field_set_cls(rm, clazz               , (java_lang_Class *) m->class);
334
335         /* The name needs to be interned */
336         /* XXX implement me better! */
337
338         rm->name                 = _Jv_java_lang_String_intern((java_lang_String *) javastring_new(m->name));
339         rm->parameterTypes       = method_get_parametertypearray(m);
340         rm->returnType           = (java_lang_Class *) method_returntype_get(m);
341         rm->exceptionTypes       = method_get_exceptionarray(m);
342         rm->modifiers            = m->flags & ACC_CLASS_REFLECT_MASK;
343         rm->slot                 = slot;
344         rm->signature            = m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL;
345         rm->annotations          = annotations;
346         rm->parameterAnnotations = parameterAnnotations;
347         rm->annotationDefault    = annotationDefault;
348
349 #else
350 # error unknown classpath configuration
351 #endif
352
353         return rm;
354 }
355
356
357 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
358 /* reflect_get_declaredannotatios *********************************************
359
360    Returns a java.util.Map<Class, Annotation> of the declared
361    annotations.
362
363 *******************************************************************************/
364
365 struct java_util_Map* reflect_get_declaredannotatios(
366         java_bytearray       *annotations,
367         java_lang_Class      *declaringClass,
368         classinfo            *referer)
369 {
370         static methodinfo        *m_parseAnnotations   = NULL;
371         utf                      *utf_parseAnnotations = NULL;
372         utf                      *utf_desc             = NULL;
373         sun_reflect_ConstantPool *constantPool         = NULL;
374         java_lang_Object         *constantPoolOop      = (java_lang_Object*)declaringClass;
375
376         constantPool = 
377                 (sun_reflect_ConstantPool*)native_new_and_init(
378                         class_sun_reflect_ConstantPool);
379                 
380         if(constantPool == NULL) {
381                 /* out of memory */
382                 return NULL;
383         }
384                 
385         LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
386                 
387         /* only resolve the method the first time */
388         if (m_parseAnnotations == NULL) {
389                 utf_parseAnnotations = utf_new_char("parseAnnotations");
390                 utf_desc = utf_new_char(
391                         "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
392                         "Ljava/util/Map;");
393
394                 if (utf_parseAnnotations == NULL || utf_desc == NULL) {
395                         /* out of memory */
396                         return NULL;
397                 }
398                 
399                 m_parseAnnotations = class_resolveclassmethod(
400                         class_sun_reflect_annotation_AnnotationParser,
401                         utf_parseAnnotations,
402                         utf_desc,
403                         referer,
404                         true);
405         
406                 if (m_parseAnnotations == NULL) {
407                         /* method not found */
408                         return NULL;
409                 }
410         }
411         
412         return (struct java_util_Map*)vm_call_method(
413                         m_parseAnnotations, NULL, annotations,
414                         constantPool, declaringClass);
415 }
416
417
418 /* reflect_get_parameterannotations *******************************************
419
420    Parses and returns the parameter annotations of a method.
421
422 *******************************************************************************/
423
424 java_objectarray* reflect_get_parameterannotations(
425         java_handle_t     *parameterAnnotations,
426         int32_t            slot,
427         java_lang_Class   *declaringClass,
428         classinfo         *referer)
429 {
430         /* This method in java would be basically the following.
431          * We don't do it in java because we don't want to make a
432          * public method with wich you can get a ConstantPool, because
433          * with that you could read any kind of constants (even private
434          * ones).
435          *
436          * ConstantPool constPool = new ConstantPool();
437          * constPool.constantPoolOop = getDeclaringClass();
438          * return sun.reflect.AnnotationParser.parseParameterAnnotations(
439          *      parameterAnnotations,
440          *      constPool,
441          *      getDeclaringClass(),
442          *      getParameterTypes().length);
443          */
444         static methodinfo        *m_parseParameterAnnotations   = NULL;
445         utf                      *utf_parseParameterAnnotations = NULL;
446         utf                      *utf_desc        = NULL;
447         sun_reflect_ConstantPool *constantPool    = NULL;
448         java_lang_Object         *constantPoolOop = (java_lang_Object*)declaringClass;
449         classinfo                *c               = NULL;
450         methodinfo               *m               = NULL;
451         int32_t                   numParameters   = -1;
452
453         /* get parameter count */
454
455         c = (classinfo *)declaringClass;
456         m = &(c->methods[slot]);
457
458         numParameters = method_get_parametercount(m);
459
460         if (numParameters < 0) {
461                 /* error parsing descriptor */
462                 return NULL;
463         }
464
465         /* get ConstantPool */
466
467         constantPool = 
468                 (sun_reflect_ConstantPool*)native_new_and_init(
469                         class_sun_reflect_ConstantPool);
470         
471         if(constantPool == NULL) {
472                 /* out of memory */
473                 return NULL;
474         }
475
476         LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
477
478         /* only resolve the method the first time */
479         if (m_parseParameterAnnotations == NULL) {
480                 utf_parseParameterAnnotations = utf_new_char("parseParameterAnnotations");
481                 utf_desc = utf_new_char(
482                         "([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)"
483                         "[[Ljava/lang/annotation/Annotation;");
484
485                 if (utf_parseParameterAnnotations == NULL || utf_desc == NULL) {
486                         /* out of memory */
487                         return NULL;
488                 }
489
490                 /* get parser method */
491
492                 m_parseParameterAnnotations = class_resolveclassmethod(
493                         class_sun_reflect_annotation_AnnotationParser,
494                         utf_parseParameterAnnotations,
495                         utf_desc,
496                         referer,
497                         true);
498
499                 if (m_parseParameterAnnotations == NULL)
500                 {
501                         /* method not found */
502                         return NULL;
503                 }
504         }
505
506         return (java_objectarray*)vm_call_method(
507                 m_parseParameterAnnotations, NULL, parameterAnnotations,
508                 constantPool, declaringClass, numParameters);
509 }
510 #endif
511
512
513 /*
514  * These are local overrides for various environment variables in Emacs.
515  * Please do not remove this and leave it at the end of the file, where
516  * Emacs will automagically detect them.
517  * ---------------------------------------------------------------------
518  * Local variables:
519  * mode: c
520  * indent-tabs-mode: t
521  * c-basic-offset: 4
522  * tab-width: 4
523  * End:
524  * vim:noexpandtab:sw=4:ts=4:
525  */