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