[IOT-1829] findResourceList is not implemented in Java API
authorLarry Sachs <larry.j.sachs@intel.com>
Mon, 6 Mar 2017 23:02:40 +0000 (15:02 -0800)
committerRick Bell <richard.s.bell@intel.com>
Wed, 8 Mar 2017 08:16:31 +0000 (08:16 +0000)
Added jni calls to support new c sdk api to return a list of resources.

OcPlatform.java now has findResources() methods that take a
OnResourcesFoundListener as a callback which has a method for the
returned array of found resources.

Change-Id: Ia874294d0a73b35f7bd23b15d9c122df2622cfdc
Signed-off-by: Larry Sachs <larry.j.sachs@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/17713
Reviewed-by: George Nash <george.nash@intel.com>
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: jihwan seo <jihwan.seo@samsung.com>
Reviewed-by: Rick Bell <richard.s.bell@intel.com>
java/iotivity-android/src/main/java/org/iotivity/base/OcPlatform.java
java/iotivity-linux/src/main/java/org/iotivity/base/OcPlatform.java
java/jni/JniOcPlatform.cpp
java/jni/JniOcPlatform.h
java/jni/JniOnResourcesFoundListener.cpp [new file with mode: 0644]
java/jni/JniOnResourcesFoundListener.h [new file with mode: 0644]
java/jni/JniUtils.cpp
java/jni/JniUtils.h
java/jni/SConscript

index 34b0026..fd11235 100644 (file)
@@ -357,6 +357,93 @@ public final class OcPlatform {
             int qualityOfService) throws OcException;
 
     /**
+     * API for Service and Resource Discovery
+     * <p>
+     * Note: This API is for client side only.
+     * </p>
+     *
+     * @param host                     Host Address of a service to direct resource discovery query.
+     *                                 If empty, performs multicast resource discovery query
+     * @param resourceUri              name of the resource. If null or empty, performs search for all
+     *                                 resource names
+     * @param connectivityTypeSet      Set of types of connectivity. Example: IP
+     * @param onResourcesFoundListener Handles events, success states and failure states.
+     * @throws OcException if failure
+     */
+    public static void findResources(
+            String host,
+            String resourceUri,
+            EnumSet<OcConnectivityType> connectivityTypeSet,
+            OnResourcesFoundListener onResourcesFoundListener) throws OcException {
+        OcPlatform.initCheck();
+
+        int connTypeInt = 0;
+
+        for (OcConnectivityType connType : OcConnectivityType.values()) {
+            if (connectivityTypeSet.contains(connType))
+                connTypeInt |= connType.getValue();
+        }
+
+        OcPlatform.findResources0(
+                host,
+                resourceUri,
+                connTypeInt,
+                onResourcesFoundListener
+        );
+    }
+
+    private static native void findResources0(
+            String host,
+            String resourceUri,
+            int connectivityType,
+            OnResourcesFoundListener onResourcesFoundListener) throws OcException;
+
+    /**
+     * API for Service and Resource Discovery.
+     * <p>
+     * Note: This API is for client side only.
+     * </p>
+     *
+     * @param host                     Host IP Address of a service to direct resource discovery query.
+     *                                 If empty, performs multicast resource discovery query
+     * @param resourceUri              name of the resource. If null or empty, performs search for all
+     *                                 resource names
+     * @param connectivityTypeSet      Set of types of connectivity. Example: IP
+     * @param onResourcesFoundListener Handles events, success states and failure states.
+     * @param qualityOfService         the quality of communication
+     * @throws OcException if failure
+     */
+    public static void findResources(
+            String host,
+            String resourceUri,
+            EnumSet<OcConnectivityType> connectivityTypeSet,
+            OnResourcesFoundListener onResourcesFoundListener,
+            QualityOfService qualityOfService) throws OcException {
+        OcPlatform.initCheck();
+
+        int connTypeInt = 0;
+
+        for (OcConnectivityType connType : OcConnectivityType.values()) {
+            if (connectivityTypeSet.contains(connType))
+                connTypeInt |= connType.getValue();
+        }
+
+        OcPlatform.findResources1(host,
+                resourceUri,
+                connTypeInt,
+                onResourcesFoundListener,
+                qualityOfService.getValue()
+        );
+    }
+
+    private static native void findResources1(
+            String host,
+            String resourceUri,
+            int connectivityType,
+            OnResourcesFoundListener onResourcesFoundListener,
+            int qualityOfService) throws OcException;
+
+    /**
      * API for Device Discovery
      *
      * @param host                  Host IP Address. If null or empty, Multicast is performed.
@@ -1134,6 +1221,15 @@ public final class OcPlatform {
     }
 
     /**
+     * An OnResourcesFoundListener can be registered via the OcPlatform.findResources call.
+     * Event listeners are notified asynchronously
+     */
+    public interface OnResourcesFoundListener {
+        public void onResourcesFound(OcResource[] resources);
+        public void onFindResourcesFailed(Throwable ex, String uri);
+    }
+
+    /**
      * An OnDeviceFoundListener can be registered via the OcPlatform.getDeviceInfo call.
      * Event listeners are notified asynchronously
      */
index 58807e9..215c946 100644 (file)
@@ -351,6 +351,93 @@ public final class OcPlatform {
             int qualityOfService) throws OcException;
 
     /**
+     * API for Service and Resource Discovery
+     * <p>
+     * Note: This API is for client side only.
+     * </p>
+     *
+     * @param host                     Host Address of a service to direct resource discovery query.
+     *                                 If empty, performs multicast resource discovery query
+     * @param resourceUri              name of the resource. If null or empty, performs search for all
+     *                                 resource names
+     * @param connectivityTypeSet      Set of types of connectivity. Example: IP
+     * @param onResourcesFoundListener Handles events, success states and failure states.
+     * @throws OcException if failure
+     */
+    public static void findResources(
+            String host,
+            String resourceUri,
+            EnumSet<OcConnectivityType> connectivityTypeSet,
+            OnResourcesFoundListener onResourcesFoundListener) throws OcException {
+        OcPlatform.initCheck();
+
+        int connTypeInt = 0;
+
+        for (OcConnectivityType connType : OcConnectivityType.values()) {
+            if (connectivityTypeSet.contains(connType))
+                connTypeInt |= connType.getValue();
+        }
+
+        OcPlatform.findResources0(
+                host,
+                resourceUri,
+                connTypeInt,
+                onResourcesFoundListener
+        );
+    }
+
+    private static native void findResources0(
+            String host,
+            String resourceUri,
+            int connectivityType,
+            OnResourcesFoundListener onResourcesFoundListener) throws OcException;
+
+    /**
+     * API for Service and Resource Discovery.
+     * <p>
+     * Note: This API is for client side only.
+     * </p>
+     *
+     * @param host                     Host IP Address of a service to direct resource discovery query.
+     *                                 If empty, performs multicast resource discovery query
+     * @param resourceUri              name of the resource. If null or empty, performs search for all
+     *                                 resource names
+     * @param connectivityTypeSet      Set of types of connectivity. Example: IP
+     * @param onResourcesFoundListener Handles events, success states and failure states.
+     * @param qualityOfService         the quality of communication
+     * @throws OcException if failure
+     */
+    public static void findResources(
+            String host,
+            String resourceUri,
+            EnumSet<OcConnectivityType> connectivityTypeSet,
+            OnResourcesFoundListener onResourcesFoundListener,
+            QualityOfService qualityOfService) throws OcException {
+        OcPlatform.initCheck();
+
+        int connTypeInt = 0;
+
+        for (OcConnectivityType connType : OcConnectivityType.values()) {
+            if (connectivityTypeSet.contains(connType))
+                connTypeInt |= connType.getValue();
+        }
+
+        OcPlatform.findResources1(host,
+                resourceUri,
+                connTypeInt,
+                onResourcesFoundListener,
+                qualityOfService.getValue()
+        );
+    }
+
+    private static native void findResources1(
+            String host,
+            String resourceUri,
+            int connectivityType,
+            OnResourcesFoundListener onResourcesFoundListener,
+            int qualityOfService) throws OcException;
+
+    /**
      * API for Device Discovery
      *
      * @param host                  Host IP Address. If null or empty, Multicast is performed.
@@ -1125,6 +1212,15 @@ public final class OcPlatform {
     }
 
     /**
+     * An OnResourcesFoundListener can be registered via the OcPlatform.findResources call.
+     * Event listeners are notified asynchronously
+     */
+    public interface OnResourcesFoundListener {
+        public void onResourcesFound(OcResource[] resources);
+        public void onFindResourcesFailed(Throwable ex, String uri);
+    }
+
+    /**
      * An OnDeviceFoundListener can be registered via the OcPlatform.getDeviceInfo call.
      * Event listeners are notified asynchronously
      */
index 5fd6685..291b471 100644 (file)
@@ -108,6 +108,78 @@ void RemoveOnResourceFoundListener(JNIEnv* env, jobject jListener)
     resourceFoundMapLock.unlock();
 }
 
+JniOnResourcesFoundListener* AddOnResourcesFoundListener(JNIEnv* env, jobject jListener)
+{
+    JniOnResourcesFoundListener *onResourcesFoundListener = nullptr;
+
+    resourcesFoundMapLock.lock();
+
+    for (auto it = onResourcesFoundListenerMap.begin();
+         it != onResourcesFoundListenerMap.end();
+         ++it)
+    {
+        if (env->IsSameObject(jListener, it->first))
+        {
+            auto refPair = it->second;
+            onResourcesFoundListener = refPair.first;
+            refPair.second++;
+            it->second = refPair;
+            onResourcesFoundListenerMap.insert(*it);
+            LOGD("OnResourcesFoundListener: ref. count incremented");
+            break;
+        }
+    }
+
+    if (!onResourcesFoundListener)
+    {
+        onResourcesFoundListener =
+            new JniOnResourcesFoundListener(env, jListener, RemoveOnResourcesFoundListener);
+        jobject jgListener = env->NewGlobalRef(jListener);
+
+        onResourcesFoundListenerMap.insert(
+            std::pair<jobject,
+                      std::pair<JniOnResourcesFoundListener*, int >>(
+                          jgListener,
+                          std::pair<JniOnResourcesFoundListener*, int>(onResourcesFoundListener,
+                                                                       1)));
+        LOGD("OnResourcesFoundListener: new listener");
+    }
+    resourcesFoundMapLock.unlock();
+    return onResourcesFoundListener;
+}
+
+void RemoveOnResourcesFoundListener(JNIEnv* env, jobject jListener)
+{
+    resourcesFoundMapLock.lock();
+
+    for (auto it = onResourcesFoundListenerMap.begin();
+         it != onResourcesFoundListenerMap.end();
+         ++it)
+    {
+        if (env->IsSameObject(jListener, it->first))
+        {
+            auto refPair = it->second;
+            if (refPair.second > 1)
+            {
+                refPair.second--;
+                it->second = refPair;
+                onResourcesFoundListenerMap.insert(*it);
+                LOGI("OnResourcesFoundListener: ref. count decremented");
+            }
+            else
+            {
+                env->DeleteGlobalRef(it->first);
+                JniOnResourcesFoundListener* listener = refPair.first;
+                delete listener;
+                onResourcesFoundListenerMap.erase(it);
+                LOGI("OnResourcesFoundListener removed");
+            }
+            break;
+        }
+    }
+    resourcesFoundMapLock.unlock();
+}
+
 JniOnDeviceInfoListener* AddOnDeviceInfoListener(JNIEnv* env, jobject jListener)
 {
     JniOnDeviceInfoListener *onDeviceInfoListener = nullptr;
@@ -985,6 +1057,175 @@ JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_findResource1(
 }
 
 /*
+* Class:     org_iotivity_base_OcPlatform
+* Method:    findResources0
+* Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnResourcesFoundListener;)V
+*/
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_findResources0(
+    JNIEnv *env,
+    jclass clazz,
+    jstring jHost,
+    jstring jResourceUri,
+    jint jConnectivityType,
+    jobject jListener)
+{
+    LOGD("OcPlatform_findResources0");
+    if (!jListener)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "onResourcesFoundListener cannot be null");
+        return;
+    }
+    const char *host = nullptr;
+    if (jHost)
+    {
+        host = env->GetStringUTFChars(jHost, nullptr);
+    }
+    const char *resourceUri = nullptr;
+    if (jResourceUri)
+    {
+        resourceUri = env->GetStringUTFChars(jResourceUri, nullptr);
+    }
+
+    JniOnResourcesFoundListener *onResourcesFoundListener = AddOnResourcesFoundListener(env, jListener);
+
+    FindResListCallback findCallback = [onResourcesFoundListener](const std::vector<std::shared_ptr<OC::OCResource>> resources)
+    {
+        onResourcesFoundListener->foundResourcesCallback(resources);
+    };
+
+    FindErrorCallback findErrorCallback = [onResourcesFoundListener](const std::string& uri, const int eCode)
+    {
+        onResourcesFoundListener->findResourcesErrorCallback(uri, eCode);
+    };
+
+    try
+    {
+        OCStackResult result = OCPlatform::findResourceList(
+            host,
+            resourceUri,
+            static_cast<OCConnectivityType>(jConnectivityType),
+            findCallback,
+            findErrorCallback,
+            OC::QualityOfService::NaQos);
+
+        if (jHost)
+        {
+            env->ReleaseStringUTFChars(jHost, host);
+        }
+        if (jResourceUri)
+        {
+            env->ReleaseStringUTFChars(jResourceUri, resourceUri);
+        }
+
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "Find resources has failed");
+            return;
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+
+        if (jHost)
+        {
+            env->ReleaseStringUTFChars(jHost, host);
+        }
+        if (jResourceUri)
+        {
+            env->ReleaseStringUTFChars(jResourceUri, resourceUri);
+        }
+
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
+* Class:     org_iotivity_base_OcPlatform
+* Method:    findResources1
+* Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnResourcesFoundListener;I)V
+*/
+JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_findResources1(
+    JNIEnv *env,
+    jclass clazz,
+    jstring jHost,
+    jstring jResourceUri,
+    jint jConnectivityType,
+    jobject jListener,
+    jint jQoS)
+{
+    LOGD("OcPlatform_findResources1");
+    if (!jListener)
+    {
+        ThrowOcException(OC_STACK_INVALID_PARAM, "onResourcesFoundListener cannot be null");
+        return;
+    }
+    const char *host = nullptr;
+    if (jHost)
+    {
+        host = env->GetStringUTFChars(jHost, nullptr);
+    }
+    const char *resourceUri = nullptr;
+    if (jResourceUri)
+    {
+        resourceUri = env->GetStringUTFChars(jResourceUri, nullptr);
+    }
+
+    JniOnResourcesFoundListener *onResourcesFoundListener = AddOnResourcesFoundListener(env, jListener);
+
+    FindResListCallback findCallback = [onResourcesFoundListener](std::vector<std::shared_ptr<OC::OCResource>> resources)
+    {
+        onResourcesFoundListener->foundResourcesCallback(resources);
+    };
+
+    FindErrorCallback findErrorCallback = [onResourcesFoundListener](const std::string& uri, const int eCode)
+    {
+        onResourcesFoundListener->findResourcesErrorCallback(uri, eCode);
+    };
+
+    try
+    {
+        OCStackResult result = OCPlatform::findResourceList(
+            host,
+            resourceUri,
+            static_cast<OCConnectivityType>(jConnectivityType),
+            findCallback,
+            findErrorCallback,
+            JniUtils::getQOS(env, static_cast<int>(jQoS)));
+
+        if (jHost)
+        {
+            env->ReleaseStringUTFChars(jHost, host);
+        }
+        if (jResourceUri)
+        {
+            env->ReleaseStringUTFChars(jResourceUri, resourceUri);
+        }
+
+        if (OC_STACK_OK != result)
+        {
+            ThrowOcException(result, "Find resources has failed");
+            return;
+        }
+    }
+    catch (OCException& e)
+    {
+        LOGE("%s", e.reason().c_str());
+
+        if (jHost)
+        {
+            env->ReleaseStringUTFChars(jHost, host);
+        }
+        if (jResourceUri)
+        {
+            env->ReleaseStringUTFChars(jResourceUri, resourceUri);
+        }
+
+        ThrowOcException(e.code(), e.reason().c_str());
+    }
+}
+
+/*
  * Class:     org_iotivity_base_OcPlatform
  * Method:    findDirectPairingDevices
  * Signature: (ILorg/iotivity/base/OcPlatform/FindDirectPairingListener;)V
index 71cf66c..0b8106a 100644 (file)
@@ -21,6 +21,7 @@
 */
 #include "JniOcStack.h"
 #include "JniOnResourceFoundListener.h"
+#include "JniOnResourcesFoundListener.h"
 #include "JniOnDeviceInfoListener.h"
 #include "JniOnPlatformInfoListener.h"
 #include "JniOnDPDevicesFoundListener.h"
@@ -38,6 +39,9 @@ using namespace OC;
 JniOnResourceFoundListener* AddOnResourceFoundListener(JNIEnv* env, jobject jListener);
 void RemoveOnResourceFoundListener(JNIEnv* env, jobject jListener);
 
+JniOnResourcesFoundListener* AddOnResourcesFoundListener(JNIEnv* env, jobject jListener);
+void RemoveOnResourcesFoundListener(JNIEnv* env, jobject jListener);
+
 JniOnDeviceInfoListener* AddOnDeviceInfoListener(JNIEnv* env, jobject jListener);
 void RemoveOnDeviceInfoListener(JNIEnv* env, jobject jListener);
 
@@ -57,6 +61,7 @@ JniOnDirectPairingListener* AddOnDirectPairingListener(JNIEnv* env, jobject jLis
 void RemoveOnDirectPairingListener(JNIEnv* env, jobject jListener);
 
 std::map<jobject, std::pair<JniOnResourceFoundListener*, int>> onResourceFoundListenerMap;
+std::map<jobject, std::pair<JniOnResourcesFoundListener*, int>> onResourcesFoundListenerMap;
 std::map<jobject, std::pair<JniOnDeviceInfoListener*, int>> onDeviceInfoListenerMap;
 std::map<jobject, std::pair<JniOnPlatformInfoListener*, int>> onPlatformInfoListenerMap;
 std::map<jobject, std::pair<JniOnPresenceListener*, int>> onPresenceListenerMap;
@@ -65,6 +70,7 @@ std::map<jobject, std::pair<JniOnDPDevicesFoundListener*, int>> onDPDevicesFound
 std::map<jobject, std::pair<JniOnDirectPairingListener*, int>> directPairingListenerMap;
 
 std::mutex resourceFoundMapLock;
+std::mutex resourcesFoundMapLock;
 std::mutex deviceInfoMapLock;
 std::mutex platformInfoMapLock;
 std::mutex presenceMapLock;
@@ -149,6 +155,22 @@ extern "C" {
 
     /*
     * Class:     org_iotivity_base_OcPlatform
+    * Method:    findResources0
+    * Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnResourcesFoundListener;)V
+    */
+    JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_findResources0
+        (JNIEnv *, jclass, jstring, jstring, jint, jobject);
+
+    /*
+    * Class:     org_iotivity_base_OcPlatform
+    * Method:    findResources1
+    * Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnResourcesFoundListener;I)V
+    */
+    JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_findResources1
+        (JNIEnv *, jclass, jstring, jstring, jint, jobject, jint);
+
+    /*
+    * Class:     org_iotivity_base_OcPlatform
     * Method:    getDeviceInfo0
     * Signature: (Ljava/lang/String;Ljava/lang/String;ILorg/iotivity/base/OcPlatform/OnDeviceFoundListener;)V
     */
diff --git a/java/jni/JniOnResourcesFoundListener.cpp b/java/jni/JniOnResourcesFoundListener.cpp
new file mode 100644 (file)
index 0000000..d3517b3
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2017 Intel Corporation.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // 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 "JniOnResourcesFoundListener.h"
+#include "JniOcResource.h"
+#include "JniUtils.h"
+
+JniOnResourcesFoundListener::JniOnResourcesFoundListener(JNIEnv *env, jobject jListener,
+    RemoveListenerCallback removeListenerCallback)
+{
+    m_jwListener = env->NewWeakGlobalRef(jListener);
+    m_removeListenerCallback = removeListenerCallback;
+}
+
+JniOnResourcesFoundListener::~JniOnResourcesFoundListener()
+{
+    LOGI("~JniOnResourcesFoundListener()");
+    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 JniOnResourcesFoundListener::foundResourcesCallback(const std::vector<std::shared_ptr<OC::OCResource>>& resources)
+{
+    jint ret = JNI_ERR;
+    JNIEnv *env = GetJNIEnv(ret);
+    if (nullptr == env)
+    {
+        return;
+    }
+
+    jobject jListener = env->NewLocalRef(m_jwListener);
+    if (!jListener)
+    {
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+
+    jobjectArray jResourceArray = JniUtils::convertResourceVectorToJavaArray(env, resources);
+    if (!jResourceArray)
+    {
+        env->DeleteLocalRef(jListener);
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+
+    if (env->ExceptionCheck())
+    {
+        env->DeleteLocalRef(jResourceArray);
+        env->DeleteLocalRef(jListener);
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+    jclass clsL = env->GetObjectClass(jListener);
+    if (!clsL)
+    {
+        env->DeleteLocalRef(jResourceArray);
+        env->DeleteLocalRef(jListener);
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+    jmethodID midL = env->GetMethodID(clsL, "onResourcesFound", "([Lorg/iotivity/base/OcResource;)V");
+    if (!midL)
+    {
+        env->DeleteLocalRef(clsL);
+        env->DeleteLocalRef(jResourceArray);
+        env->DeleteLocalRef(jListener);
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+    env->CallVoidMethod(jListener, midL, jResourceArray);
+    if (env->ExceptionCheck())
+    {
+        LOGE("Java exception is thrown");
+        env->DeleteLocalRef(clsL);
+        env->DeleteLocalRef(jResourceArray);
+        env->DeleteLocalRef(jListener);
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+
+    env->DeleteLocalRef(clsL);
+    env->DeleteLocalRef(jResourceArray);
+    env->DeleteLocalRef(jListener);
+    if (JNI_EDETACHED == ret)
+    {
+        g_jvm->DetachCurrentThread();
+    }
+}
+
+void JniOnResourcesFoundListener::findResourcesErrorCallback(const std::string& uri, const int eCode)
+{
+    LOGI("findResources error callback value : %d", eCode);
+    jint ret = JNI_ERR;
+    JNIEnv *env = GetJNIEnv(ret);
+    if (nullptr == env)
+    {
+        return;
+    }
+
+    jobject jListener = env->NewLocalRef(m_jwListener);
+    if (!jListener)
+    {
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+
+    jclass clsL = env->GetObjectClass(jListener);
+    if (!clsL)
+    {
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+
+    jobject ex = GetOcException(eCode, "stack error in onFindResourcesErrorCallback");
+    if (!ex)
+    {
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+
+
+    jmethodID midL = env->GetMethodID(clsL, "onFindResourcesFailed",
+                                      "(Ljava/lang/Throwable;Ljava/lang/String;)V");
+    if (!midL)
+    {
+        checkExAndRemoveListener(env);
+        if (JNI_EDETACHED == ret)
+        {
+            g_jvm->DetachCurrentThread();
+        }
+        return;
+    }
+    env->CallVoidMethod(jListener, midL, ex, env->NewStringUTF(uri.c_str()));
+
+    if (JNI_EDETACHED == ret)
+    {
+        g_jvm->DetachCurrentThread();
+    }
+}
+
+void JniOnResourcesFoundListener::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/java/jni/JniOnResourcesFoundListener.h b/java/jni/JniOnResourcesFoundListener.h
new file mode 100644 (file)
index 0000000..a88b90d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+* //******************************************************************
+* //
+* // Copyright 2017 Intel Corporation.
+* //
+* //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+* //
+* // 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 <jni.h>
+#include "JniOcStack.h"
+
+#ifndef _Included_org_iotivity_base_OcPlatform_OnResourcesFoundListener
+#define _Included_org_iotivity_base_OcPlatform_OnResourcesFoundListener
+
+class JniOnResourcesFoundListener
+{
+public:
+    JniOnResourcesFoundListener(JNIEnv *env, jobject jListener,
+        RemoveListenerCallback removeListenerCallback);
+    ~JniOnResourcesFoundListener();
+
+    void foundResourcesCallback(const std::vector<std::shared_ptr<OC::OCResource>>& resources);
+    void findResourcesErrorCallback(const std::string& uri, const int eCode);
+
+private:
+    RemoveListenerCallback m_removeListenerCallback;
+    jweak m_jwListener;
+    void checkExAndRemoveListener(JNIEnv* env);
+};
+
+#endif
index 3ee3ada..a99a475 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "JniUtils.h"
 #include "JniOcRepresentation.h"
+#include "JniOcResource.h"
 
 jobject JniUtils::convertStrVectorToJavaStrList(JNIEnv *env, std::vector<std::string> &vector)
 {
@@ -264,3 +265,35 @@ jobjectArray JniUtils::convertRepresentationVectorToJavaArray(JNIEnv *env,
 
     return repArr;
 }
+
+jobjectArray JniUtils::convertResourceVectorToJavaArray(JNIEnv *env,
+    const std::vector<std::shared_ptr<OC::OCResource>>& resourceVector)
+{
+    jsize len = static_cast<jsize>(resourceVector.size());
+    jobjectArray resourceArray = env->NewObjectArray(len, g_cls_OcResource, NULL);
+
+    if (!resourceArray)
+    {
+        return nullptr;
+    }
+
+    for (jsize i = 0; i < len; ++i)
+    {
+        JniOcResource *resource = new JniOcResource(resourceVector[i]);
+        jobject jResource = env->NewObject(g_cls_OcResource, g_mid_OcResource_ctor);
+
+        SetHandle<JniOcResource>(env, jResource, resource);
+        if (!jResource)
+        {
+            return nullptr;
+        }
+
+        env->SetObjectArrayElement(resourceArray, i, jResource);
+        if (env->ExceptionCheck())
+        {
+            return nullptr;
+        }
+        env->DeleteLocalRef(jResource);
+    }
+    return resourceArray;
+}
index 18a4fdb..5237866 100644 (file)
@@ -44,6 +44,8 @@ public:
         std::vector<OC::OCRepresentation>& representationVector);
     static jobjectArray convertRepresentationVectorToJavaArray(JNIEnv *env,
         const std::vector<OC::OCRepresentation>& representationVector);
+    static jobjectArray convertResourceVectorToJavaArray(JNIEnv *env,
+        const std::vector<std::shared_ptr<OC::OCResource>>& resourceVector);
 
     static OC::ServiceType getServiceType(JNIEnv *env, int type)
     {
index 1e5e5be..ac245ec 100644 (file)
@@ -112,6 +112,7 @@ ocstack_files = [
                        'JniUtils.cpp',
                        'JniEntityHandler.cpp',
                        'JniOnResourceFoundListener.cpp',
+                       'JniOnResourcesFoundListener.cpp',
                        'JniOnDeviceInfoListener.cpp',
                        'JniOnPlatformInfoListener.cpp',
                        'JniOnPresenceListener.cpp',