Line data Source code
1 : /* src/native/vm/reflection.cpp - helper functions for java/lang/reflect
2 :
3 : Copyright (C) 1996-2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
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.
12 :
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.
17 :
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
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 :
26 : #include "config.h"
27 :
28 : #include "native/llni.hpp"
29 : #include "native/native.hpp"
30 :
31 : #if defined(ENABLE_ANNOTATIONS) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
32 : # include "vm/vm.hpp"
33 : #endif
34 :
35 : #include "native/vm/reflection.hpp"
36 :
37 : #include "vm/access.hpp"
38 : #include "vm/array.hpp"
39 : #include "vm/descriptor.hpp"
40 : #include "vm/exceptions.hpp"
41 : #include "vm/global.hpp"
42 : #include "vm/globals.hpp"
43 : #include "vm/initialize.hpp"
44 : #include "vm/javaobjects.hpp"
45 : #include "vm/method.hpp"
46 : #include "vm/vm.hpp"
47 :
48 : #include "vm/jit/builtin.hpp"
49 :
50 :
51 : /**
52 : * Invoke a method on the given object with the given arguments.
53 : *
54 : * For instance methods OBJ must be != NULL and the method is looked up
55 : * in the vftbl of the object.
56 : *
57 : * For static methods, OBJ is ignored.
58 : */
59 853 : java_handle_t* Reflection::invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params)
60 : {
61 : methodinfo *resm;
62 : java_handle_t *ro;
63 : int argcount;
64 : int paramcount;
65 :
66 : /* Sanity check. */
67 :
68 853 : assert(m != NULL);
69 :
70 853 : argcount = m->parseddesc->paramcount;
71 853 : paramcount = argcount;
72 :
73 : /* If method is non-static, remove the `this' pointer. */
74 :
75 853 : if (!(m->flags & ACC_STATIC))
76 818 : paramcount--;
77 :
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. */
81 :
82 853 : if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->clazz))) {
83 0 : exceptions_throw_illegalargumentexception();
84 0 : return NULL;
85 : }
86 :
87 : /* check if we got the right number of arguments */
88 :
89 853 : ObjectArray oa(params);
90 :
91 853 : if (((params == NULL) && (paramcount != 0)) ||
92 : (params && (oa.get_length() != paramcount)))
93 : {
94 0 : exceptions_throw_illegalargumentexception();
95 0 : return NULL;
96 : }
97 :
98 : /* for instance methods we need an object */
99 :
100 853 : if (!(m->flags & ACC_STATIC) && (o == NULL)) {
101 : /* XXX not sure if that is the correct exception */
102 0 : exceptions_throw_nullpointerexception();
103 0 : return NULL;
104 : }
105 :
106 : /* for static methods, zero object to make subsequent code simpler */
107 853 : if (m->flags & ACC_STATIC)
108 35 : o = NULL;
109 :
110 853 : if (o != NULL) {
111 : /* for instance methods we must do a vftbl lookup */
112 818 : resm = method_vftbl_lookup(LLNI_vftbl_direct(o), m);
113 : }
114 : else {
115 : /* for static methods, just for convenience */
116 35 : resm = m;
117 : }
118 :
119 853 : ro = vm_call_method_objectarray(resm, o, params);
120 :
121 853 : return ro;
122 : }
123 :
124 :
125 : #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) && defined(ENABLE_ANNOTATIONS)
126 : /* reflect_get_declaredannotations *********************************************
127 :
128 : Calls the annotation parser with the unparsed annotations and returnes
129 : the parsed annotations as a map.
130 :
131 : IN:
132 : annotations........the unparsed annotations
133 : declaringClass.....the class in which the annotated element is declared
134 : referer............the calling class (for the 'referer' parameter of
135 : vm_call_method())
136 :
137 : RETURN VALUE:
138 : The parsed annotations as a
139 : java.util.Map<Class<? extends Annotation>, Annotation>.
140 :
141 : *******************************************************************************/
142 :
143 441 : java_handle_t* Reflection::get_declaredannotations(java_handle_bytearray_t *annotations, classinfo* declaringClass, classinfo *referer)
144 : {
145 : static methodinfo* m_parseAnnotations = NULL;
146 :
147 441 : java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
148 :
149 441 : if (h == NULL)
150 0 : return NULL;
151 :
152 441 : sun_reflect_ConstantPool cp(h);
153 441 : cp.set_constantPoolOop(declaringClass);
154 :
155 : /* only resolve the parser method the first time */
156 441 : if (m_parseAnnotations == NULL) {
157 : // FIXME Use globals.
158 3 : Utf8String utf_parseAnnotations = Utf8String::from_utf8("parseAnnotations");
159 3 : Utf8String utf_desc = Utf8String::from_utf8("([BLsun/reflect/ConstantPool;Ljava/lang/Class;)Ljava/util/Map;");
160 :
161 3 : if (utf_parseAnnotations == NULL || utf_desc == NULL)
162 0 : return NULL;
163 :
164 : m_parseAnnotations = class_resolveclassmethod(
165 : class_sun_reflect_annotation_AnnotationParser,
166 : utf_parseAnnotations,
167 : utf_desc,
168 : referer,
169 3 : true);
170 :
171 3 : if (m_parseAnnotations == NULL)
172 0 : return NULL;
173 : }
174 :
175 441 : return (java_handle_t*) vm_call_method(m_parseAnnotations, NULL, annotations, cp.get_handle(), declaringClass);
176 : }
177 :
178 :
179 : /* reflect_get_parameterannotations *******************************************
180 :
181 : Calls the annotation parser with the unparsed parameter annotations of
182 : a method and returnes the parsed parameter annotations in a 2 dimensional
183 : array.
184 :
185 : IN:
186 : parameterAnnotations....the unparsed parameter annotations
187 : slot....................the slot of the method
188 : declaringClass..........the class in which the annotated element is
189 : declared
190 : referer.................the calling class (for the 'referer' parameter
191 : of vm_call_method())
192 :
193 : RETURN VALUE:
194 : The parsed parameter annotations in a 2 dimensional array.
195 :
196 : *******************************************************************************/
197 :
198 12 : java_handle_objectarray_t* Reflection::get_parameterannotations(java_handle_bytearray_t* parameterAnnotations, methodinfo* m, classinfo* referer)
199 : {
200 : /* This method in java would be basically the following.
201 : * We don't do it in java because we don't want to make a
202 : * public method with wich you can get a ConstantPool, because
203 : * with that you could read any kind of constants (even private
204 : * ones).
205 : *
206 : * ConstantPool constPool = new ConstantPool();
207 : * constPool.constantPoolOop = method.getDeclaringClass();
208 : * return sun.reflect.AnnotationParser.parseParameterAnnotations(
209 : * parameterAnnotations,
210 : * constPool,
211 : * method.getDeclaringClass(),
212 : * method.getParameterTypes().length);
213 : */
214 :
215 : static methodinfo* m_parseParameterAnnotations = NULL;
216 :
217 : /* get parameter count */
218 :
219 12 : int32_t numParameters = method_get_parametercount(m);
220 :
221 : /* get ConstantPool */
222 :
223 12 : java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
224 :
225 12 : if (h == NULL)
226 0 : return NULL;
227 :
228 12 : sun_reflect_ConstantPool cp(h);
229 12 : cp.set_constantPoolOop(m->clazz);
230 :
231 : /* only resolve the parser method the first time */
232 12 : if (m_parseParameterAnnotations == NULL) {
233 1 : Utf8String utf_parseParameterAnnotations = Utf8String::from_utf8("parseParameterAnnotations");
234 1 : Utf8String utf_desc = Utf8String::from_utf8("([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;");
235 :
236 1 : if (utf_parseParameterAnnotations == NULL || utf_desc == NULL)
237 0 : return NULL;
238 :
239 : /* get parser method */
240 :
241 : m_parseParameterAnnotations = class_resolveclassmethod(
242 : class_sun_reflect_annotation_AnnotationParser,
243 : utf_parseParameterAnnotations,
244 : utf_desc,
245 : referer,
246 1 : true);
247 :
248 1 : if (m_parseParameterAnnotations == NULL)
249 0 : return NULL;
250 : }
251 :
252 12 : return (java_handle_objectarray_t*) vm_call_method(m_parseParameterAnnotations, NULL, parameterAnnotations, cp.get_handle(), m->clazz, numParameters);
253 : }
254 : #endif
255 :
256 :
257 : /*
258 : * These are local overrides for various environment variables in Emacs.
259 : * Please do not remove this and leave it at the end of the file, where
260 : * Emacs will automagically detect them.
261 : * ---------------------------------------------------------------------
262 : * Local variables:
263 : * mode: c++
264 : * indent-tabs-mode: t
265 : * c-basic-offset: 4
266 : * tab-width: 4
267 : * End:
268 : * vim:noexpandtab:sw=4:ts=4:
269 : */
|