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