Unit tests for android extension of resource contianer
[platform/upstream/iotivity.git] / service / resource-container / android / resource-container / src / main / jni / JniRcsResourceContainer.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 "JniRcsResourceContainer.h"
22
23 #include "JavaClasses.h"
24 #include "JavaLocalRef.h"
25 #include "JNIEnvWrapper.h"
26 #include "Log.h"
27 #include "Verify.h"
28 #include <dlfcn.h>
29
30 #include "ResourceContainerBundleAPI.h"
31 #include "JniBundleResource.h"
32 #include "RCSResourceContainer.h"
33
34
35
36 #define LOG_TAG "JNI-RCSResourceContainer"
37
38 using namespace OIC::Service;
39
40 #define CLS_NAME_BUNDLE_INFO "org/iotivity/service/resourcecontainer/RcsBundleInfo"
41
42 std::map< string, BundleResource::Ptr > android_resources;
43
44 namespace
45 {
46     jclass g_cls_RCSBundleInfo;
47     jfieldID g_field_mNativeHandle;
48
49     jmethodID g_ctor_RCSBundleInfo;
50
51     std::map< std::string, std::string > convertJavaMapToParamsMap(JNIEnvWrapper *env,
52             jobject mapObj)
53     {
54         EXPECT_RET_DEF(mapObj, "map is null");
55
56         auto setObj = invoke_Map_entrySet(env, mapObj);
57         auto iterObj = invoke_Set_iterator(env, setObj);
58
59         std::map< std::string, std::string > ret;
60
61         while (invoke_Iterator_hasNext(env, iterObj))
62         {
63             JavaLocalObject entryObj { env, invoke_Iterator_next(env, iterObj) };
64
65             JavaLocalString keyObj { env,
66                 static_cast< jstring >(invoke_MapEntry_getKey(env, entryObj)) };
67
68             JavaLocalString valueObj { env,
69                 static_cast< jstring >(invoke_MapEntry_getValue(env, entryObj)) };
70
71             ret.emplace(toStdString(env, keyObj), toStdString(env, valueObj));
72         }
73
74         return ret;
75     }
76
77     jobject newBundleInfoObj(JNIEnvWrapper *env, const std::unique_ptr< RCSBundleInfo > &bundleInfo)
78     {
79         LOGD("new bundle info");
80         __android_log_print(ANDROID_LOG_DEBUG, "CONTAINER", "newBundleInfoObj %s",bundleInfo->getActivatorName().c_str());
81         JavaLocalString id{env, newStringObject(env, bundleInfo->getID()) };
82         JavaLocalString path{env, newStringObject(env, bundleInfo->getPath()) };
83         JavaLocalString activatorName{env, newStringObject(env, bundleInfo->getActivatorName()) };
84         JavaLocalString libraryPath{env, newStringObject(env, bundleInfo->getLibraryPath()) };
85         JavaLocalString version{env, newStringObject(env, bundleInfo->getVersion()) };
86
87         return env->NewObject(g_cls_RCSBundleInfo, g_ctor_RCSBundleInfo,
88                 id.get(), path.get(), activatorName.get(), libraryPath.get(), version.get());
89     }
90 }
91
92 void initRCSResourceContainer(JNIEnvWrapper *env)
93 {
94     g_cls_RCSBundleInfo = env->FindClassAsGlobalRef(CLS_NAME_BUNDLE_INFO);
95
96     g_ctor_RCSBundleInfo = env->GetConstructorID(g_cls_RCSBundleInfo, "("
97             AS_SIG(CLS_NAME_STRING)
98             AS_SIG(CLS_NAME_STRING)
99             AS_SIG(CLS_NAME_STRING)
100             AS_SIG(CLS_NAME_STRING)
101             AS_SIG(CLS_NAME_STRING)
102             ")V");
103
104     auto clsJniBundleResource = env->FindClass(PACKAGE_NAME "/BundleResource");
105
106     g_field_mNativeHandle = env->GetFieldID(clsJniBundleResource, "mNativeHandle", "J");
107 }
108
109 void clearRCSResourceContainer(JNIEnvWrapper *env)
110 {
111     env->DeleteGlobalRef(g_cls_RCSBundleInfo);
112 }
113
114 JNIEXPORT void JNICALL
115 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeStartContainer
116 (JNIEnv *env, jobject, jstring configFileObj)
117 {
118     LOGD("nativeStartContainer");
119
120     // A strange error message happens if the container is used as native library on Android
121     // and further native libraries are loaded at runtime.
122     const char *error;
123     if ((error = dlerror()) != NULL)
124     {
125         __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer",
126                 "dlerror: %s.", error);
127     }
128
129     EXPECT(configFileObj, "ConfigFile is null.");
130
131     auto configFile = toStdString(env, configFileObj);
132     //  std::string nativeFilePath = env->GetStringUTFChars(configFile, NULL);
133     VERIFY_NO_EXC(env);
134
135     RCSResourceContainer::getInstance()->startContainer(configFile);
136 }
137
138 JNIEXPORT void JNICALL
139 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeStopContainer(JNIEnv *env, jobject)
140 {
141     LOGD("nativeStopContainers");
142
143     // A strange error message happens if the container is used as native library on Android
144     // and further native libraries are loaded at runtime.
145     const char *error;
146     if ((error = dlerror()) != NULL)
147     {
148         __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer",
149                 "dlerror: %s.", error);
150     }
151
152     RCSResourceContainer::getInstance()->stopContainer();
153 }
154
155 JNIEXPORT void JNICALL
156 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeAddBundle
157 (JNIEnv *env, jobject, jstring idObj, jstring uriObj, jstring pathObj, jstring activatorObj,
158  jobject paramsObj)
159 {
160     LOGD("nativeAddBundle");
161
162     // A strange error message happens if the container is used as native library on Android
163     // and further native libraries are loaded at runtime.
164     const char *error;
165     if ((error = dlerror()) != NULL)
166     {
167         __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer",
168                 "dlerror: %s.", error);
169     }
170
171     EXPECT(idObj, "BundleId is null.");
172     EXPECT(pathObj, "BundlePath is null.");
173     EXPECT(activatorObj, "Activator is null.");
174
175     JNIEnvWrapper envWrapper(env);
176
177     try
178     {
179         LOGD("nativeAddBundle before calling native");
180         RCSResourceContainer::getInstance()->addBundle(toStdString(&envWrapper, idObj),
181                 toStdString(&envWrapper, uriObj), toStdString(&envWrapper, pathObj),
182                 toStdString(&envWrapper, activatorObj),
183                 convertJavaMapToParamsMap(&envWrapper, paramsObj));
184
185         LOGD("nativeAddBundle after calling native");
186     }
187     catch (const JavaException &)
188     {
189         LOGE("Failed to add bundle.");
190     }
191 }
192
193 JNIEXPORT void JNICALL
194 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeRemoveBundle
195 (JNIEnv *env, jobject, jstring idObj)
196 {
197     LOGD("nativeRemoveBundle");
198
199     // A strange error message happens if the container is used as native library on Android
200     // and further native libraries are loaded at runtime.
201     const char *error;
202     if ((error = dlerror()) != NULL)
203     {
204         __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer",
205                 "dlerror: %s.", error);
206     }
207
208     EXPECT(idObj, "BundleId is null.");
209
210     auto id = toStdString(env, idObj);
211     VERIFY_NO_EXC(env);
212
213     RCSResourceContainer::getInstance()->removeBundle(id);
214 }
215
216
217 JNIEXPORT jobject JNICALL
218 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeListBundles
219 (JNIEnv *env, jobject)
220 {
221     LOGD("nativeListBundles");
222
223     // A strange error message happens if the container is used as native library on Android
224     // and further native libraries are loaded at runtime.
225     const char *error;
226     if ((error = dlerror()) != NULL)
227     {
228         __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer",
229                 "dlerror: %s.", error);
230     }
231
232     JNIEnvWrapper envWrapper(env);
233
234     try
235     {
236         auto listObj = newArrayList(&envWrapper);
237
238         for (const auto& bundleInfo : RCSResourceContainer::getInstance()->listBundles())
239         {
240             JavaLocalObject bundleInfoObj{ &envWrapper, newBundleInfoObj(&envWrapper, bundleInfo) };
241             invoke_Collection_add(&envWrapper, listObj, bundleInfoObj);
242         }
243         return listObj;
244     }
245     catch (const JavaException &)
246     {
247         LOGE("Failed to convert bundle info list.");
248     }
249     return nullptr;
250 }
251
252 JNIEXPORT void JNICALL
253 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeStartBundle
254 (JNIEnv *env, jobject, jstring idObj)
255 {
256     LOGD("nativeStartBundle");
257
258     // A strange error message happens if the container is used as native library on Android
259     // and further native libraries are loaded at runtime.
260     const char *error;
261     if ((error = dlerror()) != NULL)
262     {
263         __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer",
264                 "dlerror: %s.", error);
265     }
266
267     EXPECT(idObj, "BundleId is null.");
268
269     auto id = env->GetStringUTFChars(idObj, NULL);
270     VERIFY_NO_EXC(env);
271
272     RCSResourceContainer::getInstance()->startBundle(id);
273 }
274 JNICALL
275 JNIEXPORT void
276 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeStopBundle
277 (JNIEnv *env, jobject, jstring idObj)
278 {
279     LOGD("nativeStopBundle");
280
281     // A strange error message happens if the container is used as native library on Android
282     // and further native libraries are loaded at runtime.
283     const char *error;
284     if ((error = dlerror()) != NULL)
285     {
286         __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer",
287                 "dlerror: %s.", error);
288     }
289
290     EXPECT(idObj, "BundleId is null.");
291
292     auto id = env->GetStringUTFChars(idObj, NULL);
293     VERIFY_NO_EXC(env);
294
295     RCSResourceContainer::getInstance()->stopBundle(id);
296 }
297
298 JNIEXPORT void JNICALL
299 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeAddResourceConfig
300 (JNIEnv *env, jobject, jstring idObj, jstring uriObj, jobject paramsObj)
301 {
302     LOGD("nativeAddResourceConfig");
303
304     EXPECT(idObj, "BundleId is null.");
305     EXPECT(uriObj, "BundleUri is null.");
306     EXPECT(paramsObj, "Params is null.");
307
308     JNIEnvWrapper envWrapper(env);
309
310     try
311     {
312         RCSResourceContainer::getInstance()->addResourceConfig(toStdString(&envWrapper, idObj),
313                 toStdString(&envWrapper, uriObj), convertJavaMapToParamsMap(&envWrapper, paramsObj));
314     }
315     catch (const JavaException &)
316     {
317         LOGE("Failed to add bundle.");
318     }
319 }
320
321 JNIEXPORT void JNICALL
322 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeRemoveResourceConfig
323 (JNIEnv *env, jobject, jstring idObj, jstring uriObj)
324 {
325     LOGD("nativeRemoveResourceConfig");
326
327     EXPECT(idObj, "BundleId is null.");
328     EXPECT(uriObj, "BundleUri is null.");
329
330     auto id = toStdString(env, idObj);
331     VERIFY_NO_EXC(env);
332     auto uri = toStdString(env, uriObj);
333     VERIFY_NO_EXC(env);
334
335     RCSResourceContainer::getInstance()->removeResourceConfig(id, uri);
336 }
337
338 JNIEXPORT jobject JNICALL
339 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeListBundleResources
340 (JNIEnv *env, jobject, jstring idObj)
341 {
342     LOGD("nativeListBundleResources");
343
344     EXPECT_RET_DEF(idObj, "BundleId is null.");
345
346     JNIEnvWrapper envWrapper(env);
347
348     try
349     {
350         auto id = toStdString(&envWrapper, idObj);
351
352         auto listObj = newArrayList(&envWrapper);
353
354         for (const auto& s : RCSResourceContainer::getInstance()->listBundleResources(id))
355         {
356             JavaLocalString strObj{ &envWrapper, newStringObject(&envWrapper, s) };
357
358             invoke_Collection_add(&envWrapper, listObj, strObj);
359         }
360
361         return listObj;
362     }
363     catch (const JavaException &)
364     {
365         LOGE("Failed to convert bundle info list.");
366     }
367
368     return nullptr;
369 }
370
371
372 JNIEXPORT void JNICALL
373 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeRegisterBundleResource
374 (JNIEnv *env, jobject obj, jobject bundleResource, jobjectArray attributes, jstring bundleId,
375  jstring uri, jstring resourceType, jstring res_name)
376 {
377     JNIEnvWrapper envWrapper(env);
378     LOGD("nativeRegisterJniBundleResource");
379     auto str_bundle_id = toStdString(&envWrapper, bundleId);
380     __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer", "retrieved bundle id: %s.",
381             str_bundle_id.c_str());
382     auto str_uri = toStdString(&envWrapper, uri);
383     __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer", "retrieved uri: %s.",
384             str_uri.c_str());
385     auto str_resourceType = toStdString(&envWrapper, resourceType);
386     __android_log_print(ANDROID_LOG_DEBUG, "JNI-RCSResourceContainer", "retrieved resource type: %s.",
387             str_resourceType.c_str());
388     auto str_res_name = toStdString(&envWrapper, res_name);
389     LOGD("retrieved res name.");
390     JniBundleResource res;
391
392     BundleResource::Ptr androidResource = std::make_shared< JniBundleResource >
393             (env, obj, bundleResource, str_bundle_id, attributes);
394     ResourceContainerImpl *container = ResourceContainerImpl::getImplInstance();
395
396     androidResource->m_uri = str_uri;
397     androidResource->m_resourceType = str_resourceType;
398     androidResource->m_name = str_res_name;
399     androidResource->m_bundleId = str_bundle_id;
400
401     // link java resource instance to c++ resource instance
402     env->SetLongField(bundleResource, g_field_mNativeHandle, reinterpret_cast< jlong >(androidResource.get()));
403
404     container->registerResource(androidResource);
405
406     android_resources[str_uri] = androidResource;
407 }
408
409 /*
410  * Class:     org_iotivity_resourcecontainer_bundle_api_BaseActivator
411  * Method:    unregisterJavaResource
412  * Signature: (Lorg/iotivity/resourcecontainer/bundle/api/BundleResource;)V
413  */
414 JNIEXPORT void JNICALL
415 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeUnregisterBundleResource
416 (JNIEnv *env, jobject obj, jobject bundleResource, jstring uri)
417 {
418     (void)obj;
419     (void)bundleResource;
420     const char *str_uri = env->GetStringUTFChars(uri, 0);
421
422     if (android_resources[str_uri] != NULL)
423     {
424         ResourceContainerImpl *container = ResourceContainerImpl::getImplInstance();
425         container->unregisterResource(android_resources[str_uri]);
426         android_resources.erase(str_uri);
427     }
428 }
429
430 /*
431  * Class:     org_iotivity_resourcecontainer_bundle_api_BaseActivator
432  * Method:    getNumberOfConfiguredResources
433  * Signature: (Ljava/lang/String;)I
434  */
435 JNIEXPORT jint JNICALL
436 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeGetNumberOfConfiguredResources(
437     JNIEnv *env, jobject obj, jstring bundleId)
438 {
439     (void)obj;
440     LOGD("nativeGetNumberOfConfiguredResources");
441     const char *str_bundleId = env->GetStringUTFChars(bundleId, 0);
442     LOGD("retrieved bundle id");
443     __android_log_print(ANDROID_LOG_DEBUG, "CONTAINER", "getNumberOfConfiguredResources %s",str_bundleId);
444     ResourceContainerImpl *container = ResourceContainerImpl::getImplInstance();
445     vector< resourceInfo > resourceConfig;
446     container->getResourceConfiguration(str_bundleId, &resourceConfig);
447
448     return resourceConfig.size();
449 }
450
451 /*
452  * Class:     org_iotivity_resourcecontainer_bundle_api_BaseActivator
453  * Method:    getConfiguredResourceParams
454  * Signature: (Ljava/lang/String;I)[Ljava/lang/String;
455  */
456 JNIEXPORT jobjectArray JNICALL
457 Java_org_iotivity_service_resourcecontainer_RcsResourceContainer_nativeGetConfiguredResourceParams(
458     JNIEnv *env, jobject obj, jstring bundleId, jint resourceId)
459 {
460     (void)obj;
461     jobjectArray ret;
462     const char *str_bundleId = env->GetStringUTFChars(bundleId, 0);
463
464     ResourceContainerImpl *container = ResourceContainerImpl::getImplInstance();
465     vector< resourceInfo > resourceConfig;
466     container->getResourceConfiguration(str_bundleId, &resourceConfig);
467     resourceInfo conf = resourceConfig[resourceId];
468     ret = (jobjectArray) env->NewObjectArray(4, env->FindClass("java/lang/String"),
469             env->NewStringUTF(""));
470
471     env->SetObjectArrayElement(ret, 0, env->NewStringUTF(conf.name.c_str()));
472     env->SetObjectArrayElement(ret, 1, env->NewStringUTF(conf.uri.c_str()));
473     env->SetObjectArrayElement(ret, 2, env->NewStringUTF(conf.resourceType.c_str()));
474     env->SetObjectArrayElement(ret, 3, env->NewStringUTF(conf.address.c_str()));
475     return ret;
476 }
477