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