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