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