1 /* src/native/vm/reflect.c - helper functions for java/lang/reflect
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
8 This file is part of CACAO.
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.
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.
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
25 $Id: reflect.c 8289 2007-08-10 15:18:05Z twisti $
34 #if defined(ENABLE_ANNOTATIONS)
35 #include "mm/memory.h"
37 #if defined(WITH_CLASSPATH_GNU)
40 #include "native/include/sun_reflect_ConstantPool.h"
44 #include "native/jni.h"
45 #include "native/llni.h"
46 #include "native/native.h"
48 /* keep this order of the native includes */
50 #include "native/include/java_lang_String.h"
52 #if defined(WITH_CLASSPATH_SUN)
53 # include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
55 #include "native/include/java_lang_ClassLoader.h"
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"
63 #include "native/vm/java_lang_String.h"
64 #include "native/vm/reflect.h"
66 #include "vm/builtin.h"
67 #include "vm/global.h"
68 #include "vm/stringlocal.h"
70 #include "vmcore/method.h"
73 /* reflect_constructor_new *****************************************************
75 Allocates a new java.lang.reflect.Constructor object and
76 initializes the fields with the method passed.
78 *******************************************************************************/
80 java_lang_reflect_Constructor *reflect_constructor_new(methodinfo *m)
84 java_lang_reflect_Constructor *rc;
86 java_bytearray *annotations = NULL;
87 java_bytearray *parameterAnnotations = NULL;
88 annotation_bytearray_t *ba = NULL;
90 #if defined(ENABLE_ANNOTATIONS)
92 ba = method_get_annotations(m);
95 annotations = builtin_newarray_byte(ba->size);
97 if (annotations == NULL)
100 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
103 /* get parameter annotations */
104 ba = method_get_parameterannotations(m);
107 parameterAnnotations = builtin_newarray_byte(ba->size);
109 if (parameterAnnotations == NULL)
112 MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
116 /* get declaring class */
118 c = (classinfo *) m->class;
120 /* allocate a new object */
122 o = builtin_new(class_java_lang_reflect_Constructor);
127 /* initialize instance fields */
129 rc = (java_lang_reflect_Constructor *) o;
131 /* calculate the slot */
133 slot = m - c->methods;
135 #if defined(WITH_CLASSPATH_GNU)
137 LLNI_field_set_cls(rc, clazz , c);
138 LLNI_field_set_val(rc, slot , slot);
140 /* TODO: add these private fields to java.lang.reflect.Constructor
141 LLNI_field_set_ref(rc, annotations , annotations);
142 LLNI_field_set_ref(rc, parameterAnnotations, parameterAnnotations);
145 #elif defined(WITH_CLASSPATH_SUN)
147 LLNI_field_set_cls(rc, clazz , c);
148 LLNI_field_set_ref(rc, parameterTypes , method_get_parametertypearray(m));
149 LLNI_field_set_ref(rc, exceptionTypes , method_get_exceptionarray(m));
150 LLNI_field_set_val(rc, modifiers , m->flags & ACC_CLASS_REFLECT_MASK);
151 LLNI_field_set_val(rc, slot , slot);
152 LLNI_field_set_ref(rc, signature , m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL);
153 LLNI_field_set_ref(rc, annotations , annotations);
154 LLNI_field_set_ref(rc, parameterAnnotations, parameterAnnotations);
157 # error unknown classpath configuration
164 /* reflect_field_new ***********************************************************
166 Allocates a new java.lang.reflect.Field object and initializes the
167 fields with the field passed.
169 *******************************************************************************/
171 java_lang_reflect_Field *reflect_field_new(fieldinfo *f)
174 java_objectheader *o;
175 java_lang_reflect_Field *rf;
177 java_bytearray *annotations = NULL;
178 annotation_bytearray_t *ba = NULL;
180 #if defined(ENABLE_ANNOTATIONS)
181 /* get annotations */
182 ba = field_get_annotations(f);
185 annotations = builtin_newarray_byte(ba->size);
187 if (annotations == NULL)
190 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
194 /* get declaring class */
196 c = (classinfo *) f->class;
198 /* allocate a new object */
200 o = builtin_new(class_java_lang_reflect_Field);
205 /* initialize instance fields */
207 rf = (java_lang_reflect_Field *) o;
209 /* calculate the slot */
211 slot = f - c->fields;
213 #if defined(WITH_CLASSPATH_GNU)
215 LLNI_field_set_cls(rf, clazz , c);
217 /* The name needs to be interned */
218 /* XXX implement me better! */
220 LLNI_field_set_ref(rf, name , _Jv_java_lang_String_intern((java_lang_String *) javastring_new(f->name)));
221 LLNI_field_set_val(rf, slot , slot);
222 LLNI_field_set_ref(rf, annotations , annotations);
224 #elif defined(WITH_CLASSPATH_SUN)
226 LLNI_field_set_cls(rf, clazz , c);
228 /* The name needs to be interned */
229 /* XXX implement me better! */
231 LLNI_field_set_ref(rf, name , _Jv_java_lang_String_intern((java_lang_String *) javastring_new(f->name)));
232 LLNI_field_set_cls(rf, type , (java_lang_Class *) field_get_type(f));
233 LLNI_field_set_val(rf, modifiers , f->flags);
234 LLNI_field_set_val(rf, slot , slot);
235 LLNI_field_set_ref(rf, signature , f->signature ? (java_lang_String *) javastring_new(f->signature) : NULL);
236 LLNI_field_set_ref(rf, annotations , annotations);
239 # error unknown classpath configuration
246 /* reflect_method_new **********************************************************
248 Allocates a new java.lang.reflect.Method object and initializes the
249 fields with the method passed.
251 *******************************************************************************/
253 java_lang_reflect_Method *reflect_method_new(methodinfo *m)
256 java_objectheader *o;
257 java_lang_reflect_Method *rm;
259 java_bytearray *annotations = NULL;
260 java_bytearray *parameterAnnotations = NULL;
261 java_bytearray *annotationDefault = NULL;
262 annotation_bytearray_t *ba = NULL;
264 #if defined(ENABLE_ANNOTATIONS)
265 /* get annotations */
266 ba = method_get_annotations(m);
269 annotations = builtin_newarray_byte(ba->size);
271 if (annotations == NULL)
274 MCOPY(annotations->data, ba->data, uint8_t, ba->size);
277 /* get parameter annotations */
278 ba = method_get_parameterannotations(m);
281 parameterAnnotations = builtin_newarray_byte(ba->size);
283 if (parameterAnnotations == NULL)
286 MCOPY(parameterAnnotations->data, ba->data, uint8_t, ba->size);
289 /* get annotation default value */
290 ba = method_get_annotationdefault(m);
293 annotationDefault = builtin_newarray_byte(ba->size);
295 if (annotationDefault == NULL)
298 MCOPY(annotationDefault->data, ba->data, uint8_t, ba->size);
302 /* get declaring class */
304 c = (classinfo *) m->class;
306 /* allocate a new object */
308 o = builtin_new(class_java_lang_reflect_Method);
313 /* initialize instance fields */
315 rm = (java_lang_reflect_Method *) o;
317 /* calculate the slot */
319 slot = m - c->methods;
321 #if defined(WITH_CLASSPATH_GNU)
323 LLNI_field_set_cls(rm, clazz , m->class);
325 /* The name needs to be interned */
326 /* XXX implement me better! */
328 LLNI_field_set_ref(rm, name , _Jv_java_lang_String_intern((java_lang_String *) javastring_new(m->name)));
329 LLNI_field_set_val(rm, slot , slot);
330 LLNI_field_set_ref(rm, annotations , annotations);
331 LLNI_field_set_ref(rm, parameterAnnotations, parameterAnnotations);
332 LLNI_field_set_ref(rm, annotationDefault , annotationDefault);
334 #elif defined(WITH_CLASSPATH_SUN)
336 LLNI_field_set_cls(rm, clazz , (java_lang_Class *) m->class);
338 /* The name needs to be interned */
339 /* XXX implement me better! */
341 rm->name = _Jv_java_lang_String_intern((java_lang_String *) javastring_new(m->name));
342 rm->parameterTypes = method_get_parametertypearray(m);
343 rm->returnType = (java_lang_Class *) method_returntype_get(m);
344 rm->exceptionTypes = method_get_exceptionarray(m);
345 rm->modifiers = m->flags & ACC_CLASS_REFLECT_MASK;
347 rm->signature = m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL;
348 rm->annotations = annotations;
349 rm->parameterAnnotations = parameterAnnotations;
350 rm->annotationDefault = annotationDefault;
353 # error unknown classpath configuration
360 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
361 /* reflect_get_declaredannotatios *********************************************
363 Returnes a java.util.Map<Class, Annotation> of the declared
364 annotations. Only calls the AnnotationParser if the declared
365 annotations are not yet parsed.
367 *******************************************************************************/
369 struct java_util_Map* reflect_get_declaredannotatios(
370 struct java_util_Map **declaredAnnotations,
371 java_bytearray *annotations,
372 java_lang_Class *declaringClass,
375 static methodinfo *m_parseAnnotations = NULL;
376 utf *utf_parseAnnotations = NULL;
377 utf *utf_desc = NULL;
378 sun_reflect_ConstantPool *constantPool = NULL;
380 if (*declaredAnnotations == NULL) {
382 (sun_reflect_ConstantPool*)native_new_and_init(
383 class_sun_reflect_ConstantPool);
385 if(constantPool == NULL) {
390 constantPool->constantPoolOop = (java_lang_Object*)declaringClass;
392 /* only resolve the method the first time */
393 if (m_parseAnnotations == NULL) {
394 utf_parseAnnotations = utf_new_char("parseAnnotations");
395 utf_desc = utf_new_char(
396 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
399 if (utf_parseAnnotations == NULL || utf_desc == NULL) {
404 m_parseAnnotations = class_resolveclassmethod(
405 class_sun_reflect_annotation_AnnotationParser,
406 utf_parseAnnotations,
411 if (m_parseAnnotations == NULL) {
412 /* method not found */
417 *declaredAnnotations =
418 (struct java_util_Map*)vm_call_method(
419 m_parseAnnotations, NULL, annotations,
420 constantPool, declaringClass);
423 return *declaredAnnotations;
427 /* reflect_get_parameterannotations *******************************************
429 Parses and returns the parameter annotations of a method.
431 *******************************************************************************/
433 java_objectarray* reflect_get_parameterannotations(
434 java_objectheader *parameterAnnotations,
436 java_lang_Class *declaringClass,
439 /* This method in java would be basically the following.
440 * We don't do it in java because we don't want to make a
441 * public method with wich you can get a ConstantPool, because
442 * with that you could read any kind of constants (even private
445 * ConstantPool constPool = new ConstantPool();
446 * constPool.constantPoolOop = getDeclaringClass();
447 * return sun.reflect.AnnotationParser.parseParameterAnnotations(
448 * parameterAnnotations,
450 * getDeclaringClass(),
451 * getParameterTypes().length);
453 static methodinfo *m_parseParameterAnnotations = NULL;
454 utf *utf_parseParameterAnnotations = NULL;
455 utf *utf_desc = NULL;
456 sun_reflect_ConstantPool *constantPool = NULL;
458 methodinfo *m = NULL;
459 int32_t numParameters = -1;
461 /* get parameter count */
463 c = (classinfo *)declaringClass;
464 m = &(c->methods[slot]);
466 numParameters = method_get_parametercount(m);
468 if (numParameters < 0) {
469 /* error parsing descriptor */
473 /* get ConstantPool */
476 (sun_reflect_ConstantPool*)native_new_and_init(
477 class_sun_reflect_ConstantPool);
479 if(constantPool == NULL) {
484 constantPool->constantPoolOop = (java_lang_Object*)declaringClass;
486 /* only resolve the method the first time */
487 if (m_parseParameterAnnotations == NULL) {
488 utf_parseParameterAnnotations = utf_new_char("parseParameterAnnotations");
489 utf_desc = utf_new_char(
490 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)"
491 "[[Ljava/lang/annotation/Annotation;");
493 if (utf_parseParameterAnnotations == NULL || utf_desc == NULL) {
498 /* get parser method */
500 m_parseParameterAnnotations = class_resolveclassmethod(
501 class_sun_reflect_annotation_AnnotationParser,
502 utf_parseParameterAnnotations,
507 if (m_parseParameterAnnotations == NULL)
509 /* method not found */
514 return (java_objectarray*)vm_call_method(
515 m_parseParameterAnnotations, NULL, parameterAnnotations,
516 constantPool, declaringClass, numParameters);
522 * These are local overrides for various environment variables in Emacs.
523 * Please do not remove this and leave it at the end of the file, where
524 * Emacs will automagically detect them.
525 * ---------------------------------------------------------------------
528 * indent-tabs-mode: t
532 * vim:noexpandtab:sw=4:ts=4: