From: coderhyme Date: Fri, 5 Feb 2016 02:42:12 +0000 (-0800) Subject: Added SeparateResponse class for the RCSResourceObject in RE. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=61ff7411a690309b4832e1e639689f30b0e4b8e8;p=contrib%2Fiotivity.git 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 --- 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); +}