Removed return value from descriptor_params_from_paramtypes.
[cacao.git] / src / native / vm / reflection.cpp
1 /* src/native/vm/reflection.cpp - helper functions for java/lang/reflect
2
3    Copyright (C) 1996-2011
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 <stdint.h>
29
30 #include "native/llni.h"
31 #include "native/native.hpp"
32
33 #if defined(ENABLE_ANNOTATIONS) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
34 # include "vm/vm.hpp"
35 #endif
36
37 #include "native/vm/reflection.hpp"
38
39 #include "vm/access.hpp"
40 #include "vm/array.hpp"
41 #include "vm/jit/builtin.hpp"
42 #include "vm/exceptions.hpp"
43 #include "vm/global.h"
44 #include "vm/globals.hpp"
45 #include "vm/initialize.hpp"
46 #include "vm/javaobjects.hpp"
47 #include "vm/method.hpp"
48 #include "vm/string.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 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         assert(m != NULL);
69
70         argcount = m->parseddesc->paramcount;
71         paramcount = argcount;
72
73         /* If method is non-static, remove the `this' pointer. */
74
75         if (!(m->flags & ACC_STATIC))
76                 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         if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->clazz))) {
83                 exceptions_throw_illegalargumentexception();
84                 return NULL;
85         }
86
87         /* check if we got the right number of arguments */
88
89         ObjectArray oa(params);
90
91         if (((params == NULL) && (paramcount != 0)) ||
92                 (params && (oa.get_length() != paramcount))) 
93         {
94                 exceptions_throw_illegalargumentexception();
95                 return NULL;
96         }
97
98         /* for instance methods we need an object */
99
100         if (!(m->flags & ACC_STATIC) && (o == NULL)) {
101                 /* XXX not sure if that is the correct exception */
102                 exceptions_throw_nullpointerexception();
103                 return NULL;
104         }
105
106         /* for static methods, zero object to make subsequent code simpler */
107         if (m->flags & ACC_STATIC)
108                 o = NULL;
109
110         if (o != NULL) {
111                 /* for instance methods we must do a vftbl lookup */
112                 resm = method_vftbl_lookup(LLNI_vftbl_direct(o), m);
113         }
114         else {
115                 /* for static methods, just for convenience */
116                 resm = m;
117         }
118
119         ro = vm_call_method_objectarray(resm, o, params);
120
121         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 java_handle_t* Reflection::get_declaredannotations(java_handle_bytearray_t *annotations, classinfo* declaringClass, classinfo *referer)
144 {
145         static methodinfo* m_parseAnnotations = NULL;
146
147         java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
148                 
149         if (h == NULL)
150                 return NULL;
151
152         sun_reflect_ConstantPool cp(h);
153         cp.set_constantPoolOop(declaringClass);
154                 
155         /* only resolve the parser method the first time */
156         if (m_parseAnnotations == NULL) {
157                 // FIXME Use globals.
158                 utf* utf_parseAnnotations = utf_new_char("parseAnnotations");
159                 utf* utf_desc = utf_new_char("([BLsun/reflect/ConstantPool;Ljava/lang/Class;)Ljava/util/Map;");
160
161                 if (utf_parseAnnotations == NULL || utf_desc == NULL)
162                         return NULL;
163                 
164                 m_parseAnnotations = class_resolveclassmethod(
165                         class_sun_reflect_annotation_AnnotationParser,
166                         utf_parseAnnotations,
167                         utf_desc,
168                         referer,
169                         true);
170         
171                 if (m_parseAnnotations == NULL)
172                         return NULL;
173         }
174         
175         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 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         int32_t numParameters = method_get_parametercount(m);
220
221         /* get ConstantPool */
222
223         java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
224         
225         if (h == NULL)
226                 return NULL;
227
228         sun_reflect_ConstantPool cp(h);
229         cp.set_constantPoolOop(m->clazz);
230
231         /* only resolve the parser method the first time */
232         if (m_parseParameterAnnotations == NULL) {
233                 utf* utf_parseParameterAnnotations = utf_new_char("parseParameterAnnotations");
234                 utf* utf_desc = utf_new_char("([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;");
235
236                 if (utf_parseParameterAnnotations == NULL || utf_desc == NULL)
237                         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                         true);
247
248                 if (m_parseParameterAnnotations == NULL)
249                         return NULL;
250         }
251
252         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  */