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