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