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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
31 #include "ResourceContainerImpl.h"
32 #include "BundleActivator.h"
33 #include "ResourceContainer.h"
34 #include "BundleInfoInternal.h"
36 #include "oc_logger.hpp"
38 using OC::oc_log_stream;
39 using namespace OIC::Service;
41 auto error_logger = []() -> boost::iostreams::stream<OC::oc_log_stream> &
43 static OC::oc_log_stream ols(oc_make_ostream_logger);
44 static boost::iostreams::stream<OC::oc_log_stream> os(ols);
45 os->set_level(OC_LOG_ERROR);
46 os->set_module("ResourceContainerImpl");
50 auto info_logger = []() -> boost::iostreams::stream<OC::oc_log_stream> &
52 static OC::oc_log_stream ols(oc_make_ostream_logger);
53 static boost::iostreams::stream<OC::oc_log_stream> os(ols);
54 os->set_level(OC_LOG_INFO);
55 os->set_module("ResourceContainerImpl");
60 using namespace OIC::Service;
67 ResourceContainerImpl::ResourceContainerImpl()
69 // TODO Auto-generated constructor stub
73 ResourceContainerImpl::~ResourceContainerImpl()
75 // TODO Auto-generated destructor stub
78 bool has_suffix(const std::string &str, const std::string &suffix)
80 return str.size() >= suffix.size()
81 && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
84 void ResourceContainerImpl::startContainer(string configFile)
86 info_logger() << "Starting resource container" << endl;
88 m_config = new Configuration(configFile);
90 if (m_config->isLoaded())
93 m_config->getConfiguredBundles(&bundles);
95 for (unsigned int i = 0; i < bundles.size(); i++)
97 BundleInfo *bundleInfo = BundleInfo::build();
98 bundleInfo->setPath(bundles[i]["path"]);
99 bundleInfo->setVersion(bundles[i]["version"]);
100 bundleInfo->setID(bundles[i]["id"]);
101 if (!bundles[i]["activator"].empty())
103 string activatorName = bundles[i]["activator"];
104 std::replace(activatorName.begin(), activatorName.end(), '.', '/');
105 ((BundleInfoInternal *) bundleInfo)->setActivatorName(activatorName);
106 ((BundleInfoInternal *) bundleInfo)->setLibraryPath(bundles[i]["libraryPath"]);
109 info_logger() << "Init Bundle:" << bundles[i]["id"] << ";" << bundles[i]["path"]
111 registerBundle(bundleInfo);
112 activateBundle(bundleInfo);
117 error_logger() << "Container started with invalid configfile path" << endl;
121 void ResourceContainerImpl::stopContainer()
123 info_logger() << "Stopping resource container.";
124 for (std::map< std::string, BundleInfoInternal * >::iterator it = m_bundles.begin();
125 it != m_bundles.end(); ++it)
127 BundleInfoInternal *bundleInfo = it->second;
128 deactivateBundle(bundleInfo);
129 unregisterBundle(bundleInfo);
135 void ResourceContainerImpl::activateBundle(BundleInfo *bundleInfo)
137 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) bundleInfo;
139 if (bundleInfoInternal->isLoaded())
141 activateBundle(bundleInfo->getID());
145 void ResourceContainerImpl::deactivateBundle(BundleInfo *bundleInfo)
147 if (((BundleInfoInternal *) bundleInfo)->isActivated())
149 deactivateBundle(bundleInfo->getID());
153 void ResourceContainerImpl::activateBundle(string id)
156 info_logger() << "Activating bundle: " << m_bundles[id]->getID() << endl;
158 if (m_bundles[id]->getJavaBundle())
160 activateJavaBundle(id);
164 activateSoBundle(id);
167 info_logger() << "Bundle activated: " << m_bundles[id]->getID() << endl;
171 void ResourceContainerImpl::deactivateBundle(string id)
174 if (m_bundles[id]->getJavaBundle())
176 deactivateJavaBundle(id);
180 deactivateSoBundle(id);
185 void ResourceContainerImpl::registerBundle(BundleInfo *bundleInfo)
187 info_logger() << "Registering bundle: " << bundleInfo->getPath() << endl;
189 if (has_suffix(bundleInfo->getPath(), ".jar"))
191 ((BundleInfoInternal *) bundleInfo)->setJavaBundle(true);
192 registerJavaBundle(bundleInfo);
196 ((BundleInfoInternal *) bundleInfo)->setJavaBundle(false);
197 registerSoBundle(bundleInfo);
201 void ResourceContainerImpl::unregisterBundle(BundleInfo *bundleInfo)
203 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) bundleInfo;
204 if (bundleInfoInternal->isLoaded() && !bundleInfoInternal->isActivated())
206 if (!bundleInfoInternal->getJavaBundle())
208 unregisterBundleSo(bundleInfo->getID());
212 unregisterBundleJava(bundleInfo->getID());
217 void ResourceContainerImpl::unregisterBundleSo(string id)
219 void *bundleHandle = m_bundles[id]->getBundleHandle();
220 info_logger() << "Unregister bundle: " << m_bundles[id]->getID() << ", "
221 << m_bundles[id]->getID() << endl;
223 dlclose(bundleHandle);
224 if ((error = dlerror()) != NULL)
226 error_logger() << error << endl;
230 delete m_bundles[id];
235 void ResourceContainerImpl::unregisterBundleJava(string id)
237 info_logger() << "Unregister Java bundle: " << m_bundles[id]->getID() << ", "
238 << m_bundles[id]->getID() << endl;
240 info_logger() << "Destroying JVM" << endl;
241 m_bundleVM[id]->DestroyJavaVM();
243 delete m_bundles[id];
247 void ResourceContainerImpl::registerResource(BundleResource *resource)
249 string strUri = resource->m_uri;
250 string strResourceType = resource->m_resourceType;
251 ResourceObject::Ptr server = nullptr;
253 info_logger() << "Registration of resource " << strUri << "," << strResourceType
256 server = buildResourceObject(strUri, strResourceType);
258 if (server != nullptr)
260 m_mapServers[strUri] = server;
261 m_mapResources[strUri] = resource;
262 m_mapBundleResources[resource->m_bundleId].push_back(strUri);
264 resource->registerObserver(this);
266 server->setGetRequestHandler(
267 std::bind(&ResourceContainerImpl::getRequestHandler, this,
268 std::placeholders::_1, std::placeholders::_2));
270 server->setSetRequestHandler(
271 std::bind(&ResourceContainerImpl::setRequestHandler, this,
272 std::placeholders::_1, std::placeholders::_2));
274 info_logger() << "Registration finished " << strUri << "," << strResourceType
279 void ResourceContainerImpl::unregisterResource(BundleResource *resource)
281 string strUri = resource->m_uri;
282 string strResourceType = resource->m_resourceType;
284 info_logger() << "Unregistration of resource " << resource->m_uri << "," << resource->m_resourceType
287 if (m_mapServers.find(strUri) != m_mapServers.end())
289 m_mapServers[strUri].reset();
291 m_mapResources.erase(m_mapResources.find(strUri));
292 m_mapBundleResources[resource->m_bundleId].remove(strUri);
296 void ResourceContainerImpl::getBundleConfiguration(std::string bundleId,
297 configInfo *configOutput)
301 m_config->getBundleConfiguration(bundleId, (configInfo *) configOutput);
305 void ResourceContainerImpl::getResourceConfiguration(std::string bundleId,
306 std::vector< resourceInfo > *configOutput)
310 m_config->getResourceConfiguration(bundleId, configOutput);
314 RCSGetResponse ResourceContainerImpl::getRequestHandler(
315 const RCSRequest &request, const ResourceAttributes &attributes)
317 ResourceAttributes attr;
319 if (m_mapServers.find(request.getResourceUri()) != m_mapServers.end()
320 && m_mapResources.find(request.getResourceUri()) != m_mapResources.end())
322 for (string attrName : m_mapResources[request.getResourceUri()]->getAttributeNames())
324 attr[attrName] = m_mapResources[request.getResourceUri()]->getAttribute(
329 return RCSGetResponse::create(attr);
332 RCSSetResponse ResourceContainerImpl::setRequestHandler(
333 const RCSRequest &request, const ResourceAttributes &attributes)
335 ResourceAttributes attr = attributes;
337 if (m_mapServers.find(request.getResourceUri()) != m_mapServers.end()
338 && m_mapResources.find(request.getResourceUri()) != m_mapResources.end())
340 for (string attrName : m_mapResources[request.getResourceUri()]->getAttributeNames())
342 if (!attr[attrName].toString().empty())
344 m_mapResources[request.getResourceUri()]->setAttribute(attrName,
345 attr[attrName].toString());
350 return RCSSetResponse::create(attr);
353 void ResourceContainerImpl::onNotificationReceived(std::string strResourceUri)
355 info_logger() << "ResourceContainerImpl::onNotificationReceived\n\tnotification from "
356 << strResourceUri << ".\n";
358 if (m_mapServers.find(strResourceUri) != m_mapServers.end())
360 m_mapServers[strResourceUri]->notify();
364 ResourceContainerImpl *ResourceContainerImpl::getImplInstance()
366 static ResourceContainerImpl m_instance;
370 ResourceObject::Ptr ResourceContainerImpl::buildResourceObject(string strUri,
371 string strResourceType)
373 return ResourceObject::Builder(strUri, strResourceType, "DEFAULT_INTERFACE").setObservable(
374 true).setDiscoverable(true).build();
377 void ResourceContainerImpl::startBundle(string bundleId)
379 if (m_bundles.find(bundleId) != m_bundles.end())
380 activateBundle(m_bundles[bundleId]);
383 void ResourceContainerImpl::stopBundle(string bundleId)
385 if (m_bundles.find(bundleId) != m_bundles.end())
386 deactivateBundle(m_bundles[bundleId]);
389 void ResourceContainerImpl::addBundle(string bundleId, string bundleUri, string bundlePath,
390 std::map< string, string > params)
392 if (m_bundles.find(bundleId) != m_bundles.end())
393 error_logger() << "BundleId already exist" << endl;
397 BundleInfo *bundleInfo = BundleInfo::build();
398 bundleInfo->setID(bundleId);
399 bundleInfo->setPath(bundlePath);
400 if (params.find("activator") != params.end())
402 string activatorName = params["activator"];
403 std::replace(activatorName.begin(), activatorName.end(), '.', '/');
404 ((BundleInfoInternal *)bundleInfo)->setActivatorName(activatorName);
405 ((BundleInfoInternal *)bundleInfo)->setLibraryPath(params["libraryPath"]);
407 if (params.find("activator") != params.end())
409 string activatorName = params["activator"];
410 std::replace(activatorName.begin(), activatorName.end(), '.', '/');
411 ((BundleInfoInternal *)bundleInfo)->setActivatorName(activatorName);
412 ((BundleInfoInternal *)bundleInfo)->setLibraryPath(params["libraryPath"]);
415 info_logger() << "Add Bundle:" << bundleInfo->getID().c_str() << ";" <<
416 bundleInfo->getPath().c_str() <<
419 registerBundle(bundleInfo);
423 void ResourceContainerImpl::removeBundle(string bundleId)
425 if (m_bundles.find(bundleId) != m_bundles.end())
427 BundleInfoInternal *bundleInfo = m_bundles[bundleId];
428 if (bundleInfo->isActivated())
429 deactivateBundle(bundleInfo);
431 if (bundleInfo->isLoaded())
432 unregisterBundle(bundleInfo);
436 error_logger() << "Bundle with ID \'" << bundleId << "\' is not registered." << endl;
440 std::list< BundleInfo * > ResourceContainerImpl::listBundles()
442 std::list< BundleInfo * > ret;
443 for (std::map< std::string, BundleInfoInternal * >::iterator it = m_bundles.begin();
444 it != m_bundles.end(); ++it)
447 BundleInfo *bundleInfo = BundleInfo::build();
448 ((BundleInfoInternal *) bundleInfo)->setBundleInfo((BundleInfo *) it->second);
449 ret.push_back(it->second);
455 void ResourceContainerImpl::addResourceConfig(string bundleId, string resourceUri,
456 std::map< string, string > params)
458 if (m_bundles.find(bundleId) != m_bundles.end())
460 if (!m_bundles[bundleId]->getJavaBundle())
462 resourceInfo newResourceInfo;
463 newResourceInfo.uri = resourceUri;
465 if (params.find("name") != params.end())
466 newResourceInfo.name = params["name"];
467 if (params.find("resourceType") != params.end())
468 newResourceInfo.resourceType = params["resourceType"];
469 if (params.find("address") != params.end())
470 newResourceInfo.address = params["address"];
472 addSoBundleResource(bundleId, newResourceInfo);
477 error_logger() << "Bundle with ID \'" << bundleId << "\' is not registered." << endl;
481 void ResourceContainerImpl::removeResourceConfig(string bundleId, string resourceUri)
483 if (m_bundles.find(bundleId) != m_bundles.end())
485 if (!m_bundles[bundleId]->getJavaBundle())
487 removeSoBundleResource(bundleId, resourceUri);
492 error_logger() << "Bundle with ID \'" << bundleId << "\' is not registered." << endl;
496 std::list< string > ResourceContainerImpl::listBundleResources(string bundleId)
498 std::list< string > ret;
500 if (m_mapBundleResources.find(bundleId) != m_mapBundleResources.end())
502 ret = m_mapBundleResources[bundleId];
509 JavaVM *ResourceContainerImpl::getJavaVM(string bundleId)
511 return m_bundleVM[bundleId];
514 void ResourceContainerImpl::registerJavaBundle(BundleInfo *bundleInfo)
516 info_logger() << "Registering Java bundle " << bundleInfo->getID() << endl;
519 JavaVMInitArgs vm_args;
520 JavaVMOption options[3];
522 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) bundleInfo;
524 if (FILE *file = fopen(bundleInfo->getPath().c_str(), "r"))
527 info_logger() << "Resource bundle " << bundleInfo->getPath().c_str() << " available." << endl;
532 error_logger() << "Resource bundle " << bundleInfo->getPath().c_str() << " not available" << endl;
536 char optionString[] = "-Djava.compiler=NONE";
537 options[0].optionString = optionString;
538 char classpath[1000];
539 strcpy(classpath, "-Djava.class.path=");
540 strcat(classpath, bundleInfo->getPath().c_str());
543 info_logger() << "Configured classpath: " << classpath << "|" << endl;
545 options[1].optionString = classpath;
547 char libraryPath[1000];
548 strcpy(libraryPath, "-Djava.library.path=");
549 strcat(libraryPath, bundleInfo->getLibraryPath().c_str());
550 options[2].optionString = libraryPath;
552 info_logger() << "Configured library path: " << libraryPath << "|" << endl;
554 vm_args.version = JNI_VERSION_1_4;
555 vm_args.options = options;
556 vm_args.nOptions = 3;
557 vm_args.ignoreUnrecognized = 1;
560 res = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);
564 error_logger() << " cannot create JavaVM." << endl;
569 info_logger() << "JVM successfully created " << endl;
572 m_bundleVM.insert(std::pair< string, JavaVM * >(bundleInfo->getID(), jvm));
574 const char *className = bundleInfoInternal->getActivatorName().c_str();
576 info_logger() << "Looking up class: " << bundleInfoInternal->getActivatorName() << "|" << endl;
578 jclass bundleActivatorClass = env->FindClass(className);
580 if (bundleActivatorClass == NULL)
582 error_logger() << "Cannot register bundle " << bundleInfoInternal->getID()
583 << " bundle activator(" << bundleInfoInternal->getActivatorName()
584 << ") not found " << endl;
588 jmethodID activateMethod = env->GetMethodID(bundleActivatorClass, "activateBundle",
591 if (activateMethod == NULL)
593 error_logger() << "Cannot register bundle " << bundleInfoInternal->getID()
594 << " activate bundle method not found " << endl;
597 bundleInfoInternal->setJavaBundleActivatorMethod(activateMethod);
599 jmethodID deactivateMethod = env->GetMethodID(bundleActivatorClass, "deactivateBundle",
602 if (deactivateMethod == NULL)
604 error_logger() << "Cannot register bundle " << bundleInfoInternal->getID()
605 << " deactivate bundle method not found " << endl;
609 bundleInfoInternal->setJavaBundleDeactivatorMethod(deactivateMethod);
611 jmethodID constructor;
613 constructor = env->GetMethodID(bundleActivatorClass, "<init>", "(Ljava/lang/String;)V");
615 jstring bundleID = env->NewStringUTF(bundleInfoInternal->getID().c_str());
617 jobject bundleActivator = env->NewObject(bundleActivatorClass, constructor, bundleID);
619 bundleInfoInternal->setJavaBundleActivatorObject(bundleActivator);
621 bundleInfoInternal->setLoaded(true);
623 m_bundles[bundleInfo->getID()] = ((BundleInfoInternal *)bundleInfo);
625 info_logger() << "Bundle registered" << endl;
628 void ResourceContainerImpl::registerSoBundle(BundleInfo *bundleInfo)
632 activator_t *bundleActivator = NULL;
633 deactivator_t *bundleDeactivator = NULL;
634 resourceCreator_t *resourceCreator = NULL;
635 resourceDestroyer_t *resourceDestroyer = NULL;
637 //sstream << bundleInfo.path << std::ends;
639 void *bundleHandle = NULL;
640 bundleHandle = dlopen(bundleInfo->getPath().c_str(), RTLD_LAZY);
642 if (bundleHandle != NULL)
644 bundleActivator = (activator_t *) dlsym(bundleHandle, "externalActivateBundle");
645 bundleDeactivator = (deactivator_t *) dlsym(bundleHandle,
646 "externalDeactivateBundle");
647 resourceCreator = (resourceCreator_t *)dlsym(bundleHandle, "externalCreateResource");
648 resourceDestroyer = (resourceDestroyer_t *)dlsym(bundleHandle, "externalDestroyResource");
650 if ((error = dlerror()) != NULL)
652 error_logger() << error << endl;
656 ((BundleInfoInternal *) bundleInfo)->setBundleActivator(bundleActivator);
657 ((BundleInfoInternal *) bundleInfo)->setBundleDeactivator(bundleDeactivator);
658 ((BundleInfoInternal *) bundleInfo)->setResourceCreator(resourceCreator);
659 ((BundleInfoInternal *) bundleInfo)->setResourceDestroyer(resourceDestroyer);
660 ((BundleInfoInternal *) bundleInfo)->setLoaded(true);
661 ((BundleInfoInternal *) bundleInfo)->setBundleHandle(bundleHandle);
663 m_bundles[bundleInfo->getID()] = ((BundleInfoInternal *)bundleInfo);
668 if ((error = dlerror()) != NULL)
670 error_logger() << error << endl;
675 void ResourceContainerImpl::activateJavaBundle(string bundleId)
677 info_logger() << "Activating java bundle" << endl;
678 JavaVM *vm = getJavaVM(bundleId);
679 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) m_bundles[bundleId];
681 int envStat = vm->GetEnv((void **) &env, JNI_VERSION_1_4);
683 if (envStat == JNI_EDETACHED)
685 if (vm->AttachCurrentThread((void **) &env, NULL) != 0)
687 error_logger() << "Failed to attach " << endl;
690 else if (envStat == JNI_EVERSION)
692 error_logger() << "Env: version not supported " << endl;
695 env->CallVoidMethod(bundleInfoInternal->getJavaBundleActivatorObject(),
696 bundleInfoInternal->getJavaBundleActivatorMethod());
698 m_bundles[bundleId]->setActivated(true);
701 void ResourceContainerImpl::activateSoBundle(string bundleId)
703 activator_t *bundleActivator = m_bundles[bundleId]->getBundleActivator();
705 if (bundleActivator != NULL)
707 bundleActivator(this, m_bundles[bundleId]->getID());
708 m_bundles[bundleId]->setActivated(true);
712 //Unload module and return error
713 error_logger() << "Activation unsuccessful." << endl;
716 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) m_bundles[bundleId];
717 bundleInfoInternal->setActivated(true);
720 void ResourceContainerImpl::deactivateJavaBundle(string bundleId)
722 info_logger() << "Deactivating java bundle" << endl;
723 JavaVM *vm = getJavaVM(bundleId);
724 BundleInfoInternal *bundleInfoInternal = (BundleInfoInternal *) m_bundles[bundleId];
726 int envStat = vm->GetEnv((void **) &env, JNI_VERSION_1_4);
728 if (envStat == JNI_EDETACHED)
730 if (vm->AttachCurrentThread((void **) &env, NULL) != 0)
732 error_logger() << "Failed to attach " << endl;
735 else if (envStat == JNI_EVERSION)
737 error_logger() << "Env: version not supported " << endl;
740 env->CallVoidMethod(bundleInfoInternal->getJavaBundleActivatorObject(),
741 bundleInfoInternal->getJavaBundleDeactivatorMethod());
743 m_bundles[bundleId]->setActivated(false);
746 void ResourceContainerImpl::deactivateSoBundle(string id)
748 deactivator_t *bundleDeactivator = m_bundles[id]->getBundleDeactivator();
749 info_logger() << "De-activating bundle: " << m_bundles[id]->getID() << endl;
751 if (bundleDeactivator != NULL)
754 m_bundles[id]->setActivated(false);
758 //Unload module and return error
759 error_logger() << "De-activation unsuccessful." << endl;
763 void ResourceContainerImpl::addSoBundleResource(string bundleId, resourceInfo newResourceInfo)
765 resourceCreator_t *resourceCreator;
767 resourceCreator = m_bundles[bundleId]->getResourceCreator();
769 if (resourceCreator != NULL)
771 resourceCreator(newResourceInfo);
775 error_logger() << "addResource unsuccessful." << endl;
779 void ResourceContainerImpl::removeSoBundleResource(string bundleId, string resourceUri)
781 if (m_mapResources.find(resourceUri) != m_mapResources.end())
783 resourceDestroyer_t *resourceDestroyer = m_bundles[bundleId]->getResourceDestroyer();
785 if (resourceDestroyer != NULL)
787 resourceDestroyer(m_mapResources[resourceUri]);
791 error_logger() << "removeResource unsuccessful." << endl;