Merge "Merge remote-tracking branch 'origin/master' into notification-service" into...
[platform/upstream/iotivity.git] / android / android_api / base / jni / JniOnObserveListener.cpp
1 /*
2 * //******************************************************************
3 * //
4 * // Copyright 2015 Intel Corporation.
5 * //
6 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 * //
8 * // Licensed under the Apache License, Version 2.0 (the "License");
9 * // you may not use this file except in compliance with the License.
10 * // You may obtain a copy of the License at
11 * //
12 * //      http://www.apache.org/licenses/LICENSE-2.0
13 * //
14 * // Unless required by applicable law or agreed to in writing, software
15 * // distributed under the License is distributed on an "AS IS" BASIS,
16 * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * // See the License for the specific language governing permissions and
18 * // limitations under the License.
19 * //
20 * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 */
22 #include "JniOnObserveListener.h"
23 #include "JniOcResource.h"
24 #include "JniOcRepresentation.h"
25 #include "JniUtils.h"
26 #ifdef WITH_CLOUD
27 #include "JniOcAccountManager.h"
28 #endif
29
30 #define CA_OBSERVE_MAX_SEQUENCE_NUMBER 0xFFFFFF
31
32 JniOnObserveListener::JniOnObserveListener(JNIEnv *env, jobject jListener, JniOcResource* owner)
33     : m_ownerResource(owner)
34 {
35     m_jwListener = env->NewWeakGlobalRef(jListener);
36 #ifdef WITH_CLOUD
37     m_ownerAccountManager = nullptr;
38 #endif
39 }
40
41 #ifdef WITH_CLOUD
42 JniOnObserveListener::JniOnObserveListener(JNIEnv *env, jobject jListener, JniOcAccountManager* owner)
43     : m_ownerAccountManager(owner)
44 {
45     m_jwListener = env->NewWeakGlobalRef(jListener);
46     m_ownerResource = nullptr;
47 }
48 #endif
49
50 JniOnObserveListener::~JniOnObserveListener()
51 {
52     if (m_jwListener)
53     {
54         jint ret = JNI_ERR;
55         JNIEnv *env = GetJNIEnv(ret);
56         if (nullptr == env)
57         {
58             return;
59         }
60
61         env->DeleteWeakGlobalRef(m_jwListener);
62         m_jwListener = nullptr;
63
64         if (JNI_EDETACHED == ret)
65         {
66             g_jvm->DetachCurrentThread();
67         }
68     }
69 }
70
71 void JniOnObserveListener::onObserveCallback(const HeaderOptions headerOptions,
72     const OCRepresentation& ocRepresentation, const int& eCode, const int& sequenceNumber)
73 {
74     jint envRet = JNI_ERR;
75     JNIEnv *env = GetJNIEnv(envRet);
76     if (nullptr == env)
77     {
78         return;
79     }
80
81     if (nullptr == m_jwListener)
82     {
83         LOGE("listener is not available");
84         if (JNI_EDETACHED == envRet)
85         {
86             g_jvm->DetachCurrentThread();
87         }
88         return;
89     }
90
91     jobject jListener = env->NewLocalRef(m_jwListener);
92     if (!jListener)
93     {
94         checkExAndRemoveListener(env);
95         if (JNI_EDETACHED == envRet)
96         {
97             g_jvm->DetachCurrentThread();
98         }
99         return;
100     }
101
102     jclass clsL = env->GetObjectClass(jListener);
103     if (!clsL)
104     {
105         env->DeleteLocalRef(jListener);
106         checkExAndRemoveListener(env);
107         if (JNI_EDETACHED == envRet)
108         {
109             g_jvm->DetachCurrentThread();
110         }
111         return;
112     }
113
114     if (OC_STACK_OK != eCode && OC_STACK_RESOURCE_CREATED != eCode &&
115             OC_STACK_RESOURCE_DELETED != eCode && OC_STACK_RESOURCE_CHANGED != eCode)
116     {
117         jobject ex = GetOcException(eCode, "stack error in onObserveCallback");
118         if (!ex)
119         {
120             goto JNI_EXIT;
121         }
122
123         jmethodID midL = env->GetMethodID(clsL, "onObserveFailed", "(Ljava/lang/Throwable;)V");
124         if (!midL)
125         {
126             env->DeleteLocalRef(ex);
127             goto JNI_EXIT;
128         }
129         env->CallVoidMethod(jListener, midL, ex);
130     }
131     else
132     {
133         jobject jHeaderOptionList = JniUtils::convertHeaderOptionsVectorToJavaList(env, headerOptions);
134         if (!jHeaderOptionList)
135         {
136             goto JNI_EXIT;
137         }
138
139         OCRepresentation * rep = new OCRepresentation(ocRepresentation);
140         jlong handle = reinterpret_cast<jlong>(rep);
141         jobject jRepresentation = env->NewObject(g_cls_OcRepresentation,
142             g_mid_OcRepresentation_N_ctor_bool, handle, true);
143         if (!jRepresentation)
144         {
145             delete rep;
146             env->DeleteLocalRef(jHeaderOptionList);
147             goto JNI_EXIT;
148         }
149
150         jmethodID midL = env->GetMethodID(clsL, "onObserveCompleted",
151             "(Ljava/util/List;Lorg/iotivity/base/OcRepresentation;I)V");
152         if (!midL)
153         {
154             env->DeleteLocalRef(jRepresentation);
155             env->DeleteLocalRef(jHeaderOptionList);
156             goto JNI_EXIT;
157         }
158
159         env->CallVoidMethod(jListener, midL, jHeaderOptionList, jRepresentation,
160             static_cast<jint>(sequenceNumber));
161         if (env->ExceptionCheck())
162         {
163             LOGE("Java exception is thrown");
164             delete rep;
165             env->DeleteLocalRef(jRepresentation);
166             env->DeleteLocalRef(jHeaderOptionList);
167             jthrowable ex = env->ExceptionOccurred();
168             env->ExceptionClear();
169 #ifndef WITH_CLOUD
170             m_ownerResource->removeOnObserveListener(env, m_jwListener);
171 #else
172             if (nullptr != m_ownerResource)
173             {
174                 m_ownerResource->removeOnObserveListener(env, m_jwListener);
175             }
176             if (nullptr != m_ownerAccountManager)
177             {
178                 m_ownerAccountManager->removeOnObserveListener(env, m_jwListener);
179             }
180 #endif
181             env->Throw((jthrowable)ex);
182         }
183
184         if (CA_OBSERVE_MAX_SEQUENCE_NUMBER + 1 == sequenceNumber)
185         {
186             LOGI("Observe De-registration action is successful");
187             goto JNI_EXIT;
188         }
189     }
190
191     env->DeleteLocalRef(clsL);
192     env->DeleteLocalRef(jListener);
193     if (JNI_EDETACHED == envRet)
194     {
195         g_jvm->DetachCurrentThread();
196     }
197     return;
198
199 JNI_EXIT:
200     env->DeleteLocalRef(clsL);
201     env->DeleteLocalRef(jListener);
202     checkExAndRemoveListener(env);
203     if (JNI_EDETACHED == envRet)
204     {
205         g_jvm->DetachCurrentThread();
206     }
207 }
208
209 void JniOnObserveListener::checkExAndRemoveListener(JNIEnv* env)
210 {
211     LOGI("checkExAndRemoveListener");
212     if (env->ExceptionCheck())
213     {
214         jthrowable ex = env->ExceptionOccurred();
215         env->ExceptionClear();
216 #ifndef WITH_CLOUD
217         m_ownerResource->removeOnObserveListener(env, m_jwListener);
218 #else
219         if (nullptr != m_ownerResource)
220         {
221             m_ownerResource->removeOnObserveListener(env, m_jwListener);
222         }
223         if (nullptr != m_ownerAccountManager)
224         {
225             m_ownerAccountManager->removeOnObserveListener(env, m_jwListener);
226         }
227 #endif
228         env->Throw((jthrowable)ex);
229     }
230     else
231     {
232 #ifndef WITH_CLOUD
233         m_ownerResource->removeOnObserveListener(env, m_jwListener);
234 #else
235         if (nullptr != m_ownerResource)
236         {
237             m_ownerResource->removeOnObserveListener(env, m_jwListener);
238         }
239         if (nullptr != m_ownerAccountManager)
240         {
241             m_ownerAccountManager->removeOnObserveListener(env, m_jwListener);
242         }
243 #endif
244     }
245 }
246
247 jweak JniOnObserveListener::getJWListener()
248 {
249     return this->m_jwListener;
250 }