[IOT-1095] Add request parameters to attribute handlers
[platform/upstream/iotivity.git] / service / resource-container / android / resource-container / src / main / jni / JniBundleResource.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
22 #include "JniBundleResource.h"
23 #include "JniRcsResourceAttributes.h"
24 #include "JavaClasses.h"
25 #include "JavaLocalRef.h"
26 #include "JNIEnvWrapper.h"
27 #include "JniRcsValue.h"
28
29 #include <jni.h>
30 #include <string.h>
31 #include <iostream>
32 #include "Log.h"
33
34 #define LOG_TAG "JNI-JniBundleResource"
35
36 using namespace OIC::Service;
37 using namespace std;
38
39 namespace
40 {
41     jclass g_cls_RCSBundleInfo;
42     jfieldID g_field_mNativeHandle;
43 }
44
45 void initRCSJniBundleResource(JNIEnvWrapper *env)
46 {
47     auto clsJniBundleResource = env->FindClass(PACKAGE_NAME "/BundleResource");
48
49     g_field_mNativeHandle = env->GetFieldID(clsJniBundleResource, "mNativeHandle", "J");
50 }
51
52 JniBundleResource::JniBundleResource()
53 {
54
55 }
56
57 void JniBundleResource::initAttributes()
58 {
59
60 }
61
62 JniBundleResource::JniBundleResource(JNIEnv *env, jobject obj, jobject bundleResource,
63                                        string bundleId, jobjectArray attributes)
64 {
65     LOGD("Creating android resource, bundleId: %s", bundleId.c_str());
66     (void) obj;
67     m_env = env;
68     int stringCount = m_env->GetArrayLength(attributes);
69     LOGD("string count is %d", stringCount);
70
71     LOGD("Get java vm.");
72     int jvmAccess = m_env->GetJavaVM(&m_jvm);
73
74
75     for (int i = 0; i < stringCount; i++)
76     {
77         jstring str = (jstring) m_env->GetObjectArrayElement(attributes, i);
78         const char *rawString = m_env->GetStringUTFChars(str, 0);
79         string s(rawString, strlen(rawString));
80         JniBundleResource::setAttribute(s, "");
81         m_env->ReleaseStringUTFChars(str, rawString);
82         m_env->DeleteLocalRef(str);
83         LOGD("Deleting and releasing resources - JNI bundle resource");
84     }
85
86     m_bundleId = bundleId;
87
88     this->m_bundleResource = m_env->NewGlobalRef(bundleResource);
89
90     m_bundleResourceClass = (jclass) m_env->NewGlobalRef(m_env->GetObjectClass(bundleResource));
91     LOGD("Looking for setter.");
92     m_attributeSetRequestHandler = m_env->GetMethodID(m_bundleResourceClass,
93             "handleSetAttributesRequest",
94             "(Lorg/iotivity/service/resourcecontainer/RcsResourceAttributes;)V");
95     LOGD("Looking for getter.");
96     m_attributeGetRequestHandler = m_env->GetMethodID(m_bundleResourceClass,
97             "handleGetAttributesRequest",
98             "()Lorg/iotivity/service/resourcecontainer/RcsResourceAttributes;");
99
100     LOGD("Looking for onUpdatedInputResource.");
101     m_superclass = (jclass) m_env->NewGlobalRef(m_env->GetSuperclass(m_bundleResourceClass));
102
103     m_classClass = (jclass) m_env->NewGlobalRef(m_env->FindClass("java/lang/Class"));
104
105
106     m_vectorClazz = (jclass) m_env->NewGlobalRef(m_env->FindClass("java/util/Vector"));
107     if (m_env->ExceptionCheck()) {
108         m_env->ExceptionDescribe();
109     }
110
111     if (m_env->ExceptionCheck()) {
112        m_env->ExceptionDescribe();
113     }
114
115     if(m_classClass != NULL){
116         // Find the getName() method on the class object
117         jmethodID mid = env->GetMethodID(m_classClass, "getName", "()Ljava/lang/String;");
118
119         // Call the getName() to get a jstring object back
120         if(m_superclass != NULL){
121             jstring strObj = (jstring)env->CallObjectMethod(m_superclass, mid);
122
123             // Now get the c string from the java jstring object
124             const char* str = env->GetStringUTFChars(strObj, NULL);
125
126             LOGD("Name of super class is %s", str);
127
128             //check for softsensor resource
129             if(strcmp("org.iotivity.service.resourcecontainer.BundleSoftSensorResource", str) == 0){
130                m_onUpdatedInputResource = m_env->GetMethodID(m_bundleResourceClass,
131                        "onUpdatedInputResource", "(Ljava/lang/String;Ljava/util/Vector;)V");
132                if (m_env->ExceptionCheck()) {
133                    m_env->ExceptionDescribe();
134                }
135
136                LOGD("Looking up vector add method.");
137                if(m_vectorClazz != NULL){
138                    m_vectorAddMethod =  m_env->GetMethodID(m_vectorClazz, "add", "(Ljava/lang/Object;)Z");
139                    if (m_env->ExceptionCheck()) {
140                        m_env->ExceptionDescribe();
141                    }
142                }
143
144             }
145             LOGD("Deleting and releasing resources - JNIBundleResource 2");
146             m_env->ReleaseStringUTFChars(strObj, str);
147         }
148     }
149 }
150
151 JniBundleResource::~JniBundleResource()
152 {
153
154 }
155
156 RCSResourceAttributes::Value JniBundleResource::handleGetAttributeRequest(
157         const std::string &attributeName)
158 {
159     LOGD("handleGetAttributeRequest called2");
160     LOGD("Attaching thread now");
161     int attached = m_jvm->AttachCurrentThread(&m_env, NULL);
162     if(attached>0)
163     {
164         LOGE("Failed to attach thread to JavaVM");
165     }
166     else{
167         if(m_attributeGetRequestHandler != NULL){
168             jstring attrName = m_env->NewStringUTF(attributeName.c_str());
169             auto responseObj =  m_env->CallObjectMethod(m_bundleResource,
170                     m_attributeGetRequestHandler, attrName);
171
172             if (responseObj)
173             {
174                 LOGD("parsing attributes");
175                 RCSResourceAttributes attrs = toNativeAttributes(m_env, responseObj);
176                 LOGD("Received attributes %d", attrs.size());
177             }
178         }
179     }
180     return JniBundleResource::getAttribute(attributeName);
181 }
182
183 void JniBundleResource::handleSetAttributeRequest(const std::string &attributeName,
184                                       RCSResourceAttributes::Value &&value)
185 {
186     if(m_attributeSetRequestHandler != NULL){
187         jstring attrName = m_env->NewStringUTF(attributeName.c_str());
188         jstring val = m_env->NewStringUTF(value.toString().c_str());
189
190         //LOGD("handleSetAttributeRequest calling object method %d", &m_attributeSetRequestHandler);
191         m_env->CallObjectMethod(m_bundleResource, m_attributeSetRequestHandler, attrName, val);
192     }
193     JniBundleResource::setAttribute(attributeName, std::move(value));
194 }
195
196
197 void JniBundleResource::handleSetAttributesRequest(const RCSResourceAttributes &attrs,
198         const std::map< std::string, std::string > &queryParams)
199 {
200     LOGD("handleSetAttributesRequest called %d", attrs.size());
201
202     //m_env->CallObjectMethod(m_bundleResource, m_attributeSetRequestHandler, attrName, val);
203     //JniBundleResource::setAttribute(attributeName, std::move(value));
204     if(m_attributeSetRequestHandler != NULL && m_bundleResource != NULL){
205         int attached = m_jvm->AttachCurrentThread(&m_env, NULL);
206
207         if(attached>0)
208         {
209             LOGE("Failed to attach thread to JavaVM");
210         }
211         else{
212             LOGD("Creating resource attributes for JNI.");
213
214             m_env->MonitorEnter(m_bundleResource);
215             auto jniRcsAttributes = newAttributesObject(m_env, attrs);
216             LOGD("jobject created. calling");
217             m_env->CallVoidMethod(m_bundleResource,
218                     m_attributeSetRequestHandler, jniRcsAttributes);
219             JniBundleResource::setAttributes(attrs);
220             m_env->MonitorExit(m_bundleResource);
221
222             m_jvm->DetachCurrentThread();
223         }
224     }
225 }
226
227 RCSResourceAttributes JniBundleResource::handleGetAttributesRequest(const
228         std::map< std::string, std::string > &queryParams)
229 {
230     LOGD("handleGetAttributesRequest");
231
232     if(m_attributeGetRequestHandler != NULL && m_bundleResource != NULL){
233         LOGD("attaching thread");
234         int attached = m_jvm->AttachCurrentThread(&m_env, NULL);
235         if(attached>0)
236         {
237             LOGE("Failed to attach thread to JavaVM");
238         }
239         else{
240             LOGD("attached, calling get request handler");
241             auto responseObj =  m_env->CallObjectMethod(m_bundleResource,
242                     m_attributeGetRequestHandler);
243
244             if (responseObj)
245             {
246                 LOGD("parsing attributes");
247                 m_env->MonitorEnter(m_bundleResource);
248                 LOGD("to native attributes");
249                 const RCSResourceAttributes attrs = toNativeAttributes(m_env, responseObj);
250                 LOGD("Received attributes %d", attrs.size());
251                 JniBundleResource::setAttributes(attrs, false);
252                 m_env->MonitorExit(m_bundleResource);
253             }
254
255             m_jvm->DetachCurrentThread();
256         }
257         LOGD("JniBundleResource::getAttributes().size() %d",
258                 JniBundleResource::getAttributes().size());
259     }
260     return JniBundleResource::getAttributes();
261 }
262
263 void JniBundleResource::executeLogic(){
264     // IS CALLED AT JAVA LAYER
265 }
266
267 void JniBundleResource::onUpdatedInputResource(const std::string attributeName,
268         std::vector<RCSResourceAttributes::Value> values){
269     LOGD("onUpdatedInputResource");
270     if(m_vectorClazz == NULL || m_classClass == NULL){
271         return;
272     }
273     int attached = m_jvm->AttachCurrentThread(&m_env, NULL);
274     jobject valueObj;
275     if(attached>0)
276     {
277         LOGE("Failed to attach thread to JavaVM");
278     }
279     else{
280
281
282         jobject obj = m_env->NewObject(m_vectorClazz,
283                 m_env->GetMethodID(m_vectorClazz, "<init>", "()V"));
284
285         LOGD("Looking up vector add method.");
286
287         jmethodID m_vectorAddMethod =  m_env->GetMethodID(m_vectorClazz, "add",
288                 "(Ljava/lang/Object;)Z");
289         if (m_env->ExceptionCheck()) {
290             m_env->ExceptionDescribe();
291         }
292
293         if(m_vectorAddMethod == NULL){
294             m_jvm->DetachCurrentThread();
295             return;
296         }
297
298         for (int n=0;n<values.size();n++)
299         {
300            valueObj  = newRCSValueObject(m_env, values[n]);
301            m_env->CallBooleanMethod(obj, m_vectorAddMethod, valueObj);
302         }
303
304         // Find the getName() method on the class object
305         jmethodID mid = m_env->GetMethodID(m_classClass, "getName",
306                 "()Ljava/lang/String;");
307
308         // Call the getName() to get a jstring object back
309         if(m_superclass == NULL || mid == NULL){
310             m_jvm->DetachCurrentThread();
311             return;
312         }
313
314         jstring strObj = (jstring)m_env->CallObjectMethod(m_superclass, mid);
315
316         // Now get the c string from the java jstring object
317         if(strObj == NULL){
318             m_jvm->DetachCurrentThread();
319             return;
320         }
321         const char* str = m_env->GetStringUTFChars(strObj, NULL);
322
323         LOGD("Name of super class is %s", str);
324
325         jstring attrName = m_env->NewStringUTF(attributeName.c_str());
326
327         //check for softsensor resource
328         if(strcmp("org.iotivity.service.resourcecontainer.BundleSoftSensorResource", str) == 0){
329             jmethodID m_onUpdatedInputResource = m_env->GetMethodID(m_bundleResourceClass,
330                     "onUpdatedInputResource", "(Ljava/lang/String;Ljava/util/Vector;)V");
331             if(m_onUpdatedInputResource != NULL){
332                 m_env->MonitorEnter(m_bundleResource);
333                 m_env->CallVoidMethod(m_bundleResource,
334                 m_onUpdatedInputResource, attrName, obj);
335                 m_env->MonitorExit(m_bundleResource);
336                 if (m_env->ExceptionCheck()) {
337                     m_env->ExceptionDescribe();
338                 }
339             }
340         }
341         LOGD("Deleting and releasing resources - onUpdatedInputResource");
342         m_env->DeleteLocalRef(attrName);
343         m_env->ReleaseStringUTFChars(strObj, str);
344
345         if (m_env->ExceptionCheck()) {
346                m_env->ExceptionDescribe();
347         }
348         m_jvm->DetachCurrentThread();
349     }
350
351     LOGD("JniBundleResource::getAttributes().size() %d", JniBundleResource::getAttributes().size());
352 }
353
354 JNIEXPORT void
355 JNICALL Java_org_iotivity_service_resourcecontainer_BundleResource_updateNativeInstance
356 (JNIEnv* env, jobject obj, jobject updates)
357 {
358     LOGD("updateNativeInstance");
359     BundleResource* JniBundleResource =
360             reinterpret_cast<BundleResource*>(env->GetLongField(obj, g_field_mNativeHandle));
361     RCSResourceAttributes attrs = toNativeAttributes(env, updates);
362     LOGD("Received attributes %d", attrs.size());
363     JniBundleResource->setAttributes(attrs, true);
364 }