Merge branch '1.3-rel' (5fdb8a1)
[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 "experimental/logger.h"
35 #include "OCPlatform.h"
36
37 #define LOG_TAG_RE "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_RE, "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 && *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     void insertValue(std::vector<std::string>& container, std::string value)
125     {
126             if (value.empty())
127             {
128                 return;
129             }
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             {
241                 invokeOCFunc(OC::OCPlatform::bindInterfaceToResource, handle, interfaceName);
242             });
243
244             std::for_each(m_types.begin() + 1, m_types.end(),
245                     [&handle](const std::string& typeName)
246             {
247                 invokeOCFunc(OC::OCPlatform::bindTypeToResource, handle, typeName);
248             });
249
250             server->init(handle, m_interfaces, m_types, m_defaultInterface);
251
252             return server;
253         }
254
255
256         RCSResourceObject::RCSResourceObject(const std::string& uri,
257                 uint8_t properties, RCSResourceAttributes&& attrs) :
258                 m_properties{ properties },
259                 m_uri{ uri },
260                 m_interfaces{ },
261                 m_types{ },
262                 m_defaultInterface{ },
263                 m_resourceHandle{ },
264                 m_resourceAttributes{ std::move(attrs) },
265                 m_getRequestHandler{ },
266                 m_setRequestHandler{ },
267                 m_autoNotifyPolicy{ AutoNotifyPolicy::UPDATED },
268                 m_setRequestHandlerPolicy{ SetRequestHandlerPolicy::NEVER },
269                 m_attributeUpdatedListeners{ },
270                 m_lockOwner{ },
271                 m_mutex{ },
272                 m_mutexAttributeUpdatedListeners{ }
273         {
274             m_lockOwner.reset(new AtomicThreadId);
275         }
276
277         void RCSResourceObject::init(OCResourceHandle handle,
278                 const std::vector< std::string >& interfaces,
279                 const std::vector< std::string >& types,
280                 const std::string& defaultInterface)
281         {
282             m_resourceHandle = handle;
283             m_interfaces = interfaces;
284             m_types = types;
285             m_defaultInterface = defaultInterface;
286
287             for (const auto& itf : interfaces)
288             {
289                 m_interfaceHandlers.insert({ itf, getDefaultInterfaceHandler(itf,
290                         m_defaultInterface) });
291             }
292         }
293
294         RCSResourceObject::~RCSResourceObject()
295         {
296             if (m_resourceHandle)
297             {
298                 try
299                 {
300                     invokeOCFunc(OC::OCPlatform::unregisterResource, m_resourceHandle);
301                 }
302                 catch (...)
303                 {
304                     OIC_LOG(WARNING, LOG_TAG_RE, "Failed to unregister resource.");
305                 }
306             }
307         }
308
309         template< typename K, typename V >
310         void RCSResourceObject::setAttributeInternal(K&& key, V&& value)
311         {
312             bool needToNotify = false;
313             bool valueUpdated = false;
314
315             {
316                 WeakGuard lock(*this);
317
318                 if (lock.hasLocked())
319                 {
320                     needToNotify = true;
321                     valueUpdated = testValueUpdated(key, value);
322                 }
323
324                 m_resourceAttributes[std::forward< K >(key)] = std::forward< V >(value);
325             }
326
327             if (needToNotify)
328             {
329                 autoNotify(valueUpdated);
330             }
331         }
332         void RCSResourceObject::setAttribute(const std::string& key,
333                 const RCSResourceAttributes::Value& value)
334         {
335             setAttributeInternal(key, value);
336         }
337
338         void RCSResourceObject::setAttribute(const std::string& key,
339                 RCSResourceAttributes::Value&& value)
340         {
341             setAttributeInternal(key, std::move(value));
342         }
343
344         void RCSResourceObject::setAttribute(std::string&& key,
345                 const RCSResourceAttributes::Value& value)
346         {
347             setAttributeInternal(std::move(key), value);
348         }
349
350         void RCSResourceObject::setAttribute(std::string&& key,
351                 RCSResourceAttributes::Value&& value)
352         {
353             setAttributeInternal(std::move(key), std::move(value));
354         }
355
356         RCSResourceAttributes::Value RCSResourceObject::getAttributeValue(
357                 const std::string& key) const
358         {
359             WeakGuard lock(*this);
360             return m_resourceAttributes.at(key);
361         }
362
363         bool RCSResourceObject::removeAttribute(const std::string& key)
364         {
365             bool needToNotify = false;
366             bool erased = false;
367             {
368                 WeakGuard lock(*this);
369
370                 if (m_resourceAttributes.erase(key))
371                 {
372                     erased = true;
373                     needToNotify = lock.hasLocked();
374                 }
375             }
376
377             if (needToNotify)
378             {
379                 autoNotify(true);
380             }
381
382             return erased;
383         }
384
385         bool RCSResourceObject::containsAttribute(const std::string& key) const
386         {
387             WeakGuard lock(*this);
388             return m_resourceAttributes.contains(key);
389         }
390
391         RCSResourceAttributes& RCSResourceObject::getAttributes()
392         {
393             expectOwnLock();
394             return m_resourceAttributes;
395         }
396
397         const RCSResourceAttributes& RCSResourceObject::getAttributes() const
398         {
399             expectOwnLock();
400             return m_resourceAttributes;
401         }
402
403         void RCSResourceObject::expectOwnLock() const
404         {
405             if (getLockOwner() != std::this_thread::get_id())
406             {
407                 throw NoLockException{ "Must acquire the lock first using LockGuard." };
408             }
409         }
410
411         std::thread::id RCSResourceObject::getLockOwner() const noexcept
412         {
413             return *m_lockOwner;
414         }
415
416         void RCSResourceObject::setLockOwner(std::thread::id&& id) const noexcept
417         {
418             m_lockOwner->store(std::move(id));
419         }
420
421         bool RCSResourceObject::isObservable() const
422         {
423             return ::hasProperty(m_properties, OC_OBSERVABLE);
424         }
425
426         bool RCSResourceObject::isDiscoverable() const
427         {
428             return ::hasProperty(m_properties, OC_DISCOVERABLE);
429         }
430
431         void RCSResourceObject::setGetRequestHandler(GetRequestHandler h)
432         {
433             m_getRequestHandler = std::make_shared< GetRequestHandler >(std::move(h));
434         }
435
436         void RCSResourceObject::setSetRequestHandler(SetRequestHandler h)
437         {
438             m_setRequestHandler = std::make_shared< SetRequestHandler >(std::move(h));
439         }
440
441         void RCSResourceObject::notify() const
442         {
443             typedef OCStackResult (*NotifyAllObservers)(OCResourceHandle);
444
445             invokeOCFuncWithResultExpect({ OC_STACK_OK, OC_STACK_NO_OBSERVERS },
446                     static_cast< NotifyAllObservers >(OC::OCPlatform::notifyAllObservers),
447                     m_resourceHandle);
448         }
449
450         void RCSResourceObject::addAttributeUpdatedListener(const std::string& key,
451                 AttributeUpdatedListener h)
452         {
453             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
454
455             m_attributeUpdatedListeners[key] =
456                     std::make_shared< AttributeUpdatedListener >(std::move(h));
457         }
458
459         void RCSResourceObject::addAttributeUpdatedListener(std::string&& key,
460                 AttributeUpdatedListener h)
461         {
462             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
463
464             m_attributeUpdatedListeners[std::move(key)] =
465                     std::make_shared< AttributeUpdatedListener >(std::move(h));
466         }
467
468         bool RCSResourceObject::removeAttributeUpdatedListener(const std::string& key)
469         {
470             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
471
472             return m_attributeUpdatedListeners.erase(key) != 0;
473         }
474
475         bool RCSResourceObject::testValueUpdated(const std::string& key,
476                 const RCSResourceAttributes::Value& value) const
477         {
478             return m_resourceAttributes.contains(key) == false
479                     || m_resourceAttributes.at(key) != value;
480         }
481
482         void RCSResourceObject::setAutoNotifyPolicy(AutoNotifyPolicy policy)
483         {
484             m_autoNotifyPolicy = policy;
485         }
486
487         RCSResourceObject::AutoNotifyPolicy RCSResourceObject::getAutoNotifyPolicy() const
488         {
489             return m_autoNotifyPolicy;
490         }
491
492         void RCSResourceObject::setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy)
493         {
494             m_setRequestHandlerPolicy = policy;
495         }
496
497         auto RCSResourceObject::getSetRequestHandlerPolicy() const -> SetRequestHandlerPolicy
498         {
499             return m_setRequestHandlerPolicy;
500         }
501
502         void RCSResourceObject::bindResource(const RCSResourceObject::Ptr& resource)
503         {
504             if (!resource || resource.get() == this)
505             {
506                 throw RCSInvalidParameterException("The resource is invalid!");
507             }
508
509             invokeOCFunc(OC::OCPlatform::bindResource,
510                     m_resourceHandle, resource->m_resourceHandle);
511
512             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
513             m_boundResources.push_back(resource);
514         }
515
516         void RCSResourceObject::unbindResource(const RCSResourceObject::Ptr& resource)
517         {
518             if (!resource || resource.get() == this)
519             {
520                 throw RCSInvalidParameterException("The resource is invalid!");
521             }
522
523             invokeOCFunc(OC::OCPlatform::unbindResource,
524                     m_resourceHandle, resource->m_resourceHandle);
525
526             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
527             m_boundResources.erase(std::find(m_boundResources.begin(), m_boundResources.end(),
528                     resource));
529         }
530
531         std::vector< RCSResourceObject::Ptr > RCSResourceObject::getBoundResources() const
532         {
533             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
534             return m_boundResources;
535         }
536
537         std::string RCSResourceObject::getUri() const
538         {
539             return m_uri;
540         }
541
542         std::string RCSResourceObject::getDefaultInterface() const
543         {
544             return m_defaultInterface;
545         }
546
547         std::vector< std::string > RCSResourceObject::getInterfaces() const
548         {
549             return m_interfaces;
550         }
551
552         std::vector< std::string > RCSResourceObject::getTypes() const
553         {
554             return m_types;
555         }
556
557         OCResourceHandle RCSResourceObject::getResourceHandle() const
558         {
559             return m_resourceHandle;
560         }
561
562         RCSRepresentation RCSResourceObject::getRepresentation(const RCSRequest& request) const
563         {
564             if (request.getOCRequest()->getRequestType() == "GET")
565             {
566                 return findInterfaceHandler(
567                         request.getInterface()).getGetResponseBuilder()(request, *this);
568             }
569
570             if (request.getOCRequest()->getRequestType() == "POST")
571             {
572                 return findInterfaceHandler(
573                         request.getInterface()).getSetResponseBuilder()(request, *this);
574             }
575
576             throw RCSBadRequestException{ "Unsupported request type!" };
577         }
578
579         void RCSResourceObject::autoNotify(bool isAttributesChanged) const
580         {
581             autoNotify(isAttributesChanged, m_autoNotifyPolicy);
582         }
583
584         void RCSResourceObject::autoNotify(
585                         bool isAttributesChanged, AutoNotifyPolicy autoNotifyPolicy) const
586         {
587             if(autoNotifyPolicy == AutoNotifyPolicy::NEVER)
588             {
589                 return;
590             }
591
592             if(autoNotifyPolicy == AutoNotifyPolicy::UPDATED &&
593                     isAttributesChanged == false)
594             {
595                 return;
596             }
597
598             notify();
599         }
600
601         OCEntityHandlerResult RCSResourceObject::entityHandler(
602                 const std::weak_ptr< RCSResourceObject >& weakRes,
603                 const std::shared_ptr< OC::OCResourceRequest >& request)
604         {
605             auto resource = weakRes.lock();
606
607             if (!resource)
608             {
609                 return OC_EH_ERROR;
610             }
611
612             OIC_LOG(WARNING, LOG_TAG_RE, "entityHandler");
613             if (!request)
614             {
615                 return OC_EH_ERROR;
616             }
617
618             try
619             {
620                 RCSRequest rcsRequest{ resource, request };
621
622                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::RequestFlag)
623                 {
624                     return resource->handleRequest(rcsRequest);
625                 }
626
627                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::ObserverFlag)
628                 {
629                     return resource->handleObserve(rcsRequest);
630                 }
631             }
632             catch (const std::exception& e)
633             {
634                 OIC_LOG_V(WARNING, LOG_TAG_RE, "Failed to handle request : %s", e.what());
635                 throw;
636             }
637             catch (...)
638             {
639                 OIC_LOG(WARNING, LOG_TAG_RE, "Failed to handle request.");
640                 throw;
641             }
642
643             return OC_EH_ERROR;
644         }
645
646         OCEntityHandlerResult RCSResourceObject::handleRequest(
647                 const RCSRequest& request)
648         {
649             if (request.getInterface() != "" &&
650                     m_interfaceHandlers.find(request.getInterface()) == m_interfaceHandlers.end())
651             {
652                 return OC_EH_ERROR;
653             }
654
655             if (request.getOCRequest()->getRequestType() == "GET")
656             {
657                 return handleRequestGet(request);
658             }
659
660             if (request.getOCRequest()->getRequestType() == "POST")
661             {
662                 return handleRequestSet(request);
663             }
664
665             return OC_EH_ERROR;
666         }
667
668         OCEntityHandlerResult RCSResourceObject::handleRequestGet(const RCSRequest& request)
669         {
670             if (!findInterfaceHandler(request.getInterface()).isGetSupported())
671             {
672                 return OC_EH_ERROR;
673             }
674
675             auto attrs = getAttributesFromOCRequest(request.getOCRequest());
676
677             auto response = invokeHandler(attrs, request, m_getRequestHandler);
678
679             if (response.isSeparate())
680             {
681                 return OC_EH_SLOW;
682             }
683
684             return sendResponse(request, response,
685                          findInterfaceHandler(request.getInterface()).getGetResponseBuilder());
686         }
687
688         bool RCSResourceObject::applyAcceptanceMethod(
689                 const RCSSetResponse& response, const RCSResourceAttributes& requestAttrs)
690         {
691             auto requestHandler = response.getHandler();
692
693             assert(requestHandler != nullptr);
694
695             RCSResourceAttributes result;
696
697             auto replaced = requestHandler->applyAcceptanceMethod(response.getAcceptanceMethod(),
698                     *this, requestAttrs);
699
700             OIC_LOG_V(WARNING, LOG_TAG_RE, "replaced num %" PRIuPTR, replaced.size());
701             for (const auto& attrKeyValPair : replaced)
702             {
703                 std::shared_ptr< AttributeUpdatedListener > foundListener;
704                 {
705                     std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
706
707                     auto it = m_attributeUpdatedListeners.find(attrKeyValPair.first);
708                     if (it != m_attributeUpdatedListeners.end())
709                     {
710                         foundListener = it->second;
711                     }
712                 }
713
714                 if (foundListener)
715                 {
716                     (*foundListener)(attrKeyValPair.second, requestAttrs.at(attrKeyValPair.first));
717                 }
718             }
719
720             return !replaced.empty();
721         }
722
723         OCEntityHandlerResult RCSResourceObject::handleRequestSet(const RCSRequest& request)
724         {
725             if (!findInterfaceHandler(request.getInterface()).isSetSupported())
726             {
727                 return OC_EH_ERROR;
728             }
729
730             auto attrs = getAttributesFromOCRequest(request.getOCRequest());
731
732             auto response = invokeHandler(attrs, request, m_setRequestHandler);
733
734             if (response.isSeparate())
735             {
736                 return OC_EH_SLOW;
737             }
738
739             autoNotify(applyAcceptanceMethod(response, attrs), m_autoNotifyPolicy);
740
741             return sendResponse(request, response,
742                     findInterfaceHandler(request.getInterface()).getSetResponseBuilder());
743         }
744
745         OCEntityHandlerResult RCSResourceObject::handleObserve(const RCSRequest&)
746         {
747             if (!isObservable())
748             {
749                 return OC_EH_ERROR;
750             }
751
752             return OC_EH_OK;
753         }
754
755         InterfaceHandler RCSResourceObject::findInterfaceHandler(
756                 const std::string& interfaceName) const
757         {
758             auto it = m_interfaceHandlers.find(interfaceName);
759
760             if (it != m_interfaceHandlers.end())
761             {
762                 return it->second;
763             }
764
765             assert(m_interfaceHandlers.find(m_defaultInterface) != m_interfaceHandlers.end());
766
767             return m_interfaceHandlers.find(m_defaultInterface)->second;
768         }
769
770         template <typename RESPONSE, typename RESPONSE_BUILDER>
771         OCEntityHandlerResult RCSResourceObject::sendResponse(
772                 const RCSRequest& request, const RESPONSE& response,
773                 const RESPONSE_BUILDER& resBuilder)
774         {
775             auto reqHandler = response.getHandler();
776             auto ocResponse = std::make_shared< OC::OCResourceResponse >();
777
778             ocResponse->setResponseResult(OC_EH_OK);
779
780             if (reqHandler->hasCustomRepresentation())
781             {
782                 ocResponse->setResourceRepresentation(reqHandler->getRepresentation());
783             }
784             else
785             {
786                 ocResponse->setResourceRepresentation(
787                         RCSRepresentation::toOCRepresentation(resBuilder(request, *this)));
788             }
789
790             return ::sendResponse(request.getOCRequest(), ocResponse);
791         }
792
793
794         RCSResourceObject::LockGuard::LockGuard(const RCSResourceObject::Ptr ptr) :
795                 m_resourceObject(*ptr),
796                 m_autoNotifyPolicy{ ptr->getAutoNotifyPolicy() },
797                 m_isOwningLock{ false }
798         {
799             init();
800         }
801
802         RCSResourceObject::LockGuard::LockGuard(
803                 const RCSResourceObject& serverResource) :
804                 m_resourceObject(serverResource),
805                 m_autoNotifyPolicy{ serverResource.getAutoNotifyPolicy() },
806                 m_isOwningLock{ false }
807         {
808             init();
809         }
810
811         RCSResourceObject::LockGuard::LockGuard(
812                 const RCSResourceObject::Ptr ptr, AutoNotifyPolicy autoNotifyPolicy) :
813                 m_resourceObject(*ptr),
814                 m_autoNotifyPolicy { autoNotifyPolicy },
815                 m_isOwningLock{ false }
816         {
817             init();
818         }
819
820         RCSResourceObject::LockGuard::LockGuard(
821                 const RCSResourceObject& resourceObject, AutoNotifyPolicy autoNotifyPolicy) :
822                 m_resourceObject(resourceObject),
823                 m_autoNotifyPolicy { autoNotifyPolicy },
824                 m_isOwningLock{ false }
825         {
826             init();
827         }
828
829         RCSResourceObject::LockGuard::~LockGuard() noexcept(false)
830         {
831             if (!std::uncaught_exception() && m_autoNotifyFunc)
832             {
833                 m_autoNotifyFunc();
834             }
835
836             if (m_isOwningLock)
837             {
838                 m_resourceObject.setLockOwner(std::thread::id{ });
839                 m_resourceObject.m_mutex.unlock();
840             }
841         }
842
843         void RCSResourceObject::LockGuard::init()
844         {
845             if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
846             {
847                 m_resourceObject.m_mutex.lock();
848                 m_resourceObject.setLockOwner(std::this_thread::get_id());
849                 m_isOwningLock = true;
850             }
851             m_autoNotifyFunc = ::createAutoNotifyInvoker(&RCSResourceObject::autoNotify,
852                     m_resourceObject, m_resourceObject.m_resourceAttributes, m_autoNotifyPolicy);
853         }
854
855       RCSResourceObject::WeakGuard::WeakGuard(
856                 const RCSResourceObject& resourceObject) :
857                 m_isOwningLock{ false },
858                 m_resourceObject(resourceObject)
859         {
860             if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
861             {
862                 m_resourceObject.m_mutex.lock();
863                 m_resourceObject.setLockOwner(std::this_thread::get_id());
864                 m_isOwningLock = true;
865             }
866         }
867
868         RCSResourceObject::WeakGuard::~WeakGuard()
869         {
870             if (m_isOwningLock)
871             {
872                 m_resourceObject.setLockOwner(std::thread::id{ });
873                 m_resourceObject.m_mutex.unlock();
874             }
875         }
876
877         bool RCSResourceObject::WeakGuard::hasLocked() const
878         {
879             return m_isOwningLock;
880         }
881
882     }
883 }