summaryrefslogtreecommitdiffstats
path: root/src/java_lang_Class.cc
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2011-09-23 17:24:51 -0700
committerElliott Hughes <enh@google.com>2011-09-23 18:08:21 -0700
commit8060925c45cc2607ab92390d7366c6c0cfdfe4bb (patch)
tree42a50d2de4cc7622b19d6cd7a20b3d99d60a00a2 /src/java_lang_Class.cc
parentbc2f3e3e41d02eb2896dc16390c5c4023a7b5649 (diff)
downloadart-8060925c45cc2607ab92390d7366c6c0cfdfe4bb.zip
art-8060925c45cc2607ab92390d7366c6c0cfdfe4bb.tar.gz
art-8060925c45cc2607ab92390d7366c6c0cfdfe4bb.tar.bz2
Implement Class.getDeclared(Constructors|Fields|Methods).
This required making sure that a Method* that represents a constructor has java.lang.reflect.Constructor as its class. Change-Id: I25908845a2b8d686d5404ac584693db0edd5853c
Diffstat (limited to 'src/java_lang_Class.cc')
-rw-r--r--src/java_lang_Class.cc112
1 files changed, 108 insertions, 4 deletions
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index c334f04..d77e3f0 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -18,6 +18,7 @@
#include "class_linker.h"
#include "class_loader.h"
#include "object.h"
+#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -53,6 +54,107 @@ jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initia
return AddLocalReference<jclass>(env, c);
}
+template<typename T>
+jobjectArray ToArray(JNIEnv* env, const char* array_class_name, const std::vector<T*>& objects) {
+ jclass array_class = env->FindClass(array_class_name);
+ jobjectArray result = env->NewObjectArray(objects.size(), array_class, NULL);
+ for (size_t i = 0; i < objects.size(); ++i) {
+ ScopedLocalRef<jobject> object(env, AddLocalReference<jobject>(env, objects[i]));
+ env->SetObjectArrayElement(result, i, object.get());
+ }
+ return result;
+}
+
+bool IsVisibleConstructor(Method* m, bool public_only) {
+ if (public_only && !m->IsPublic()) {
+ return false;
+ }
+ if (m->IsMiranda() || m->IsStatic()) {
+ return false;
+ }
+ if (m->GetName()->CharAt(0) != '<') {
+ return false;
+ }
+ m->InitJavaFields();
+ return true;
+}
+
+jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+ Class* c = Decode<Class*>(env, javaClass);
+
+ std::vector<Method*> constructors;
+ for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
+ Method* m = c->GetDirectMethod(i);
+ if (IsVisibleConstructor(m, publicOnly)) {
+ constructors.push_back(m);
+ }
+ }
+
+ return ToArray(env, "java/lang/reflect/Constructor", constructors);
+}
+
+bool IsVisibleField(Field* f, bool public_only) {
+ if (public_only && ~f->IsPublic()) {
+ return false;
+ }
+ f->InitJavaFields();
+ return true;
+}
+
+jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+ Class* c = Decode<Class*>(env, javaClass);
+
+ std::vector<Field*> fields;
+ for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
+ Field* f = c->GetInstanceField(i);
+ if (IsVisibleField(f, publicOnly)) {
+ fields.push_back(f);
+ }
+ }
+ for (size_t i = 0; i < c->NumStaticFields(); ++i) {
+ Field* f = c->GetStaticField(i);
+ if (IsVisibleField(f, publicOnly)) {
+ fields.push_back(f);
+ }
+ }
+
+ return ToArray(env, "java/lang/reflect/Field", fields);
+}
+
+bool IsVisibleMethod(Method* m, bool public_only) {
+ if (public_only && !m->IsPublic()) {
+ return false;
+ }
+ if (m->IsMiranda()) {
+ return false;
+ }
+ if (m->GetName()->CharAt(0) == '<') {
+ return false;
+ }
+ m->InitJavaFields();
+ return true;
+}
+
+jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
+ Class* c = Decode<Class*>(env, javaClass);
+
+ std::vector<Method*> methods;
+ for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
+ Method* m = c->GetVirtualMethod(i);
+ if (IsVisibleMethod(m, publicOnly)) {
+ methods.push_back(m);
+ }
+ }
+ for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
+ Method* m = c->GetDirectMethod(i);
+ if (IsVisibleMethod(m, publicOnly)) {
+ methods.push_back(m);
+ }
+ }
+
+ return ToArray(env, "java/lang/reflect/Method", methods);
+}
+
jboolean Class_desiredAssertionStatus(JNIEnv* env, jobject javaThis) {
return JNI_FALSE;
}
@@ -115,15 +217,17 @@ jobject Class_getDeclaredField(JNIEnv* env, jclass, jclass jklass, jobject jname
String* name = Decode<String*>(env, jname);
DCHECK(name->IsString());
- for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+ for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
Field* f = klass->GetInstanceField(i);
if (f->GetName()->Equals(name)) {
+ f->InitJavaFields();
return AddLocalReference<jclass>(env, f);
}
}
for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
Field* f = klass->GetStaticField(i);
if (f->GetName()->Equals(name)) {
+ f->InitJavaFields();
return AddLocalReference<jclass>(env, f);
}
}
@@ -319,10 +423,10 @@ static JNINativeMethod gMethods[] = {
NATIVE_METHOD(Class, getClassLoader, "(Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
NATIVE_METHOD(Class, getComponentType, "()Ljava/lang/Class;"),
NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
- //NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
+ NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
NATIVE_METHOD(Class, getDeclaredField, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;"),
- //NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
- //NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
+ NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
NATIVE_METHOD(Class, getDeclaringClass, "()Ljava/lang/Class;"),
//NATIVE_METHOD(Class, getEnclosingClass, "()Ljava/lang/Class;"),
NATIVE_METHOD(Class, getEnclosingConstructor, "()Ljava/lang/reflect/Constructor;"),