1 /* src/native/vm/reflection.cpp - helper functions for java/lang/reflect
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 #include "native/jni.h"
31 #include "native/llni.h"
32 #include "native/native.h"
34 #if defined(ENABLE_ANNOTATIONS) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
38 #include "native/vm/reflection.hpp"
40 #include "vm/access.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.hpp"
43 #include "vm/global.h"
44 #include "vm/globals.hpp"
45 #include "vm/initialize.h"
46 #include "vm/javaobjects.hpp"
47 #include "vm/method.h"
48 #include "vm/string.hpp"
52 * Invoke a method on the given object with the given arguments.
54 * For instance methods OBJ must be != NULL and the method is looked up
55 * in the vftbl of the object.
57 * For static methods, OBJ is ignored.
59 java_handle_t* Reflection::invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params)
70 argcount = m->parseddesc->paramcount;
71 paramcount = argcount;
73 /* If method is non-static, remove the `this' pointer. */
75 if (!(m->flags & ACC_STATIC))
78 /* For instance methods the object has to be an instance of the
79 class the method belongs to. For static methods the obj
80 parameter is ignored. */
82 if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->clazz))) {
83 exceptions_throw_illegalargumentexception();
87 /* check if we got the right number of arguments */
89 if (((params == NULL) && (paramcount != 0)) ||
90 (params && (LLNI_array_size(params) != paramcount)))
92 exceptions_throw_illegalargumentexception();
96 /* for instance methods we need an object */
98 if (!(m->flags & ACC_STATIC) && (o == NULL)) {
99 /* XXX not sure if that is the correct exception */
100 exceptions_throw_nullpointerexception();
104 /* for static methods, zero object to make subsequent code simpler */
105 if (m->flags & ACC_STATIC)
109 /* for instance methods we must do a vftbl lookup */
110 resm = method_vftbl_lookup(LLNI_vftbl_direct(o), m);
113 /* for static methods, just for convenience */
117 ro = vm_call_method_objectarray(resm, o, params);
123 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) && defined(ENABLE_ANNOTATIONS)
124 /* reflect_get_declaredannotations *********************************************
126 Calls the annotation parser with the unparsed annotations and returnes
127 the parsed annotations as a map.
130 annotations........the unparsed annotations
131 declaringClass.....the class in which the annotated element is declared
132 referer............the calling class (for the 'referer' parameter of
136 The parsed annotations as a
137 java.util.Map<Class<? extends Annotation>, Annotation>.
139 *******************************************************************************/
141 java_handle_t* Reflection::get_declaredannotations(java_handle_bytearray_t *annotations, classinfo* declaringClass, classinfo *referer)
143 static methodinfo* m_parseAnnotations = NULL;
145 java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
150 sun_reflect_ConstantPool cp(h);
151 cp.set_constantPoolOop(declaringClass);
153 /* only resolve the parser method the first time */
154 if (m_parseAnnotations == NULL) {
155 // FIXME Use globals.
156 utf* utf_parseAnnotations = utf_new_char("parseAnnotations");
157 utf* utf_desc = utf_new_char("([BLsun/reflect/ConstantPool;Ljava/lang/Class;)Ljava/util/Map;");
159 if (utf_parseAnnotations == NULL || utf_desc == NULL)
162 m_parseAnnotations = class_resolveclassmethod(
163 class_sun_reflect_annotation_AnnotationParser,
164 utf_parseAnnotations,
169 if (m_parseAnnotations == NULL)
173 return (java_handle_t*) vm_call_method(m_parseAnnotations, NULL, annotations, cp.get_handle(), declaringClass);
177 /* reflect_get_parameterannotations *******************************************
179 Calls the annotation parser with the unparsed parameter annotations of
180 a method and returnes the parsed parameter annotations in a 2 dimensional
184 parameterAnnotations....the unparsed parameter annotations
185 slot....................the slot of the method
186 declaringClass..........the class in which the annotated element is
188 referer.................the calling class (for the 'referer' parameter
192 The parsed parameter annotations in a 2 dimensional array.
194 *******************************************************************************/
196 java_handle_objectarray_t* Reflection::get_parameterannotations(java_handle_bytearray_t* parameterAnnotations, methodinfo* m, classinfo* referer)
198 /* This method in java would be basically the following.
199 * We don't do it in java because we don't want to make a
200 * public method with wich you can get a ConstantPool, because
201 * with that you could read any kind of constants (even private
204 * ConstantPool constPool = new ConstantPool();
205 * constPool.constantPoolOop = method.getDeclaringClass();
206 * return sun.reflect.AnnotationParser.parseParameterAnnotations(
207 * parameterAnnotations,
209 * method.getDeclaringClass(),
210 * method.getParameterTypes().length);
213 static methodinfo* m_parseParameterAnnotations = NULL;
215 /* get parameter count */
217 int32_t numParameters = method_get_parametercount(m);
219 if (numParameters < 0)
222 /* get ConstantPool */
224 java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
229 sun_reflect_ConstantPool cp(h);
230 cp.set_constantPoolOop(m->clazz);
232 /* only resolve the parser method the first time */
233 if (m_parseParameterAnnotations == NULL) {
234 utf* utf_parseParameterAnnotations = utf_new_char("parseParameterAnnotations");
235 utf* utf_desc = utf_new_char("([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;");
237 if (utf_parseParameterAnnotations == NULL || utf_desc == NULL)
240 /* get parser method */
242 m_parseParameterAnnotations = class_resolveclassmethod(
243 class_sun_reflect_annotation_AnnotationParser,
244 utf_parseParameterAnnotations,
249 if (m_parseParameterAnnotations == NULL)
253 return (java_handle_objectarray_t*) vm_call_method(m_parseParameterAnnotations, NULL, parameterAnnotations, cp.get_handle(), m->clazz, numParameters);
259 * These are local overrides for various environment variables in Emacs.
260 * Please do not remove this and leave it at the end of the file, where
261 * Emacs will automagically detect them.
262 * ---------------------------------------------------------------------
265 * indent-tabs-mode: t
269 * vim:noexpandtab:sw=4:ts=4: