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