Updating JNI modules of service provider
[platform/upstream/iotivity.git] / service / simulator / java / jni / simulator_manager_jni.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 "simulator_manager_jni.h"
22 #include "simulator_resource_server_jni.h"
23 #include "simulator_common_jni.h"
24 #include "simulator_manager.h"
25 #include "simulator_remote_resource_jni.h"
26 #include "simulator_resource_model_jni.h"
27
28 SimulatorClassRefs gSimulatorClassRefs;
29 std::mutex gEnvMutex;
30 JavaVM *gvm;
31
32 JNIEnv *getEnv()
33 {
34     std::unique_lock<std::mutex> lock(gEnvMutex);
35     if (nullptr == gvm)
36         return NULL;
37
38     JNIEnv *env = NULL;
39     jint ret = gvm->GetEnv((void **)&env, JNI_VERSION_1_6);
40     switch (ret)
41     {
42         case JNI_OK:
43             return env;
44         case JNI_EDETACHED:
45             if (0 == gvm->AttachCurrentThread((void **)&env, NULL))
46                 return env;
47     }
48
49     return NULL;
50 }
51
52 void releaseEnv()
53 {
54     std::unique_lock<std::mutex> lock(gEnvMutex);
55     if (nullptr == gvm)
56         return;
57     gvm->DetachCurrentThread();
58 }
59
60 class JNILogger : public ILogger
61 {
62     public:
63         void setJavaLogger(JNIEnv *env, jobject logger)
64         {
65             m_logger = env->NewWeakGlobalRef(logger);
66         }
67
68         void write(std::string time, ILogger::Level level, std::string message)
69         {
70             JNIEnv *env = getEnv();
71             if (nullptr == env)
72                 return;
73
74             jobject logger = env->NewLocalRef(m_logger);
75             if (!logger)
76             {
77                 releaseEnv();
78                 return;
79             }
80
81             jclass loggerCls = env->GetObjectClass(logger);
82             if (!loggerCls)
83             {
84                 releaseEnv();
85                 return;
86             }
87
88             jmethodID writeMId = env->GetMethodID(loggerCls, "write",
89                                                   "(Ljava/lang/String;ILjava/lang/String;)V");
90             if (!writeMId)
91             {
92                 releaseEnv();
93                 return;
94             }
95
96             jstring msg = env->NewStringUTF(message.c_str());
97             jstring timeStr = env->NewStringUTF(time.c_str());
98             env->CallVoidMethod(logger, writeMId, timeStr, static_cast<jint>(level), msg);
99             env->DeleteLocalRef(msg);
100             env->DeleteLocalRef(timeStr);
101             releaseEnv();
102         }
103
104     private:
105         jweak m_logger;
106 };
107
108
109 jobject SimulatorRemoteResourceToJava(JNIEnv *env, jlong resource)
110 {
111     jmethodID constructor = env->GetMethodID(gSimulatorClassRefs.classSimulatorRemoteResource, "<init>",
112                             "(J)V");
113     if (NULL == constructor)
114     {
115         return NULL;
116     }
117
118     jobject resourceObj = (jobject) env->NewObject(gSimulatorClassRefs.classSimulatorRemoteResource,
119                           constructor, resource);
120     if (NULL == resourceObj)
121     {
122         return NULL;
123     }
124
125     return resourceObj;
126 }
127
128 class JNIFoundResourceListener
129 {
130     public:
131         void setJavaFoundResourceListener(JNIEnv *env, jobject listener)
132         {
133             m_listener = env->NewWeakGlobalRef(listener);
134         }
135
136         void onFoundResource(std::shared_ptr<SimulatorRemoteResource> resource)
137         {
138             JNIEnv *env = getEnv();
139             if (nullptr == env)
140                 return;
141
142             jobject foundResourceListener = env->NewLocalRef(m_listener);
143             if (!foundResourceListener)
144             {
145                 releaseEnv();
146                 return;
147             }
148
149             jclass foundResourceCls = env->GetObjectClass(foundResourceListener);
150             if (!foundResourceCls)
151             {
152                 releaseEnv();
153                 return;
154             }
155
156             jmethodID foundResourceMId = env->GetMethodID(foundResourceCls, "onResourceCallback",
157                                          "(Lorg/oic/simulator/clientcontroller/SimulatorRemoteResource;)V");
158             if (!foundResourceMId)
159             {
160                 releaseEnv();
161                 return;
162             }
163
164             JniSimulatorRemoteResource *jniSimulatorResource = new JniSimulatorRemoteResource(resource);
165
166             if (!jniSimulatorResource)
167             {
168                 releaseEnv();
169                 return;
170             }
171
172             jobject simulatorResource = SimulatorRemoteResourceToJava(env,
173                                         reinterpret_cast<jlong>(jniSimulatorResource));
174
175             env->CallVoidMethod(foundResourceListener, foundResourceMId, simulatorResource);
176             if ((env)->ExceptionCheck())
177             {
178                 releaseEnv();
179                 return;
180             }
181
182             releaseEnv();
183         }
184
185     private:
186         jweak m_listener;
187
188 };
189
190 void onResourceModelChange(jweak jlistenerRef, const std::string &uri,
191                            const SimulatorResourceModel &resModel)
192 {
193     JNIEnv *env = getEnv();
194     if (nullptr == env)
195         return;
196
197     jobject modelChangeListener = env->NewLocalRef(jlistenerRef);
198     if (!modelChangeListener)
199     {
200         releaseEnv();
201         return;
202     }
203
204     jclass modelChangeCls = env->GetObjectClass(modelChangeListener);
205     if (!modelChangeCls)
206     {
207         releaseEnv();
208         return;
209     }
210
211     jmethodID foundModelChangeMId = env->GetMethodID(modelChangeCls, "onResourceModelChanged",
212                                     "(Ljava/lang/String;Lorg/oic/simulator/serviceprovider/SimulatorResourceModel;)V");
213     if (!foundModelChangeMId)
214     {
215         releaseEnv();
216         return;
217     }
218
219     JniSimulatorResourceModel *jniModel = new JniSimulatorResourceModel(resModel);
220     if (!jniModel)
221     {
222         releaseEnv();
223         return;
224     }
225
226     jobject jModel = JniSimulatorResourceModel::toJava(env, reinterpret_cast<jlong>(jniModel));
227
228     jstring jUri = env->NewStringUTF(uri.c_str());
229
230     env->CallVoidMethod(modelChangeListener, foundModelChangeMId, jUri, jModel);
231     if ((env)->ExceptionCheck())
232     {
233         releaseEnv();
234         return;
235     }
236
237     env->DeleteLocalRef(jUri);
238
239     releaseEnv();
240 }
241
242
243 JNIEXPORT jobject JNICALL
244 Java_org_oic_simulator_SimulatorManagerNativeInterface_createResource
245 (JNIEnv *env, jclass object, jstring configPath, jobject listener)
246 {
247     if (!configPath)
248         return NULL;
249
250     if (!listener)
251         return NULL;
252
253     jweak jlistenerRef = env->NewWeakGlobalRef(listener);
254     SimulatorResourceServer::ResourceModelChangedCB callback =  [jlistenerRef](const std::string & uri,
255             const SimulatorResourceModel & resModel)
256     {
257         onResourceModelChange(jlistenerRef, uri, resModel);
258     };
259
260     const char *configPathCStr = env->GetStringUTFChars(configPath, NULL);
261     SimulatorResourceServerPtr resource = SimulatorManager::getInstance()->createResource(
262             configPathCStr, callback);
263     if (nullptr == resource)
264     {
265         if (configPathCStr)
266             env->ReleaseStringUTFChars(configPath, configPathCStr);
267         return NULL;
268     }
269
270     JniSimulatorResource *jniSimResource = new JniSimulatorResource(resource);
271     jobject jSimulatorResource = JniSimulatorResource::toJava(env,
272                                  reinterpret_cast<jlong>(jniSimResource));
273
274     jniSimResource->setResourceInfo(env, jSimulatorResource);
275
276     if (configPathCStr)
277         env->ReleaseStringUTFChars(configPath, configPathCStr);
278     return jSimulatorResource;
279 }
280
281 JNIEXPORT jobjectArray JNICALL
282 Java_org_oic_simulator_SimulatorManagerNativeInterface_createResources
283 (JNIEnv *env, jclass object, jstring configPath, jint count, jobject listener)
284 {
285     if (!configPath)
286         return NULL;
287
288     if (!listener)
289         return NULL;
290
291     jweak jlistenerRef = env->NewWeakGlobalRef(listener);
292     SimulatorResourceServer::ResourceModelChangedCB callback =  [jlistenerRef](const std::string & uri,
293             const SimulatorResourceModel & resModel)
294     {
295         onResourceModelChange(jlistenerRef, uri, resModel);
296     };
297
298
299     const char *configPathCStr = env->GetStringUTFChars(configPath, NULL);
300     std::vector<SimulatorResourceServerPtr> resources =
301         SimulatorManager::getInstance()->createResource(configPathCStr, count, callback);
302
303     // Construct the object array and send it java layer
304     jobjectArray resourceArray = env->NewObjectArray(resources.size(),
305                                  gSimulatorClassRefs.classSimulatorResource, NULL);
306     if (resourceArray)
307     {
308         for (size_t i = 0; i < resources.size(); i++)
309         {
310             JniSimulatorResource *jniSimResource = new JniSimulatorResource(resources[i]);
311             jobject jSimulatorResource = JniSimulatorResource::toJava(env,
312                                          reinterpret_cast<jlong>(jniSimResource));
313             jniSimResource->setResourceInfo(env, jSimulatorResource);
314             env->SetObjectArrayElement(resourceArray, i, jSimulatorResource);
315         }
316     }
317
318     if (configPathCStr)
319         env->ReleaseStringUTFChars(configPath, configPathCStr);
320     return resourceArray;
321 }
322
323 JNIEXPORT jobjectArray JNICALL
324 Java_org_oic_simulator_SimulatorManagerNativeInterface_getResources
325 (JNIEnv *env, jclass object)
326 {
327     //TODO: Need to implement this method
328     return nullptr;
329 }
330
331 JNIEXPORT void JNICALL
332 Java_org_oic_simulator_SimulatorManagerNativeInterface_deleteResource
333 (JNIEnv *env, jclass object, jobject jResource)
334 {
335     if (!jResource)
336         return;
337
338     SimulatorResourceServerPtr resource =
339         JniSimulatorResource::getJniSimulatorResourcePtr(env, jResource);
340     if (!resource)
341         return;
342
343     SimulatorManager::getInstance()->deleteResource(resource);
344 }
345
346 JNIEXPORT void JNICALL
347 Java_org_oic_simulator_SimulatorManagerNativeInterface_deleteResources
348 (JNIEnv *env, jclass object, jstring resourceType)
349 {
350     std::string type;
351     const char *typeCStr = NULL;
352     if (resourceType)
353     {
354         typeCStr = env->GetStringUTFChars(resourceType, NULL);
355         type = typeCStr;
356     }
357
358     SimulatorManager::getInstance()->deleteResources(type);
359     if (typeCStr)
360         env->ReleaseStringUTFChars(resourceType, typeCStr);
361 }
362
363 JNIEXPORT jint JNICALL
364 Java_org_oic_simulator_SimulatorManagerNativeInterface_findResource
365 (JNIEnv *env, jobject object, jstring resourceType, jobject listener)
366 {
367     const char *typeCStr = NULL;
368
369     if (resourceType)
370     {
371         typeCStr = env->GetStringUTFChars(resourceType, NULL);
372     }
373
374     JNIFoundResourceListener *resourceListener = new JNIFoundResourceListener();
375     resourceListener->setJavaFoundResourceListener(env, listener);
376
377     SimulatorResult result = SimulatorManager::getInstance()->findResource(typeCStr,
378                              std::bind(&JNIFoundResourceListener::onFoundResource, resourceListener, std::placeholders::_1));
379
380     if (typeCStr)
381         env->ReleaseStringUTFChars(resourceType, typeCStr);
382     return result;
383 }
384
385 JNIEXPORT jobject JNICALL
386 Java_org_oic_simulator_SimulatorManagerNativeInterface_getFoundResources
387 (JNIEnv *env, jobject object, jstring resourceType)
388 {
389     const char *typeCStr = NULL;
390     if (resourceType)
391     {
392         typeCStr = env->GetStringUTFChars(resourceType, NULL);
393     }
394
395     std::vector<SimulatorRemoteResourcePtr> resourceList;
396     resourceList = SimulatorManager::getInstance()->getFoundResources(typeCStr);
397     if (resourceList.empty())
398     {
399         if (typeCStr)
400             env->ReleaseStringUTFChars(resourceType, typeCStr);
401         return NULL;
402     }
403
404     jobject vectorObj = env->NewObject(gSimulatorClassRefs.classVector,
405                                        gSimulatorClassRefs.classVectorCtor);
406     if (!vectorObj)
407     {
408         if (typeCStr)
409             env->ReleaseStringUTFChars(resourceType, typeCStr);
410         return NULL;
411     }
412
413     // Convert to java SimulatorRemoteResource object
414     for (unsigned int i = 0; i < resourceList.size(); i++)
415     {
416         JniSimulatorRemoteResource *jniSimulatorResource = new JniSimulatorRemoteResource(resourceList[i]);
417         if (!jniSimulatorResource)
418         {
419             if (typeCStr)
420                 env->ReleaseStringUTFChars(resourceType, typeCStr);
421             return NULL;
422         }
423
424         jobject resource = SimulatorRemoteResourceToJava(env,
425                            reinterpret_cast<jlong>(jniSimulatorResource));
426         env->CallVoidMethod(vectorObj, gSimulatorClassRefs.classVectorAddElement, resource);
427     }
428
429     if (typeCStr)
430         env->ReleaseStringUTFChars(resourceType, typeCStr);
431     return vectorObj;
432 }
433
434 JNIEXPORT void JNICALL
435 Java_org_oic_simulator_SimulatorManagerNativeInterface_setLogger
436 (JNIEnv *env, jclass object, jobject logger)
437 {
438     static std::shared_ptr<ILogger> target(new JNILogger());
439     dynamic_cast<JNILogger *>(target.get())->setJavaLogger(env, logger);
440     SimulatorManager::getInstance()->setLogger(target);
441 }
442
443 static bool getClassRef(JNIEnv *env, const char *className, jclass &classRef)
444 {
445     jclass localClassRef = nullptr;
446     localClassRef = env->FindClass(className);
447     if (!localClassRef)
448         return false;
449
450     classRef = (jclass)env->NewGlobalRef(localClassRef);
451     env->DeleteLocalRef(localClassRef);
452     return true;
453 }
454
455 #ifdef __cplusplus
456 extern "C" {
457 #endif
458 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
459 {
460     if (!vm)
461     {
462         return JNI_ERR;
463     }
464
465     JNIEnv *env = NULL;
466     if (JNI_OK != vm->GetEnv((void **) &env, JNI_VERSION_1_6))
467     {
468         return JNI_ERR;
469     }
470
471     // Get the class references
472     if (false == getClassRef(env, "java/lang/Integer", gSimulatorClassRefs.classInteger))
473     {
474         return JNI_ERR;
475     }
476
477     if (false == getClassRef(env, "java/lang/Double", gSimulatorClassRefs.classDouble))
478     {
479         return JNI_ERR;
480     }
481
482     if (false == getClassRef(env, "java/lang/String", gSimulatorClassRefs.classString))
483     {
484         return JNI_ERR;
485     }
486
487     if (false == getClassRef(env, "java/util/HashMap", gSimulatorClassRefs.classHashMap))
488     {
489         return JNI_ERR;
490     }
491
492     if (false == getClassRef(env, "java/util/Vector", gSimulatorClassRefs.classVector))
493     {
494         return JNI_ERR;
495     }
496
497     if (false == getClassRef(env, "java/util/Map", gSimulatorClassRefs.classMap))
498     {
499         return JNI_ERR;
500     }
501
502     if (false == getClassRef(env, "java/util/Map$Entry", gSimulatorClassRefs.classMapEntry))
503     {
504         return JNI_ERR;
505     }
506
507     if (false == getClassRef(env, "java/util/Set", gSimulatorClassRefs.classSet))
508     {
509         return JNI_ERR;
510     }
511
512     if (false == getClassRef(env, "java/util/Iterator", gSimulatorClassRefs.classIterator))
513     {
514         return JNI_ERR;
515     }
516
517     if (false == getClassRef(env, "org/oic/simulator/serviceprovider/SimulatorResourceServer",
518                              gSimulatorClassRefs.classSimulatorResource))
519     {
520         return JNI_ERR;
521     }
522
523     if (false == getClassRef(env, "org/oic/simulator/serviceprovider/SimulatorResourceModel",
524                              gSimulatorClassRefs.classSimulatorResourceModel))
525     {
526         return JNI_ERR;
527     }
528
529     if (false == getClassRef(env, "org/oic/simulator/SimulatorResourceAttribute",
530                              gSimulatorClassRefs.classSimulatorResourceAttribute))
531     {
532         return JNI_ERR;
533     }
534
535     if (false == getClassRef(env, "org/oic/simulator/clientcontroller/SimulatorRemoteResource",
536                              gSimulatorClassRefs.classSimulatorRemoteResource))
537     {
538         return JNI_ERR;
539     }
540
541     // Get the reference to methods
542     gSimulatorClassRefs.classIntegerCtor = env->GetMethodID(gSimulatorClassRefs.classInteger, "<init>",
543                                            "(I)V");
544     if (!gSimulatorClassRefs.classIntegerCtor)
545         return JNI_ERR;
546
547     gSimulatorClassRefs.classDoubleCtor = env->GetMethodID(gSimulatorClassRefs.classDouble, "<init>",
548                                           "(D)V");
549     if (!gSimulatorClassRefs.classDoubleCtor)
550         return JNI_ERR;
551
552     gSimulatorClassRefs.classHashMapCtor = env->GetMethodID(gSimulatorClassRefs.classHashMap, "<init>",
553                                            "()V");
554     if (!gSimulatorClassRefs.classHashMapCtor)
555         return JNI_ERR;
556
557     gSimulatorClassRefs.classHashMapPut = env->GetMethodID(gSimulatorClassRefs.classHashMap, "put",
558                                           "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
559     if (!gSimulatorClassRefs.classHashMapPut)
560         return JNI_ERR;
561
562     gSimulatorClassRefs.classVectorCtor = env->GetMethodID(gSimulatorClassRefs.classVector, "<init>",
563                                           "()V");
564     if (!gSimulatorClassRefs.classVectorCtor)
565         return JNI_ERR;
566
567     gSimulatorClassRefs.classVectorAddElement = env->GetMethodID(gSimulatorClassRefs.classVector,
568             "addElement",
569             "(Ljava/lang/Object;)V");
570     if (!gSimulatorClassRefs.classVectorAddElement)
571         return JNI_ERR;
572
573     gSimulatorClassRefs.classMapEntrySet = env->GetMethodID(
574             gSimulatorClassRefs.classMap, "entrySet", "()Ljava/util/Set;");
575     if (!gSimulatorClassRefs.classMapEntrySet)
576         return JNI_ERR;
577
578     gSimulatorClassRefs.classMapGetKey = env->GetMethodID(
579             gSimulatorClassRefs.classMapEntry, "getKey", "()Ljava/lang/Object;");
580     if (!gSimulatorClassRefs.classMapGetKey)
581         return JNI_ERR;
582
583     gSimulatorClassRefs.classMapGetValue = env->GetMethodID(
584             gSimulatorClassRefs.classMapEntry, "getValue", "()Ljava/lang/Object;");
585     if (!gSimulatorClassRefs.classMapGetValue)
586         return JNI_ERR;
587
588     gSimulatorClassRefs.classIteratorId = env->GetMethodID(
589             gSimulatorClassRefs.classSet, "iterator", "()Ljava/util/Iterator;");
590     if (!gSimulatorClassRefs.classIteratorId)
591         return JNI_ERR;
592
593     gSimulatorClassRefs.classHasNextId = env->GetMethodID(
594             gSimulatorClassRefs.classIterator, "hasNext", "()Z");
595     if (!gSimulatorClassRefs.classHasNextId)
596         return JNI_ERR;
597
598     gSimulatorClassRefs.classNextId = env->GetMethodID(
599                                           gSimulatorClassRefs.classIterator, "next", "()Ljava/lang/Object;");
600     if (!gSimulatorClassRefs.classNextId)
601         return JNI_ERR;
602
603     gSimulatorClassRefs.classSimulatorResourceCtor = env->GetMethodID(
604                 gSimulatorClassRefs.classSimulatorResource, "<init>", "(J)V");
605     if (!gSimulatorClassRefs.classSimulatorResourceCtor)
606         return JNI_ERR;
607
608     gSimulatorClassRefs.classSimulatorResourceSetURI = env->GetMethodID(
609                 gSimulatorClassRefs.classSimulatorResource, "setURI", "(Ljava/lang/String;)V");
610     if (!gSimulatorClassRefs.classSimulatorResourceSetURI)
611         return JNI_ERR;
612
613     gSimulatorClassRefs.classSimulatorResourceSetResourceType = env->GetMethodID(
614                 gSimulatorClassRefs.classSimulatorResource, "setResourceType", "(Ljava/lang/String;)V");
615     if (!gSimulatorClassRefs.classSimulatorResourceSetResourceType)
616         return JNI_ERR;
617
618     gSimulatorClassRefs.classSimulatorResourceSetInterfaceType = env->GetMethodID(
619                 gSimulatorClassRefs.classSimulatorResource, "setInterfaceType", "(Ljava/lang/String;)V");
620     if (!gSimulatorClassRefs.classSimulatorResourceSetInterfaceType)
621         return JNI_ERR;
622
623     gSimulatorClassRefs.classSimulatorResourceSetName = env->GetMethodID(
624                 gSimulatorClassRefs.classSimulatorResource, "setName", "(Ljava/lang/String;)V");
625     if (!gSimulatorClassRefs.classSimulatorResourceSetName)
626         return JNI_ERR;
627
628     gSimulatorClassRefs.classSimulatorResourceModelCtor = env->GetMethodID(
629                 gSimulatorClassRefs.classSimulatorResourceModel, "<init>", "(J)V");
630     if (!gSimulatorClassRefs.classSimulatorResourceModelCtor)
631         return JNI_ERR;
632
633     gSimulatorClassRefs.classSimulatorResourceAttributeCtor = env->GetMethodID(
634                 gSimulatorClassRefs.classSimulatorResourceAttribute, "<init>", "(J)V");
635     if (!gSimulatorClassRefs.classSimulatorResourceAttributeCtor)
636         return JNI_ERR;
637
638     gSimulatorClassRefs.classSimulatorResourceModelId = env->GetMethodID(
639                 gSimulatorClassRefs.classSimulatorResourceModel, "<init>", "(J)V");
640     if (!gSimulatorClassRefs.classSimulatorResourceModelId)
641         return JNI_ERR;
642
643     gvm = vm;
644     return JNI_VERSION_1_6;
645 }
646
647 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
648 {
649 }
650
651 #ifdef __cplusplus
652 }
653 #endif