Added SeparateResponse class for the RCSResourceObject in RE.
authorcoderhyme <jhyo.kim@samsung.com>
Fri, 5 Feb 2016 02:42:12 +0000 (18:42 -0800)
committerUze Choi <uzchoi@samsung.com>
Sat, 13 Feb 2016 05:39:51 +0000 (05:39 +0000)
The class is to support the SLOW response concept of the base.
For it, the RCSRequest now holds its owner resource object.

- how to use

RCSSeparateResponse separateResponse;

...

server->setSetRequestHandler([](const RCSRequest& r, RCSResourceAttributes& attrs){
    // make separate response to set result later
    separateResponse = RCSSeparateResponse(r);

    return RCSSetResponse::separate();
});

...

// the set method will throw an exception when the operation is failed.
separateResponse.set();

Change-Id: I054ee3948d7742b5c45f821f3fec48216915f273
Signed-off-by: coderhyme <jhyo.kim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/4947
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Madan Lanka <lanka.madan@samsung.com>
Reviewed-by: JungYong KIM <jyong2.kim@samsung.com>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
service/resource-encapsulation/include/RCSRequest.h
service/resource-encapsulation/include/RCSResourceObject.h
service/resource-encapsulation/include/RCSResponse.h
service/resource-encapsulation/include/RCSSeparateResponse.h [new file with mode: 0755]
service/resource-encapsulation/src/serverBuilder/src/RCSRequest.cpp
service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp
service/resource-encapsulation/src/serverBuilder/src/RCSResponse.cpp
service/resource-encapsulation/src/serverBuilder/src/RCSSeparateResponse.cpp [new file with mode: 0755]
service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp
service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp

index 0b45032..eb5a350 100644 (file)
@@ -38,38 +38,44 @@ namespace OIC
 {
     namespace Service
     {
+        class RCSResourceObject;
+
         /**
         * This class describes the request.
         *
         */
         class RCSRequest
         {
-            public:
-                /**
-                * Constructor to set resource URI.
-                *
-                * @param resourceUri URI of the resource for which the request is generated.
-                */
-                explicit RCSRequest(const std::string& resourceUri);
+        public:
+            RCSRequest() = default;
+
+            /**
+            * Constructor to set resource URI.
+            *
+            * @param resourceUri URI of the resource for which the request is generated.
+            */
+            explicit RCSRequest(const std::string& resourceUri);
 
-                explicit RCSRequest(const std::shared_ptr< OC::OCResourceRequest >&);
+            RCSRequest(const std::shared_ptr< RCSResourceObject >&,
+                    const std::shared_ptr< OC::OCResourceRequest >&);
 
-                RCSRequest &operator=(RCSRequest &) = delete;
+            std::weak_ptr< RCSResourceObject > getResourceObject() const noexcept;
 
-                /**
-                * @return Returns the URI of the request.
-                *
-                */
-                std::string getResourceUri() const;
+            /**
+            * @return Returns the URI of the request.
+            *
+            */
+            std::string getResourceUri() const;
 
-                const std::shared_ptr< OC::OCResourceRequest >& getOCRequest() const;
+            const std::shared_ptr< OC::OCResourceRequest >& getOCRequest() const noexcept;
 
-                const std::map< std::string, std::string >& getQueryParams() const;
+            const std::map< std::string, std::string >& getQueryParams() const;
 
-                std::string getInterface() const;
+            std::string getInterface() const;
 
-            private:
-                const std::shared_ptr< OC::OCResourceRequest > m_ocRequest;
+        private:
+            std::weak_ptr< RCSResourceObject > m_resourceObject;
+            std::shared_ptr< OC::OCResourceRequest > m_ocRequest;
         };
 
     }
index 146ca8f..9eb4543 100644 (file)
@@ -77,7 +77,7 @@ namespace OIC
          * in instead of overriding SetRequestHandler.
          * </p>
          */
-        class RCSResourceObject
+        class RCSResourceObject : public std::enable_shared_from_this< RCSResourceObject >
         {
             private:
                 class WeakGuard;
@@ -470,7 +470,8 @@ namespace OIC
         private:
             RCSResourceObject(const std::string&, uint8_t, RCSResourceAttributes&&);
 
-            OCEntityHandlerResult entityHandler(const std::shared_ptr< OC::OCResourceRequest >&);
+            static OCEntityHandlerResult entityHandler(const std::weak_ptr< RCSResourceObject >&,
+                    const std::shared_ptr< OC::OCResourceRequest >&);
 
             OCEntityHandlerResult handleRequest(const std::shared_ptr< OC::OCResourceRequest >&);
             OCEntityHandlerResult handleRequestGet(const std::shared_ptr< OC::OCResourceRequest >&);
index 13d94c2..041a187 100644 (file)
@@ -127,11 +127,16 @@ namespace OIC
              */
             static RCSGetResponse create(RCSResourceAttributes&& attrs, int errorCode);
 
+            static RCSGetResponse separate();
+
+            bool isSeparate() const;
+
             //! @cond
             RequestHandler* getHandler() const;
             //! @endcond
 
         private:
+            RCSGetResponse();
             RCSGetResponse(std::shared_ptr< RequestHandler >&&);
 
         private:
@@ -289,6 +294,9 @@ namespace OIC
              */
             static RCSSetResponse create(RCSResourceAttributes&& attrs, int errorCode);
 
+            static RCSSetResponse separate();
+
+            bool isSeparate() const;
 
             //! @cond
             SetRequestHandler* getHandler() const;
@@ -313,6 +321,7 @@ namespace OIC
             RCSSetResponse& setAcceptanceMethod(AcceptanceMethod method);
 
         private:
+            RCSSetResponse();
             RCSSetResponse(std::shared_ptr< SetRequestHandler >&&);
             RCSSetResponse(std::shared_ptr< SetRequestHandler >&&, AcceptanceMethod);
 
diff --git a/service/resource-encapsulation/include/RCSSeparateResponse.h b/service/resource-encapsulation/include/RCSSeparateResponse.h
new file mode 100755 (executable)
index 0000000..b23cea5
--- /dev/null
@@ -0,0 +1,56 @@
+//******************************************************************
+//
+// Copyright 2015 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef SERVERBUILDER_RCSSEPARATERESPONSE_H
+#define SERVERBUILDER_RCSSEPARATERESPONSE_H
+
+#include "RCSRequest.h"
+
+namespace OIC
+{
+    namespace Service
+    {
+        class RCSResourceAttributes;
+        class RCSRequest;
+
+        class RCSSeparateResponse
+        {
+        public:
+            explicit RCSSeparateResponse(const RCSRequest&);
+            explicit RCSSeparateResponse(RCSRequest&&);
+
+            RCSSeparateResponse(const RCSSeparateResponse&) = delete;
+            RCSSeparateResponse& operator=(const RCSSeparateResponse&) = delete;
+
+            RCSSeparateResponse(RCSSeparateResponse&&) = default;
+            RCSSeparateResponse& operator=(RCSSeparateResponse&&) =default;
+
+            void set();
+
+        private:
+            RCSRequest m_request;
+
+            bool m_done;
+        };
+
+    }
+}
+
+#endif // SERVERBUILDER_RCSSEPARATERESPONSE_H
index b6d5dfc..88513af 100644 (file)
@@ -27,7 +27,9 @@ namespace OIC
     namespace Service
     {
 
-        RCSRequest::RCSRequest(const std::shared_ptr< OC::OCResourceRequest >& ocRequest) :
+        RCSRequest::RCSRequest(const std::shared_ptr< RCSResourceObject >& resourceObject,
+                const std::shared_ptr< OC::OCResourceRequest >& ocRequest) :
+                m_resourceObject{ resourceObject },
                 m_ocRequest{ ocRequest }
         {
         }
@@ -38,12 +40,18 @@ namespace OIC
             m_ocRequest->setResourceUri(resourceUri);
         }
 
+
+        std::weak_ptr< RCSResourceObject > RCSRequest::getResourceObject() const noexcept
+        {
+            return m_resourceObject;
+        }
+
         std::string RCSRequest::getResourceUri() const
         {
             return m_ocRequest->getResourceUri();
         }
 
-        const std::shared_ptr< OC::OCResourceRequest >& RCSRequest::getOCRequest() const
+        const std::shared_ptr< OC::OCResourceRequest >& RCSRequest::getOCRequest() const noexcept
         {
             return m_ocRequest;
         }
@@ -63,5 +71,6 @@ namespace OIC
 
             return it->second;
         }
+
     }
 }
index 5b4c8b7..feb2068 100644 (file)
@@ -100,13 +100,13 @@ namespace
 
     template< typename HANDLER, typename RESPONSE =
             typename std::decay<HANDLER>::type::result_type >
-    RESPONSE invokeHandler(RCSResourceAttributes& attrs,
+    RESPONSE invokeHandler(const RCSResourceObject::Ptr& resObj, RCSResourceAttributes& attrs,
             const std::shared_ptr< OC::OCResourceRequest >& ocRequest,
             std::shared_ptr< HANDLER > handler)
     {
         if (handler)
         {
-            return (*handler)(RCSRequest{ ocRequest }, attrs);
+            return (*handler)(RCSRequest{ resObj, ocRequest }, attrs);
         }
 
         return RESPONSE::defaultAction();
@@ -240,7 +240,7 @@ namespace OIC
                 new RCSResourceObject{ m_uri, m_properties, std::move(m_resourceAttributes) } };
 
             OC::EntityHandler entityHandler{ std::bind(&RCSResourceObject::entityHandler,
-                    server.get(), std::placeholders::_1) };
+                    std::weak_ptr< RCSResourceObject >{ server }, std::placeholders::_1) };
 
             typedef OCStackResult (*RegisterResource)(OCResourceHandle&, std::string&,
                     const std::string&, const std::string&, OC::EntityHandler, uint8_t);
@@ -535,6 +535,7 @@ namespace OIC
 
         RCSRepresentation RCSResourceObject::toRepresentation() const
         {
+            WeakGuard lock{*this};
             return RCSRepresentation{ m_uri, m_interfaces, m_types, m_resourceAttributes };
          }
 
@@ -554,8 +555,13 @@ namespace OIC
         }
 
         OCEntityHandlerResult RCSResourceObject::entityHandler(
+                const std::weak_ptr< RCSResourceObject >& weakRes,
                 const std::shared_ptr< OC::OCResourceRequest >& request)
         {
+            auto resource = weakRes.lock();
+
+            if (!resource) return OC_EH_ERROR;
+
             OIC_LOG(WARNING, LOG_TAG, "entityHandler");
             if (!request)
             {
@@ -566,12 +572,12 @@ namespace OIC
             {
                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::RequestFlag)
                 {
-                    return handleRequest(request);
+                    return resource->handleRequest(request);
                 }
 
                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::ObserverFlag)
                 {
-                    return handleObserve(request);
+                    return resource->handleObserve(request);
                 }
             }
             catch (const std::exception& e)
@@ -618,7 +624,11 @@ namespace OIC
 
             auto attrs = getAttributesFromOCRequest(request);
 
-            return sendResponse(*this, request, invokeHandler(attrs, request, m_getRequestHandler));
+            auto response = invokeHandler(shared_from_this(), attrs, request, m_getRequestHandler);
+
+            if (response.isSeparate()) return OC_EH_SLOW;
+
+            return sendResponse(*this, request, response);
         }
 
         bool RCSResourceObject::applyAcceptanceMethod(const RCSSetResponse& response,
@@ -660,7 +670,9 @@ namespace OIC
             assert(request != nullptr);
 
             auto attrs = getAttributesFromOCRequest(request);
-            auto response = invokeHandler(attrs, request, m_setRequestHandler);
+            auto response = invokeHandler(shared_from_this(), attrs, request, m_setRequestHandler);
+
+            if (response.isSeparate()) return OC_EH_SLOW;
 
             auto attrsChanged = applyAcceptanceMethod(response, attrs);
 
index 9a91c61..79d42c3 100644 (file)
@@ -61,6 +61,20 @@ namespace OIC
                 std::move(attrs), errorCode) };
         }
 
+        RCSGetResponse RCSGetResponse::separate()
+        {
+            return RCSGetResponse();
+        }
+
+        bool RCSGetResponse::isSeparate() const
+        {
+            return !m_handler;
+        }
+
+        RCSGetResponse::RCSGetResponse()
+        {
+        }
+
         RCSGetResponse::RCSGetResponse(std::shared_ptr< RequestHandler >&& handler) :
                 m_handler{ std::move(handler) }
         {
@@ -123,6 +137,16 @@ namespace OIC
             return std::make_shared< SetRequestHandler >(std::move(attrs), errorCode);
         }
 
+        RCSSetResponse RCSSetResponse::separate()
+        {
+            return RCSSetResponse();
+        }
+
+        RCSSetResponse::RCSSetResponse() :
+                m_acceptanceMethod { AcceptanceMethod::DEFAULT }
+        {
+        }
+
         RCSSetResponse::RCSSetResponse(std::shared_ptr< SetRequestHandler >&& handler) :
                 m_acceptanceMethod { AcceptanceMethod::DEFAULT },
                 m_handler{ std::move(handler) }
@@ -137,6 +161,12 @@ namespace OIC
             assert(m_handler);
         }
 
+        bool RCSSetResponse::isSeparate() const
+        {
+            return !m_handler;
+        }
+
+
         SetRequestHandler* RCSSetResponse::getHandler() const
         {
             return m_handler.get();
diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSSeparateResponse.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSSeparateResponse.cpp
new file mode 100755 (executable)
index 0000000..98001e8
--- /dev/null
@@ -0,0 +1,93 @@
+//******************************************************************\r
+//\r
+// Copyright 2015 Samsung Electronics All Rights Reserved.\r
+//\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
+//\r
+// Licensed under the Apache License, Version 2.0 (the "License");\r
+// you may not use this file except in compliance with the License.\r
+// You may obtain a copy of the License at\r
+//\r
+//      http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+// Unless required by applicable law or agreed to in writing, software\r
+// distributed under the License is distributed on an "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+// See the License for the specific language governing permissions and\r
+// limitations under the License.\r
+//\r
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
+\r
+#include "RCSSeparateResponse.h"\r
+\r
+#include "RCSRequest.h"\r
+#include "RCSResourceObject.h"\r
+#include "RCSRepresentation.h"\r
+#include "AssertUtils.h"\r
+\r
+#include "OCPlatform.h"\r
+#include "OCResourceResponse.h"\r
+#include "OCResourceRequest.h"\r
+\r
+namespace OIC\r
+{\r
+    namespace Service\r
+    {\r
+\r
+        namespace\r
+        {\r
+            void validateRequest(const RCSRequest& request)\r
+            {\r
+                if (!request.getOCRequest() || request.getResourceObject().expired())\r
+                {\r
+                    throw RCSInvalidParameterException{\r
+                        "The request is incomplete. The resource for the request might be destroyed." };\r
+                }\r
+            }\r
+        }\r
+\r
+        RCSSeparateResponse::RCSSeparateResponse(const RCSRequest& request) :\r
+                m_request{ request },\r
+                m_done{ false }\r
+        {\r
+            validateRequest(m_request);\r
+        }\r
+\r
+        RCSSeparateResponse::RCSSeparateResponse(RCSRequest&& request) :\r
+                m_request{ std::move(request) },\r
+                m_done{ false }\r
+        {\r
+            validateRequest(m_request);\r
+        }\r
+\r
+        void RCSSeparateResponse::set()\r
+        {\r
+            assert(m_request.getOCRequest());\r
+\r
+            auto resObj = m_request.getResourceObject().lock();\r
+            if (!resObj)\r
+            {\r
+                throw RCSBadRequestException{ "ResourceObject is unspecified(or destroyed)!" };\r
+            }\r
+\r
+            if (m_done) throw RCSBadRequestException{ "The response is already set!" };\r
+\r
+            auto ocRequest = m_request.getOCRequest();\r
+            auto response = std::make_shared< OC::OCResourceResponse >();\r
+\r
+            response->setRequestHandle(ocRequest->getRequestHandle());\r
+            response->setResourceHandle(ocRequest->getResourceHandle());\r
+\r
+            response->setResponseResult(OC_EH_OK);\r
+\r
+            // TODO the response should be different by the request interface.\r
+            response->setResourceRepresentation(\r
+                    RCSRepresentation::toOCRepresentation(resObj->toRepresentation()));\r
+\r
+            invokeOCFunc(OC::OCPlatform::sendResponse, response);\r
+\r
+            m_done = true;\r
+        }\r
+\r
+    }\r
+}\r
index a4ed8a3..52ee306 100644 (file)
@@ -21,6 +21,8 @@
 #include "UnitTestHelper.h"
 
 #include "RCSResourceObject.h"
+#include "RCSRequest.h"
+#include "RCSSeparateResponse.h"
 
 #include "OCPlatform.h"
 
@@ -479,6 +481,54 @@ TEST_F(ResourceObjectHandlingRequestTest, SendSetResponseWithCustomAttrs)
     ASSERT_EQ(OC_EH_OK, handler(createRequest(OC_REST_POST)));
 }
 
+TEST_F(ResourceObjectHandlingRequestTest, SeparateResponseIsSlowResponse)
+{
+    server->setGetRequestHandler(
+            [](const RCSRequest&, RCSResourceAttributes&) -> RCSGetResponse
+            {
+                return RCSGetResponse::separate();
+            }
+    );
+
+    ASSERT_EQ(OC_EH_SLOW, handler(createRequest()));
+}
+
+TEST_F(ResourceObjectHandlingRequestTest, SetMethodOfSeparateResponseInvokesSendResponse)
+{
+    RCSRequest aRequest;
+    server->setGetRequestHandler(
+            [&aRequest](const RCSRequest& request, RCSResourceAttributes&) -> RCSGetResponse
+            {
+                aRequest = request;
+                return RCSGetResponse::separate();
+            }
+    );
+    handler(createRequest(OC_REST_GET));
+
+    mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
+
+    RCSSeparateResponse(aRequest).set();
+}
+
+
+TEST_F(ResourceObjectHandlingRequestTest, SetMethodOfSeparateResponseThrowsIfTheResourceIsDestroyed)
+{
+    RCSRequest aRequest;
+    server->setGetRequestHandler(
+            [&aRequest](const RCSRequest& request, RCSResourceAttributes&) -> RCSGetResponse
+            {
+                aRequest = request;
+                return RCSGetResponse::separate();
+            }
+    );
+    handler(createRequest(OC_REST_GET));
+
+    RCSSeparateResponse resp(aRequest);
+
+    server.reset();
+
+    EXPECT_THROW(resp.set(), RCSBadRequestException);
+}
 
 
 class SetRequestHandlerPolicyTest: public ResourceObjectHandlingRequestTest
index 2ba3817..d76184e 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#include <UnitTestHelper.h>
+#include "UnitTestHelper.h"
 
-#include <RCSResponse.h>
-#include <RCSResourceObject.h>
+#include "RCSRequest.h"
+#include "RCSResponse.h"
+#include "RCSSeparateResponse.h"
+#include "RCSResourceObject.h"
 
-#include <RequestHandler.h>
-#include <ResourceAttributesConverter.h>
+#include "RequestHandler.h"
+#include "ResourceAttributesConverter.h"
 
-#include <OCPlatform.h>
+#include "OCPlatform.h"
 
 using namespace std;
 
@@ -185,3 +187,16 @@ TEST_F(RCSResponseTest, SetResponseHasMethodSetBySetter)
 
     EXPECT_EQ(method, response.getAcceptanceMethod());
 }
+
+TEST_F(RCSResponseTest, SeparateResponseHasNoHandler)
+{
+    RCSGetResponse response = RCSGetResponse::separate();
+    EXPECT_EQ(nullptr, response.getHandler());
+}
+
+TEST_F(RCSResponseTest, ThrowIfRequestIsInvalidWhenConstructingSeparateResponse)
+{
+    RCSRequest aRequest;
+
+    EXPECT_THROW(RCSSeparateResponse resp(aRequest), RCSInvalidParameterException);
+}