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