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