From: hyuna0213.jo Date: Tue, 2 Aug 2016 09:10:47 +0000 (+0900) Subject: Implementation of JNI for deleting resource from RD X-Git-Tag: 1.2.0+RC1~124 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ea65e0ced7092a716f9b4d946d08dd2d6f2b662b;p=platform%2Fupstream%2Fiotivity.git Implementation of JNI for deleting resource from RD Added JNI code for deleteResourceFromRD() of OCPlatform for converting from Java to C++ and vice versa. Change-Id: I7fb825817db4fbfc4734087222162e3b022e1f51 Signed-off-by: hyuna0213.jo Reviewed-on: https://gerrit.iotivity.org/gerrit/9925 Tested-by: jenkins-iotivity Reviewed-by: jihwan seo Reviewed-by: Habib Virji Reviewed-by: Ashok Babu Channa --- diff --git a/android/android_api/base/jni/Android.mk b/android/android_api/base/jni/Android.mk index d9b3048..6d3581e 100644 --- a/android/android_api/base/jni/Android.mk +++ b/android/android_api/base/jni/Android.mk @@ -95,12 +95,13 @@ LOCAL_SRC_FILES := JniOcStack.cpp \ JniOnDPDevicesFoundListener.cpp \ JniOnDirectPairingListener.cpp \ JniOcDirectPairDevice.cpp \ - JniOnPublishResourceListener.cpp + JniOnPublishResourceListener.cpp \ + JniOnDeleteResourceListener.cpp ifeq ($(MQ_FLAG), 1) #new listener will be added. endif - + ifeq ($(SECURED), 1) LOCAL_SRC_FILES += JniOcSecureResource.cpp \ JniOcProvisioning.cpp \ diff --git a/android/android_api/base/jni/JniOcPlatform.cpp b/android/android_api/base/jni/JniOcPlatform.cpp index e5058c4..00917c7 100644 --- a/android/android_api/base/jni/JniOcPlatform.cpp +++ b/android/android_api/base/jni/JniOcPlatform.cpp @@ -547,6 +547,89 @@ void RemoveOnPublishResourceListener(JNIEnv* env, jobject jListener) publishResourceListenerMapLock.unlock(); } +JniOnDeleteResourceListener* AddOnDeleteResourceListener(JNIEnv* env, jobject jListener) +{ + if (!env) + { + LOGD("env is null"); + return nullptr; + } + + JniOnDeleteResourceListener *onDeleteResourceListener = nullptr; + + deleteResourceListenerMapLock.lock(); + + for (auto it = onDeleteResourceListenerMap.begin(); it != + onDeleteResourceListenerMap.end(); ++it) + { + if (env->IsSameObject(jListener, it->first)) + { + auto refPair = it->second; + onDeleteResourceListener = refPair.first; + refPair.second++; + it->second = refPair; + onDeleteResourceListenerMap.insert(*it); + LOGD("onDeleteResourceListener: ref. count incremented"); + break; + } + } + if (!onDeleteResourceListener) + { + onDeleteResourceListener = new JniOnDeleteResourceListener(env, jListener, + RemoveOnDeleteResourceListener); + jobject jgListener = env->NewGlobalRef(jListener); + onDeleteResourceListenerMap.insert( + std::pair>( + jgListener, + std::pair(onDeleteResourceListener, 1))); + LOGI("onDeleteResourceListener: new listener"); + } + deleteResourceListenerMapLock.unlock(); + return onDeleteResourceListener; +} + +void RemoveOnDeleteResourceListener(JNIEnv* env, jobject jListener) +{ + if (!env) + { + ThrowOcException(JNI_EXCEPTION, "env is null"); + return; + } + + deleteResourceListenerMapLock.lock(); + bool isFound = false; + for (auto it = onDeleteResourceListenerMap.begin(); it != + onDeleteResourceListenerMap.end(); ++it) + { + if (env->IsSameObject(jListener, it->first)) + { + auto refPair = it->second; + if (refPair.second > 1) + { + refPair.second--; + it->second = refPair; + onDeleteResourceListenerMap.insert(*it); + LOGI("onDeleteResourceListener: ref. count decremented"); + } + else + { + env->DeleteGlobalRef(it->first); + JniOnDeleteResourceListener* listener = refPair.first; + delete listener; + onDeleteResourceListenerMap.erase(it); + LOGI("onDeleteResourceListener is removed"); + } + isFound = true; + break; + } + } + if (!isFound) + { + ThrowOcException(JNI_EXCEPTION, "onDeleteResourceListener not found"); + } + deleteResourceListenerMapLock.unlock(); +} + /* * Class: org_iotivity_base_OcPlatform * Method: configure @@ -2542,3 +2625,151 @@ JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_publishResourceToRD1( return; #endif } + +/* + * Class: org_iotivity_base_OcPlatform + * Method: deleteResourceFromRD0 + * Signature: (Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnDeleteResourceListener;I)V + */ +JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_deleteResourceFromRD0( + JNIEnv *env, + jclass clazz, + jstring jHost, + jint jConnectivityType, + jobject jListener, + jint jQoS) +{ + LOGD("OcPlatform_deleteResourceFromRD"); +#ifdef RD_CLIENT + std::string host; + if (jHost) + { + host = env->GetStringUTFChars(jHost, nullptr); + } + if (!jListener) + { + ThrowOcException(OC_STACK_INVALID_PARAM, "onDeleteResourceListener cannot be null"); + return; + } + JniOnDeleteResourceListener *onDelResListener = AddOnDeleteResourceListener(env, jListener); + + DeleteResourceCallback delResCallback = [onDelResListener](const int eCode) + { + onDelResListener->onDeleteResourceCallback(eCode); + }; + + try + { + OCStackResult result = OCPlatform::deleteResourceFromRD( + host, + static_cast(jConnectivityType), + delResCallback, + JniUtils::getQOS(env, static_cast(jQoS))); + + if (OC_STACK_OK != result) + { + ThrowOcException(result, "Delete resource has failed"); + return; + } + } + catch (OCException& e) + { + LOGE("%s", e.reason().c_str()); + ThrowOcException(e.code(), e.reason().c_str()); + } +#else + ThrowOcException(OC_STACK_ERROR, "Delete resource has failed"); + return; +#endif +} + +/* + * Class: org_iotivity_base_OcPlatform + * Method: deleteResourceFromRD1 + * Signature: (Ljava/lang/String;I[Lorg/iotivity/base/OcResourceHandle;Lorg/iotivity/base/OcPlatform/OnDeleteResourceListener;I)V + */ +JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_deleteResourceFromRD1( + JNIEnv *env, + jclass clazz, + jstring jHost, + jint jConnectivityType, + jobjectArray jResourceHandleArray, + jint jQoS, + jobject jListener) +{ + LOGD("OcPlatform_deleteResourceFromRD"); +#ifdef RD_CLIENT + if (!env) + { + ThrowOcException(OC_STACK_INVALID_PARAM, "env is null"); + return; + } + std::string host; + if (jHost) + { + host = env->GetStringUTFChars(jHost, nullptr); + } + if (!jListener) + { + ThrowOcException(OC_STACK_INVALID_PARAM, "onDeleteResourceListener cannot be null"); + return; + } + if (!jResourceHandleArray) + { + ThrowOcException(OC_STACK_INVALID_PARAM, "resourceHandleList cannot be null"); + return; + } + JniOnDeleteResourceListener *onDelResListener = AddOnDeleteResourceListener(env, jListener); + + DeleteResourceCallback delResCallback = [onDelResListener](const int eCode) + { + onDelResListener->onDeleteResourceCallback(eCode); + }; + + std::vector resourceHandleList; + size_t len = env->GetArrayLength(jResourceHandleArray); + for (size_t i = 0; i < len; ++i) + { + jobject jResourceHandle = env->GetObjectArrayElement(jResourceHandleArray, i); + if (!jResourceHandle) + { + ThrowOcException(JNI_EXCEPTION, "resource handle cannot be null"); + return; + } + + JniOcResourceHandle* jniOcResourceHandle = + JniOcResourceHandle::getJniOcResourceHandlePtr(env, jResourceHandle); + if (!jniOcResourceHandle) + { + ThrowOcException(OC_STACK_INVALID_PARAM, "resource handle is invalid"); + return; + } + + resourceHandleList.push_back(jniOcResourceHandle->getOCResourceHandle()); + } + + try + { + OCStackResult result = OCPlatform::deleteResourceFromRD( + host, + static_cast(jConnectivityType), + resourceHandleList, + delResCallback, + JniUtils::getQOS(env, static_cast(jQoS))); + + if (OC_STACK_OK != result) + { + ThrowOcException(result, "Delete resource has failed"); + return; + } + } + catch (OCException& e) + { + LOGE("%s", e.reason().c_str()); + ThrowOcException(e.code(), e.reason().c_str()); + } +#else + ThrowOcException(OC_STACK_ERROR, "Delete resource has failed"); + return; +#endif +} diff --git a/android/android_api/base/jni/JniOcPlatform.h b/android/android_api/base/jni/JniOcPlatform.h index 9c02910..f4b733f 100644 --- a/android/android_api/base/jni/JniOcPlatform.h +++ b/android/android_api/base/jni/JniOcPlatform.h @@ -27,6 +27,7 @@ #include "JniOnDirectPairingListener.h" #include "JniOnPresenceListener.h" #include "JniOnPublishResourceListener.h" +#include "JniOnDeleteResourceListener.h" #include #ifndef _Included_org_iotivity_base_OcPlatform @@ -55,6 +56,9 @@ void RemoveOnDirectPairingListener(JNIEnv* env, jobject jListener); JniOnPublishResourceListener* AddOnPublishResourceListener(JNIEnv* env, jobject jListener); void RemoveOnPublishResourceListener(JNIEnv* env, jobject jListener); +JniOnDeleteResourceListener* AddOnDeleteResourceListener(JNIEnv* env, jobject jListener); +void RemoveOnDeleteResourceListener(JNIEnv* env, jobject jListener); + std::map> onResourceFoundListenerMap; std::map> onDeviceInfoListenerMap; std::map> onPlatformInfoListenerMap; @@ -62,6 +66,7 @@ std::map> onPresenceListenerMap; std::map> onDPDevicesFoundListenerMap; std::map> directPairingListenerMap; std::map> onPublishResourceListenerMap; +std::map> onDeleteResourceListenerMap; std::mutex resourceFoundMapLock; std::mutex deviceInfoMapLock; @@ -70,6 +75,7 @@ std::mutex presenceMapLock; std::mutex dpDevicesFoundListenerMapLock; std::mutex directPairingListenerMapLock; std::mutex publishResourceListenerMapLock; +std::mutex deleteResourceListenerMapLock; #ifdef __cplusplus extern "C" { @@ -347,6 +353,22 @@ extern "C" { */ JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_publishResourceToRD1 (JNIEnv *, jclass, jstring, jint, jobjectArray, jobject, jint); + + /* + * Class: org_iotivity_base_OcPlatform + * Method: deleteResourceFromRD0 + * Signature: (Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnDeleteResourceListener;I)V + */ + JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_deleteResourceFromRD0 + (JNIEnv *, jclass, jstring, jint, jobject, jint); + + /* + * Class: org_iotivity_base_OcPlatform + * Method: deleteResourceFromRD1 + * Signature: (Ljava/lang/String;I[Lorg/iotivity/base/OcResourceHandle;Lorg/iotivity/base/OcPlatform/OnDeleteResourceListener;I)V + */ + JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_deleteResourceFromRD1 + (JNIEnv *, jclass, jstring, jint, jobjectArray, jobject, jint); #ifdef __cplusplus } #endif diff --git a/android/android_api/base/jni/JniOnDeleteResourceListener.cpp b/android/android_api/base/jni/JniOnDeleteResourceListener.cpp new file mode 100644 index 0000000..ebde57f --- /dev/null +++ b/android/android_api/base/jni/JniOnDeleteResourceListener.cpp @@ -0,0 +1,112 @@ +/* **************************************************************** + * + * Copyright 2016 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +#include "JniOnDeleteResourceListener.h" + +JniOnDeleteResourceListener::JniOnDeleteResourceListener(JNIEnv *env, jobject jListener, + RemoveListenerCallback removeListenerCallback) +{ + m_jwListener = env->NewWeakGlobalRef(jListener); + m_removeListenerCallback = removeListenerCallback; +} + +JniOnDeleteResourceListener::~JniOnDeleteResourceListener() +{ + LOGI("~JniOnDeleteResourceListener()"); + if (m_jwListener) + { + jint ret = JNI_ERR; + JNIEnv *env = GetJNIEnv(ret); + if (nullptr == env) + { + return; + } + env->DeleteWeakGlobalRef(m_jwListener); + m_jwListener = nullptr; + if (JNI_EDETACHED == ret) + { + g_jvm->DetachCurrentThread(); + } + } +} + +void JniOnDeleteResourceListener::onDeleteResourceCallback(const int eCode) +{ + jint envRet = JNI_ERR; + JNIEnv *env = GetJNIEnv(envRet); + if (nullptr == env) + { + return; + } + + jobject jListener = env->NewLocalRef(m_jwListener); + if (!jListener) + { + checkExAndRemoveListener(env); + if (JNI_EDETACHED == envRet) + { + g_jvm->DetachCurrentThread(); + } + return; + } + jclass clsL = env->GetObjectClass(jListener); + if (!clsL) + { + checkExAndRemoveListener(env); + if (JNI_EDETACHED == envRet) + { + g_jvm->DetachCurrentThread(); + } + return; + } + + jint jres = static_cast(eCode); + jmethodID midL = env->GetMethodID(clsL, "onDeleteResource", "(I)V"); + if (!midL) + { + checkExAndRemoveListener(env); + if (JNI_EDETACHED == envRet) + { + g_jvm->DetachCurrentThread(); + } + return; + } + env->CallVoidMethod(jListener, midL, jres); + + checkExAndRemoveListener(env); + if (JNI_EDETACHED == envRet) + { + g_jvm->DetachCurrentThread(); + } +} + +void JniOnDeleteResourceListener::checkExAndRemoveListener(JNIEnv* env) +{ + if (env->ExceptionCheck()) + { + jthrowable ex = env->ExceptionOccurred(); + env->ExceptionClear(); + m_removeListenerCallback(env, m_jwListener); + env->Throw((jthrowable)ex); + } + else + { + m_removeListenerCallback(env, m_jwListener); + } +} diff --git a/android/android_api/base/jni/JniOnDeleteResourceListener.h b/android/android_api/base/jni/JniOnDeleteResourceListener.h new file mode 100644 index 0000000..267646f --- /dev/null +++ b/android/android_api/base/jni/JniOnDeleteResourceListener.h @@ -0,0 +1,40 @@ +/* **************************************************************** + * + * Copyright 2016 Samsung Electronics All Rights Reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************/ +#include "JniOcStack.h" + +#ifndef _Included_org_iotivity_base_OcPlatform_OnDeleteResourceListener +#define _Included_org_iotivity_base_OcPlatform_OnDeleteResourceListener + +using namespace OC; + +class JniOnDeleteResourceListener +{ +public: + JniOnDeleteResourceListener(JNIEnv *env, jobject listener, + RemoveListenerCallback removeListenerCallback); + ~JniOnDeleteResourceListener(); + void onDeleteResourceCallback(const int eCode); +private: + RemoveListenerCallback m_removeListenerCallback; + jweak m_jwListener; + void checkExAndRemoveListener(JNIEnv* env); +}; + +#endif diff --git a/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java b/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java index 45a3e98..6fd9d31 100644 --- a/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java +++ b/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java @@ -1095,6 +1095,151 @@ public final class OcPlatform { int qualityOfService) throws OcException; /** + * API to delete resource from remote resource-directory. + * + * @param host Host Address of a service to publish resource. + * @param connectivityTypeSet Set of types of connectivity. Example: IP + * @param onDeleteResourceListener Handles events, success states and failure states. + * @throws OcException if failure + */ + public static void deleteResourceFromRD( + String host, + EnumSet connectivityTypeSet, + OnDeleteResourceListener onDeleteResourceListener) throws OcException { + OcPlatform.initCheck(); + + int connTypeInt = 0; + + for (OcConnectivityType connType : OcConnectivityType.values()) { + if (connectivityTypeSet.contains(connType)) { + connTypeInt |= connType.getValue(); + } + } + + OcPlatform.deleteResourceFromRD0( + host, + connTypeInt, + onDeleteResourceListener, + sPlatformQualityOfService.getValue() + ); + } + + /** + * API to delete resource from remote resource-directory. + * + * @param host Host Address of a service to publish resource. + * @param connectivityTypeSet Set of types of connectivity. Example: IP + * @param onDeleteResourceListener Handles events, success states and failure states. + * @param qualityOfService the quality of communication. + * @throws OcException if failure + */ + public static void deleteResourceFromRD( + String host, + EnumSet connectivityTypeSet, + OnDeleteResourceListener onDeleteResourceListener, + QualityOfService qualityOfService) throws OcException { + OcPlatform.initCheck(); + + int connTypeInt = 0; + + for (OcConnectivityType connType : OcConnectivityType.values()) { + if (connectivityTypeSet.contains(connType)) { + connTypeInt |= connType.getValue(); + } + } + + OcPlatform.deleteResourceFromRD0( + host, + connTypeInt, + onDeleteResourceListener, + qualityOfService.getValue() + ); + } + + private static native void deleteResourceFromRD0( + String host, + int connectivityType, + OnDeleteResourceListener onDeleteResourceListener, + int qualityOfService) throws OcException; + + /** + * API to delete resource from remote resource-directory. + * + * @param host Host Address of a service to publish resource. + * @param connectivityTypeSet Set of types of connectivity. Example: IP + * @param ocResourceHandleList reference to list of resource handles to be published. + * @param onDeleteResourceListener Handles events, success states and failure states. + * @throws OcException if failure + */ + public static void deleteResourceFromRD( + String host, + EnumSet connectivityTypeSet, + List ocResourceHandleList, + OnDeleteResourceListener onDeleteResourceListener) throws OcException { + OcPlatform.initCheck(); + + int connTypeInt = 0; + + for (OcConnectivityType connType : OcConnectivityType.values()) { + if (connectivityTypeSet.contains(connType)) { + connTypeInt |= connType.getValue(); + } + } + + OcPlatform.deleteResourceFromRD1( + host, + connTypeInt, + ocResourceHandleList.toArray( + new OcResourceHandle[ocResourceHandleList.size()]), + onDeleteResourceListener, + sPlatformQualityOfService.getValue() + ); + } + + /** + * API to delete resource from remote resource-directory. + * + * @param host Host IP Address of a service to publish resource. + * @param connectivityTypeSet Set of types of connectivity. Example: IP + * @param ocResourceHandleList reference to list of resource handles to be published. + * @param onDeleteResourceListener Handles events, success states and failure states. + * @param qualityOfService the quality of communication + * @throws OcException if failure + */ + public static void deleteResourceFromRD( + String host, + EnumSet connectivityTypeSet, + List ocResourceHandleList, + OnDeleteResourceListener onDeleteResourceListener, + QualityOfService qualityOfService) throws OcException { + OcPlatform.initCheck(); + + int connTypeInt = 0; + + for (OcConnectivityType connType : OcConnectivityType.values()) { + if (connectivityTypeSet.contains(connType)) { + connTypeInt |= connType.getValue(); + } + } + + OcPlatform.deleteResourceFromRD1( + host, + connTypeInt, + ocResourceHandleList.toArray( + new OcResourceHandle[ocResourceHandleList.size()]), + onDeleteResourceListener, + qualityOfService.getValue() + ); + } + + private static native void deleteResourceFromRD1( + String host, + int connectivityType, + OcResourceHandle[] ocResourceHandleArray, + OnDeleteResourceListener onDeleteResourceListener, + int qualityOfService) throws OcException; + + /** * An OnPublishResourceListener can be registered via the OcPlatform.publishResourceToRD call. * Event listeners are notified asynchronously */ @@ -1104,6 +1249,15 @@ public final class OcPlatform { } /** + * An OnDeleteResourceListener can be registered via the OcPlatform.deleteResourceFromRD call. + * Event listeners are notified asynchronously + */ + public interface OnDeleteResourceListener { + public void onDeleteResourceCompleted(int result); + public void onDeleteResourceFailed(Throwable ex); + } + + /** * An FindDirectPairingListener can be registered via the OcPlatform.findDirectPairingDevices call. * Event listeners are notified asynchronously */