[IOT-1095] Add request parameters to attribute handlers
[platform/upstream/iotivity.git] / service / resource-container / src / ResourceContainerImpl.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 "ResourceContainerImpl.h"
22
23 #include <dlfcn.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fstream>
27 #include <iostream>
28 #include <stdio.h>
29 #include <thread>
30 #include <mutex>
31 #include <algorithm>
32
33 #include "BundleActivator.h"
34 #include "SoftSensorResource.h"
35 #include "InternalTypes.h"
36
37 using namespace OIC::Service;
38 using namespace std;
39
40 namespace OIC
41 {
42     namespace Service
43     {
44         ResourceContainerImpl::ResourceContainerImpl()
45         {
46             m_config = nullptr;
47         }
48
49         ResourceContainerImpl::~ResourceContainerImpl()
50         {
51             m_config = nullptr;
52         }
53
54         bool has_suffix(const std::string &str, const std::string &suffix)
55         {
56             return str.size() >= suffix.size()
57                    && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
58         }
59
60         void ResourceContainerImpl::startContainer(const std::string &configFile)
61         {
62             OIC_LOG(INFO, CONTAINER_TAG, "Starting resource container.");
63 #if (JAVA_SUPPORT)
64             OIC_LOG(INFO, CONTAINER_TAG, "Resource container has Java support.");
65 #else
66             OIC_LOG(INFO, CONTAINER_TAG, "Resource container without Java support.");
67 #endif
68
69
70             activationLock.lock();
71             try{
72                 if (!configFile.empty())
73                 {
74                     m_config = new Configuration(configFile);
75
76                     if (m_config->isLoaded())
77                     {
78                         configInfo bundles;
79                         m_config->getConfiguredBundles(&bundles);
80
81                         for (unsigned int i = 0; i < bundles.size(); i++)
82                         {
83                             shared_ptr<BundleInfoInternal> bundleInfo(new BundleInfoInternal);
84                             bundleInfo->setPath(bundles[i][BUNDLE_PATH]);
85                             bundleInfo->setVersion(bundles[i][BUNDLE_VERSION]);
86                             bundleInfo->setID(bundles[i][BUNDLE_ID]);
87                             if (!bundles[i][BUNDLE_ACTIVATOR].empty())
88                             {
89                                 string activatorName = bundles[i][BUNDLE_ACTIVATOR];
90                                 std::replace(activatorName.begin(), activatorName.end(), '.', '/');
91                                 bundleInfo->setActivatorName(activatorName);
92                                 bundleInfo->setLibraryPath(bundles[i][BUNDLE_LIBRARY_PATH]);
93                             }
94
95                             OIC_LOG_V(INFO, CONTAINER_TAG, "Init Bundle:(%s)",
96                                      std::string(bundles[i][BUNDLE_ID] + ";" +
97                                                  bundles[i][BUNDLE_PATH]).c_str());
98
99                             registerBundle(bundleInfo);
100                             activateBundle(bundleInfo);
101                         }
102                     }
103                     else
104                     {
105                         OIC_LOG_V(ERROR, CONTAINER_TAG, "Container started with invalid configfile path.");
106                     }
107                 }
108                 else
109                 {
110                     OIC_LOG_V(INFO, CONTAINER_TAG, "No configuration file for the container provided.");
111                 }
112
113                 OIC_LOG(INFO, CONTAINER_TAG, "Resource container started.");
114             }catch(...){
115                 OIC_LOG(INFO, CONTAINER_TAG, "Resource container failed starting.");
116             }
117             activationLock.unlock();
118         }
119
120         void ResourceContainerImpl::stopContainer()
121         {
122             OIC_LOG(INFO, CONTAINER_TAG, "Stopping resource container.");
123
124             for (std::map< std::string, shared_ptr<BundleInfoInternal> >::iterator it = m_bundles.begin();
125                  it != m_bundles.end(); ++it)
126             {
127                 deactivateBundle(it->second);
128                 unregisterBundle(it->second);
129             }
130
131             if (!m_mapServers.empty())
132             {
133                 map< std::string, RCSResourceObject::Ptr >::iterator itor = m_mapServers.begin();
134
135                 while (itor != m_mapServers.end())
136                 {
137                     (itor++)->second.reset();
138                 }
139
140                 m_mapResources.clear();
141                 m_mapBundleResources.clear();
142             }
143
144             if (m_config)
145                 delete m_config;
146         }
147
148         void ResourceContainerImpl::activateBundle(shared_ptr<RCSBundleInfo> bundleInfo)
149         {
150             activationLock.lock();
151
152             shared_ptr<BundleInfoInternal> bundleInfoInternal =
153                     std::static_pointer_cast<BundleInfoInternal>(bundleInfo);
154
155             if (bundleInfoInternal->isLoaded())
156             {
157                 activateBundle(bundleInfo->getID());
158             }
159             activationLock.unlock();
160         }
161
162         void ResourceContainerImpl::deactivateBundle(shared_ptr<RCSBundleInfo> bundleInfo)
163         {
164             shared_ptr<BundleInfoInternal> bundleInfoInternal =
165                                 std::static_pointer_cast<BundleInfoInternal>(bundleInfo);
166             if (bundleInfoInternal->isActivated())
167             {
168                 deactivateBundle(bundleInfoInternal->getID());
169             }
170         }
171
172         void ResourceContainerImpl::activateBundle(const std::string &id)
173         {
174             OIC_LOG_V(INFO, CONTAINER_TAG, "Activating bundle: (%s)",
175                      std::string(m_bundles[id]->getID()).c_str());
176
177             activationLock.lock();
178             try{
179                 activateBundleThread(id);
180             }
181             catch(...){
182                 OIC_LOG_V(INFO, CONTAINER_TAG, "Activating bundle: (%s) failed",
183                                      std::string(m_bundles[id]->getID()).c_str());
184             }
185             activationLock.unlock();
186             OIC_LOG_V(INFO, CONTAINER_TAG, "Bundle activated: (%s)",
187                      std::string(m_bundles[id]->getID()).c_str());
188         }
189
190         void ResourceContainerImpl::deactivateBundle(const std::string &id)
191         {
192             if (m_bundles[id]->getJavaBundle())
193             {
194 #if(JAVA_SUPPORT)
195                 deactivateJavaBundle(id);
196 #endif
197             }
198             else
199             {
200                 deactivateSoBundle(id);
201             }
202         }
203
204         // loads the bundle
205         void ResourceContainerImpl::registerBundle(shared_ptr<RCSBundleInfo> bundleInfo)
206         {
207             OIC_LOG_V(INFO, CONTAINER_TAG, "Registering bundle: (%s)",
208                      std::string(bundleInfo->getPath()).c_str());
209             shared_ptr<BundleInfoInternal> bundleInfoInternal =
210                                           std::static_pointer_cast<BundleInfoInternal>(bundleInfo);
211
212             if (has_suffix(bundleInfo->getPath(), ".jar"))
213             {
214 #if(JAVA_SUPPORT)
215                 bundleInfoInternal->setJavaBundle(true);
216                 bundleInfoInternal->setSoBundle(false);
217                 registerJavaBundle(bundleInfo);
218 #else
219                 // android .jar library
220                 bundleInfoInternal->setSoBundle(false);
221                 bundleInfoInternal->setJavaBundle(false);
222                 registerExtBundle(bundleInfo);
223 #endif
224             }
225             else if(has_suffix(bundleInfo->getPath(), ".so"))
226             {
227                 bundleInfoInternal->setSoBundle(true);
228                 bundleInfoInternal->setJavaBundle(false);
229                 registerSoBundle(bundleInfo);
230             }
231             // other cases might be for example .apk for android, which are loaded in the wrapper
232             else{
233                 bundleInfoInternal->setSoBundle(false);
234                 bundleInfoInternal->setJavaBundle(false);
235                 registerExtBundle(bundleInfo);
236             }
237         }
238
239         void ResourceContainerImpl::unregisterBundle(shared_ptr<RCSBundleInfo> bundleInfo)
240         {
241             shared_ptr<BundleInfoInternal> bundleInfoInternal =
242                                           std::static_pointer_cast<BundleInfoInternal>(bundleInfo);
243             if (bundleInfoInternal->isLoaded() && !bundleInfoInternal->isActivated())
244             {
245                 if (bundleInfoInternal->getSoBundle())
246                 {
247                     unregisterBundleSo(bundleInfo->getID());
248                 }
249                 else if(bundleInfoInternal->getJavaBundle())
250                 {
251 #if(JAVA_SUPPORT)
252                     unregisterBundleJava(bundleInfo->getID());
253 #endif
254                 }
255             }
256         }
257
258         void ResourceContainerImpl::unregisterBundleSo(const std::string &id)
259         {
260             void *bundleHandle = m_bundles[id]->getBundleHandle();
261
262             OIC_LOG_V(INFO, CONTAINER_TAG, "Unregister bundle: (%s)",
263                      std::string(m_bundles[id]->getID()).c_str());
264
265             const char *error;
266             dlclose(bundleHandle);
267
268             if ((error = dlerror()) != NULL)
269             {
270                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Error (%s)", error);
271             }
272             else
273             {
274                 m_bundles.erase(id);
275             }
276         }
277
278         int ResourceContainerImpl::registerResource(BundleResource::Ptr resource)
279         {
280             string strUri = resource->m_uri;
281             string strResourceType = resource->m_resourceType;
282             string strInterface = resource->m_interface;
283             RCSResourceObject::Ptr server = nullptr;
284             int ret = EINVAL;
285
286             OIC_LOG_V(INFO, CONTAINER_TAG, "Registration of resource (%s)" ,
287                      std::string(strUri + ", " + strResourceType + "," +
288                              resource->m_bundleId).c_str());
289
290             registrationLock.lock();
291             if (m_mapResources.find(strUri) == m_mapResources.end())
292             {
293                 if (strInterface.empty()) {
294                     strInterface = "oic.if.baseline";
295                 }
296
297                 server = buildResourceObject(strUri, strResourceType, strInterface);
298
299                 if (server != nullptr)
300                 {
301                     m_mapServers[strUri] = server;
302                     m_mapResources[strUri] = resource;
303                     m_mapBundleResources[resource->m_bundleId].push_back(strUri);
304
305                     server->setGetRequestHandler(
306                         std::bind(&ResourceContainerImpl::getRequestHandler, this,
307                                   std::placeholders::_1, std::placeholders::_2));
308
309                     server->setSetRequestHandler(
310                         std::bind(&ResourceContainerImpl::setRequestHandler, this,
311                                   std::placeholders::_1, std::placeholders::_2));
312
313                     OIC_LOG_V(INFO, CONTAINER_TAG, "Registration finished (%s)",
314                             std::string(strUri + ", " +
315                                                           strResourceType).c_str());
316
317                     if (m_config && m_config->isHasInput(resource->m_bundleId))
318                     {
319                         OIC_LOG_V(INFO, CONTAINER_TAG, "Resource has input (%s)",
320                               std::string(strUri + ", " +
321                               strResourceType).c_str());
322                         discoverInputResource(strUri);
323                     }
324                     else{
325                         OIC_LOG_V(INFO, CONTAINER_TAG, "Resource has no input (%s)",
326                                  std::string(strUri + ", " +
327                                  strResourceType).c_str());
328                     }
329                     OIC_LOG_V(INFO, CONTAINER_TAG, "Registration finished (%s)",
330                                                 std::string(strUri + ", " +
331                                                             strResourceType).c_str());
332
333                     // to get notified if bundle resource attributes are updated
334                     resource->registerObserver(this);
335                     ret = 0;
336                 }
337             }
338             else
339             {
340                 OIC_LOG_V(ERROR, CONTAINER_TAG, "resource with (%s)",
341                          std::string(strUri + " already exists.").c_str());
342                 ret = -EEXIST;
343             }
344             registrationLock.unlock();
345
346             return ret;
347         }
348
349         void ResourceContainerImpl::unregisterResource(BundleResource::Ptr resource)
350         {
351             string strUri = resource->m_uri;
352             string strResourceType = resource->m_resourceType;
353
354             OIC_LOG_V(INFO, CONTAINER_TAG, "Unregistration of resource (%s)",
355                      std::string(resource->m_uri + ", " +
356                                  resource->m_resourceType).c_str());
357
358             if (m_config && m_config->isHasInput(resource->m_bundleId))
359             {
360                 OIC_LOG_V(INFO, CONTAINER_TAG, "Calling undiscover (%s)",
361                                      std::string(resource->m_uri + ", " +
362                                                  resource->m_resourceType).c_str());
363                 undiscoverInputResource(strUri);
364             }
365
366             if (m_mapServers.find(strUri) != m_mapServers.end())
367             {
368                 OIC_LOG_V(INFO, CONTAINER_TAG, "Resetting server (%s)",
369                                      std::string(resource->m_uri + ", " +
370                                                  resource->m_resourceType).c_str());
371                 m_mapServers[strUri].reset();
372
373                 m_mapResources.erase(m_mapResources.find(strUri));
374
375                 OIC_LOG_V(INFO, CONTAINER_TAG, "Remove bundle resource (%s)",
376                                      std::string(resource->m_uri + ", " +
377                                                  resource->m_resourceType).c_str());
378                 m_mapBundleResources[resource->m_bundleId].remove(strUri);
379             }
380         }
381
382         void ResourceContainerImpl::getBundleConfiguration(const std::string &bundleId,
383                 configInfo *configOutput)
384         {
385             if (m_config)
386             {
387                 m_config->getBundleConfiguration(bundleId, (configInfo *) configOutput);
388             }
389         }
390
391         void ResourceContainerImpl::getResourceConfiguration(const std::string &bundleId,
392                 std::vector< resourceInfo > *configOutput)
393         {
394             if (m_config)
395             {
396                 m_config->getResourceConfiguration(bundleId, configOutput);
397             }
398             else{
399                 OIC_LOG_V(DEBUG, CONTAINER_TAG, "no config present ");
400             }
401         }
402
403         RCSGetResponse ResourceContainerImpl::getRequestHandler(const RCSRequest &request,
404                 const RCSResourceAttributes &)
405         {
406             RCSResourceAttributes attr;
407             std::string strResourceUri = request.getResourceUri();
408             const std::map< std::string, std::string > &queryParams  = request.getQueryParams();
409
410             OIC_LOG_V(INFO, CONTAINER_TAG, "Container get request for %s",strResourceUri.c_str());
411
412             if (m_mapServers.find(strResourceUri) != m_mapServers.end()
413                 && m_mapResources.find(strResourceUri) != m_mapResources.end())
414             {
415                 if (m_mapResources[strResourceUri])
416                 {
417                     auto getFunction = [this, &attr, &strResourceUri, queryParams]()
418                     {
419                         attr = m_mapResources[strResourceUri]->handleGetAttributesRequest(queryParams);
420                     };
421                     boost::thread getThread(getFunction);
422                     getThread.timed_join(boost::posix_time::seconds(BUNDLE_SET_GET_WAIT_SEC));
423
424                 }
425             }
426             OIC_LOG_V(INFO, CONTAINER_TAG, "Container get request for %s finished, %zu attributes",strResourceUri.c_str(), attr.size());
427
428             return RCSGetResponse::create(std::move(attr), 200);
429         }
430
431         RCSSetResponse ResourceContainerImpl::setRequestHandler(const RCSRequest &request,
432                 const RCSResourceAttributes &attributes)
433         {
434             RCSResourceAttributes attr;
435             std::list<std::string> lstAttributes;
436             std::string strResourceUri = request.getResourceUri();
437             const std::map< std::string, std::string > &queryParams  = request.getQueryParams();
438
439             OIC_LOG_V(INFO, CONTAINER_TAG, "Container set request for %s, %zu attributes",strResourceUri.c_str(), attributes.size());
440
441             if (m_mapServers.find(strResourceUri) != m_mapServers.end()
442                 && m_mapResources.find(strResourceUri) != m_mapResources.end())
443             {
444                 if (m_mapResources[strResourceUri])
445                 {
446                     auto setFunction = [this, &lstAttributes, &strResourceUri, &attributes, &attr, queryParams]()
447                     {
448                         lstAttributes = m_mapResources[strResourceUri]->getAttributeNames();
449
450                         for (RCSResourceAttributes::const_iterator itor = attributes.begin();
451                              itor != attributes.end(); itor++)
452                         {
453                             if (std::find(lstAttributes.begin(), lstAttributes.end(), itor->key())
454                                 != lstAttributes.end())
455                             {
456                                 attr[itor->key()] = itor->value();
457                             }
458                         }
459
460                         OIC_LOG_V(INFO, CONTAINER_TAG, "Calling handleSetAttributeRequest");
461                         m_mapResources[strResourceUri]->handleSetAttributesRequest(attr, queryParams);
462                     };
463                     boost::thread setThread(setFunction);
464                     setThread.timed_join(boost::posix_time::seconds(BUNDLE_SET_GET_WAIT_SEC));
465                 }
466             }
467
468             return RCSSetResponse::create(std::move(attr), 200);
469         }
470
471         void ResourceContainerImpl::onNotificationReceived(const std::string &strResourceUri)
472         {
473             OIC_LOG_V(INFO, CONTAINER_TAG,
474                      "notification from (%s)", std::string(strResourceUri + ".").c_str());
475
476             if (m_mapServers.find(strResourceUri) != m_mapServers.end())
477             {
478                 m_mapServers[strResourceUri]->notify();
479             }
480         }
481
482         ResourceContainerImpl *ResourceContainerImpl::getImplInstance()
483         {
484             static ResourceContainerImpl m_instance;
485             return &m_instance;
486         }
487
488         RCSResourceObject::Ptr ResourceContainerImpl::buildResourceObject(const std::string &strUri,
489                 const std::string &strResourceType, const std::string &strInterface)
490         {
491             return RCSResourceObject::Builder(strUri, strResourceType,
492                                               strInterface).setObservable(
493                        true).setDiscoverable(true).build();
494         }
495
496         void ResourceContainerImpl::startBundle(const std::string &bundleId)
497         {
498             OIC_LOG_V(INFO, CONTAINER_TAG, "startBundle %s",bundleId.c_str());
499             if (m_bundles.find(bundleId) != m_bundles.end())
500             {
501                 if (!m_bundles[bundleId]->isActivated())
502                     activateBundle(m_bundles[bundleId]);
503                 else
504                 {
505                     OIC_LOG(ERROR, CONTAINER_TAG, "Bundle already started");
506                 }
507             }
508             else
509             {
510                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Bundle with ID \'(%s)",
511                          std::string(bundleId + "\' is not registered.").c_str());
512             }
513         }
514
515         void ResourceContainerImpl::stopBundle(const std::string &bundleId)
516         {
517             OIC_LOG_V(INFO, CONTAINER_TAG, "stopBundle %s",bundleId.c_str());
518             if (m_bundles.find(bundleId) != m_bundles.end())
519             {
520                 if (m_bundles[bundleId]->isActivated())
521                     deactivateBundle(m_bundles[bundleId]);
522                 else
523                 {
524                     OIC_LOG(ERROR, CONTAINER_TAG, "Bundle not activated");
525                 }
526             }
527             else
528             {
529                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Bundle with ID \'(%s)",
530                          std::string(bundleId + "\' is not registered.").c_str());
531             }
532         }
533
534         void ResourceContainerImpl::addBundle(const std::string &bundleId,
535                                               const std::string &bundleUri,
536                                               const std::string &bundlePath,
537                                               const std::string &activator,
538                                               std::map< string, string > params)
539         {
540             (void) bundleUri;
541
542             if (m_bundles.find(bundleId) != m_bundles.end())
543                 OIC_LOG(ERROR, CONTAINER_TAG, "BundleId already exist");
544
545             else
546             {
547                 shared_ptr<BundleInfoInternal> bundleInfo = std::make_shared<BundleInfoInternal>();
548                 bundleInfo->setID(bundleId);
549                 bundleInfo->setPath(bundlePath);
550                 bundleInfo->setActivatorName(activator);
551                 if (params.find("libraryPath") != params.end())
552                 {
553                     string activatorName = activator; // modify activator for Java bundle
554                     std::replace(activatorName.begin(), activatorName.end(), '.', '/');
555                     bundleInfo->setActivatorName(activatorName);
556                     bundleInfo->setLibraryPath(params[BUNDLE_LIBRARY_PATH]);
557                 }
558
559                 OIC_LOG_V(INFO, CONTAINER_TAG, "Add Bundle: (%s)",
560                          std::string(bundleInfo->getID() + "; " +
561                                      bundleInfo->getPath()).c_str());
562
563                 registerBundle(bundleInfo);
564             }
565         }
566
567         void ResourceContainerImpl::removeBundle(const std::string &bundleId)
568         {
569             OIC_LOG_V(INFO, CONTAINER_TAG, "removeBundle %s",bundleId.c_str());
570             if (m_bundles.find(bundleId) != m_bundles.end())
571             {
572                 shared_ptr<BundleInfoInternal> bundleInfo = m_bundles[bundleId];
573                 if (bundleInfo->isActivated())
574                     deactivateBundle(bundleInfo);
575
576                 if (bundleInfo->isLoaded())
577                     unregisterBundle(bundleInfo);
578             }
579             else
580             {
581                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Bundle with ID \'(%s)",
582                          std::string(bundleId + "\' is not ced.").c_str());
583             }
584         }
585
586         std::list<std::unique_ptr<RCSBundleInfo>> ResourceContainerImpl::listBundles()
587         {
588             OIC_LOG_V(INFO, CONTAINER_TAG,
589                                  "list bundles (%d)", m_bundles.size());
590             std::list<std::unique_ptr<RCSBundleInfo> > ret;
591             for (std::map< std::string, shared_ptr<BundleInfoInternal> >::iterator it = m_bundles.begin();
592                  it != m_bundles.end(); ++it)
593             {
594                 {
595                     std::unique_ptr<BundleInfoInternal> bundleInfo(new BundleInfoInternal);
596                     bundleInfo->setBundleInfo(it->second);
597                     ret.push_back(std::move(bundleInfo));
598                 }
599             }
600             return ret;
601         }
602
603         void ResourceContainerImpl::addResourceConfig(const std::string &bundleId,
604                 const std::string &resourceUri, std::map< string, string > params)
605         {
606             if (m_bundles.find(bundleId) != m_bundles.end())
607             {
608                 if (!m_bundles[bundleId]->getJavaBundle())
609                 {
610                     resourceInfo newResourceInfo;
611                     newResourceInfo.uri = resourceUri;
612
613                     if (params.find(OUTPUT_RESOURCE_NAME) != params.end())
614                         newResourceInfo.name = params[OUTPUT_RESOURCE_NAME];
615                     if (params.find(OUTPUT_RESOURCE_TYPE) != params.end())
616                         newResourceInfo.resourceType = params[OUTPUT_RESOURCE_TYPE];
617                     if (params.find(OUTPUT_RESOURCE_ADDR) != params.end())
618                         newResourceInfo.address = params[OUTPUT_RESOURCE_ADDR];
619
620                     addSoBundleResource(bundleId, newResourceInfo);
621                 }
622             }
623             else
624             {
625                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Bundle with ID \'(%s)",
626                          std::string(bundleId + "\' is not registered.").c_str());
627             }
628         }
629
630         void ResourceContainerImpl::removeResourceConfig(const std::string &bundleId,
631                 const std::string &resourceUri)
632         {
633             OIC_LOG_V(INFO, CONTAINER_TAG, "removeResourceConfig %s, %s",bundleId.c_str(),
634                     resourceUri.c_str());
635             if (m_bundles.find(bundleId) != m_bundles.end())
636             {
637                 if (m_bundles[bundleId]->getSoBundle())
638                 {
639                     removeSoBundleResource(bundleId, resourceUri);
640                 }
641             }
642             else
643             {
644                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Bundle with ID \'(%s)",
645                          std::string(bundleId + "\' is not registered.").c_str());
646             }
647         }
648
649         std::list< string > ResourceContainerImpl::listBundleResources(const std::string &bundleId)
650         {
651             OIC_LOG_V(INFO, CONTAINER_TAG, "listBundleResources %s",bundleId.c_str());
652             std::list < string > ret;
653
654             if (m_mapBundleResources.find(bundleId) != m_mapBundleResources.end())
655             {
656                 ret = m_mapBundleResources[bundleId];
657             }
658
659             return ret;
660
661         }
662
663         void ResourceContainerImpl::registerSoBundle(shared_ptr<RCSBundleInfo> bundleInfo)
664         {
665             OIC_LOG_V(DEBUG, CONTAINER_TAG, "Register SO bundle");
666             const char *error;
667
668             activator_t *bundleActivator = NULL;
669             deactivator_t *bundleDeactivator = NULL;
670             resourceCreator_t *resourceCreator = NULL;
671             resourceDestroyer_t *resourceDestroyer = NULL;
672             shared_ptr<BundleInfoInternal> bundleInfoInternal =
673                                 std::static_pointer_cast<BundleInfoInternal>(bundleInfo);
674
675             void *bundleHandle = NULL;
676             bundleHandle = dlopen(bundleInfo->getPath().c_str(), RTLD_LAZY);
677             if ((error = dlerror()) != NULL)
678             {
679               OIC_LOG_V(ERROR, CONTAINER_TAG, "Error while loading .so bundle: (%s)", error);
680             }
681
682             if (bundleHandle != NULL)
683             {
684                 OIC_LOG_V(DEBUG, CONTAINER_TAG, "Activator name %s",
685                         bundleInfoInternal->getActivatorName().c_str());
686                 bundleActivator =
687                     (activator_t *) dlsym(bundleHandle,
688                                           ("" + bundleInfoInternal->getActivatorName()
689                                            + "_externalActivateBundle").c_str());
690                 if ((error = dlerror()) != NULL)
691                 {
692                   OIC_LOG_V(ERROR, CONTAINER_TAG, "Error while loading .so bundle: (%s)", error);
693                 }
694                 else{
695                   OIC_LOG_V(DEBUG, CONTAINER_TAG, "Looked up %s", ("" +
696                           bundleInfoInternal->getActivatorName()
697                           + "_externalActivateBundle").c_str());
698                 }
699                 bundleDeactivator =
700                     (deactivator_t *) dlsym(bundleHandle,
701                                             ("" + bundleInfoInternal->getActivatorName()
702                                              + "_externalDeactivateBundle").c_str());
703                 if ((error = dlerror()) != NULL)
704                 {
705                   OIC_LOG_V(ERROR, CONTAINER_TAG, "Error while loading .so bundle: (%s)", error);
706                 }
707                 else{
708                   OIC_LOG_V(DEBUG, CONTAINER_TAG, "Looked up %s", ("" +
709                           bundleInfoInternal->getActivatorName()
710                           + "_externalDeactivateBundle").c_str());
711                 }
712                 resourceCreator =
713                     (resourceCreator_t *) dlsym(bundleHandle,
714                                                 ("" + bundleInfoInternal->getActivatorName()
715                                                  + "_externalCreateResource").c_str());
716                 if ((error = dlerror()) != NULL)
717                 {
718                   OIC_LOG_V(ERROR, CONTAINER_TAG, "Error while loading .so bundle: (%s)", error);
719                 }
720                 else{
721                   OIC_LOG_V(DEBUG, CONTAINER_TAG, "Looked up %s", ("" +
722                           bundleInfoInternal->getActivatorName()
723                           + "_externalCreateResource").c_str());
724                 }
725                 resourceDestroyer =
726                     (resourceDestroyer_t *) dlsym(bundleHandle,
727                                                   ("" + bundleInfoInternal->getActivatorName()
728                                                    + "_externalDestroyResource").c_str());
729                 if ((error = dlerror()) != NULL)
730                 {
731                   OIC_LOG_V(ERROR, CONTAINER_TAG, "Error while loading .so bundle: (%s)", error);
732                 }
733                 else{
734                   OIC_LOG_V(DEBUG, CONTAINER_TAG, "Looked up %s", ("" +
735                           bundleInfoInternal->getActivatorName()
736                           + "_externalDestroyResource").c_str());
737                 }
738
739
740                 if ((error = dlerror()) != NULL)
741                 {
742                     OIC_LOG_V(ERROR, CONTAINER_TAG, "Error : (%s)", error);
743                 }
744                 else
745                 {
746                     bundleInfoInternal->setBundleActivator(bundleActivator);
747                     bundleInfoInternal->setBundleDeactivator(bundleDeactivator);
748                     bundleInfoInternal->setResourceCreator(resourceCreator);
749                     bundleInfoInternal->setResourceDestroyer(resourceDestroyer);
750                     bundleInfoInternal->setLoaded(true);
751                     bundleInfoInternal->setBundleHandle(bundleHandle);
752
753                     m_bundles[bundleInfo->getID()] = bundleInfoInternal;
754                 }
755             }
756             else
757             {
758                 if ((error = dlerror()) != NULL)
759                 {
760                     OIC_LOG_V(ERROR, CONTAINER_TAG, "Error : (%s)", error);
761                 }
762             }
763             OIC_LOG_V(DEBUG, CONTAINER_TAG, "Register SO bundle finished");
764         }
765
766         void ResourceContainerImpl::registerExtBundle(shared_ptr<RCSBundleInfo> bundleInfo){
767             OIC_LOG_V(INFO, CONTAINER_TAG, "Registering ext bundle (%s)",
768                                  std::string(bundleInfo->getID()).c_str());
769             OIC_LOG_V(INFO, CONTAINER_TAG, "Activator name (%s)",
770                                              std::string(bundleInfo->getActivatorName()).c_str());
771
772             shared_ptr<BundleInfoInternal> bundleInfoInternal =
773                                 std::static_pointer_cast<BundleInfoInternal>(bundleInfo);
774
775             m_bundles[bundleInfo->getID()] = bundleInfoInternal;
776             // in this case at least the resource configuration needs to be loaded
777             // in order to mark potential input resources for soft sensors
778             std::vector< resourceInfo > temp;
779             OIC_LOG_V(INFO, CONTAINER_TAG, "Loading resource config(%s)",
780                                                          std::string(bundleInfo->getID()).c_str());
781             getResourceConfiguration(bundleInfo->getID(),
782                             &temp);
783
784             OIC_LOG(INFO, CONTAINER_TAG, "Bundle registered");
785         }
786
787         void ResourceContainerImpl::activateSoBundle(const std::string &bundleId)
788         {
789             activator_t *bundleActivator = m_bundles[bundleId]->getBundleActivator();
790
791             if (bundleActivator != NULL)
792             {
793                 bundleActivator(this, m_bundles[bundleId]->getID());
794                 m_bundles[bundleId]->setActivated(true);
795             }
796             else
797             {
798                 //Unload module and return error
799                 OIC_LOG(ERROR, CONTAINER_TAG, "Activation unsuccessful.");
800             }
801
802             shared_ptr<BundleInfoInternal> bundleInfoInternal = m_bundles[bundleId];
803             bundleInfoInternal->setActivated(true);
804
805         }
806
807         void ResourceContainerImpl::undiscoverInputResource(const std::string &outputResourceUri)
808         {
809             auto foundDiscoverResource = m_mapDiscoverResourceUnits.find(outputResourceUri);
810             if (foundDiscoverResource != m_mapDiscoverResourceUnits.end())
811             {
812                 OIC_LOG(DEBUG, CONTAINER_TAG, "Erase discover resource.");
813                 m_mapDiscoverResourceUnits.erase(foundDiscoverResource);
814                 OIC_LOG(DEBUG, CONTAINER_TAG, "Erase discover resource done.");
815             }
816         }
817
818         void ResourceContainerImpl::discoverInputResource(const std::string &outputResourceUri)
819         {
820             OIC_LOG_V(DEBUG, CONTAINER_TAG, "Discover input resource %s", outputResourceUri.c_str());
821             auto foundOutputResource = m_mapResources.find(outputResourceUri);
822
823             resourceInfo info;
824             m_config->getResourceConfiguration(foundOutputResource->second->m_bundleId,
825                 outputResourceUri, &info);
826             map< string, vector< map< string, string > > > resourceProperty = info.resourceProperty;
827
828             try
829             {
830                 resourceProperty.at(INPUT_RESOURCE);
831             }
832             catch (std::out_of_range &e)
833             {
834                 OIC_LOG_V(DEBUG, CONTAINER_TAG, "No input resource %s", outputResourceUri.c_str());
835                 return;
836             }
837
838             for (auto iter : resourceProperty)
839             {
840                 if (iter.first.compare(INPUT_RESOURCE) == 0)
841                 {
842                     for (auto it : iter.second)
843                     {
844                         auto makeValue = [&](const std::string & reference) mutable -> std::string
845                         {
846                             std::string retStr = "";
847                             try
848                             {
849                                 retStr = it.at(reference);
850                             }
851                             catch (std::out_of_range &e)
852                             {
853                                 return "";
854                             }
855                             return retStr;
856                         };
857                         std::string uri = makeValue(INPUT_RESOURCE_URI);
858                         std::string type = makeValue(INPUT_RESOURCE_TYPE);
859                         std::string attributeName = makeValue(INPUT_RESOURCE_ATTRIBUTENAME);
860
861
862                         OIC_LOG_V(DEBUG, CONTAINER_TAG, "Start discovery: %s, %s, %s", uri.c_str(),
863                                 type.c_str(), attributeName.c_str());
864                         DiscoverResourceUnit::Ptr newDiscoverUnit = std::make_shared
865                                 < DiscoverResourceUnit > (outputResourceUri);
866                         newDiscoverUnit->startDiscover(
867                             DiscoverResourceUnit::DiscoverResourceInfo(uri, type,
868                                     attributeName),
869                             std::bind(&SoftSensorResource::onUpdatedInputResource,
870                                       std::static_pointer_cast< SoftSensorResource >
871                         (foundOutputResource->second),
872                                       std::placeholders::_1, std::placeholders::_2));
873
874                         auto foundDiscoverResource = m_mapDiscoverResourceUnits.find(
875                                                          outputResourceUri);
876                         if (foundDiscoverResource != m_mapDiscoverResourceUnits.end())
877                         {
878                             foundDiscoverResource->second.push_back(newDiscoverUnit);
879                         }
880                         else
881                         {
882                             m_mapDiscoverResourceUnits.insert(
883                                 std::make_pair(outputResourceUri,
884                                                std::list< DiscoverResourceUnit::Ptr >
885                             { newDiscoverUnit }));
886                         }
887                     }
888                 }
889             }
890         }
891
892         void ResourceContainerImpl::deactivateSoBundle(const std::string &id)
893         {
894             deactivator_t *bundleDeactivator = m_bundles[id]->getBundleDeactivator();
895
896             OIC_LOG_V(INFO, CONTAINER_TAG, "De-activating bundle: (%s)", std::string(
897                          m_bundles[id]->getID()).c_str());
898
899             if (bundleDeactivator != NULL)
900             {
901                 bundleDeactivator();
902                 m_bundles[id]->setActivated(false);
903             }
904             else
905             {
906                 //Unload module and return error
907                 OIC_LOG(ERROR, CONTAINER_TAG, "De-activation unsuccessful.");
908             }
909         }
910
911         void ResourceContainerImpl::addSoBundleResource(const std::string &bundleId,
912                 resourceInfo newResourceInfo)
913         {
914             resourceCreator_t *resourceCreator;
915
916             resourceCreator = m_bundles[bundleId]->getResourceCreator();
917
918             if (resourceCreator != NULL)
919             {
920                 resourceCreator(newResourceInfo);
921             }
922             else
923             {
924                 OIC_LOG(ERROR, CONTAINER_TAG, "addResource unsuccessful.");
925             }
926         }
927
928         void ResourceContainerImpl::removeSoBundleResource(const std::string &bundleId,
929                 const std::string &resourceUri)
930         {
931             if (m_mapResources.find(resourceUri) != m_mapResources.end())
932             {
933                 resourceDestroyer_t *resourceDestroyer =
934                     m_bundles[bundleId]->getResourceDestroyer();
935
936                 if (resourceDestroyer != NULL)
937                 {
938                     resourceDestroyer(m_mapResources[resourceUri]);
939                 }
940                 else
941                 {
942                     OIC_LOG(ERROR, CONTAINER_TAG, "removeResource unsuccessful.");
943                 }
944             }
945         }
946
947         void ResourceContainerImpl::activateBundleThread(const std::string &id)
948         {
949             OIC_LOG_V(INFO, CONTAINER_TAG, "Activating bundle: (%s)",
950                      std::string(m_bundles[id]->getID()).c_str());
951
952             if (m_bundles[id]->getJavaBundle())
953             {
954 #if(JAVA_SUPPORT)
955                 activateJavaBundle(id);
956 #endif
957             }
958             else if(m_bundles[id]->getSoBundle())
959             {
960                 activateSoBundle (id);
961             }
962
963             OIC_LOG_V(INFO, CONTAINER_TAG, "Bundle activated: (%s)",
964                      std::string(m_bundles[id]->getID()).c_str());
965         }
966
967 #if(JAVA_SUPPORT)
968         JavaVM *ResourceContainerImpl::getJavaVM(string bundleId)
969         {
970             return m_bundleVM[bundleId];
971         }
972
973         void ResourceContainerImpl::registerJavaBundle(shared_ptr<RCSBundleInfo> bundleInfo)
974         {
975             OIC_LOG_V(INFO, CONTAINER_TAG, "Registering Java bundle (%s)",
976                      std::string(bundleInfo->getID()).c_str());
977             JavaVM *jvm;
978             JNIEnv *env;
979             JavaVMInitArgs vm_args;
980             JavaVMOption options[3];
981
982             shared_ptr<BundleInfoInternal> bundleInfoInternal =
983                                 std::static_pointer_cast<BundleInfoInternal>(bundleInfo);
984
985
986             if (FILE *file = fopen(bundleInfo->getPath().c_str(), "r"))
987             {
988                 fclose(file);
989
990                 OIC_LOG_V(INFO, CONTAINER_TAG, "Resource bundle (%s)",
991                          std::string(bundleInfo->getPath() +
992                                      " available.").c_str());
993             }
994             else
995             {
996                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Resource bundle (%s)",
997                          std::string(bundleInfo->getPath() + " not available.").c_str());
998
999                 return;
1000             }
1001
1002             char optionString[] = "-Djava.compiler=NONE";
1003             options[0].optionString = optionString;
1004             char classpath[1000];
1005             strcpy(classpath, "-Djava.class.path=");
1006             strncat(classpath, bundleInfo->getPath().c_str(), BUNDLE_PATH_MAXLEN);
1007
1008             OIC_LOG(INFO, CONTAINER_TAG,
1009                    std::string("Configured classpath: ").append(classpath).c_str());
1010
1011             options[1].optionString = classpath;
1012
1013             char libraryPath[1000];
1014             strcpy(libraryPath, "-Djava.library.path=");
1015             strncat(libraryPath, bundleInfo->getLibraryPath().c_str(), BUNDLE_PATH_MAXLEN);
1016             options[2].optionString = libraryPath;
1017
1018             OIC_LOG(INFO, CONTAINER_TAG,
1019                    std::string("Configured library path: ").append(libraryPath).c_str());
1020
1021             vm_args.version = JNI_VERSION_1_4;
1022             vm_args.options = options;
1023             vm_args.nOptions = 3;
1024             vm_args.ignoreUnrecognized = 1;
1025
1026             int res;
1027             res = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);
1028
1029             if (res < 0)
1030             {
1031                 OIC_LOG(ERROR, CONTAINER_TAG, "cannot create JavaVM.");
1032                 return;
1033             }
1034             else
1035             {
1036                 OIC_LOG(INFO, CONTAINER_TAG, "JVM successfully created.");
1037             }
1038
1039             m_bundleVM.insert(std::pair< string, JavaVM * >(bundleInfo->getID(), jvm));
1040
1041             const char *className = bundleInfoInternal->getActivatorName().c_str();
1042
1043             OIC_LOG_V(INFO, CONTAINER_TAG, "Looking up class: (%s)", std::string(
1044                          bundleInfoInternal->getActivatorName() + "|").c_str());
1045
1046             jclass bundleActivatorClass = env->FindClass(className);
1047
1048             if (bundleActivatorClass == NULL)
1049             {
1050                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Cannot register bundle (%s)",
1051                          std::string( bundleInfoInternal->getID()
1052                                       + " bundle activator(" +
1053                                       bundleInfoInternal->getActivatorName()
1054                                       + ") not found ").c_str());
1055                 return;
1056             }
1057
1058             jmethodID activateMethod = env->GetMethodID(bundleActivatorClass, "activateBundle",
1059                                        "()V");
1060
1061             if (activateMethod == NULL)
1062             {
1063                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Cannot register bundle (%s)",
1064                          std::string( bundleInfoInternal->getID()
1065                                       + " activate bundle method not found ").c_str());
1066                 return;
1067             }
1068             bundleInfoInternal->setJavaBundleActivatorMethod(activateMethod);
1069
1070             jmethodID deactivateMethod = env->GetMethodID(bundleActivatorClass, "deactivateBundle",
1071                                          "()V");
1072
1073             if (deactivateMethod == NULL)
1074             {
1075                 OIC_LOG_V(ERROR, CONTAINER_TAG, "Cannot register bundle (%s)",
1076                          std::string( bundleInfoInternal->getID()
1077                                       + " deactivate bundle method not found ").c_str());
1078                 return;
1079             }
1080
1081             bundleInfoInternal->setJavaBundleDeactivatorMethod(deactivateMethod);
1082
1083             jmethodID constructor;
1084
1085             constructor = env->GetMethodID(bundleActivatorClass, "<init>", "(Ljava/lang/String;)V");
1086
1087             jstring bundleID = env->NewStringUTF(bundleInfoInternal->getID().c_str());
1088
1089             jobject bundleActivator = env->NewObject(bundleActivatorClass, constructor, bundleID);
1090
1091             bundleInfoInternal->setJavaBundleActivatorObject(bundleActivator);
1092
1093             bundleInfoInternal->setLoaded(true);
1094
1095             m_bundles[bundleInfo->getID()] = bundleInfoInternal;
1096
1097
1098             OIC_LOG(INFO, CONTAINER_TAG, "Bundle registered");
1099         }
1100
1101
1102
1103         void ResourceContainerImpl::activateJavaBundle(string bundleId)
1104         {
1105             OIC_LOG(INFO, CONTAINER_TAG, "Activating java bundle");
1106
1107             JavaVM *vm = getJavaVM(bundleId);
1108             bundleInfoInternal = m_bundles[bundleId];
1109             JNIEnv *env;
1110             int envStat = vm->GetEnv((void **) &env, JNI_VERSION_1_4);
1111
1112             if (envStat == JNI_EDETACHED)
1113             {
1114                 if (vm->AttachCurrentThread((void **) &env, NULL) != 0)
1115                 {
1116                     OIC_LOG(ERROR, CONTAINER_TAG, "Failed to attach ");
1117                 }
1118             }
1119             else if (envStat == JNI_EVERSION)
1120             {
1121                 OIC_LOG(ERROR, CONTAINER_TAG, "Env: version not supported ");
1122             }
1123
1124             env->CallVoidMethod(bundleInfoInternal->getJavaBundleActivatorObject(),
1125                                 bundleInfoInternal->getJavaBundleActivatorMethod());
1126
1127             m_bundles[bundleId]->setActivated(true);
1128         }
1129
1130         void ResourceContainerImpl::deactivateJavaBundle(string bundleId)
1131         {
1132             OIC_LOG(INFO, CONTAINER_TAG, "Deactivating java bundle");
1133
1134             JavaVM *vm = getJavaVM(bundleId);
1135             shared_ptr<BundleInfoInternal>bundleInfoInternal = m_bundles[bundleId];
1136             JNIEnv *env;
1137             int envStat = vm->GetEnv((void **) &env, JNI_VERSION_1_4);
1138
1139             if (envStat == JNI_EDETACHED)
1140             {
1141                 if (vm->AttachCurrentThread((void **) &env, NULL) != 0)
1142                 {
1143                     OIC_LOG(ERROR, CONTAINER_TAG, "Failed to attach ");
1144                 }
1145             }
1146             else if (envStat == JNI_EVERSION)
1147             {
1148                 OIC_LOG(ERROR, CONTAINER_TAG, "Env: version not supported ");
1149             }
1150
1151             env->CallVoidMethod(bundleInfoInternal->getJavaBundleActivatorObject(),
1152                                 bundleInfoInternal->getJavaBundleDeactivatorMethod());
1153
1154             m_bundles[bundleId]->setActivated(false);
1155         }
1156
1157         void ResourceContainerImpl::unregisterBundleJava(string id)
1158         {
1159             OIC_LOG_V(INFO, CONTAINER_TAG, "Unregister Java bundle: (%s)", std::string(
1160                          m_bundles[id]->getID()).c_str());
1161
1162             OIC_LOG(INFO, CONTAINER_TAG, "Destroying JVM");
1163
1164             m_bundleVM[id]->DestroyJavaVM();
1165
1166             m_bundles.erase(id);
1167         }
1168 #endif
1169     }
1170 }