1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
30 #include "ResourceContainerImpl.h"
31 #include "BundleActivator.h"
32 #include "RCSResourceContainer.h"
33 #include "BundleInfoInternal.h"
35 #include "oc_logger.hpp"
37 using OC::oc_log_stream;
38 using namespace OIC::Service;
40 auto error_logger = []() -> boost::iostreams::stream<OC::oc_log_stream> &
42 static OC::oc_log_stream ols(oc_make_ostream_logger);
43 static boost::iostreams::stream<OC::oc_log_stream> os(ols);
44 os->set_level(OC_LOG_ERROR);
45 os->set_module("ResourceContainerImpl");
49 auto info_logger = []() -> boost::iostreams::stream<OC::oc_log_stream> &
51 static OC::oc_log_stream ols(oc_make_ostream_logger);
52 static boost::iostreams::stream<OC::oc_log_stream> os(ols);
53 os->set_level(OC_LOG_INFO);
54 os->set_module("ResourceContainerImpl");
59 using namespace OIC::Service;
66 ResourceContainerImpl::ResourceContainerImpl()
71 ResourceContainerImpl::~ResourceContainerImpl()
76 bool has_suffix(const std::string &str, const std::string &suffix)
78 return str.size() >= suffix.size()
79 && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
82 void ResourceContainerImpl::startContainer(const std::string &configFile)
84 info_logger() << "Starting resource container " << endl;
86 info_logger() << "Resource container has Java support" << endl;
88 info_logger() << "Resource container without Java support" << endl;
91 if(!configFile.empty()){
92 m_config = new Configuration(configFile);
94 if (m_config->isLoaded())
97 m_config->getConfiguredBundles(&bundles);
99 for (unsigned int i = 0; i < bundles.size(); i++)
101 RCSBundleInfo *bundleInfo = RCSBundleInfo::build();
102 bundleInfo->setPath(bundles[i]["path"]);
103 bundleInfo->setVersion(bundles[i]["version"]);
104 bundleInfo->setID(bundles[i]["id"]);
105 if (!bundles[i]["activator"].empty())
107 string activatorName = bundles[i]["activator"];
108 std::replace(activatorName.begin(), activatorName.end(), '.', '/');
109 ((BundleInfoInternal *) bundleInfo)->setActivatorName(activatorName);
110 ((BundleInfoInternal *) bundleInfo)->setLibraryPath(
111 bundles[i]["libraryPath"]);
114 info_logger() << "Init Bundle:" << bundles[i]["id"] << ";" << bundles[i]["path"]
116 registerBundle(bundleInfo);
117 activateBundle(bundleInfo);
122 error_logger() << "Container started with invalid configfile path" << endl;
126 info_logger() << "No configuration file for the container provided" << endl;
130 void ResourceContainerImpl::stopContainer()
132 info_logger() << "Stopping resource container.";
133 for (std::map< std::string, BundleInfoInternal * >::iterator it = m_bundles.begin();
134 it != m_bundles.end(); ++it)
136 BundleInfoInternal *bundleInfo = it->second;
137 deactivateBundle(bundleInfo);
138 unregisterBundle(bundleInfo);
141 if (!m_mapServers.empty())
143 map< std::string, RCSResourceObject::Ptr >::iterator itor = m_mapServers.begin();
145 while (itor != m_mapServers.end())
147 (itor++)->second.reset();
150 m_mapResources.clear();
151 m_mapBundleResources.clear();
157 void ResourceContainerImpl::activateBundle(RCSBundleInfo *bundleInfo)
159 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) bundleInfo;
161 if (bundleInfoInternal->isLoaded())
163 activateBundle(bundleInfo->getID());
167 void ResourceContainerImpl::deactivateBundle(RCSBundleInfo *bundleInfo)
169 if (((BundleInfoInternal *) bundleInfo)->isActivated())
171 deactivateBundle(bundleInfo->getID());
175 void ResourceContainerImpl::activateBundle(const std::string &id)
178 info_logger() << "Activating bundle: " << m_bundles[id]->getID() << endl;
180 if (m_bundles[id]->getJavaBundle())
183 activateJavaBundle(id);
188 activateSoBundle(id);
191 info_logger() << "Bundle activated: " << m_bundles[id]->getID() << endl;
195 void ResourceContainerImpl::deactivateBundle(const std::string &id)
198 if (m_bundles[id]->getJavaBundle())
201 deactivateJavaBundle(id);
206 deactivateSoBundle(id);
211 void ResourceContainerImpl::registerBundle(RCSBundleInfo *bundleInfo)
213 info_logger() << "Registering bundle: " << bundleInfo->getPath() << endl;
215 if (has_suffix(bundleInfo->getPath(), ".jar"))
218 ((BundleInfoInternal *) bundleInfo)->setJavaBundle(true);
219 registerJavaBundle(bundleInfo);
224 ((BundleInfoInternal *) bundleInfo)->setJavaBundle(false);
225 registerSoBundle(bundleInfo);
229 void ResourceContainerImpl::unregisterBundle(RCSBundleInfo *bundleInfo)
231 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) bundleInfo;
232 if (bundleInfoInternal->isLoaded() && !bundleInfoInternal->isActivated())
234 if (!bundleInfoInternal->getJavaBundle())
236 unregisterBundleSo(bundleInfo->getID());
241 unregisterBundleJava(bundleInfo->getID());
247 void ResourceContainerImpl::unregisterBundleSo(const std::string &id)
249 void *bundleHandle = m_bundles[id]->getBundleHandle();
250 info_logger() << "Unregister bundle: " << m_bundles[id]->getID() << ", "
251 << m_bundles[id]->getID() << endl;
253 dlclose(bundleHandle);
254 if ((error = dlerror()) != NULL)
256 error_logger() << error << endl;
260 delete m_bundles[id];
265 void ResourceContainerImpl::registerResource(BundleResource *resource)
267 string strUri = resource->m_uri;
268 string strResourceType = resource->m_resourceType;
269 RCSResourceObject::Ptr server = nullptr;
271 info_logger() << "Registration of resource " << strUri << "," << strResourceType << endl;
273 if (m_mapResources.find(strUri) == m_mapResources.end())
275 server = buildResourceObject(strUri, strResourceType);
277 if (server != nullptr)
279 m_mapServers[strUri] = server;
280 m_mapResources[strUri] = resource;
281 m_mapBundleResources[resource->m_bundleId].push_back(strUri);
283 resource->registerObserver(this);
285 server->setGetRequestHandler(
286 std::bind(&ResourceContainerImpl::getRequestHandler, this,
287 std::placeholders::_1, std::placeholders::_2));
289 server->setSetRequestHandler(
290 std::bind(&ResourceContainerImpl::setRequestHandler, this,
291 std::placeholders::_1, std::placeholders::_2));
293 info_logger() << "Registration finished " << strUri << "," << strResourceType
299 error_logger() << "resource with " << strUri << " already exists." << endl;
303 void ResourceContainerImpl::unregisterResource(BundleResource *resource)
305 string strUri = resource->m_uri;
306 string strResourceType = resource->m_resourceType;
308 info_logger() << "Unregistration of resource " << resource->m_uri << "," << resource->m_resourceType
311 if (m_mapServers.find(strUri) != m_mapServers.end())
313 m_mapServers[strUri].reset();
315 m_mapResources.erase(m_mapResources.find(strUri));
316 m_mapBundleResources[resource->m_bundleId].remove(strUri);
320 void ResourceContainerImpl::getBundleConfiguration(const std::string &bundleId,
321 configInfo *configOutput)
325 m_config->getBundleConfiguration(bundleId, (configInfo *) configOutput);
329 void ResourceContainerImpl::getResourceConfiguration(const std::string &bundleId,
330 std::vector< resourceInfo > *configOutput)
334 m_config->getResourceConfiguration(bundleId, configOutput);
338 RCSGetResponse ResourceContainerImpl::getRequestHandler(const RCSRequest &request,
339 const RCSResourceAttributes &attributes)
341 RCSResourceAttributes attr;
343 if (m_mapServers.find(request.getResourceUri()) != m_mapServers.end()
344 && m_mapResources.find(request.getResourceUri()) != m_mapResources.end())
346 for (string attrName : m_mapResources[request.getResourceUri()]->getAttributeNames())
348 attr[attrName] = m_mapResources[request.getResourceUri()]->getAttribute(
353 return RCSGetResponse::create(attr);
356 RCSSetResponse ResourceContainerImpl::setRequestHandler(const RCSRequest &request,
357 const RCSResourceAttributes &attributes)
359 RCSResourceAttributes attr = attributes;
361 if (m_mapServers.find(request.getResourceUri()) != m_mapServers.end()
362 && m_mapResources.find(request.getResourceUri()) != m_mapResources.end())
364 for (string attrName : m_mapResources[request.getResourceUri()]->getAttributeNames())
366 if (!attr[attrName].toString().empty())
368 m_mapResources[request.getResourceUri()]->setAttribute(attrName,
369 attr[attrName].toString());
374 return RCSSetResponse::create(attr);
377 void ResourceContainerImpl::onNotificationReceived(const std::string &strResourceUri)
379 info_logger() << "ResourceContainerImpl::onNotificationReceived\n\tnotification from "
380 << strResourceUri << ".\n";
382 if (m_mapServers.find(strResourceUri) != m_mapServers.end())
384 m_mapServers[strResourceUri]->notify();
388 ResourceContainerImpl *ResourceContainerImpl::getImplInstance()
390 static ResourceContainerImpl m_instance;
394 RCSResourceObject::Ptr ResourceContainerImpl::buildResourceObject(const std::string & strUri,
395 const std::string & strResourceType)
397 return RCSResourceObject::Builder(strUri, strResourceType, "DEFAULT_INTERFACE").setObservable(
398 true).setDiscoverable(true).build();
401 void ResourceContainerImpl::startBundle(const std::string &bundleId)
403 if (m_bundles.find(bundleId) != m_bundles.end())
405 if (!m_bundles[bundleId]->isActivated())
406 activateBundle(m_bundles[bundleId]);
408 error_logger() << "Bundle already started" << endl;
412 error_logger() << "Bundle with ID \'" << bundleId << "\' is not registered." << endl;
416 void ResourceContainerImpl::stopBundle(const std::string &bundleId)
418 if (m_bundles.find(bundleId) != m_bundles.end())
420 if (m_bundles[bundleId]->isActivated())
421 deactivateBundle(m_bundles[bundleId]);
423 error_logger() << "Bundle not activated" << endl;
427 error_logger() << "Bundle with ID \'" << bundleId << "\' is not registered." << endl;
431 void ResourceContainerImpl::addBundle(const std::string &bundleId, const std::string &bundleUri, const std::string &bundlePath,
432 std::map< string, string > params)
434 if (m_bundles.find(bundleId) != m_bundles.end())
435 error_logger() << "BundleId already exist" << endl;
439 RCSBundleInfo *bundleInfo = RCSBundleInfo::build();
440 bundleInfo->setID(bundleId);
441 bundleInfo->setPath(bundlePath);
442 if (params.find("activator") != params.end())
444 string activatorName = params["activator"];
445 std::replace(activatorName.begin(), activatorName.end(), '.', '/');
446 ((BundleInfoInternal *) bundleInfo)->setActivatorName(activatorName);
447 ((BundleInfoInternal *) bundleInfo)->setLibraryPath(params["libraryPath"]);
450 info_logger() << "Add Bundle:" << bundleInfo->getID().c_str() << ";"
451 << bundleInfo->getPath().c_str() << endl;
453 registerBundle(bundleInfo);
457 void ResourceContainerImpl::removeBundle(const std::string &bundleId)
459 if (m_bundles.find(bundleId) != m_bundles.end())
461 BundleInfoInternal *bundleInfo = m_bundles[bundleId];
462 if (bundleInfo->isActivated())
463 deactivateBundle(bundleInfo);
465 if (bundleInfo->isLoaded())
466 unregisterBundle(bundleInfo);
470 error_logger() << "Bundle with ID \'" << bundleId << "\' is not registered."
475 std::list< RCSBundleInfo * > ResourceContainerImpl::listBundles()
477 std::list< RCSBundleInfo * > ret;
478 for (std::map< std::string, BundleInfoInternal * >::iterator it = m_bundles.begin();
479 it != m_bundles.end(); ++it)
482 RCSBundleInfo *bundleInfo = RCSBundleInfo::build();
483 ((BundleInfoInternal *) bundleInfo)->setBundleInfo((RCSBundleInfo *) it->second);
484 ret.push_back(it->second);
490 void ResourceContainerImpl::addResourceConfig(const std::string &bundleId, const std::string &resourceUri,
491 std::map< string, string > params)
493 if (m_bundles.find(bundleId) != m_bundles.end())
495 if (!m_bundles[bundleId]->getJavaBundle())
497 resourceInfo newResourceInfo;
498 newResourceInfo.uri = resourceUri;
500 if (params.find("name") != params.end())
501 newResourceInfo.name = params["name"];
502 if (params.find("resourceType") != params.end())
503 newResourceInfo.resourceType = params["resourceType"];
504 if (params.find("address") != params.end())
505 newResourceInfo.address = params["address"];
507 addSoBundleResource(bundleId, newResourceInfo);
512 error_logger() << "Bundle with ID \'" << bundleId << "\' is not registered."
517 void ResourceContainerImpl::removeResourceConfig(const std::string &bundleId, const std::string &resourceUri)
519 if (m_bundles.find(bundleId) != m_bundles.end())
521 if (!m_bundles[bundleId]->getJavaBundle())
523 removeSoBundleResource(bundleId, resourceUri);
528 error_logger() << "Bundle with ID \'" << bundleId << "\' is not registered."
533 std::list< string > ResourceContainerImpl::listBundleResources(const std::string &bundleId)
535 std::list< string > ret;
537 if (m_mapBundleResources.find(bundleId) != m_mapBundleResources.end())
539 ret = m_mapBundleResources[bundleId];
546 void ResourceContainerImpl::registerSoBundle(RCSBundleInfo *bundleInfo)
550 activator_t *bundleActivator = NULL;
551 deactivator_t *bundleDeactivator = NULL;
552 resourceCreator_t *resourceCreator = NULL;
553 resourceDestroyer_t *resourceDestroyer = NULL;
555 //sstream << bundleInfo.path << std::ends;
557 void *bundleHandle = NULL;
558 bundleHandle = dlopen(bundleInfo->getPath().c_str(), RTLD_LAZY);
560 if (bundleHandle != NULL)
562 bundleActivator = (activator_t *) dlsym(bundleHandle, "externalActivateBundle");
563 bundleDeactivator = (deactivator_t *) dlsym(bundleHandle,
564 "externalDeactivateBundle");
565 resourceCreator = (resourceCreator_t *) dlsym(bundleHandle,
566 "externalCreateResource");
567 resourceDestroyer = (resourceDestroyer_t *) dlsym(bundleHandle,
568 "externalDestroyResource");
570 if ((error = dlerror()) != NULL)
572 error_logger() << error << endl;
576 ((BundleInfoInternal *) bundleInfo)->setBundleActivator(bundleActivator);
577 ((BundleInfoInternal *) bundleInfo)->setBundleDeactivator(bundleDeactivator);
578 ((BundleInfoInternal *) bundleInfo)->setResourceCreator(resourceCreator);
579 ((BundleInfoInternal *) bundleInfo)->setResourceDestroyer(resourceDestroyer);
580 ((BundleInfoInternal *) bundleInfo)->setLoaded(true);
581 ((BundleInfoInternal *) bundleInfo)->setBundleHandle(bundleHandle);
583 m_bundles[bundleInfo->getID()] = ((BundleInfoInternal *) bundleInfo);
588 if ((error = dlerror()) != NULL)
590 error_logger() << error << endl;
595 void ResourceContainerImpl::activateSoBundle(const std::string &bundleId)
597 activator_t *bundleActivator = m_bundles[bundleId]->getBundleActivator();
599 if (bundleActivator != NULL)
601 bundleActivator(this, m_bundles[bundleId]->getID());
602 m_bundles[bundleId]->setActivated(true);
606 //Unload module and return error
607 error_logger() << "Activation unsuccessful." << endl;
610 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) m_bundles[bundleId];
611 bundleInfoInternal->setActivated(true);
614 void ResourceContainerImpl::deactivateSoBundle(const std::string &id)
616 deactivator_t *bundleDeactivator = m_bundles[id]->getBundleDeactivator();
617 info_logger() << "De-activating bundle: " << m_bundles[id]->getID() << endl;
619 if (bundleDeactivator != NULL)
622 m_bundles[id]->setActivated(false);
626 //Unload module and return error
627 error_logger() << "De-activation unsuccessful." << endl;
631 void ResourceContainerImpl::addSoBundleResource(const std::string &bundleId,
632 resourceInfo newResourceInfo)
634 resourceCreator_t *resourceCreator;
636 resourceCreator = m_bundles[bundleId]->getResourceCreator();
638 if (resourceCreator != NULL)
640 resourceCreator(newResourceInfo);
644 error_logger() << "addResource unsuccessful." << endl;
648 void ResourceContainerImpl::removeSoBundleResource(const std::string &bundleId, const std::string &resourceUri)
650 if (m_mapResources.find(resourceUri) != m_mapResources.end())
652 resourceDestroyer_t *resourceDestroyer =
653 m_bundles[bundleId]->getResourceDestroyer();
655 if (resourceDestroyer != NULL)
657 resourceDestroyer(m_mapResources[resourceUri]);
661 error_logger() << "removeResource unsuccessful." << endl;
667 JavaVM *ResourceContainerImpl::getJavaVM(string bundleId)
669 return m_bundleVM[bundleId];
672 void ResourceContainerImpl::registerJavaBundle(RCSBundleInfo *bundleInfo)
674 info_logger() << "Registering Java bundle " << bundleInfo->getID() << endl;
677 JavaVMInitArgs vm_args;
678 JavaVMOption options[3];
680 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) bundleInfo;
682 if (FILE *file = fopen(bundleInfo->getPath().c_str(), "r"))
685 info_logger() << "Resource bundle " << bundleInfo->getPath().c_str() << " available." << endl;
690 error_logger() << "Resource bundle " << bundleInfo->getPath().c_str() << " not available" << endl;
694 char optionString[] = "-Djava.compiler=NONE";
695 options[0].optionString = optionString;
696 char classpath[1000];
697 strcpy(classpath, "-Djava.class.path=");
698 strcat(classpath, bundleInfo->getPath().c_str());
700 info_logger() << "Configured classpath: " << classpath << "|" << endl;
702 options[1].optionString = classpath;
704 char libraryPath[1000];
705 strcpy(libraryPath, "-Djava.library.path=");
706 strcat(libraryPath, bundleInfo->getLibraryPath().c_str());
707 options[2].optionString = libraryPath;
709 info_logger() << "Configured library path: " << libraryPath << "|" << endl;
711 vm_args.version = JNI_VERSION_1_4;
712 vm_args.options = options;
713 vm_args.nOptions = 3;
714 vm_args.ignoreUnrecognized = 1;
717 res = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);
721 error_logger() << " cannot create JavaVM." << endl;
726 info_logger() << "JVM successfully created " << endl;
729 m_bundleVM.insert(std::pair< string, JavaVM * >(bundleInfo->getID(), jvm));
731 const char *className = bundleInfoInternal->getActivatorName().c_str();
733 info_logger() << "Looking up class: " << bundleInfoInternal->getActivatorName() << "|" << endl;
735 jclass bundleActivatorClass = env->FindClass(className);
737 if (bundleActivatorClass == NULL)
739 error_logger() << "Cannot register bundle " << bundleInfoInternal->getID()
740 << " bundle activator(" << bundleInfoInternal->getActivatorName()
741 << ") not found " << endl;
745 jmethodID activateMethod = env->GetMethodID(bundleActivatorClass, "activateBundle",
748 if (activateMethod == NULL)
750 error_logger() << "Cannot register bundle " << bundleInfoInternal->getID()
751 << " activate bundle method not found " << endl;
754 bundleInfoInternal->setJavaBundleActivatorMethod(activateMethod);
756 jmethodID deactivateMethod = env->GetMethodID(bundleActivatorClass, "deactivateBundle",
759 if (deactivateMethod == NULL)
761 error_logger() << "Cannot register bundle " << bundleInfoInternal->getID()
762 << " deactivate bundle method not found " << endl;
766 bundleInfoInternal->setJavaBundleDeactivatorMethod(deactivateMethod);
768 jmethodID constructor;
770 constructor = env->GetMethodID(bundleActivatorClass, "<init>", "(Ljava/lang/String;)V");
772 jstring bundleID = env->NewStringUTF(bundleInfoInternal->getID().c_str());
774 jobject bundleActivator = env->NewObject(bundleActivatorClass, constructor, bundleID);
776 bundleInfoInternal->setJavaBundleActivatorObject(bundleActivator);
778 bundleInfoInternal->setLoaded(true);
780 m_bundles[bundleInfo->getID()] = ((BundleInfoInternal *)bundleInfo);
782 info_logger() << "Bundle registered" << endl;
785 void ResourceContainerImpl::activateJavaBundle(string bundleId)
787 info_logger() << "Activating java bundle" << endl;
788 JavaVM *vm = getJavaVM(bundleId);
789 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) m_bundles[bundleId];
791 int envStat = vm->GetEnv((void **) &env, JNI_VERSION_1_4);
793 if (envStat == JNI_EDETACHED)
795 if (vm->AttachCurrentThread((void **) &env, NULL) != 0)
797 error_logger() << "Failed to attach " << endl;
800 else if (envStat == JNI_EVERSION)
802 error_logger() << "Env: version not supported " << endl;
805 env->CallVoidMethod(bundleInfoInternal->getJavaBundleActivatorObject(),
806 bundleInfoInternal->getJavaBundleActivatorMethod());
808 m_bundles[bundleId]->setActivated(true);
811 void ResourceContainerImpl::deactivateJavaBundle(string bundleId)
813 info_logger() << "Deactivating java bundle" << endl;
814 JavaVM *vm = getJavaVM(bundleId);
815 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) m_bundles[bundleId];
817 int envStat = vm->GetEnv((void **) &env, JNI_VERSION_1_4);
819 if (envStat == JNI_EDETACHED)
821 if (vm->AttachCurrentThread((void **) &env, NULL) != 0)
823 error_logger() << "Failed to attach " << endl;
826 else if (envStat == JNI_EVERSION)
828 error_logger() << "Env: version not supported " << endl;
831 env->CallVoidMethod(bundleInfoInternal->getJavaBundleActivatorObject(),
832 bundleInfoInternal->getJavaBundleDeactivatorMethod());
834 m_bundles[bundleId]->setActivated(false);
837 void ResourceContainerImpl::unregisterBundleJava(string id)
839 info_logger() << "Unregister Java bundle: " << m_bundles[id]->getID() << ", "
840 << m_bundles[id]->getID() << endl;
842 info_logger() << "Destroying JVM" << endl;
843 m_bundleVM[id]->DestroyJavaVM();
845 delete m_bundles[id];