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