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 24JavaObject::JavaObject() 25 : object_(JNI_NULL), 26 ref_count_(new int(0)) { 27} 28 29JavaObject::JavaObject(const JavaObject& java_obj) 30 : object_(java_obj.object_), 31 ref_count_(java_obj.ref_count_) { 32 Retain(); 33} 34 35JavaObject::JavaObject(jobject object, JNIEnv* env) 36 : object_(NULL), 37 ref_count_(new int(0)) { 38 Retain(); 39 object_ = env->NewGlobalRef(object_); 40} 41 42JavaObject::~JavaObject() { 43 Release(); 44} 45 46JavaObject& 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 54void JavaObject::Retain() { 55 if (ref_count_) 56 ++(*ref_count_); 57 else 58 ALOGE("JavaObject: Reference count is NULL! JavaObject may be corrupted."); 59} 60 61void 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 ALOGE("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 ALOGE("JavaObject: Reference count is NULL! JavaObject may be corrupted."); 76 } 77} 78 79void JavaObject::Reset() { 80 Release(); 81 object_ = NULL; 82 ref_count_ = new int(0); 83} 84 85JavaVM* GetCurrentJavaVM() { 86 return g_current_java_vm_; 87} 88 89JNIEnv* 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 98jstring ToJString(JNIEnv* env, const std::string& value) { 99 return env->NewStringUTF(value.c_str()); 100} 101 102std::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 111jboolean ToJBool(bool value) { 112 return value ? JNI_TRUE : JNI_FALSE; 113} 114 115bool 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. 121bool 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 126template<typename T> 127jobject 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 133Value 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 162jobject 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