Modified RCSResourceObject to eliminate its inheritance from enable_shared_from_this.
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / serverBuilder / src / RCSResourceObject.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "RCSResourceObject.h"
22
23 #include <functional>
24
25 #include "RequestHandler.h"
26 #include "AssertUtils.h"
27 #include "AtomicHelper.h"
28 #include "ResourceAttributesConverter.h"
29 #include "ResourceAttributesUtils.h"
30 #include "RCSRequest.h"
31 #include "RCSRepresentation.h"
32 #include "InterfaceHandler.h"
33
34 #include "logger.h"
35 #include "OCPlatform.h"
36
37 #define LOG_TAG "RCSResourceObject"
38
39 namespace
40 {
41     using namespace OIC::Service;
42
43     inline bool hasProperty(uint8_t base, uint8_t target)
44     {
45         return (base & target) == target;
46     }
47
48     inline uint8_t makePropertyFlags(uint8_t base, uint8_t target, bool add)
49     {
50         if (add)
51         {
52             return base | target;
53         }
54
55         return base & ~target;
56     }
57
58     OCEntityHandlerResult sendResponse(const std::shared_ptr< OC::OCResourceRequest >& ocRequest,
59             const std::shared_ptr< OC::OCResourceResponse >& ocResponse)
60     {
61         ocResponse->setRequestHandle(ocRequest->getRequestHandle());
62         ocResponse->setResourceHandle(ocRequest->getResourceHandle());
63
64         try
65         {
66             if (OC::OCPlatform::sendResponse(ocResponse) == OC_STACK_OK)
67             {
68                 return OC_EH_OK;
69             }
70         }
71         catch (const OC::OCException& e)
72         {
73             OIC_LOG_V(WARNING, LOG_TAG, "Error (%s)", e.what());
74         }
75
76         return OC_EH_ERROR;
77     }
78
79     RCSResourceAttributes getAttributesFromOCRequest(
80             const std::shared_ptr< OC::OCResourceRequest >& request)
81     {
82         return ResourceAttributesConverter::fromOCRepresentation(
83                 request->getResourceRepresentation());
84     }
85
86     template< typename HANDLER, typename RESPONSE =
87             typename std::decay<HANDLER>::type::result_type >
88     RESPONSE invokeHandler(RCSResourceAttributes& attrs, const RCSRequest& request,
89             std::shared_ptr< HANDLER > handler)
90     {
91         if (handler)
92         {
93             return (*handler)(request, attrs);
94         }
95
96         return RESPONSE::defaultAction();
97     }
98
99     typedef void (RCSResourceObject::* AutoNotifyFunc)
100             (bool, RCSResourceObject::AutoNotifyPolicy) const;
101
102     std::function<void()> createAutoNotifyInvoker(AutoNotifyFunc autoNotifyFunc,
103             const RCSResourceObject& resourceObject,
104             const RCSResourceAttributes& resourceAttributes,
105             RCSResourceObject::AutoNotifyPolicy autoNotifyPolicy)
106     {
107         if(autoNotifyPolicy == RCSResourceObject::AutoNotifyPolicy::UPDATED)
108         {
109             auto&& compareAttributesFunc =
110                     std::bind(std::not_equal_to<RCSResourceAttributes>(),
111                                 resourceAttributes,
112                                 std::cref(resourceAttributes));
113             return std::bind(autoNotifyFunc,
114                     &resourceObject, std::move(compareAttributesFunc), autoNotifyPolicy);
115         }
116         else if(autoNotifyPolicy == RCSResourceObject::AutoNotifyPolicy::ALWAYS)
117         {
118             return std::bind(autoNotifyFunc,
119                     &resourceObject, true, autoNotifyPolicy);
120         }
121         return {};
122     }
123
124 } // unnamed namespace
125
126 namespace OIC
127 {
128     namespace Service
129     {
130
131         RCSResourceObject::Builder::Builder(std::string uri, std::string type,
132                 std::string interface) :
133                 m_uri{ std::move(uri) },
134                 m_types{ std::move(type) },
135                 m_interfaces{ std::move(interface) },
136                 m_defaultInterface { BASELINE_INTERFACE },
137                 m_properties{ OC_DISCOVERABLE | OC_OBSERVABLE },
138                 m_resourceAttributes{ }
139         {
140         }
141
142         RCSResourceObject::Builder& RCSResourceObject::Builder::addInterface(std::string interface)
143         {
144             m_interfaces.push_back(std::move(interface));
145             return *this;
146         }
147
148         RCSResourceObject::Builder& RCSResourceObject::Builder::addType(std::string type)
149         {
150             m_types.push_back(std::move(type));
151             return *this;
152         }
153
154         RCSResourceObject::Builder& RCSResourceObject::Builder::setDefaultInterface(
155                 std::string interface)
156         {
157             if (std::find(m_interfaces.begin(), m_interfaces.end(), interface) ==
158                     m_interfaces.end())
159             {
160                 throw RCSBadRequestException{"The interface should be added, first."};
161             }
162
163             m_defaultInterface = std::move(interface);
164
165             return *this;
166         }
167
168         RCSResourceObject::Builder& RCSResourceObject::Builder::setDiscoverable(
169                 bool discoverable)
170         {
171             m_properties = ::makePropertyFlags(m_properties, OC_DISCOVERABLE, discoverable);
172             return *this;
173         }
174
175         RCSResourceObject::Builder& RCSResourceObject::Builder::setObservable(
176                 bool observable)
177         {
178             m_properties = ::makePropertyFlags(m_properties, OC_OBSERVABLE, observable);
179             return *this;
180         }
181
182         RCSResourceObject::Builder& RCSResourceObject::Builder::setSecureFlag(
183             bool secureFlag)
184         {
185             m_properties = ::makePropertyFlags(m_properties, OC_SECURE, secureFlag);
186             return *this;
187         }
188         RCSResourceObject::Builder& RCSResourceObject::Builder::setAttributes(
189                 const RCSResourceAttributes& attrs)
190         {
191             m_resourceAttributes = attrs;
192             return *this;
193         }
194
195         RCSResourceObject::Builder& RCSResourceObject::Builder::setAttributes(
196                 RCSResourceAttributes&& attrs)
197         {
198             m_resourceAttributes = std::move(attrs);
199             return *this;
200         }
201
202         RCSResourceObject::Ptr RCSResourceObject::Builder::build()
203         {
204             OCResourceHandle handle{ nullptr };
205
206             RCSResourceObject::Ptr server {
207                 new RCSResourceObject{ m_uri, m_properties, std::move(m_resourceAttributes) } };
208
209             OC::EntityHandler entityHandler{ std::bind(&RCSResourceObject::entityHandler,
210                     std::weak_ptr< RCSResourceObject >{ server }, std::placeholders::_1) };
211
212             typedef OCStackResult (*RegisterResource)(OCResourceHandle&, std::string&,
213                     const std::string&, const std::string&, OC::EntityHandler, uint8_t);
214
215             invokeOCFunc(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
216                     handle, m_uri, m_types[0], m_interfaces[0], entityHandler, m_properties);
217
218             std::for_each(m_interfaces.begin() + 1, m_interfaces.end(),
219                     [&handle](const std::string& interfaceName){
220                 invokeOCFunc(OC::OCPlatform::bindInterfaceToResource, handle, interfaceName);
221             });
222
223             std::for_each(m_types.begin() + 1, m_types.end(),
224                     [&handle](const std::string& typeName){
225                 invokeOCFunc(OC::OCPlatform::bindTypeToResource, handle, typeName);
226             });
227
228             server->init(handle, m_interfaces, m_types, m_defaultInterface);
229
230             return server;
231         }
232
233
234         RCSResourceObject::RCSResourceObject(const std::string& uri,
235                 uint8_t properties, RCSResourceAttributes&& attrs) :
236                 m_properties{ properties },
237                 m_uri{ uri },
238                 m_interfaces{ },
239                 m_types{ },
240                 m_defaultInterface{ },
241                 m_resourceHandle{ },
242                 m_resourceAttributes{ std::move(attrs) },
243                 m_getRequestHandler{ },
244                 m_setRequestHandler{ },
245                 m_autoNotifyPolicy{ AutoNotifyPolicy::UPDATED },
246                 m_setRequestHandlerPolicy{ SetRequestHandlerPolicy::NEVER },
247                 m_attributeUpdatedListeners{ },
248                 m_lockOwner{ },
249                 m_mutex{ },
250                 m_mutexAttributeUpdatedListeners{ }
251         {
252             m_lockOwner.reset(new AtomicThreadId);
253         }
254
255         void RCSResourceObject::init(OCResourceHandle handle,
256                 const std::vector< std::string >& interfaces,
257                 const std::vector< std::string >& types,
258                 const std::string& defaultInterface)
259         {
260             m_resourceHandle = handle;
261             m_interfaces = interfaces;
262             m_types = types;
263             m_defaultInterface = defaultInterface;
264
265             for (const auto& itf : interfaces)
266             {
267                 m_interfaceHandlers.insert({ itf, getDefaultInterfaceHandler(itf,
268                         m_defaultInterface) });
269             }
270         }
271
272         RCSResourceObject::~RCSResourceObject()
273         {
274             if (m_resourceHandle)
275             {
276                 try
277                 {
278                     invokeOCFunc(OC::OCPlatform::unregisterResource, m_resourceHandle);
279                 }
280                 catch (...)
281                 {
282                     OIC_LOG(WARNING, LOG_TAG, "Failed to unregister resource.");
283                 }
284             }
285         }
286
287         template< typename K, typename V >
288         void RCSResourceObject::setAttributeInternal(K&& key, V&& value)
289         {
290             bool needToNotify = false;
291             bool valueUpdated = false;
292
293             {
294                 WeakGuard lock(*this);
295
296                 if (lock.hasLocked())
297                 {
298                     needToNotify = true;
299                     valueUpdated = testValueUpdated(key, value);
300                 }
301
302                 m_resourceAttributes[std::forward< K >(key)] = std::forward< V >(value);
303             }
304
305             if (needToNotify) autoNotify(valueUpdated);
306         }
307         void RCSResourceObject::setAttribute(const std::string& key,
308                 const RCSResourceAttributes::Value& value)
309         {
310             setAttributeInternal(key, value);
311         }
312
313         void RCSResourceObject::setAttribute(const std::string& key,
314                 RCSResourceAttributes::Value&& value)
315         {
316             setAttributeInternal(key, std::move(value));
317         }
318
319         void RCSResourceObject::setAttribute(std::string&& key,
320                 const RCSResourceAttributes::Value& value)
321         {
322             setAttributeInternal(std::move(key), value);
323         }
324
325         void RCSResourceObject::setAttribute(std::string&& key,
326                 RCSResourceAttributes::Value&& value)
327         {
328             setAttributeInternal(std::move(key), std::move(value));
329         }
330
331         RCSResourceAttributes::Value RCSResourceObject::getAttributeValue(
332                 const std::string& key) const
333         {
334             WeakGuard lock(*this);
335             return m_resourceAttributes.at(key);
336         }
337
338         bool RCSResourceObject::removeAttribute(const std::string& key)
339         {
340             bool needToNotify = false;
341             bool erased = false;
342             {
343                 WeakGuard lock(*this);
344
345                 if (m_resourceAttributes.erase(key))
346                 {
347                     erased = true;
348                     needToNotify = lock.hasLocked();
349                 }
350             }
351
352             if (needToNotify) autoNotify(true);
353
354             return erased;
355         }
356
357         bool RCSResourceObject::containsAttribute(const std::string& key) const
358         {
359             WeakGuard lock(*this);
360             return m_resourceAttributes.contains(key);
361         }
362
363         RCSResourceAttributes& RCSResourceObject::getAttributes()
364         {
365             expectOwnLock();
366             return m_resourceAttributes;
367         }
368
369         const RCSResourceAttributes& RCSResourceObject::getAttributes() const
370         {
371             expectOwnLock();
372             return m_resourceAttributes;
373         }
374
375         void RCSResourceObject::expectOwnLock() const
376         {
377             if (getLockOwner() != std::this_thread::get_id())
378             {
379                 throw NoLockException{ "Must acquire the lock first using LockGuard." };
380             }
381         }
382
383         std::thread::id RCSResourceObject::getLockOwner() const noexcept
384         {
385             return *m_lockOwner;
386         }
387
388         void RCSResourceObject::setLockOwner(std::thread::id&& id) const noexcept
389         {
390             m_lockOwner->store(std::move(id));
391         }
392
393         bool RCSResourceObject::isObservable() const
394         {
395             return ::hasProperty(m_properties, OC_OBSERVABLE);
396         }
397
398         bool RCSResourceObject::isDiscoverable() const
399         {
400             return ::hasProperty(m_properties, OC_DISCOVERABLE);
401         }
402
403         void RCSResourceObject::setGetRequestHandler(GetRequestHandler h)
404         {
405             m_getRequestHandler = std::make_shared< GetRequestHandler >(std::move(h));
406         }
407
408         void RCSResourceObject::setSetRequestHandler(SetRequestHandler h)
409         {
410             m_setRequestHandler = std::make_shared< SetRequestHandler >(std::move(h));
411         }
412
413         void RCSResourceObject::notify() const
414         {
415             typedef OCStackResult (*NotifyAllObservers)(OCResourceHandle);
416
417             invokeOCFuncWithResultExpect({ OC_STACK_OK, OC_STACK_NO_OBSERVERS },
418                     static_cast< NotifyAllObservers >(OC::OCPlatform::notifyAllObservers),
419                     m_resourceHandle);
420         }
421
422         void RCSResourceObject::addAttributeUpdatedListener(const std::string& key,
423                 AttributeUpdatedListener h)
424         {
425             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
426
427             m_attributeUpdatedListeners[key] =
428                     std::make_shared< AttributeUpdatedListener >(std::move(h));
429         }
430
431         void RCSResourceObject::addAttributeUpdatedListener(std::string&& key,
432                 AttributeUpdatedListener h)
433         {
434             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
435
436             m_attributeUpdatedListeners[std::move(key)] =
437                     std::make_shared< AttributeUpdatedListener >(std::move(h));
438         }
439
440         bool RCSResourceObject::removeAttributeUpdatedListener(const std::string& key)
441         {
442             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
443
444             return m_attributeUpdatedListeners.erase(key) != 0;
445         }
446
447         bool RCSResourceObject::testValueUpdated(const std::string& key,
448                 const RCSResourceAttributes::Value& value) const
449         {
450             return m_resourceAttributes.contains(key) == false
451                     || m_resourceAttributes.at(key) != value;
452         }
453
454         void RCSResourceObject::setAutoNotifyPolicy(AutoNotifyPolicy policy)
455         {
456             m_autoNotifyPolicy = policy;
457         }
458
459         RCSResourceObject::AutoNotifyPolicy RCSResourceObject::getAutoNotifyPolicy() const
460         {
461             return m_autoNotifyPolicy;
462         }
463
464         void RCSResourceObject::setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy)
465         {
466             m_setRequestHandlerPolicy = policy;
467         }
468
469         auto RCSResourceObject::getSetRequestHandlerPolicy() const -> SetRequestHandlerPolicy
470         {
471             return m_setRequestHandlerPolicy;
472         }
473
474         void RCSResourceObject::bindResource(const RCSResourceObject::Ptr& resource)
475         {
476             if (!resource || resource.get() == this)
477             {
478                 throw RCSInvalidParameterException("The resource is invalid!");
479             }
480
481             invokeOCFunc(OC::OCPlatform::bindResource,
482                     m_resourceHandle, resource->m_resourceHandle);
483
484             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
485             m_boundResources.push_back(resource);
486         }
487
488         void RCSResourceObject::unbindResource(const RCSResourceObject::Ptr& resource)
489         {
490             if (!resource || resource.get() == this)
491             {
492                 throw RCSInvalidParameterException("The resource is invalid!");
493             }
494
495             invokeOCFunc(OC::OCPlatform::unbindResource,
496                     m_resourceHandle, resource->m_resourceHandle);
497
498             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
499             m_boundResources.erase(std::find(m_boundResources.begin(), m_boundResources.end(),
500                     resource));
501         }
502
503         std::vector< RCSResourceObject::Ptr > RCSResourceObject::getBoundResources() const
504         {
505             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
506             return m_boundResources;
507         }
508
509         std::string RCSResourceObject::getUri() const
510         {
511             return m_uri;
512         }
513
514         std::string RCSResourceObject::getDefaultInterface() const
515         {
516             return m_defaultInterface;
517         }
518
519         std::vector< std::string > RCSResourceObject::getInterfaces() const
520         {
521             return m_interfaces;
522         }
523
524         std::vector< std::string > RCSResourceObject::getTypes() const
525         {
526             return m_types;
527         }
528
529         RCSRepresentation RCSResourceObject::getRepresentation(const RCSRequest& request) const
530         {
531             if (request.getOCRequest()->getRequestType() == "GET")
532             {
533                 return findInterfaceHandler(
534                         request.getInterface()).getGetResponseBuilder()(request, *this);
535             }
536
537             if (request.getOCRequest()->getRequestType() == "POST")
538             {
539                 return findInterfaceHandler(
540                         request.getInterface()).getSetResponseBuilder()(request, *this);
541             }
542
543             throw RCSBadRequestException{ "Unsupported request type!" };
544         }
545
546         void RCSResourceObject::autoNotify(bool isAttributesChanged) const
547         {
548             autoNotify(isAttributesChanged, m_autoNotifyPolicy);
549         }
550
551         void RCSResourceObject::autoNotify(
552                         bool isAttributesChanged, AutoNotifyPolicy autoNotifyPolicy) const
553         {
554             if(autoNotifyPolicy == AutoNotifyPolicy::NEVER) return;
555             if(autoNotifyPolicy == AutoNotifyPolicy::UPDATED &&
556                     isAttributesChanged == false) return;
557
558             notify();
559         }
560
561         OCEntityHandlerResult RCSResourceObject::entityHandler(
562                 const std::weak_ptr< RCSResourceObject >& weakRes,
563                 const std::shared_ptr< OC::OCResourceRequest >& request)
564         {
565             auto resource = weakRes.lock();
566
567             if (!resource) return OC_EH_ERROR;
568
569             OIC_LOG(WARNING, LOG_TAG, "entityHandler");
570             if (!request)
571             {
572                 return OC_EH_ERROR;
573             }
574
575             try
576             {
577                 RCSRequest rcsRequest{ resource, request };
578
579                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::RequestFlag)
580                 {
581                     return resource->handleRequest(rcsRequest);
582                 }
583
584                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::ObserverFlag)
585                 {
586                     return resource->handleObserve(rcsRequest);
587                 }
588             }
589             catch (const std::exception& e)
590             {
591                 OIC_LOG_V(WARNING, LOG_TAG, "Failed to handle request : %s", e.what());
592                 throw;
593             }
594             catch (...)
595             {
596                 OIC_LOG(WARNING, LOG_TAG, "Failed to handle request.");
597                 throw;
598             }
599
600             return OC_EH_ERROR;
601         }
602
603         OCEntityHandlerResult RCSResourceObject::handleRequest(
604                 const RCSRequest& request)
605         {
606             if (request.getInterface() != "" &&
607                     m_interfaceHandlers.find(request.getInterface()) == m_interfaceHandlers.end())
608             {
609                 return OC_EH_ERROR;
610             }
611
612             if (request.getOCRequest()->getRequestType() == "GET")
613             {
614                 return handleRequestGet(request);
615             }
616
617             if (request.getOCRequest()->getRequestType() == "POST")
618             {
619                 return handleRequestSet(request);
620             }
621
622             return OC_EH_ERROR;
623         }
624
625         OCEntityHandlerResult RCSResourceObject::handleRequestGet(const RCSRequest& request)
626         {
627             if (!findInterfaceHandler(request.getInterface()).isGetSupported())
628             {
629                 return OC_EH_ERROR;
630             }
631
632             auto attrs = getAttributesFromOCRequest(request.getOCRequest());
633
634             auto response = invokeHandler(attrs, request, m_getRequestHandler);
635
636             if (response.isSeparate()) return OC_EH_SLOW;
637
638             return sendResponse(request, response,
639                          findInterfaceHandler(request.getInterface()).getGetResponseBuilder());
640         }
641
642         bool RCSResourceObject::applyAcceptanceMethod(
643                 const RCSSetResponse& response, const RCSResourceAttributes& requestAttrs)
644         {
645             auto requestHandler = response.getHandler();
646
647             assert(requestHandler != nullptr);
648
649             RCSResourceAttributes result;
650
651             auto replaced = requestHandler->applyAcceptanceMethod(response.getAcceptanceMethod(),
652                     *this, requestAttrs);
653
654             OIC_LOG_V(WARNING, LOG_TAG, "replaced num %zu", replaced.size());
655             for (const auto& attrKeyValPair : replaced)
656             {
657                 std::shared_ptr< AttributeUpdatedListener > foundListener;
658                 {
659                     std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
660
661                     auto it = m_attributeUpdatedListeners.find(attrKeyValPair.first);
662                     if (it != m_attributeUpdatedListeners.end())
663                     {
664                         foundListener = it->second;
665                     }
666                 }
667
668                 if (foundListener)
669                 {
670                     (*foundListener)(attrKeyValPair.second, requestAttrs.at(attrKeyValPair.first));
671                 }
672             }
673
674             return !replaced.empty();
675         }
676
677         OCEntityHandlerResult RCSResourceObject::handleRequestSet(const RCSRequest& request)
678         {
679             if (!findInterfaceHandler(request.getInterface()).isSetSupported())
680             {
681                 return OC_EH_ERROR;
682             }
683
684             auto attrs = getAttributesFromOCRequest(request.getOCRequest());
685
686             auto response = invokeHandler(attrs, request, m_setRequestHandler);
687
688             if (response.isSeparate()) return OC_EH_SLOW;
689
690             autoNotify(applyAcceptanceMethod(response, attrs), m_autoNotifyPolicy);
691
692             return sendResponse(request, response,
693                     findInterfaceHandler(request.getInterface()).getSetResponseBuilder());
694         }
695
696         OCEntityHandlerResult RCSResourceObject::handleObserve(const RCSRequest&)
697         {
698             if (!isObservable())
699             {
700                 return OC_EH_ERROR;
701             }
702
703             return OC_EH_OK;
704         }
705
706         InterfaceHandler RCSResourceObject::findInterfaceHandler(
707                 const std::string& interfaceName) const
708         {
709             auto it = m_interfaceHandlers.find(interfaceName);
710
711             if (it != m_interfaceHandlers.end()) return it->second;
712
713             assert(m_interfaceHandlers.find(m_defaultInterface) != m_interfaceHandlers.end());
714
715             return m_interfaceHandlers.find(m_defaultInterface)->second;
716         }
717
718         template <typename RESPONSE, typename RESPONSE_BUILDER>
719         OCEntityHandlerResult RCSResourceObject::sendResponse(
720                 const RCSRequest& request, const RESPONSE& response,
721                 const RESPONSE_BUILDER& resBuilder)
722         {
723             auto reqHandler = response.getHandler();
724             auto ocResponse = std::make_shared< OC::OCResourceResponse >();
725
726             ocResponse->setResponseResult(OC_EH_OK);
727             ocResponse->setErrorCode(reqHandler->getErrorCode());
728
729             if (reqHandler->hasCustomRepresentation())
730             {
731                 ocResponse->setResourceRepresentation(reqHandler->getRepresentation());
732             }
733             else
734             {
735                 ocResponse->setResourceRepresentation(
736                         RCSRepresentation::toOCRepresentation(resBuilder(request, *this)));
737             }
738
739             return ::sendResponse(request.getOCRequest(), ocResponse);
740         }
741
742
743         RCSResourceObject::LockGuard::LockGuard(const RCSResourceObject::Ptr ptr) :
744                 m_resourceObject(*ptr),
745                 m_autoNotifyPolicy{ ptr->getAutoNotifyPolicy() },
746                 m_isOwningLock{ false }
747         {
748             init();
749         }
750
751         RCSResourceObject::LockGuard::LockGuard(
752                 const RCSResourceObject& serverResource) :
753                 m_resourceObject(serverResource),
754                 m_autoNotifyPolicy{ serverResource.getAutoNotifyPolicy() },
755                 m_isOwningLock{ false }
756         {
757             init();
758         }
759
760         RCSResourceObject::LockGuard::LockGuard(
761                 const RCSResourceObject::Ptr ptr, AutoNotifyPolicy autoNotifyPolicy) :
762                 m_resourceObject(*ptr),
763                 m_autoNotifyPolicy { autoNotifyPolicy },
764                 m_isOwningLock{ false }
765         {
766             init();
767         }
768
769         RCSResourceObject::LockGuard::LockGuard(
770                 const RCSResourceObject& resourceObject, AutoNotifyPolicy autoNotifyPolicy) :
771                 m_resourceObject(resourceObject),
772                 m_autoNotifyPolicy { autoNotifyPolicy },
773                 m_isOwningLock{ false }
774         {
775             init();
776         }
777
778         RCSResourceObject::LockGuard::~LockGuard() noexcept(false)
779         {
780             if (!std::uncaught_exception() && m_autoNotifyFunc) m_autoNotifyFunc();
781
782             if (m_isOwningLock)
783             {
784                 m_resourceObject.setLockOwner(std::thread::id{ });
785                 m_resourceObject.m_mutex.unlock();
786             }
787         }
788
789         void RCSResourceObject::LockGuard::init()
790         {
791             if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
792             {
793                 m_resourceObject.m_mutex.lock();
794                 m_resourceObject.setLockOwner(std::this_thread::get_id());
795                 m_isOwningLock = true;
796             }
797             m_autoNotifyFunc = ::createAutoNotifyInvoker(&RCSResourceObject::autoNotify,
798                     m_resourceObject, m_resourceObject.m_resourceAttributes, m_autoNotifyPolicy);
799         }
800
801         RCSResourceObject::WeakGuard::WeakGuard(
802                 const RCSResourceObject& resourceObject) :
803                 m_isOwningLock{ false },
804                 m_resourceObject(resourceObject)
805         {
806             if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
807             {
808                 m_resourceObject.m_mutex.lock();
809                 m_resourceObject.setLockOwner(std::this_thread::get_id());
810                 m_isOwningLock = true;
811             }
812         }
813
814         RCSResourceObject::WeakGuard::~WeakGuard()
815         {
816             if (m_isOwningLock)
817             {
818                 m_resourceObject.setLockOwner(std::thread::id{ });
819                 m_resourceObject.m_mutex.unlock();
820             }
821         }
822
823         bool RCSResourceObject::WeakGuard::hasLocked() const
824         {
825             return m_isOwningLock;
826         }
827
828     }
829 }