More java.lang.Class functionality.

(Some of these are just stubs, but I need them to get the GC daemons
going.)

Change-Id: I3c472bf06d3a11a183781605cd3ed9fc67640d33
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index b91410d..7648425 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -24,6 +24,16 @@
 
 namespace {
 
+jboolean Class_desiredAssertionStatus(JNIEnv* env, jobject javaThis) {
+    return JNI_FALSE;
+}
+
+jobject Class_getClassLoader(JNIEnv* env, jclass, jobject javaClass) {
+  Class* c = Decode<Class*>(env, javaClass);
+  Object* result = reinterpret_cast<Object*>(const_cast<ClassLoader*>(c->GetClassLoader()));
+  return AddLocalReference<jobject>(env, result);
+}
+
 jclass Class_getComponentType(JNIEnv* env, jobject javaThis) {
   Class* c = Decode<Class*>(env, javaThis);
   if (!c->IsArrayClass()) {
@@ -46,14 +56,92 @@
 }
 
 jobjectArray Class_getDeclaredClasses(JNIEnv* env, jclass java_lang_Class_class, jclass c, jboolean publicOnly) {
-  UNIMPLEMENTED(WARNING);
+  UNIMPLEMENTED(WARNING) << "needs annotations";
   return env->NewObjectArray(0, java_lang_Class_class, NULL);
 }
 
+jclass Class_getDeclaringClass(JNIEnv* env, jobject javaThis) {
+  UNIMPLEMENTED(WARNING) << "needs annotations";
+  return NULL;
+}
+
+jobject Class_getEnclosingConstructor(JNIEnv* env, jobject javaThis) {
+  UNIMPLEMENTED(WARNING) << "needs annotations";
+  return NULL;
+}
+
+jobject Class_getEnclosingMethod(JNIEnv* env, jobject javaThis) {
+  UNIMPLEMENTED(WARNING) << "needs annotations";
+  return NULL;
+}
+
+/*
+ * private native String getNameNative()
+ *
+ * Return the class' name. The exact format is bizarre, but it's the specified
+ * behavior: keywords for primitive types, regular "[I" form for primitive
+ * arrays (so "int" but "[I"), and arrays of reference types written
+ * between "L" and ";" but with dots rather than slashes (so "java.lang.String"
+ * but "[Ljava.lang.String;"). Madness.
+ */
+jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
+  Class* c = Decode<Class*>(env, javaThis);
+  std::string descriptor(c->GetDescriptor()->ToModifiedUtf8());
+  if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
+    // The descriptor indicates that this is the class for
+    // a primitive type; special-case the return value.
+    const char* name = NULL;
+    switch (descriptor[0]) {
+    case 'Z': name = "boolean"; break;
+    case 'B': name = "byte";    break;
+    case 'C': name = "char";    break;
+    case 'S': name = "short";   break;
+    case 'I': name = "int";     break;
+    case 'J': name = "long";    break;
+    case 'F': name = "float";   break;
+    case 'D': name = "double";  break;
+    case 'V': name = "void";    break;
+    default:
+      LOG(FATAL) << "Unknown primitive type: " << PrintableChar(descriptor[0]);
+    }
+    return env->NewStringUTF(name);
+  }
+
+  // Convert the UTF-8 name to a java.lang.String. The
+  // name must use '.' to separate package components.
+  if (descriptor.size() > 2 && descriptor[0] == 'L' && descriptor[descriptor.size() - 1] == ';') {
+    descriptor.erase(0, 1);
+    descriptor.erase(descriptor.size() - 1);
+  }
+  std::replace(descriptor.begin(), descriptor.end(), '/', '.');
+  return env->NewStringUTF(descriptor.c_str());
+}
+
+jclass Class_getSuperclass(JNIEnv* env, jobject javaThis) {
+  Class* c = Decode<Class*>(env, javaThis);
+  Class* result = c->GetSuperClass();
+  return AddLocalReference<jclass>(env, result);
+}
+
+jboolean Class_isAnonymousClass(JNIEnv* env, jobject javaThis) {
+  UNIMPLEMENTED(WARNING) << "needs annotations";
+  return JNI_FALSE;
+}
+
+jboolean Class_isInterface(JNIEnv* env, jobject javaThis) {
+  Class* c = Decode<Class*>(env, javaThis);
+  return c->IsInterface();
+}
+
+jboolean Class_isPrimitive(JNIEnv* env, jobject javaThis) {
+  Class* c = Decode<Class*>(env, javaThis);
+  return c->IsPrimitive();
+}
+
 static JNINativeMethod gMethods[] = {
   //NATIVE_METHOD(Class, classForName, "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
-  //NATIVE_METHOD(Class, desiredAssertionStatus, "()Z"),
-  //NATIVE_METHOD(Class, getClassLoader, "(Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
+  NATIVE_METHOD(Class, desiredAssertionStatus, "()Z"),
+  NATIVE_METHOD(Class, getClassLoader, "(Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
   NATIVE_METHOD(Class, getComponentType, "()Ljava/lang/Class;"),
   //NATIVE_METHOD(Class, getDeclaredAnnotation, "(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"),
   //NATIVE_METHOD(Class, getDeclaredAnnotations, "()[Ljava/lang/annotation/Annotation;"),
@@ -63,22 +151,22 @@
   //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, getDeclaringClass, "()Ljava/lang/Class;"),
+  NATIVE_METHOD(Class, getDeclaringClass, "()Ljava/lang/Class;"),
   //NATIVE_METHOD(Class, getEnclosingClass, "()Ljava/lang/Class;"),
-  //NATIVE_METHOD(Class, getEnclosingConstructor, "()Ljava/lang/reflect/Constructor;"),
-  //NATIVE_METHOD(Class, getEnclosingMethod, "()Ljava/lang/reflect/Method;"),
+  NATIVE_METHOD(Class, getEnclosingConstructor, "()Ljava/lang/reflect/Constructor;"),
+  NATIVE_METHOD(Class, getEnclosingMethod, "()Ljava/lang/reflect/Method;"),
   //NATIVE_METHOD(Class, getInnerClassName, "()Ljava/lang/String;"),
   //NATIVE_METHOD(Class, getInterfaces, "()[Ljava/lang/Class;"),
   //NATIVE_METHOD(Class, getModifiers, "(Ljava/lang/Class;Z)I"),
-  //NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
+  NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
   //NATIVE_METHOD(Class, getSignatureAnnotation, "()[Ljava/lang/Object;"),
-  //NATIVE_METHOD(Class, getSuperclass, "()Ljava/lang/Class;"),
-  //NATIVE_METHOD(Class, isAnonymousClass, "()Z"),
+  NATIVE_METHOD(Class, getSuperclass, "()Ljava/lang/Class;"),
+  NATIVE_METHOD(Class, isAnonymousClass, "()Z"),
   //NATIVE_METHOD(Class, isAssignableFrom, "(Ljava/lang/Class;)Z"),
   //NATIVE_METHOD(Class, isDeclaredAnnotationPresent, "(Ljava/lang/Class;)Z"),
   //NATIVE_METHOD(Class, isInstance, "(Ljava/lang/Object;)Z"),
-  //NATIVE_METHOD(Class, isInterface, "()Z"),
-  //NATIVE_METHOD(Class, isPrimitive, "()Z"),
+  NATIVE_METHOD(Class, isInterface, "()Z"),
+  NATIVE_METHOD(Class, isPrimitive, "()Z"),
   //NATIVE_METHOD(Class, newInstanceImpl, "()Ljava/lang/Object;"),
 };