Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / service / things-manager / sdk / java / jni / jniutil / src / jni_things_manager_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_things_manager_jvm.h"
21 #include <string>
22 #include "jni_things_manager.h"
23 #include "jni_things_manager_util.h"
24 #include "JniOcResource.h"
25
26 #define TM_ERROR_JNI_FOUND_CLASS_FAILED -2005
27
28 /**
29  * @class   JClassMap
30  * @brief   This class provides functions for initializing the Java class path and Java class.
31  *
32  */
33 class JClassMap
34 {
35     public:
36         /**
37               *  Java Class
38               */
39         jclass classRef;
40         /**
41               *  Java Class Path
42               */
43         const char *szClassPath;
44
45         /**
46              * @brief constructor
47              */
48         JClassMap(const char *path)
49             : classRef(NULL)
50         {
51             szClassPath = path;
52         }
53 };
54
55 /**
56  * @class   JObjectMap
57  * @brief   This class provides functins for initializing the Java Class path and Java Class
58  * Object.
59  *
60  */
61 class JObjectMap
62 {
63     public:
64         /**
65             *  Java Object
66             */
67         jobject object;
68         /**
69              *  Java Class Path
70              */
71         const char *szClassPath;
72
73         /**
74              * @brief constructor
75              */
76         JObjectMap(const char *path)
77             : object(NULL)
78         {
79             szClassPath = path;
80         }
81 };
82
83 static JClassMap gJClassMapArray[] =
84 {
85     JClassMap(TM_SERVICE_NATIVE_API_CLASS_PATH),
86     JClassMap(TM_SERVICE_CALLBACK_CLASS_PATH),
87     JClassMap(TM_SERVICE_OCRESOURCE_PATH),
88     JClassMap(TM_SERVICE_OCREPRESENTATION_PATH),
89     JClassMap(TM_SERVICE_HEADER_OPTION_PATH),
90     JClassMap(TM_SERVICE_ACTIONSET_PATH),
91     JClassMap(TM_SERVICE_CAPABILITY_PATH),
92     JClassMap(TM_SERVICE_ACTION_PATH),
93     JClassMap(TM_SERVICE_PLATFORM_CLASS_PATH),
94     JClassMap(TM_SERVICE_PLATFORM_CONFIG_CLASS_PATH),
95     JClassMap(TM_SERVICE_OCRESOURCEHANDLE_PATH)
96 };
97
98 static JObjectMap gJObjectMapArray[] =
99 {
100     JObjectMap(TM_SERVICE_CALLBACK_CLASS_PATH)
101 };
102
103 static JNINativeMethod gThingsManagerMethodTable[] =
104 {
105     { "findCandidateResources", "(Ljava/util/Vector;I)I", (void *) JNIThingsManagerFindCandidateResource},
106     { "subscribeCollectionPresence", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsManagerSubscribeCollectionPresence},
107     { "bindResourceToGroup", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/base/OcResourceHandle;)Lorg/iotivity/base/OcResourceHandle;", (void *) JNIThingsManagerBindResourceToGroup},
108     { "findGroup", "(Ljava/util/Vector;)I", (void *) JNIThingsManagerFindGroup},
109     { "createGroup", "(Ljava/lang/String;)I", (void *) JNIThingsManagerCreateGroup},
110     { "joinGroup", "(Ljava/lang/String;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIThingsManagerJoinGroupString},
111     { "joinGroup", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIThingsManagerJoinGroupObject},
112     { "leaveGroup", "(Ljava/lang/String;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIThingsManagerLeaveGroup},
113     { "leaveGroup", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;Lorg/iotivity/base/OcResourceHandle;)I", (void *) JNIThingsManagerLeaveGroupForResource},
114     { "deleteGroup", "(Ljava/lang/String;)V", (void *) JNIThingsManagerDeleteGroup},
115     { "getGroupList", "()Ljava/util/Map;", (void *) JNIThingsManagerGetGroupList},
116     { "updateConfigurations", "(Lorg/iotivity/base/OcResource;Ljava/util/Map;)I", (void *) JNIThingsManagerUpdateConfigurations},
117     { "getConfigurations", "(Lorg/iotivity/base/OcResource;Ljava/util/Vector;)I", (void *) JNIThingsManagerGetConfigurations},
118     { "getListOfSupportedConfigurationUnits", "()Ljava/lang/String;", (void *) JNIThingsManagerGetListOfSupportedConfigurationUnits},
119     { "doBootstrap", "()I", (void *) JNIThingsManagerDoBootstrap},
120     { "reboot", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsManagerReboot},
121     { "factoryReset", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsManagerFactoryReset},
122     { "addActionSet", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/service/tm/ActionSet;)I", (void *) JNIThingsManagerAddActionSet},
123     { "executeActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIThingsManagerExecuteActionSet},
124     { "executeActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;J)I", (void *) JNIThingsManagerExecuteActionSetWithDelay},
125     { "cancelActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIThingsManagerCancelActionSet},
126     { "getActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIThingsManagerGetActionSet},
127     { "deleteActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIThingsManagerDeleteActionSet},
128 };
129
130 static int gThingsManagerMethodTableSize = sizeof(gThingsManagerMethodTable) / sizeof(
131             gThingsManagerMethodTable[0]);
132
133
134 int InitializeJClassMapArray(JNIEnv *env)
135 {
136     LOGI("InitializeJClassMapArray: Enter");
137
138     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
139
140     for (unsigned int i = 0; i < nLen; i++)
141     {
142         jclass classRef = env->FindClass(gJClassMapArray[i].szClassPath);
143         if (NULL == classRef)
144         {
145             LOGE("FindClass failed for [%s]", gJClassMapArray[i].szClassPath);
146             return -1;
147         }
148         gJClassMapArray[i].classRef = (jclass)env->NewGlobalRef(classRef);
149         env->DeleteLocalRef(classRef);
150     }
151
152     LOGI("InitializeJClassMapArray: Exit");
153     return 0;
154 }
155
156 jclass GetJClass(const char *szClassPath)
157 {
158     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
159
160     jclass classRef = NULL;
161
162     for (unsigned int i = 0; i < nLen; i++)
163     {
164         if (0 == strcmp(gJClassMapArray[i].szClassPath, szClassPath))
165         {
166             classRef = gJClassMapArray[i].classRef;
167             break;
168         }
169     }
170
171     return classRef;
172 }
173
174 void DeleteClassMapArray(JNIEnv *env)
175 {
176     LOGI("DeleteClassMapArray: Enter");
177
178     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
179     for (unsigned int i = 0; i < nLen; i++)
180     {
181         if (NULL != gJClassMapArray[i].classRef)
182         {
183             env->DeleteGlobalRef(gJClassMapArray[i].classRef);
184             gJClassMapArray[i].classRef = NULL;
185         }
186     }
187
188     LOGI("DeleteClassMapArray: Exit");
189 }
190
191 int InitializeJObjectMapArray(JNIEnv *env)
192 {
193     LOGI("InitializeJObjectMapArray: Enter");
194
195     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
196
197     for (unsigned int i = 0; i < nLen; i++)
198     {
199         jclass classRef = env->FindClass(gJObjectMapArray[i].szClassPath);
200         if (NULL == classRef)
201         {
202             LOGE("InitializeJObjectMapArray: FindClass failed for [%s]", gJObjectMapArray[i].szClassPath);
203             return -1;
204         }
205
206         std::string methodSignature = "()L";
207         methodSignature.append(gJObjectMapArray[i].szClassPath);
208         methodSignature.append(";");
209
210         // Get the object form "getInstance"
211         jmethodID methodid = env->GetStaticMethodID(classRef, "getInstance", methodSignature.c_str());
212         if (NULL == methodid)
213         {
214             LOGE("InitializeJObjectMapArray: GetStaticMethodID failed for [%s]",
215                  gJObjectMapArray[i].szClassPath);
216             return -1;
217         }
218
219         // Get the singleton object
220         jobject objectRef = (jobject)env->CallStaticObjectMethod(classRef, methodid);
221         if (NULL == objectRef)
222         {
223             LOGE("InitializeJObjectMapArray: CallStaticObjectMethod failed for [%s]",
224                  gJObjectMapArray[i].szClassPath);
225             return -1;
226         }
227
228         gJObjectMapArray[i].object = (jobject)env->NewGlobalRef(objectRef);
229         env->DeleteLocalRef(classRef);
230     }
231
232     LOGI("InitializeJObjectMapArray: Exit");
233     return 0;
234 }
235
236 jobject GetJObjectInstance(const char *szClassPath)
237 {
238     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
239
240     jobject object = NULL;
241
242     for (unsigned int i = 0; i < nLen; i++)
243     {
244         if (0 == strcmp(gJObjectMapArray[i].szClassPath, szClassPath))
245         {
246             object = gJObjectMapArray[i].object;
247             break;
248         }
249     }
250
251     return object;
252 }
253
254 void DeleteObjectMapArray(JNIEnv *env)
255 {
256     LOGI("DeleteObjectMapArray: Enter");
257
258     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
259     for (unsigned int i = 0; i < nLen; i++)
260     {
261         if (NULL != gJObjectMapArray[i].object)
262         {
263             env->DeleteGlobalRef(gJObjectMapArray[i].object);
264             gJObjectMapArray[i].object = NULL;
265         }
266     }
267
268     LOGI("DeleteObjectMapArray: Exit");
269 }
270
271 JavaVM *ThingsManagerJVM::m_jvm = NULL;
272 std::mutex ThingsManagerJVM::m_currentThreadMutex;
273 JNIEnv *ThingsManagerJVM::getEnv()
274 {
275     std::unique_lock<std::mutex> scoped_lock(m_currentThreadMutex);
276
277     if (NULL == m_jvm)
278     {
279         LOGE("Failed to get JVM");
280         return NULL;
281     }
282
283     JNIEnv *env = NULL;
284     jint ret = m_jvm->GetEnv((void **)&env, JNI_CURRENT_VERSION);
285     switch (ret)
286     {
287         case JNI_OK:
288             return env;
289         case JNI_EDETACHED:
290             if (0 > m_jvm->AttachCurrentThread(&env, NULL))
291             {
292                 LOGE("Failed to attach current thread to env");
293                 return NULL;
294             }
295             return env;
296         case JNI_EVERSION:
297             LOGE("JNI version not supported");
298         default:
299             LOGE("Failed to get the environment");
300             return NULL;
301     }
302 }
303
304 void ThingsManagerJVM::releaseEnv()
305 {
306     std::unique_lock<std::mutex> scoped_lock(m_currentThreadMutex);
307
308     if (0 == m_jvm)
309     {
310         LOGE("Failed to release JVM");
311         return;
312     }
313
314     m_jvm->DetachCurrentThread();
315 }
316
317 #ifdef __cplusplus
318 extern "C" {
319 #endif
320 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
321 {
322     LOGD("JNI_OnLoad: Enter");
323
324     if (!vm)
325     {
326         LOGE("JNI_OnLoad: vm is invalid");
327         return JNI_ERR;
328     }
329
330     JNIEnv *env = NULL;
331     if (JNI_OK != vm->GetEnv((void **) &env, JNI_CURRENT_VERSION))
332     {
333         LOGE("JNI_OnLoad: Version check is failed!");
334         return JNI_ERR;
335     }
336
337     if (0 != InitializeJClassMapArray(env))
338     {
339         LOGE("JNI_OnLoad: Initialize JClass Array failed!");
340         return JNI_ERR;
341     }
342
343     if (0 != InitializeJObjectMapArray(env))
344     {
345         LOGE("JNI_OnLoad: Initialize JObject Array failed!");
346         return JNI_ERR;
347     }
348
349     jclass thingsManagerClassRef = GetJClass(TM_SERVICE_NATIVE_API_CLASS_PATH);
350     if (NULL == thingsManagerClassRef)
351     {
352         LOGE("JNI_OnLoad: GetJClass gThingsManagerClass failed !");
353         return JNI_ERR;
354     }
355     env->RegisterNatives(thingsManagerClassRef, gThingsManagerMethodTable,
356                          gThingsManagerMethodTableSize);
357
358     ThingsManagerJVM::m_jvm = vm;
359
360     LOGI("JNI_OnLoad: Exit");
361     return JNI_CURRENT_VERSION;
362 }
363
364 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
365 {
366     LOGD("JNI_OnUnload: Enter");
367
368     JNIEnv *env = NULL;
369     if (JNI_OK != vm->GetEnv((void **)&env, JNI_CURRENT_VERSION))
370     {
371         LOGE("JNI_OnLoad: Version check is failed!");
372         return;
373     }
374
375     // delete all class references
376     DeleteClassMapArray(env);
377
378     // delete all jobject
379     DeleteObjectMapArray(env);
380
381     LOGD("JNI_OnUnload: Exit");
382 }
383
384 #ifdef __cplusplus
385 }
386 #endif