1 /* 2 * Copyright (C) 2011 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 <string> 18 19 #include "jni/jni_util.h" 20 21 #include "base/logging.h" 22 23 #if 0 24 JavaObject::JavaObject() 25 : object_(JNI_NULL), 26 ref_count_(new int(0)) { 27 } 28 29 JavaObject::JavaObject(const JavaObject& java_obj) 30 : object_(java_obj.object_), 31 ref_count_(java_obj.ref_count_) { 32 Retain(); 33 } 34 35 JavaObject::JavaObject(jobject object, JNIEnv* env) 36 : object_(NULL), 37 ref_count_(new int(0)) { 38 Retain(); 39 object_ = env->NewGlobalRef(object_); 40 } 41 42 JavaObject::~JavaObject() { 43 Release(); 44 } 45 46 JavaObject& JavaObject::operator=(const JavaObject& java_obj) { 47 Release(); 48 object_ = java_obj.object_; 49 ref_count_ = java_obj.ref_count_; 50 Retain(); 51 return *this; 52 } 53 54 void JavaObject::Retain() { 55 if (ref_count_) 56 ++(*ref_count_); 57 else 58 LOGE("JavaObject: Reference count is NULL! JavaObject may be corrupted."); 59 } 60 61 void JavaObject::Release() { 62 if (ref_count_) { 63 if (*ref_count_ > 0) 64 --(*ref_count_); 65 if (*ref_count_ == 0) { 66 JNIEnv* env = GetCurrentJNIEnv(); 67 if (!env) 68 LOGE("JavaObject: Releasing outside of Java thread. Will just leak!"); 69 else if (object_) 70 env->DeleteGlobalRef(object_); 71 delete ref_count_; 72 ref_count_ = NULL; 73 } 74 } else { 75 LOGE("JavaObject: Reference count is NULL! JavaObject may be corrupted."); 76 } 77 } 78 79 void JavaObject::Reset() { 80 Release(); 81 object_ = NULL; 82 ref_count_ = new int(0); 83 } 84 85 JavaVM* GetCurrentJavaVM() { 86 return g_current_java_vm_; 87 } 88 89 JNIEnv* GetCurrentJNIEnv() { 90 JavaVM* vm = GetCurrentJavaVM(); 91 JNIEnv* env = NULL; 92 const jint result = vm->GetEnv(reinterpret_cast<void**>(&env), 93 JNI_VERSION_1_4); 94 return result == JNI_OK ? env : NULL; 95 } 96 #endif 97 98 jstring ToJString(JNIEnv* env, const std::string& value) { 99 return env->NewStringUTF(value.c_str()); 100 } 101 102 std::string ToCppString(JNIEnv* env, jstring value) { 103 jboolean isCopy; 104 const char* c_value = env->GetStringUTFChars(value, &isCopy); 105 std::string result(c_value); 106 if (isCopy == JNI_TRUE) 107 env->ReleaseStringUTFChars(value, c_value); 108 return result; 109 } 110 111 jboolean ToJBool(bool value) { 112 return value ? JNI_TRUE : JNI_FALSE; 113 } 114 115 bool ToCppBool(jboolean value) { 116 return value == JNI_TRUE; 117 } 118 119 // TODO: We actually shouldn't use such a function as it requires a class name lookup at every 120 // invocation. Instead, store the class objects and use those. 121 bool IsJavaInstanceOf(JNIEnv* env, jobject object, const std::string& class_name) { 122 jclass clazz = env->FindClass(class_name.c_str()); 123 return clazz ? env->IsInstanceOf(object, clazz) == JNI_TRUE : false; 124 } 125 126 template<typename T> 127 jobject CreateJObject(JNIEnv* env, const std::string& class_name, const std::string& signature, T value) { 128 jobject result = JNI_NULL; 129 130 return result; 131 } 132 133 Value ToCValue(JNIEnv* env, jobject object) { 134 Value result = MakeNullValue(); 135 if (object != NULL) { 136 if (IsJavaInstanceOf(env, object, "java/lang/Boolean")) { 137 jmethodID method = env->GetMethodID(env->GetObjectClass(object), "booleanValue", "()Z"); 138 result = MakeIntValue(env->CallBooleanMethod(object, method) == JNI_TRUE ? 1 : 0); 139 } else if (IsJavaInstanceOf(env, object, "java/lang/Integer")) { 140 jmethodID method = env->GetMethodID(env->GetObjectClass(object), "intValue", "()I"); 141 result = MakeIntValue(env->CallIntMethod(object, method)); 142 } else if (IsJavaInstanceOf(env, object, "java/lang/Float")) { 143 jmethodID method = env->GetMethodID(env->GetObjectClass(object), "floatValue", "()F"); 144 result = MakeFloatValue(env->CallFloatMethod(object, method)); 145 } else if (IsJavaInstanceOf(env, object, "java/lang/String")) { 146 result = MakeStringValue(ToCppString(env, static_cast<jstring>(object)).c_str()); 147 } else if (IsJavaInstanceOf(env, object, "[I")) { 148 jint* elems = env->GetIntArrayElements(static_cast<jintArray>(object), NULL); 149 const jint count = env->GetArrayLength(static_cast<jintArray>(object)); 150 result = MakeIntArrayValue(elems, count); 151 env->ReleaseIntArrayElements(static_cast<jintArray>(object), elems, JNI_ABORT); 152 } else if (IsJavaInstanceOf(env, object, "[F")) { 153 jfloat* elems = env->GetFloatArrayElements(static_cast<jfloatArray>(object), NULL); 154 const jint count = env->GetArrayLength(static_cast<jfloatArray>(object)); 155 result = MakeFloatArrayValue(elems, count); 156 env->ReleaseFloatArrayElements(static_cast<jfloatArray>(object), elems, JNI_ABORT); 157 } 158 } 159 return result; 160 } 161 162 jobject ToJObject(JNIEnv* env, const Value& value) { 163 jobject result = JNI_NULL; 164 if (ValueIsInt(value)) { 165 jclass clazz = env->FindClass("java/lang/Integer"); 166 jmethodID constructorID = env->GetMethodID(clazz, "<init>", "(I)V"); 167 result = env->NewObject(clazz, constructorID, GetIntValue(value)); 168 } else if (ValueIsFloat(value)) { 169 jclass clazz = env->FindClass("java/lang/Float"); 170 jmethodID constructorID = env->GetMethodID(clazz, "<init>", "(F)V"); 171 result = env->NewObject(clazz, constructorID, GetFloatValue(value)); 172 } else if (ValueIsString(value)) { 173 result = ToJString(env, GetStringValue(value)); 174 } else if (ValueIsIntArray(value)) { 175 result = env->NewIntArray(GetValueCount(value)); 176 env->SetIntArrayRegion(static_cast<jintArray>(result), 177 0, 178 GetValueCount(value), 179 reinterpret_cast<const jint*>(GetIntArrayValue(value))); 180 } else if (ValueIsFloatArray(value)) { 181 result = env->NewFloatArray(GetValueCount(value)); 182 env->SetFloatArrayRegion(static_cast<jfloatArray>(result), 183 0, 184 GetValueCount(value), 185 reinterpret_cast<const jfloat*>(GetFloatArrayValue(value))); 186 } 187 return result; 188 } 189