blob: 0c6bbe5abbd7f80b5906ac99ab999f11a87c2020 [file] [log] [blame]
Elliott Hughesd369bb72011-09-12 14:41:14 -07001/*
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#include "jni_internal.h"
18#include "class_linker.h"
19#include "object.h"
20
21#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
22
23namespace art {
24
25namespace {
26
Elliott Hughes6bdc3b22011-09-16 19:24:10 -070027jboolean Class_desiredAssertionStatus(JNIEnv* env, jobject javaThis) {
28 return JNI_FALSE;
29}
30
31jobject Class_getClassLoader(JNIEnv* env, jclass, jobject javaClass) {
32 Class* c = Decode<Class*>(env, javaClass);
33 Object* result = reinterpret_cast<Object*>(const_cast<ClassLoader*>(c->GetClassLoader()));
34 return AddLocalReference<jobject>(env, result);
35}
36
Elliott Hughesd369bb72011-09-12 14:41:14 -070037jclass Class_getComponentType(JNIEnv* env, jobject javaThis) {
38 Class* c = Decode<Class*>(env, javaThis);
39 if (!c->IsArrayClass()) {
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -070040 return NULL;
Elliott Hughesd369bb72011-09-12 14:41:14 -070041 }
42
43 /*
44 * We can't just return c->GetComponentType(), because that gives
45 * us the base type (e.g. X[][][] returns X). If this is a multi-
46 * dimensional array, we have to do the lookup by name.
47 */
48 Class* result;
49 std::string descriptor(c->GetDescriptor()->ToModifiedUtf8());
50 if (descriptor[1] == '[') {
51 result = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str() + 1, c->GetClassLoader());
52 } else {
53 result = c->GetComponentType();
54 }
55 return AddLocalReference<jclass>(env, result);
Elliott Hughesd369bb72011-09-12 14:41:14 -070056}
57
58jobjectArray Class_getDeclaredClasses(JNIEnv* env, jclass java_lang_Class_class, jclass c, jboolean publicOnly) {
Elliott Hughes6bdc3b22011-09-16 19:24:10 -070059 UNIMPLEMENTED(WARNING) << "needs annotations";
Elliott Hughesd369bb72011-09-12 14:41:14 -070060 return env->NewObjectArray(0, java_lang_Class_class, NULL);
61}
62
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -070063jobject Class_getDeclaredConstructorOrMethod(JNIEnv* env, jclass,
64 jclass jklass, jstring jname, jobjectArray jsignature) {
65 Class* klass = Decode<Class*>(env, jklass);
66 DCHECK(klass->IsClass());
67 String* name = Decode<String*>(env, jname);
68 DCHECK(name->IsString());
69 Object* signature_obj = Decode<Object*>(env, jsignature);
70 DCHECK(signature_obj->IsArrayInstance());
71 // check that this is a Class[] by checkin that component type is Class
72 // foo->GetClass()->GetClass() is an idiom for getting java.lang.Class from an arbitrary object
73 DCHECK(signature_obj->GetClass()->GetComponentType() == signature_obj->GetClass()->GetClass());
74 ObjectArray<Class>* signature = down_cast<ObjectArray<Class>*>(signature_obj);
75
76 std::string name_string = name->ToModifiedUtf8();
77 std::string signature_string;
78 signature_string += "(";
79 for (int i = 0; i < signature->GetLength(); i++) {
80 Class* argument_class = signature->Get(0);
81 if (argument_class == NULL) {
82 UNIMPLEMENTED(FATAL) << "throw null pointer exception?";
83 }
84 signature_string += argument_class->GetDescriptor()->ToModifiedUtf8();
85 }
86 signature_string += ")";
87
88 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
89 Method* method = klass->GetVirtualMethod(i);
90 if (!method->GetName()->Equals(name)) {
91 continue;
92 }
93 std::string method_signature = method->GetSignature()->ToModifiedUtf8();
94 if (!StringPiece(method_signature).starts_with(signature_string)) {
95 continue;
96 }
97 return AddLocalReference<jobject>(env, method);
98 }
99
100 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
101 Method* method = klass->GetVirtualMethod(i);
102 if (!method->GetName()->Equals(name)) {
103 continue;
104 }
105 std::string method_signature = method->GetSignature()->ToModifiedUtf8();
106 if (!StringPiece(method_signature).starts_with(signature_string)) {
107 continue;
108 }
109 return AddLocalReference<jobject>(env, method);
110 }
111
112 return NULL;
113}
114
115jobject Class_getDeclaredField(JNIEnv* env, jclass, jclass jklass, jobject jname) {
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700116 Class* klass = Decode<Class*>(env, jklass);
117 DCHECK(klass->IsClass());
118 String* name = Decode<String*>(env, jname);
119 DCHECK(name->IsString());
120
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700121 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700122 Field* f = klass->GetInstanceField(i);
123 if (f->GetName()->Equals(name)) {
124 return AddLocalReference<jclass>(env, f);
125 }
126 }
127 for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
128 Field* f = klass->GetStaticField(i);
129 if (f->GetName()->Equals(name)) {
130 return AddLocalReference<jclass>(env, f);
131 }
132 }
133 return NULL;
134}
135
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700136jclass Class_getDeclaringClass(JNIEnv* env, jobject javaThis) {
137 UNIMPLEMENTED(WARNING) << "needs annotations";
138 return NULL;
139}
140
141jobject Class_getEnclosingConstructor(JNIEnv* env, jobject javaThis) {
142 UNIMPLEMENTED(WARNING) << "needs annotations";
143 return NULL;
144}
145
146jobject Class_getEnclosingMethod(JNIEnv* env, jobject javaThis) {
147 UNIMPLEMENTED(WARNING) << "needs annotations";
148 return NULL;
149}
150
151/*
152 * private native String getNameNative()
153 *
154 * Return the class' name. The exact format is bizarre, but it's the specified
155 * behavior: keywords for primitive types, regular "[I" form for primitive
156 * arrays (so "int" but "[I"), and arrays of reference types written
157 * between "L" and ";" but with dots rather than slashes (so "java.lang.String"
158 * but "[Ljava.lang.String;"). Madness.
159 */
160jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
161 Class* c = Decode<Class*>(env, javaThis);
162 std::string descriptor(c->GetDescriptor()->ToModifiedUtf8());
163 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
164 // The descriptor indicates that this is the class for
165 // a primitive type; special-case the return value.
166 const char* name = NULL;
167 switch (descriptor[0]) {
168 case 'Z': name = "boolean"; break;
169 case 'B': name = "byte"; break;
170 case 'C': name = "char"; break;
171 case 'S': name = "short"; break;
172 case 'I': name = "int"; break;
173 case 'J': name = "long"; break;
174 case 'F': name = "float"; break;
175 case 'D': name = "double"; break;
176 case 'V': name = "void"; break;
177 default:
178 LOG(FATAL) << "Unknown primitive type: " << PrintableChar(descriptor[0]);
179 }
180 return env->NewStringUTF(name);
181 }
182
183 // Convert the UTF-8 name to a java.lang.String. The
184 // name must use '.' to separate package components.
185 if (descriptor.size() > 2 && descriptor[0] == 'L' && descriptor[descriptor.size() - 1] == ';') {
186 descriptor.erase(0, 1);
187 descriptor.erase(descriptor.size() - 1);
188 }
189 std::replace(descriptor.begin(), descriptor.end(), '/', '.');
190 return env->NewStringUTF(descriptor.c_str());
191}
192
193jclass Class_getSuperclass(JNIEnv* env, jobject javaThis) {
194 Class* c = Decode<Class*>(env, javaThis);
195 Class* result = c->GetSuperClass();
196 return AddLocalReference<jclass>(env, result);
197}
198
199jboolean Class_isAnonymousClass(JNIEnv* env, jobject javaThis) {
200 UNIMPLEMENTED(WARNING) << "needs annotations";
201 return JNI_FALSE;
202}
203
204jboolean Class_isInterface(JNIEnv* env, jobject javaThis) {
205 Class* c = Decode<Class*>(env, javaThis);
206 return c->IsInterface();
207}
208
209jboolean Class_isPrimitive(JNIEnv* env, jobject javaThis) {
210 Class* c = Decode<Class*>(env, javaThis);
211 return c->IsPrimitive();
212}
213
Elliott Hughesd369bb72011-09-12 14:41:14 -0700214static JNINativeMethod gMethods[] = {
215 //NATIVE_METHOD(Class, classForName, "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700216 NATIVE_METHOD(Class, desiredAssertionStatus, "()Z"),
217 NATIVE_METHOD(Class, getClassLoader, "(Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700218 NATIVE_METHOD(Class, getComponentType, "()Ljava/lang/Class;"),
219 //NATIVE_METHOD(Class, getDeclaredAnnotation, "(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"),
220 //NATIVE_METHOD(Class, getDeclaredAnnotations, "()[Ljava/lang/annotation/Annotation;"),
221 NATIVE_METHOD(Class, getDeclaredClasses, "(Ljava/lang/Class;Z)[Ljava/lang/Class;"),
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700222 NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700223 //NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700224 NATIVE_METHOD(Class, getDeclaredField, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700225 //NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
226 //NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700227 NATIVE_METHOD(Class, getDeclaringClass, "()Ljava/lang/Class;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700228 //NATIVE_METHOD(Class, getEnclosingClass, "()Ljava/lang/Class;"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700229 NATIVE_METHOD(Class, getEnclosingConstructor, "()Ljava/lang/reflect/Constructor;"),
230 NATIVE_METHOD(Class, getEnclosingMethod, "()Ljava/lang/reflect/Method;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700231 //NATIVE_METHOD(Class, getInnerClassName, "()Ljava/lang/String;"),
232 //NATIVE_METHOD(Class, getInterfaces, "()[Ljava/lang/Class;"),
233 //NATIVE_METHOD(Class, getModifiers, "(Ljava/lang/Class;Z)I"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700234 NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700235 //NATIVE_METHOD(Class, getSignatureAnnotation, "()[Ljava/lang/Object;"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700236 NATIVE_METHOD(Class, getSuperclass, "()Ljava/lang/Class;"),
237 NATIVE_METHOD(Class, isAnonymousClass, "()Z"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700238 //NATIVE_METHOD(Class, isAssignableFrom, "(Ljava/lang/Class;)Z"),
239 //NATIVE_METHOD(Class, isDeclaredAnnotationPresent, "(Ljava/lang/Class;)Z"),
240 //NATIVE_METHOD(Class, isInstance, "(Ljava/lang/Object;)Z"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700241 NATIVE_METHOD(Class, isInterface, "()Z"),
242 NATIVE_METHOD(Class, isPrimitive, "()Z"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700243 //NATIVE_METHOD(Class, newInstanceImpl, "()Ljava/lang/Object;"),
244};
245
246} // namespace
247
248void register_java_lang_Class(JNIEnv* env) {
249 jniRegisterNativeMethods(env, "java/lang/Class", gMethods, NELEM(gMethods));
250}
251
252} // namespace art