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 ALOGE("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 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
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
ToJString(JNIEnv * env,const std::string & value)98 jstring ToJString(JNIEnv* env, const std::string& value) {
99 return env->NewStringUTF(value.c_str());
100 }
101
ToCppString(JNIEnv * env,jstring value)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
ToJBool(bool value)111 jboolean ToJBool(bool value) {
112 return value ? JNI_TRUE : JNI_FALSE;
113 }
114
ToCppBool(jboolean value)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.
IsJavaInstanceOf(JNIEnv * env,jobject object,const std::string & class_name)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>
CreateJObject(JNIEnv * env,const std::string & class_name,const std::string & signature,T value)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
ToCValue(JNIEnv * env,jobject object)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
ToJObject(JNIEnv * env,const Value & value)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