Imported Upstream version 1.0.0
[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
21 #include <string>
22
23 #include "jni_things_manager_jvm.h"
24 #include "jni_group_manager.h"
25 #include "jni_things_configuration.h"
26 #include "jni_things_maintenance.h"
27 #include "jni_things_manager_util.h"
28 #include "JniOcResource.h"
29
30 #define TM_ERROR_JNI_FOUND_CLASS_FAILED -2005
31
32 /**
33  * This class provides functions for initializing the Java class path and Java class.
34  */
35 class JClassMap
36 {
37     public:
38         /**
39          *  Java Class
40          */
41         jclass classRef;
42         /**
43          *  Java Class Path
44          */
45         const char *szClassPath;
46
47         /**
48          * constructor
49          */
50         JClassMap(const char *path)
51             : classRef(NULL)
52         {
53             szClassPath = path;
54         }
55 };
56
57 /**
58  * This class provides functions for initializing the Java Class path
59  *  and Java Class Object.
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_GROUP_MANAGER_CLASS_PATH),
86     JClassMap(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH),
87     JClassMap(TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH),
88     JClassMap(TM_SERVICE_OCRESOURCE_PATH),
89     JClassMap(TM_SERVICE_OCREPRESENTATION_PATH),
90     JClassMap(TM_SERVICE_HEADER_OPTION_PATH),
91     JClassMap(TM_SERVICE_ACTIONSET_PATH),
92     JClassMap(TM_SERVICE_CAPABILITY_PATH),
93     JClassMap(TM_SERVICE_ACTION_PATH),
94     JClassMap(TM_SERVICE_PLATFORM_CLASS_PATH),
95     JClassMap(TM_SERVICE_PLATFORM_CONFIG_CLASS_PATH),
96     JClassMap(TM_SERVICE_OCRESOURCEHANDLE_PATH)
97 };
98
99 static JObjectMap gJObjectMapArray[] =
100 {
101     JObjectMap(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH),
102     JObjectMap(TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH)
103 };
104
105 static JNINativeMethod gGroupManagerMethodTable[] =
106 {
107     { "nativeFindCandidateResource", "(Ljava/util/Vector;I)I", (void *) JNIGroupManagerFindCandidateResource},
108     { "nativeSubscribeCollectionPresence", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIGroupManagerSubscribeCollectionPresence},
109     { "nativeBindResourceToGroup", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/base/OcResourceHandle;)Lorg/iotivity/base/OcResourceHandle;", (void *) JNIGroupManagerBindResourceToGroup},
110     { "nativeAddActionSet", "(Lorg/iotivity/base/OcResource;Lorg/iotivity/service/tm/ActionSet;)I", (void *) JNIGroupManagerAddActionSet},
111     { "nativeExecuteActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIGroupManagerExecuteActionSet},
112     { "nativeExecuteActionSetWithDelay", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;J)I", (void *) JNIGroupManagerExecuteActionSetWithDelay},
113     { "nativeCancelActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIGroupManagerCancelActionSet},
114     { "nativeGetActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIGroupManagerGetActionSet},
115     { "nativeDeleteActionSet", "(Lorg/iotivity/base/OcResource;Ljava/lang/String;)I", (void *) JNIGroupManagerDeleteActionSet}
116 };
117
118 static JNINativeMethod gThingsConfigurationMethodTable[] =
119 {
120     { "nativeUpdateConfigurations", "(Lorg/iotivity/base/OcResource;Ljava/util/Map;)I", (void *) JNIThingsConfigurationUpdateConfigurations},
121     { "nativeGetConfigurations", "(Lorg/iotivity/base/OcResource;Ljava/util/Vector;)I", (void *) JNIThingsConfigurationGetConfigurations},
122     { "nativeGetListOfSupportedConfigurationUnits", "()Ljava/lang/String;", (void *) JNIThingsConfigurationGetListOfSupportedConfigurationUnits},
123     { "nativeDoBootstrap", "()I", (void *) JNIThingsConfigurationDoBootstrap},
124 };
125
126 static JNINativeMethod gThingsMaintenanceMethodTable[] =
127 {
128     { "nativeReboot", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsMaintenanceReboot},
129     { "nativeFactoryReset", "(Lorg/iotivity/base/OcResource;)I", (void *) JNIThingsMaintenanceFactoryReset},
130     { "nativeGetListOfSupportedMaintenanceUnits", "()Ljava/lang/String;", (void *) JNIThingsMaintenanceGetListOfSupportedConfigurationUnits}
131
132 };
133
134 static int gGroupManagerMethodTableSize = sizeof(gGroupManagerMethodTable) / sizeof(
135             gGroupManagerMethodTable[0]);
136
137 static int gThingsConfigurationMethodTableSize = sizeof(gThingsConfigurationMethodTable) / sizeof(
138             gThingsConfigurationMethodTable[0]);
139
140 static int gThingsMaintenanceMethodTableSize = sizeof(gThingsMaintenanceMethodTable) / sizeof(
141             gThingsMaintenanceMethodTable[0]);
142
143
144 int InitializeJClassMapArray(JNIEnv *env)
145 {
146     LOGI("InitializeJClassMapArray: Enter");
147
148     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
149
150     for (unsigned int i = 0; i < nLen; i++)
151     {
152         jclass classRef = env->FindClass(gJClassMapArray[i].szClassPath);
153         if (NULL == classRef)
154         {
155             LOGE("FindClass failed for [%s]", gJClassMapArray[i].szClassPath);
156             return -1;
157         }
158         gJClassMapArray[i].classRef = (jclass)env->NewGlobalRef(classRef);
159         env->DeleteLocalRef(classRef);
160     }
161
162     LOGI("InitializeJClassMapArray: Exit");
163     return 0;
164 }
165
166 jclass GetJClass(const char *szClassPath)
167 {
168     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
169
170     jclass classRef = NULL;
171
172     for (unsigned int i = 0; i < nLen; i++)
173     {
174         if (0 == strcmp(gJClassMapArray[i].szClassPath, szClassPath))
175         {
176             classRef = gJClassMapArray[i].classRef;
177             break;
178         }
179     }
180
181     return classRef;
182 }
183
184 void DeleteClassMapArray(JNIEnv *env)
185 {
186     LOGI("DeleteClassMapArray: Enter");
187
188     unsigned int nLen = sizeof(gJClassMapArray) / sizeof(JClassMap);
189     for (unsigned int i = 0; i < nLen; i++)
190     {
191         if (NULL != gJClassMapArray[i].classRef)
192         {
193             env->DeleteGlobalRef(gJClassMapArray[i].classRef);
194             gJClassMapArray[i].classRef = NULL;
195         }
196     }
197
198     LOGI("DeleteClassMapArray: Exit");
199 }
200
201 int InitializeJObjectMapArray(JNIEnv *env)
202 {
203     LOGI("InitializeJObjectMapArray: Enter");
204
205     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
206
207     for (unsigned int i = 0; i < nLen; i++)
208     {
209         jclass classRef = env->FindClass(gJObjectMapArray[i].szClassPath);
210         if (NULL == classRef)
211         {
212             LOGE("InitializeJObjectMapArray: FindClass failed for [%s]", gJObjectMapArray[i].szClassPath);
213             return -1;
214         }
215
216         std::string methodSignature = "()L";
217         methodSignature.append(gJObjectMapArray[i].szClassPath);
218         methodSignature.append(";");
219
220         // Get the object form "getInstance"
221         jmethodID methodid = env->GetStaticMethodID(classRef, "getInstance", methodSignature.c_str());
222         if (NULL == methodid)
223         {
224             LOGE("InitializeJObjectMapArray: GetStaticMethodID failed for [%s]",
225                  gJObjectMapArray[i].szClassPath);
226             return -1;
227         }
228
229         // Get the singleton object
230         jobject objectRef = (jobject)env->CallStaticObjectMethod(classRef, methodid);
231         if (NULL == objectRef)
232         {
233             LOGE("InitializeJObjectMapArray: CallStaticObjectMethod failed for [%s]",
234                  gJObjectMapArray[i].szClassPath);
235             return -1;
236         }
237
238         gJObjectMapArray[i].object = (jobject)env->NewGlobalRef(objectRef);
239         env->DeleteLocalRef(classRef);
240     }
241
242     LOGI("InitializeJObjectMapArray: Exit");
243     return 0;
244 }
245
246 jobject GetJObjectInstance(const char *szClassPath)
247 {
248     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
249
250     jobject object = NULL;
251
252     for (unsigned int i = 0; i < nLen; i++)
253     {
254         if (0 == strcmp(gJObjectMapArray[i].szClassPath, szClassPath))
255         {
256             object = gJObjectMapArray[i].object;
257             break;
258         }
259     }
260
261     return object;
262 }
263
264 void DeleteObjectMapArray(JNIEnv *env)
265 {
266     LOGI("DeleteObjectMapArray: Enter");
267
268     unsigned int nLen = sizeof(gJObjectMapArray) / sizeof(JObjectMap);
269     for (unsigned int i = 0; i < nLen; i++)
270     {
271         if (NULL != gJObjectMapArray[i].object)
272         {
273             env->DeleteGlobalRef(gJObjectMapArray[i].object);
274             gJObjectMapArray[i].object = NULL;
275         }
276     }
277
278     LOGI("DeleteObjectMapArray: Exit");
279 }
280
281 JavaVM *ThingsManagerJVM::m_jvm = NULL;
282 std::mutex ThingsManagerJVM::m_currentThreadMutex;
283 JNIEnv *ThingsManagerJVM::getEnv()
284 {
285     std::unique_lock<std::mutex> scoped_lock(m_currentThreadMutex);
286
287     if (NULL == m_jvm)
288     {
289         LOGE("Failed to get JVM");
290         return NULL;
291     }
292
293     JNIEnv *env = NULL;
294     jint ret = m_jvm->GetEnv((void **)&env, JNI_CURRENT_VERSION);
295     switch (ret)
296     {
297         case JNI_OK:
298             return env;
299         case JNI_EDETACHED:
300             if (0 > m_jvm->AttachCurrentThread(&env, NULL))
301             {
302                 LOGE("Failed to attach current thread to env");
303                 return NULL;
304             }
305             return env;
306         case JNI_EVERSION:
307             LOGE("JNI version not supported");
308         default:
309             LOGE("Failed to get the environment");
310             return NULL;
311     }
312 }
313
314 void ThingsManagerJVM::releaseEnv()
315 {
316     std::unique_lock<std::mutex> scoped_lock(m_currentThreadMutex);
317
318     if (0 == m_jvm)
319     {
320         LOGE("Failed to release JVM");
321         return;
322     }
323
324     m_jvm->DetachCurrentThread();
325 }
326
327 #ifdef __cplusplus
328 extern "C" {
329 #endif
330 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
331 {
332     LOGD("JNI_OnLoad: Enter");
333
334     if (!vm)
335     {
336         LOGE("JNI_OnLoad: vm is invalid");
337         return JNI_ERR;
338     }
339
340     JNIEnv *env = NULL;
341     if (JNI_OK != vm->GetEnv((void **) &env, JNI_CURRENT_VERSION))
342     {
343         LOGE("JNI_OnLoad: Version check is failed!");
344         return JNI_ERR;
345     }
346
347     if (0 != InitializeJClassMapArray(env))
348     {
349         LOGE("JNI_OnLoad: Initialize JClass Array failed!");
350         return JNI_ERR;
351     }
352
353     if (0 != InitializeJObjectMapArray(env))
354     {
355         LOGE("JNI_OnLoad: Initialize JObject Array failed!");
356         return JNI_ERR;
357     }
358
359     // Group Manager
360     jclass groupManagerClassRef = GetJClass(TM_SERVICE_GROUP_MANAGER_CLASS_PATH);
361
362     if (NULL == groupManagerClassRef)
363     {
364         LOGE("JNI_OnLoad: GetJClass gThingsManagerClass failed !");
365         return JNI_ERR;
366     }
367
368     env->RegisterNatives(groupManagerClassRef, gGroupManagerMethodTable,
369                          gGroupManagerMethodTableSize);
370
371     //Things Configuration
372     jclass thingsConfigurationClassRef = GetJClass(TM_SERVICE_THINGS_CONFIGURATION_CLASS_PATH);
373
374     if (NULL == thingsConfigurationClassRef)
375     {
376         LOGE("JNI_OnLoad: GetJClass gThingsManagerClass failed !");
377         return JNI_ERR;
378     }
379
380     env->RegisterNatives(thingsConfigurationClassRef, gThingsConfigurationMethodTable,
381                          gThingsConfigurationMethodTableSize);
382
383     //Things Maintenance
384     jclass thingsMaintenanceClassRef = GetJClass(TM_SERVICE_THINGS_MAINTENANCE_CLASS_PATH);
385
386     if (NULL == thingsMaintenanceClassRef)
387     {
388         LOGE("JNI_OnLoad: GetJClass gThingsManagerClass failed !");
389         return JNI_ERR;
390     }
391
392     env->RegisterNatives(thingsMaintenanceClassRef, gThingsMaintenanceMethodTable,
393                          gThingsMaintenanceMethodTableSize);
394
395     ThingsManagerJVM::m_jvm = vm;
396
397     LOGI("JNI_OnLoad: Exit");
398     return JNI_CURRENT_VERSION;
399 }
400
401 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
402 {
403     LOGD("JNI_OnUnload: Enter");
404
405     JNIEnv *env = NULL;
406     if (JNI_OK != vm->GetEnv((void **)&env, JNI_CURRENT_VERSION))
407     {
408         LOGE("JNI_OnLoad: Version check is failed!");
409         return;
410     }
411
412     // delete all class references
413     DeleteClassMapArray(env);
414
415     // delete all jobject
416     DeleteObjectMapArray(env);
417
418     LOGD("JNI_OnUnload: Exit");
419 }
420
421 #ifdef __cplusplus
422 }
423 #endif