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