Modify permissions for files in Things Manager
[platform/upstream/iotivity.git] / service / easy-setup / sdk / mediator / android / jni / jniutil / src / jni_easy_setup_jvm.cpp
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20 #include "jni_easy_setup_jvm.h"
21 #include <string>
22 #include "jni_easy_setup.h"
23
24 /**
25  * @class   JClassMap
26  * @brief   This class provides functions for initializing the Java class path and Java class.
27  *
28  */
29 class JClassMap {
30 public:
31     /**
32      *  Java Class
33      */
34     jclass classRef;
35     /**
36      *  Java Class Path
37      */
38     const char *szClassPath;
39
40     /**
41      * @brief constructor
42      */
43     JClassMap(const char *path) :
44             classRef(NULL) {
45         szClassPath = path;
46     }
47 };
48
49 /**
50  * @class   JObjectMap
51  * @brief   This class provides functins for initializing the Java Class path and Java Class
52  * Object.
53  *
54  */
55 class JObjectMap {
56 public:
57     /**
58      *  Java Object
59      */
60     jobject object;
61     /**
62      *  Java Class Path
63      */
64     const char *szClassPath;
65
66     /**
67      * @brief constructor
68      */
69     JObjectMap(const char *path) :
70             object(NULL) {
71         szClassPath = path;
72     }
73 };
74
75 static JClassMap gJClassMapArray[] = { JClassMap(
76         EASY_SETUP_SERVICE_NATIVE_API_CLASS_PATH), JClassMap(
77         EASY_SETUP_SERVICE_CALLBACK_NATIVE_API_CLASS_PATH) };
78
79 static JObjectMap gJObjectMapArray[] = { JObjectMap(
80         EASY_SETUP_SERVICE_CALLBACK_NATIVE_API_CLASS_PATH) };
81
82 static JNINativeMethod gEasySetupMethodTable[] = {
83     { "InitEasySetup", "()V", (void *) JNIInitEasySetup },
84     { "TerminateEasySetup", "()V", (void *) JNITerminateEasySetup },
85     { "ProvisionEnrollee", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V",
86                                 (void *) JNIProvisionEnrollee },
87     { "StopEnrolleeProvisioning", "(I)V", (void *) JNIStopEnrolleeProvisioning }, };
88
89 static int gEasySetupMethodTableSize = sizeof(gEasySetupMethodTable)
90         / sizeof(gEasySetupMethodTable[0]);
91
92 int InitializeJClassMapArray(JNIEnv *env) {
93     LOGI("InitializeJClassMapArray: Enter");
94
95     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
96
97     for (unsigned int i = 0; i < nLen; i++) {
98         jclass classRef = env->FindClass(gJClassMapArray[i].szClassPath);
99         if (NULL == classRef) {
100             LOGE("FindClass failed for [%s]", gJClassMapArray[i].szClassPath);
101             return -1;
102         }
103         gJClassMapArray[i].classRef = (jclass) env->NewGlobalRef(classRef);
104         env->DeleteLocalRef(classRef);
105     }
106
107     LOGI("InitializeJClassMapArray: Exit");
108     return 0;
109 }
110
111 jclass GetJClass(const char *szClassPath) {
112     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
113
114     jclass classRef = NULL;
115
116     for (unsigned int i = 0; i < nLen; i++) {
117         if (0 == strcmp(gJClassMapArray[i].szClassPath, szClassPath)) {
118             classRef = gJClassMapArray[i].classRef;
119             break;
120         }
121     }
122
123     return classRef;
124 }
125
126 void DeleteClassMapArray(JNIEnv *env) {
127     LOGI("DeleteClassMapArray: Enter");
128
129     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
130     for (unsigned int i = 0; i < nLen; i++) {
131         if (NULL != gJClassMapArray[i].classRef) {
132             env->DeleteGlobalRef(gJClassMapArray[i].classRef);
133             gJClassMapArray[i].classRef = NULL;
134         }
135     }
136
137     LOGI("DeleteClassMapArray: Exit");
138 }
139
140 int InitializeJObjectMapArray(JNIEnv *env) {
141     LOGI("InitializeJObjectMapArray: Enter");
142
143     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
144
145     for (unsigned int i = 0; i < nLen; i++) {
146         jclass classRef = env->FindClass(gJObjectMapArray[i].szClassPath);
147         if (NULL == classRef) {
148             LOGE("InitializeJObjectMapArray: FindClass failed for [%s]",
149                     gJObjectMapArray[i].szClassPath);
150             return -1;
151         }
152
153         std::string methodSignature = "()L";
154         methodSignature.append(gJObjectMapArray[i].szClassPath);
155         methodSignature.append(";");
156
157         // Get the object form "getInstance"
158         jmethodID methodid = env->GetStaticMethodID(classRef, "getInstance",
159                 methodSignature.c_str());
160         if (NULL == methodid) {
161             LOGE("InitializeJObjectMapArray: GetStaticMethodID failed for [%s]",
162                     gJObjectMapArray[i].szClassPath);
163             return -1;
164         }
165
166         // Get the singleton object
167         jobject objectRef = (jobject) env->CallStaticObjectMethod(classRef,
168                 methodid);
169         if (NULL == objectRef) {
170             LOGE(
171                     "InitializeJObjectMapArray: CallStaticObjectMethod failed for [%s]",
172                     gJObjectMapArray[i].szClassPath);
173             return -1;
174         }
175
176         gJObjectMapArray[i].object = (jobject) env->NewGlobalRef(objectRef);
177         env->DeleteLocalRef(classRef);
178     }
179
180     LOGI("InitializeJObjectMapArray: Exit");
181     return 0;
182 }
183
184 jobject GetJObjectInstance(const char *szClassPath) {
185     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
186
187     jobject object = NULL;
188
189     for (unsigned int i = 0; i < nLen; i++) {
190         if (0 == strcmp(gJObjectMapArray[i].szClassPath, szClassPath)) {
191             object = gJObjectMapArray[i].object;
192             break;
193         }
194     }
195
196     return object;
197 }
198
199 void DeleteObjectMapArray(JNIEnv *env) {
200     LOGI("DeleteObjectMapArray: Enter");
201
202     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
203     for (unsigned int i = 0; i < nLen; i++) {
204         if (NULL != gJObjectMapArray[i].object) {
205             env->DeleteGlobalRef(gJObjectMapArray[i].object);
206             gJObjectMapArray[i].object = NULL;
207         }
208     }
209
210     LOGI("DeleteObjectMapArray: Exit");
211 }
212
213 JavaVM *EasySetupJVM::m_jvm = NULL;
214 std::mutex EasySetupJVM::m_currentThreadMutex;
215 JNIEnv *EasySetupJVM::getEnv() {
216     std::unique_lock < std::mutex > scoped_lock(m_currentThreadMutex);
217
218     if (NULL == m_jvm) {
219         LOGE("Failed to get JVM");
220         return NULL;
221     }
222
223     JNIEnv *env = NULL;
224     jint ret = m_jvm->GetEnv((void **) &env, JNI_CURRENT_VERSION);
225     switch (ret) {
226     case JNI_OK:
227         return env;
228     case JNI_EDETACHED:
229         if (0 > m_jvm->AttachCurrentThread(&env, NULL)) {
230             LOGE("Failed to attach current thread to env");
231             return NULL;
232         }
233         return env;
234     case JNI_EVERSION:
235         LOGE("JNI version not supported");
236     default:
237         LOGE("Failed to get the environment");
238         return NULL;
239     }
240 }
241
242 void EasySetupJVM::releaseEnv() {
243     std::unique_lock < std::mutex > scoped_lock(m_currentThreadMutex);
244
245     if (0 == m_jvm) {
246         LOGE("Failed to release JVM");
247         return;
248     }
249
250     m_jvm->DetachCurrentThread();
251 }
252
253 #ifdef __cplusplus
254 extern "C" {
255 #endif
256 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
257     LOGD("JNI_OnLoad: Enter");
258
259     if (!vm) {
260         LOGE("JNI_OnLoad: vm is invalid");
261         return JNI_ERR;
262     }
263
264     JNIEnv *env = NULL;
265     if (JNI_OK != vm->GetEnv((void **) &env, JNI_CURRENT_VERSION)) {
266         LOGE("JNI_OnLoad: Version check is failed!");
267         return JNI_ERR;
268     }
269
270     if (0 != InitializeJClassMapArray(env)) {
271         LOGE("JNI_OnLoad: Initialize JClass Array failed!");
272         return JNI_ERR;
273     }
274
275     if (0 != InitializeJObjectMapArray(env)) {
276         LOGE("JNI_OnLoad: Initialize JObject Array failed!");
277         return JNI_ERR;
278     }
279
280     jclass easySetupClassRef = GetJClass(
281             EASY_SETUP_SERVICE_NATIVE_API_CLASS_PATH);
282     if (NULL == easySetupClassRef) {
283         LOGE("JNI_OnLoad: GetJClass gEasySetupClass failed !");
284         return JNI_ERR;
285     }
286     env->RegisterNatives(easySetupClassRef, gEasySetupMethodTable,
287             gEasySetupMethodTableSize);
288
289     EasySetupJVM::m_jvm = vm;
290
291     LOGI("JNI_OnLoad: Exit");
292     return JNI_CURRENT_VERSION;
293 }
294
295 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
296 {
297     LOGD("JNI_OnUnload: Enter");
298
299     JNIEnv *env = NULL;
300     if (JNI_OK != vm->GetEnv((void **)&env, JNI_CURRENT_VERSION))
301     {
302         LOGE("JNI_OnLoad: Version check is failed!");
303         return;
304     }
305
306     // delete all class references
307     DeleteClassMapArray(env);
308
309     // delete all jobject
310     DeleteObjectMapArray(env);
311
312     LOGD("JNI_OnUnload: Exit");
313 }
314
315 #ifdef __cplusplus
316 }
317 #endif
318