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