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
32 #if defined(ENABLE_ANNOTATIONS)
33 #include "mm/memory.h"
35 #if defined(WITH_CLASSPATH_GNU)
38 #include "native/include/sun_reflect_ConstantPool.h"
42 #include "native/jni.h"
43 #include "native/llni.h"
44 #include "native/native.h"
46 /* keep this order of the native includes */
48 #include "native/include/java_lang_String.h"
50 #if defined(WITH_CLASSPATH_SUN)
51 # include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
53 #include "native/include/java_lang_ClassLoader.h"
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"
61 #include "native/vm/reflect.h"
63 #include "vm/builtin.h"
64 #include "vm/global.h"
65 #include "vm/stringlocal.h"
67 #include "vmcore/method.h"
70 /* reflect_constructor_new *****************************************************
72 Allocates a new java.lang.reflect.Constructor object and
73 initializes the fields with the method passed.
75 *******************************************************************************/
77 java_lang_reflect_Constructor *reflect_constructor_new(methodinfo *m)
81 java_lang_reflect_Constructor *rc;
84 /* get declaring class */
88 /* allocate a new object */
90 o = builtin_new(class_java_lang_reflect_Constructor);
95 /* initialize instance fields */
97 rc = (java_lang_reflect_Constructor *) o;
99 /* calculate the slot */
101 slot = m - c->methods;
103 #if defined(WITH_CLASSPATH_GNU)
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));
110 #elif defined(WITH_CLASSPATH_SUN)
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));
122 # error unknown classpath configuration
129 /* reflect_field_new ***********************************************************
131 Allocates a new java.lang.reflect.Field object and initializes the
132 fields with the field passed.
134 *******************************************************************************/
136 java_lang_reflect_Field *reflect_field_new(fieldinfo *f)
140 java_lang_reflect_Field *rf;
143 /* get declaring class */
147 /* allocate a new object */
149 o = builtin_new(class_java_lang_reflect_Field);
154 /* initialize instance fields */
156 rf = (java_lang_reflect_Field *) o;
158 /* calculate the slot */
160 slot = f - c->fields;
162 #if defined(WITH_CLASSPATH_GNU)
164 LLNI_field_set_cls(rf, clazz , c);
166 /* The name needs to be interned */
167 /* XXX implement me better! */
169 LLNI_field_set_ref(rf, name , javastring_intern(javastring_new(f->name)));
170 LLNI_field_set_val(rf, slot , slot);
171 LLNI_field_set_ref(rf, annotations , field_get_annotations(f));
173 #elif defined(WITH_CLASSPATH_SUN)
175 LLNI_field_set_cls(rf, clazz , c);
177 /* The name needs to be interned */
178 /* XXX implement me better! */
180 LLNI_field_set_ref(rf, name , javastring_intern(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));
188 # error unknown classpath configuration
195 /* reflect_method_new **********************************************************
197 Allocates a new java.lang.reflect.Method object and initializes the
198 fields with the method passed.
200 *******************************************************************************/
202 java_lang_reflect_Method *reflect_method_new(methodinfo *m)
206 java_lang_reflect_Method *rm;
209 /* get declaring class */
213 /* allocate a new object */
215 o = builtin_new(class_java_lang_reflect_Method);
220 /* initialize instance fields */
222 rm = (java_lang_reflect_Method *) o;
224 /* calculate the slot */
226 slot = m - c->methods;
228 #if defined(WITH_CLASSPATH_GNU)
230 LLNI_field_set_cls(rm, clazz , m->class);
232 /* The name needs to be interned */
233 /* XXX implement me better! */
235 LLNI_field_set_ref(rm, name , javastring_intern(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));
241 #elif defined(WITH_CLASSPATH_SUN)
243 LLNI_field_set_cls(rm, clazz , m->class);
245 /* The name needs to be interned */
246 /* XXX implement me better! */
248 LLNI_field_set_ref(rm, name , javastring_intern(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));
260 # error unknown classpath configuration
267 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
268 /* reflect_get_declaredannotatios *********************************************
270 Calls the annotation parser with the unparsed annotations and returnes
271 the parsed annotations as a map.
274 annotations........the unparsed annotations
275 declaringClass.....the class in which the annotated element is declared
276 referer............the calling class (for the 'referer' parameter of
280 The parsed annotations as a
281 java.util.Map<Class<? extends Annotation>, Annotation>.
283 *******************************************************************************/
285 struct java_util_Map* reflect_get_declaredannotatios(
286 java_handle_bytearray_t *annotations,
287 java_lang_Class *declaringClass,
290 static methodinfo *m_parseAnnotations = NULL;
291 /* parser method (chached, therefore static) */
292 utf *utf_parseAnnotations = NULL;
293 /* parser method name */
294 utf *utf_desc = NULL;
295 /* parser method descriptor (signature) */
296 sun_reflect_ConstantPool *constantPool = NULL;
297 /* constant pool of the declaring class */
298 java_lang_Object *constantPoolOop = (java_lang_Object*)declaringClass;
299 /* constantPoolOop field of the constant pool */
300 /* object (sun.reflect.ConstantPool) */
303 (sun_reflect_ConstantPool*)native_new_and_init(
304 class_sun_reflect_ConstantPool);
306 if(constantPool == NULL) {
311 LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
313 /* only resolve the parser method the first time */
314 if (m_parseAnnotations == NULL) {
315 utf_parseAnnotations = utf_new_char("parseAnnotations");
316 utf_desc = utf_new_char(
317 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
320 if (utf_parseAnnotations == NULL || utf_desc == NULL) {
325 m_parseAnnotations = class_resolveclassmethod(
326 class_sun_reflect_annotation_AnnotationParser,
327 utf_parseAnnotations,
332 if (m_parseAnnotations == NULL) {
333 /* method not found */
338 return (struct java_util_Map*)vm_call_method(
339 m_parseAnnotations, NULL, annotations,
340 constantPool, declaringClass);
344 /* reflect_get_parameterannotations *******************************************
346 Calls the annotation parser with the unparsed parameter annotations of
347 a method and returnes the parsed parameter annotations in a 2 dimensional
351 parameterAnnotations....the unparsed parameter annotations
352 slot....................the slot of the method
353 declaringClass..........the class in which the annotated element is
355 referer.................the calling class (for the 'referer' parameter
359 The parsed parameter annotations in a 2 dimensional array.
361 *******************************************************************************/
363 java_handle_objectarray_t* reflect_get_parameterannotations(
364 java_handle_t *parameterAnnotations,
366 java_lang_Class *declaringClass,
369 /* This method in java would be basically the following.
370 * We don't do it in java because we don't want to make a
371 * public method with wich you can get a ConstantPool, because
372 * with that you could read any kind of constants (even private
375 * ConstantPool constPool = new ConstantPool();
376 * constPool.constantPoolOop = method.getDeclaringClass();
377 * return sun.reflect.AnnotationParser.parseParameterAnnotations(
378 * parameterAnnotations,
380 * method.getDeclaringClass(),
381 * method.getParameterTypes().length);
383 static methodinfo *m_parseParameterAnnotations = NULL;
384 /* parser method (cached, therefore static) */
385 utf *utf_parseParameterAnnotations = NULL;
386 /* parser method name */
387 utf *utf_desc = NULL;
388 /* parser method descriptor (signature) */
389 sun_reflect_ConstantPool *constantPool = NULL;
390 /* constant pool of the declaring class */
391 java_lang_Object *constantPoolOop = (java_lang_Object*)declaringClass;
392 /* constantPoolOop field of the constant pool object */
394 /* classinfo of the decaring class */
395 methodinfo *m = NULL;
396 /* method info of the annotated method */
397 int32_t numParameters = -1;
398 /* parameter count of the annotated method */
400 /* get parameter count */
402 c = LLNI_classinfo_unwrap(declaringClass);
403 m = &(c->methods[slot]);
405 numParameters = method_get_parametercount(m);
407 if (numParameters < 0) {
408 /* error parsing descriptor */
412 /* get ConstantPool */
415 (sun_reflect_ConstantPool*)native_new_and_init(
416 class_sun_reflect_ConstantPool);
418 if(constantPool == NULL) {
423 LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
425 /* only resolve the parser method the first time */
426 if (m_parseParameterAnnotations == NULL) {
427 utf_parseParameterAnnotations = utf_new_char("parseParameterAnnotations");
428 utf_desc = utf_new_char(
429 "([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)"
430 "[[Ljava/lang/annotation/Annotation;");
432 if (utf_parseParameterAnnotations == NULL || utf_desc == NULL) {
437 /* get parser method */
439 m_parseParameterAnnotations = class_resolveclassmethod(
440 class_sun_reflect_annotation_AnnotationParser,
441 utf_parseParameterAnnotations,
446 if (m_parseParameterAnnotations == NULL)
448 /* method not found */
453 return (java_handle_objectarray_t*)vm_call_method(
454 m_parseParameterAnnotations, NULL, parameterAnnotations,
455 constantPool, declaringClass, numParameters);
461 * These are local overrides for various environment variables in Emacs.
462 * Please do not remove this and leave it at the end of the file, where
463 * Emacs will automagically detect them.
464 * ---------------------------------------------------------------------
467 * indent-tabs-mode: t
471 * vim:noexpandtab:sw=4:ts=4: