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