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 * private 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    // ignore thisPtr in args[0]
34    ClassObject* declaringClass = (ClassObject*) args[1];
35    int slot = args[2];
36    Method* meth;
37
38    meth = dvmSlotToMethod(declaringClass, slot);
39    RETURN_INT(dvmFixMethodFlags(meth->accessFlags));
40}
41
42/*
43 * private Object invokeNative(Object obj, Object[] args, Class declaringClass,
44 *   Class[] parameterTypes, Class returnType, int slot, boolean noAccessCheck)
45 *
46 * Invoke a static or virtual method via reflection.
47 */
48static void Dalvik_java_lang_reflect_Method_invokeNative(const u4* args,
49    JValue* pResult)
50{
51    // ignore thisPtr in args[0]
52    Object* methObj = (Object*) args[1];        // null for static methods
53    ArrayObject* argList = (ArrayObject*) args[2];
54    ClassObject* declaringClass = (ClassObject*) args[3];
55    ArrayObject* params = (ArrayObject*) args[4];
56    ClassObject* returnType = (ClassObject*) args[5];
57    int slot = args[6];
58    bool noAccessCheck = (args[7] != 0);
59    const Method* meth;
60    Object* result;
61
62    /*
63     * "If the underlying method is static, the class that declared the
64     * method is initialized if it has not already been initialized."
65     */
66    meth = dvmSlotToMethod(declaringClass, slot);
67    assert(meth != NULL);
68
69    if (dvmIsStaticMethod(meth)) {
70        if (!dvmIsClassInitialized(declaringClass)) {
71            if (!dvmInitClass(declaringClass))
72                goto init_failed;
73        }
74    } else {
75        /* looks like interfaces need this too? */
76        if (dvmIsInterfaceClass(declaringClass) &&
77            !dvmIsClassInitialized(declaringClass))
78        {
79            if (!dvmInitClass(declaringClass))
80                goto init_failed;
81        }
82
83        /* make sure the object is an instance of the expected class */
84        if (!dvmVerifyObjectInClass(methObj, declaringClass)) {
85            assert(dvmCheckException(dvmThreadSelf()));
86            RETURN_VOID();
87        }
88
89        /* do the virtual table lookup for the method */
90        meth = dvmGetVirtualizedMethod(methObj->clazz, meth);
91        if (meth == NULL) {
92            assert(dvmCheckException(dvmThreadSelf()));
93            RETURN_VOID();
94        }
95    }
96
97    /*
98     * If the method has a return value, "result" will be an object or
99     * a boxed primitive.
100     */
101    result = dvmInvokeMethod(methObj, meth, argList, params, returnType,
102                noAccessCheck);
103
104    RETURN_PTR(result);
105
106init_failed:
107    /*
108     * If initialization failed, an exception will be raised.
109     */
110    LOGD("Method.invoke() on bad class %s failed\n",
111        declaringClass->descriptor);
112    assert(dvmCheckException(dvmThreadSelf()));
113    RETURN_VOID();
114}
115
116/*
117 * public Annotation[] getDeclaredAnnotations(Class declaringClass, int slot)
118 *
119 * Return the annotations declared for this method.
120 */
121static void Dalvik_java_lang_reflect_Method_getDeclaredAnnotations(
122    const u4* args, JValue* pResult)
123{
124    // ignore thisPtr in args[0]
125    ClassObject* declaringClass = (ClassObject*) args[1];
126    int slot = args[2];
127    Method* meth;
128
129    meth = dvmSlotToMethod(declaringClass, slot);
130    assert(meth != NULL);
131
132    ArrayObject* annos = dvmGetMethodAnnotations(meth);
133    dvmReleaseTrackedAlloc((Object*)annos, NULL);
134    RETURN_PTR(annos);
135}
136
137/*
138 * public Annotation[] getParameterAnnotations(Class declaringClass, int slot)
139 *
140 * Return the annotations declared for this method's parameters.
141 */
142static void Dalvik_java_lang_reflect_Method_getParameterAnnotations(
143    const u4* args, JValue* pResult)
144{
145    // ignore thisPtr in args[0]
146    ClassObject* declaringClass = (ClassObject*) args[1];
147    int slot = args[2];
148    Method* meth;
149
150    meth = dvmSlotToMethod(declaringClass, slot);
151    assert(meth != NULL);
152
153    ArrayObject* annos = dvmGetParameterAnnotations(meth);
154    dvmReleaseTrackedAlloc((Object*)annos, NULL);
155    RETURN_PTR(annos);
156}
157
158/*
159 * private Object getDefaultValue(Class declaringClass, int slot)
160 *
161 * Return the default value for the annotation member represented by
162 * this Method instance.  Returns NULL if none is defined.
163 */
164static void Dalvik_java_lang_reflect_Method_getDefaultValue(const u4* args,
165    JValue* pResult)
166{
167    // ignore thisPtr in args[0]
168    ClassObject* declaringClass = (ClassObject*) args[1];
169    int slot = args[2];
170    Method* meth;
171
172    /* make sure this is an annotation class member */
173    if (!dvmIsAnnotationClass(declaringClass))
174        RETURN_PTR(NULL);
175
176    meth = dvmSlotToMethod(declaringClass, slot);
177    assert(meth != NULL);
178
179    Object* def = dvmGetAnnotationDefaultValue(meth);
180    dvmReleaseTrackedAlloc(def, NULL);
181    RETURN_PTR(def);
182}
183
184/*
185 * private Object[] getSignatureAnnotation()
186 *
187 * Returns the signature annotation.
188 */
189static void Dalvik_java_lang_reflect_Method_getSignatureAnnotation(
190    const u4* args, JValue* pResult)
191{
192    // ignore thisPtr in args[0]
193    ClassObject* declaringClass = (ClassObject*) args[1];
194    int slot = args[2];
195    Method* meth;
196
197    meth = dvmSlotToMethod(declaringClass, slot);
198    assert(meth != NULL);
199
200    ArrayObject* arr = dvmGetMethodSignatureAnnotation(meth);
201    dvmReleaseTrackedAlloc((Object*) arr, NULL);
202    RETURN_PTR(arr);
203}
204
205const DalvikNativeMethod dvm_java_lang_reflect_Method[] = {
206    { "getMethodModifiers", "(Ljava/lang/Class;I)I",
207        Dalvik_java_lang_reflect_Method_getMethodModifiers },
208    { "invokeNative",       "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;",
209        Dalvik_java_lang_reflect_Method_invokeNative },
210    { "getDeclaredAnnotations", "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;",
211        Dalvik_java_lang_reflect_Method_getDeclaredAnnotations },
212    { "getParameterAnnotations", "(Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;",
213        Dalvik_java_lang_reflect_Method_getParameterAnnotations },
214    { "getDefaultValue",    "(Ljava/lang/Class;I)Ljava/lang/Object;",
215        Dalvik_java_lang_reflect_Method_getDefaultValue },
216    { "getSignatureAnnotation",  "(Ljava/lang/Class;I)[Ljava/lang/Object;",
217        Dalvik_java_lang_reflect_Method_getSignatureAnnotation },
218    { NULL, NULL, NULL },
219};
220