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>
{
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;
};
}
* in instead of overriding SetRequestHandler.
* </p>
*/
- class RCSResourceObject
+ class RCSResourceObject : public std::enable_shared_from_this< RCSResourceObject >
{
private:
class WeakGuard;
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 >&);
*/
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:
*/
static RCSSetResponse create(RCSResourceAttributes&& attrs, int errorCode);
+ static RCSSetResponse separate();
+
+ bool isSeparate() const;
//! @cond
SetRequestHandler* getHandler() const;
RCSSetResponse& setAcceptanceMethod(AcceptanceMethod method);
private:
+ RCSSetResponse();
RCSSetResponse(std::shared_ptr< SetRequestHandler >&&);
RCSSetResponse(std::shared_ptr< SetRequestHandler >&&, AcceptanceMethod);
--- /dev/null
+//******************************************************************
+//
+// 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
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 }
{
}
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;
}
return it->second;
}
+
}
}
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();
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);
RCSRepresentation RCSResourceObject::toRepresentation() const
{
+ WeakGuard lock{*this};
return RCSRepresentation{ m_uri, m_interfaces, m_types, m_resourceAttributes };
}
}
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)
{
{
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)
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,
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);
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) }
{
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) }
assert(m_handler);
}
+ bool RCSSetResponse::isSeparate() const
+ {
+ return !m_handler;
+ }
+
+
SetRequestHandler* RCSSetResponse::getHandler() const
{
return m_handler.get();
--- /dev/null
+//******************************************************************\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
#include "UnitTestHelper.h"
#include "RCSResourceObject.h"
+#include "RCSRequest.h"
+#include "RCSSeparateResponse.h"
#include "OCPlatform.h"
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
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#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;
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);
+}