1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * java.lang.reflect.Method
19 */
20#include "Dalvik.h"
21#include "native/InternalNativePriv.h"
22
23
24/*
25 * static int getMethodModifiers(Class decl_class, int slot)
26 *
27 * (Not sure why the access flags weren't stored in the class along with
28 * everything else.  Not sure why this isn't static.)
29 */
30static void Dalvik_java_lang_reflect_Method_getMethodModifiers(const u4* args,
31    JValue* pResult)
32{
33    ClassObject* declaringClass = (ClassObject*) args[0];
34    int slot = args[1];
35    Method* meth;
36
37    meth = dvmSlotToMethod(declaringClass, slot);
38    RETURN_INT(dvmFixMethodFlags(meth->accessFlags));
39}
40
41/*
42 * private Object invokeNative(Object obj, Object[] args, Class declaringClass,
43 *   Class[] parameterTypes, Class returnType, int slot, boolean noAccessCheck)
44 *
45 * Invoke a static or virtual method via reflection.
46 */
47static void Dalvik_java_lang_reflect_Method_invokeNative(const u4* args,
48    JValue* pResult)
49{
50    // ignore thisPtr in args[0]
51    Object* methObj = (Object*) args[1];        // null for static methods
52    ArrayObject* argList = (ArrayObject*) args[2];
53    ClassObject* declaringClass = (ClassObject*) args[3];
54    ArrayObject* params = (ArrayObject*) args[4];
55    ClassObject* returnType = (ClassObject*) args[5];
56    int slot = args[6];
57    bool noAccessCheck = (args[7] != 0);
58    const Method* meth;
59    Object* result;
60
61    /*
62     * "If the underlying method is static, the class that declared the
63     * method is initialized if it has not already been initialized."
64     */
65    meth = dvmSlotToMethod(declaringClass, slot);
66    assert(meth != NULL);
67
68    if (dvmIsStaticMethod(meth)) {
69        if (!dvmIsClassInitialized(declaringClass)) {
70            if (!dvmInitClass(declaringClass))
71                goto init_failed;
72        }
73    } else {
74        /* looks like interfaces need this too? */
75        if (dvmIsInterfaceClass(declaringClass) &&
76            !dvmIsClassInitialized(declaringClass))
77        {
78            if (!dvmInitClass(declaringClass))
79                goto init_failed;
80        }
81
82        /* make sure the object is an instance of the expected class */
83        if (!dvmVerifyObjectInClass(methObj, declaringClass)) {
84            assert(dvmCheckException(dvmThreadSelf()));
85            RETURN_VOID();
86        }
87
88        /* do the virtual table lookup for the method */
89        meth = dvmGetVirtualizedMethod(methObj->clazz, meth);
90        if (meth == NULL) {
91            assert(dvmCheckException(dvmThreadSelf()));
92            RETURN_VOID();
93        }
94    }
95
96    /*
97     * If the method has a return value, "result" will be an object or
98     * a boxed primitive.
99     */
100    result = dvmInvokeMethod(methObj, meth, argList, params, returnType,
101                noAccessCheck);
102
103    RETURN_PTR(result);
104
105init_failed:
106    /*
107     * If initialization failed, an exception will be raised.
108     */
109    ALOGD("Method.invoke() on bad class %s failed",
110        declaringClass->descriptor);
111    assert(dvmCheckException(dvmThreadSelf()));
112    RETURN_VOID();
113}
114
115/*
116 * static Annotation[] getDeclaredAnnotations(Class declaringClass, int slot)
117 *
118 * Return the annotations declared for this method.
119 */
120static void Dalvik_java_lang_reflect_Method_getDeclaredAnnotations(
121    const u4* args, JValue* pResult)
122{
123    ClassObject* declaringClass = (ClassObject*) args[0];
124    int slot = args[1];
125    Method* meth;
126
127    meth = dvmSlotToMethod(declaringClass, slot);
128    assert(meth != NULL);
129
130    ArrayObject* annos = dvmGetMethodAnnotations(meth);
131    dvmReleaseTrackedAlloc((Object*)annos, NULL);
132    RETURN_PTR(annos);
133}
134
135/*
136 * static Annotation getAnnotation(
137 *         Class declaringClass, int slot, Class annotationType);
138 */
139static void Dalvik_java_lang_reflect_Method_getAnnotation(const u4* args,
140    JValue* pResult)
141{
142    ClassObject* clazz = (ClassObject*) args[0];
143    int slot = args[1];
144    ClassObject* annotationClazz = (ClassObject*) args[2];
145
146    Method* meth = dvmSlotToMethod(clazz, slot);
147    RETURN_PTR(dvmGetMethodAnnotation(clazz, meth, annotationClazz));
148}
149
150/*
151 * static boolean isAnnotationPresent(
152 *         Class declaringClass, int slot, Class annotationType);
153 */
154static void Dalvik_java_lang_reflect_Method_isAnnotationPresent(const u4* args,
155    JValue* pResult)
156{
157    ClassObject* clazz = (ClassObject*) args[0];
158    int slot = args[1];
159    ClassObject* annotationClazz = (ClassObject*) args[2];
160
161    Method* meth = dvmSlotToMethod(clazz, slot);
162    RETURN_BOOLEAN(dvmIsMethodAnnotationPresent(clazz, meth, annotationClazz));
163}
164
165/*
166 * static Annotation[][] getParameterAnnotations(Class declaringClass, int slot)
167 *
168 * Return the annotations declared for this method's parameters.
169 */
170static void Dalvik_java_lang_reflect_Method_getParameterAnnotations(
171    const u4* args, JValue* pResult)
172{
173    ClassObject* declaringClass = (ClassObject*) args[0];
174    int slot = args[1];
175    Method* meth;
176
177    meth = dvmSlotToMethod(declaringClass, slot);
178    assert(meth != NULL);
179
180    ArrayObject* annos = dvmGetParameterAnnotations(meth);
181    dvmReleaseTrackedAlloc((Object*)annos, NULL);
182    RETURN_PTR(annos);
183}
184
185/*
186 * private Object getDefaultValue(Class declaringClass, int slot)
187 *
188 * Return the default value for the annotation member represented by
189 * this Method instance.  Returns NULL if none is defined.
190 */
191static void Dalvik_java_lang_reflect_Method_getDefaultValue(const u4* args,
192    JValue* pResult)
193{
194    // ignore thisPtr in args[0]
195    ClassObject* declaringClass = (ClassObject*) args[1];
196    int slot = args[2];
197    Method* meth;
198
199    /* make sure this is an annotation class member */
200    if (!dvmIsAnnotationClass(declaringClass))
201        RETURN_PTR(NULL);
202
203    meth = dvmSlotToMethod(declaringClass, slot);
204    assert(meth != NULL);
205
206    Object* def = dvmGetAnnotationDefaultValue(meth);
207    dvmReleaseTrackedAlloc(def, NULL);
208    RETURN_PTR(def);
209}
210
211/*
212 * static Object[] getSignatureAnnotation()
213 *
214 * Returns the signature annotation.
215 */
216static void Dalvik_java_lang_reflect_Method_getSignatureAnnotation(
217    const u4* args, JValue* pResult)
218{
219    ClassObject* declaringClass = (ClassObject*) args[0];
220    int slot = args[1];
221    Method* meth;
222
223    meth = dvmSlotToMethod(declaringClass, slot);
224    assert(meth != NULL);
225
226    ArrayObject* arr = dvmGetMethodSignatureAnnotation(meth);
227    dvmReleaseTrackedAlloc((Object*) arr, NULL);
228    RETURN_PTR(arr);
229}
230
231const DalvikNativeMethod dvm_java_lang_reflect_Method[] = {
232    { "getMethodModifiers", "(Ljava/lang/Class;I)I",
233        Dalvik_java_lang_reflect_Method_getMethodModifiers },
234    { "invokeNative",       "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;",
235        Dalvik_java_lang_reflect_Method_invokeNative },
236    { "getDeclaredAnnotations", "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;",
237        Dalvik_java_lang_reflect_Method_getDeclaredAnnotations },
238    { "getAnnotation", "(Ljava/lang/Class;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;",
239        Dalvik_java_lang_reflect_Method_getAnnotation },
240    { "isAnnotationPresent", "(Ljava/lang/Class;ILjava/lang/Class;)Z",
241        Dalvik_java_lang_reflect_Method_isAnnotationPresent },
242    { "getParameterAnnotations", "(Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;",
243        Dalvik_java_lang_reflect_Method_getParameterAnnotations },
244    { "getDefaultValue",    "(Ljava/lang/Class;I)Ljava/lang/Object;",
245        Dalvik_java_lang_reflect_Method_getDefaultValue },
246    { "getSignatureAnnotation",  "(Ljava/lang/Class;I)[Ljava/lang/Object;",
247        Dalvik_java_lang_reflect_Method_getSignatureAnnotation },
248    { NULL, NULL, NULL },
249};
250