From 61ff7411a690309b4832e1e639689f30b0e4b8e8 Mon Sep 17 00:00:00 2001
From: coderhyme
Date: Thu, 4 Feb 2016 18:42:12 -0800
Subject: [PATCH] Added SeparateResponse class for the RCSResourceObject in RE.
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
Reviewed-on: https://gerrit.iotivity.org/gerrit/4947
Tested-by: jenkins-iotivity
Reviewed-by: Madan Lanka
Reviewed-by: JungYong KIM
Reviewed-by: Uze Choi
---
.../resource-encapsulation/include/RCSRequest.h | 44 +++++-----
.../include/RCSResourceObject.h | 5 +-
.../resource-encapsulation/include/RCSResponse.h | 9 +++
.../include/RCSSeparateResponse.h | 56 +++++++++++++
.../src/serverBuilder/src/RCSRequest.cpp | 13 ++-
.../src/serverBuilder/src/RCSResourceObject.cpp | 26 ++++--
.../src/serverBuilder/src/RCSResponse.cpp | 30 +++++++
.../src/serverBuilder/src/RCSSeparateResponse.cpp | 93 ++++++++++++++++++++++
.../unittests/RCSResourceObjectTest.cpp | 50 ++++++++++++
.../serverBuilder/unittests/RCSResponseTest.cpp | 27 +++++--
10 files changed, 317 insertions(+), 36 deletions(-)
create mode 100755 service/resource-encapsulation/include/RCSSeparateResponse.h
create mode 100755 service/resource-encapsulation/src/serverBuilder/src/RCSSeparateResponse.cpp
diff --git a/service/resource-encapsulation/include/RCSRequest.h b/service/resource-encapsulation/include/RCSRequest.h
index 0b45032..eb5a350 100644
--- a/service/resource-encapsulation/include/RCSRequest.h
+++ b/service/resource-encapsulation/include/RCSRequest.h
@@ -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;
};
}
diff --git a/service/resource-encapsulation/include/RCSResourceObject.h b/service/resource-encapsulation/include/RCSResourceObject.h
index 146ca8f..9eb4543 100644
--- a/service/resource-encapsulation/include/RCSResourceObject.h
+++ b/service/resource-encapsulation/include/RCSResourceObject.h
@@ -77,7 +77,7 @@ namespace OIC
* in instead of overriding SetRequestHandler.
*
*/
- 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 >&);
diff --git a/service/resource-encapsulation/include/RCSResponse.h b/service/resource-encapsulation/include/RCSResponse.h
index 13d94c2..041a187 100644
--- a/service/resource-encapsulation/include/RCSResponse.h
+++ b/service/resource-encapsulation/include/RCSResponse.h
@@ -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
index 0000000..b23cea5
--- /dev/null
+++ b/service/resource-encapsulation/include/RCSSeparateResponse.h
@@ -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
diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSRequest.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSRequest.cpp
index b6d5dfc..88513af 100644
--- a/service/resource-encapsulation/src/serverBuilder/src/RCSRequest.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/src/RCSRequest.cpp
@@ -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;
}
+
}
}
diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp
index 5b4c8b7..feb2068 100644
--- a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp
@@ -100,13 +100,13 @@ namespace
template< typename HANDLER, typename RESPONSE =
typename std::decay::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);
diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSResponse.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSResponse.cpp
index 9a91c61..79d42c3 100644
--- a/service/resource-encapsulation/src/serverBuilder/src/RCSResponse.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/src/RCSResponse.cpp
@@ -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
index 0000000..98001e8
--- /dev/null
+++ b/service/resource-encapsulation/src/serverBuilder/src/RCSSeparateResponse.cpp
@@ -0,0 +1,93 @@
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "RCSSeparateResponse.h"
+
+#include "RCSRequest.h"
+#include "RCSResourceObject.h"
+#include "RCSRepresentation.h"
+#include "AssertUtils.h"
+
+#include "OCPlatform.h"
+#include "OCResourceResponse.h"
+#include "OCResourceRequest.h"
+
+namespace OIC
+{
+ namespace Service
+ {
+
+ namespace
+ {
+ void validateRequest(const RCSRequest& request)
+ {
+ if (!request.getOCRequest() || request.getResourceObject().expired())
+ {
+ throw RCSInvalidParameterException{
+ "The request is incomplete. The resource for the request might be destroyed." };
+ }
+ }
+ }
+
+ RCSSeparateResponse::RCSSeparateResponse(const RCSRequest& request) :
+ m_request{ request },
+ m_done{ false }
+ {
+ validateRequest(m_request);
+ }
+
+ RCSSeparateResponse::RCSSeparateResponse(RCSRequest&& request) :
+ m_request{ std::move(request) },
+ m_done{ false }
+ {
+ validateRequest(m_request);
+ }
+
+ void RCSSeparateResponse::set()
+ {
+ assert(m_request.getOCRequest());
+
+ auto resObj = m_request.getResourceObject().lock();
+ if (!resObj)
+ {
+ throw RCSBadRequestException{ "ResourceObject is unspecified(or destroyed)!" };
+ }
+
+ if (m_done) throw RCSBadRequestException{ "The response is already set!" };
+
+ auto ocRequest = m_request.getOCRequest();
+ auto response = std::make_shared< OC::OCResourceResponse >();
+
+ response->setRequestHandle(ocRequest->getRequestHandle());
+ response->setResourceHandle(ocRequest->getResourceHandle());
+
+ response->setResponseResult(OC_EH_OK);
+
+ // TODO the response should be different by the request interface.
+ response->setResourceRepresentation(
+ RCSRepresentation::toOCRepresentation(resObj->toRepresentation()));
+
+ invokeOCFunc(OC::OCPlatform::sendResponse, response);
+
+ m_done = true;
+ }
+
+ }
+}
diff --git a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp
index a4ed8a3..52ee306 100644
--- a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp
@@ -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
diff --git a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp
index 2ba3817..d76184e 100644
--- a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp
@@ -18,15 +18,17 @@
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#include
+#include "UnitTestHelper.h"
-#include
-#include
+#include "RCSRequest.h"
+#include "RCSResponse.h"
+#include "RCSSeparateResponse.h"
+#include "RCSResourceObject.h"
-#include
-#include
+#include "RequestHandler.h"
+#include "ResourceAttributesConverter.h"
-#include
+#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);
+}
--
2.7.4