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