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