summaryrefslogtreecommitdiff
path: root/implementation/plugin/src/plugin_manager_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'implementation/plugin/src/plugin_manager_impl.cpp')
-rw-r--r--implementation/plugin/src/plugin_manager_impl.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/implementation/plugin/src/plugin_manager_impl.cpp b/implementation/plugin/src/plugin_manager_impl.cpp
new file mode 100644
index 0000000..6da2d82
--- /dev/null
+++ b/implementation/plugin/src/plugin_manager_impl.cpp
@@ -0,0 +1,216 @@
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <sstream>
+#include <vector>
+#include <stdlib.h>
+#include <iostream>
+
+#ifdef _WIN32
+ #ifndef _WINSOCKAPI_
+ #include <Windows.h>
+ #endif
+#else
+ #include <dlfcn.h>
+#endif
+
+#include <vsomeip/plugins/application_plugin.hpp>
+#include <vsomeip/plugins/pre_configuration_plugin.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/plugin_manager_impl.hpp"
+
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+
+#include "../../utility/include/utility.hpp"
+
+namespace vsomeip_v3 {
+
+std::shared_ptr<plugin_manager_impl> plugin_manager_impl::the_plugin_manager__ =
+ std::make_shared<plugin_manager_impl>();
+
+std::shared_ptr<plugin_manager_impl> plugin_manager_impl::get() {
+ return the_plugin_manager__;
+}
+
+plugin_manager_impl::plugin_manager_impl() :
+ plugins_loaded_(false) {
+}
+
+plugin_manager_impl::~plugin_manager_impl() {
+ handles_.clear();
+ plugins_.clear();
+}
+
+void plugin_manager_impl::load_plugins() {
+ {
+ std::lock_guard<std::mutex> its_lock_start_stop(loader_mutex_);
+ if (plugins_loaded_) {
+ return;
+ }
+ plugins_loaded_ = true;
+ }
+
+ // Get plug-ins libraries from environment
+ std::vector<std::string> plugins;
+ const char *its_plugins = getenv(VSOMEIP_ENV_LOAD_PLUGINS);
+ if (nullptr != its_plugins) {
+ std::string token;
+ std::stringstream ss(its_plugins);
+ while(std::getline(ss, token, ',')) {
+ plugins.push_back(token);
+ }
+ }
+
+ std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
+ // Load plug-in info from libraries parsed before
+ for (const auto& plugin_name : plugins) {
+ void* handle = load_library(plugin_name);
+ plugin_init_func its_init_func = reinterpret_cast<plugin_init_func>(
+ load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL));
+ if (its_init_func) {
+ create_plugin_func its_create_func = (*its_init_func)();
+ if (its_create_func) {
+ auto its_plugin = (*its_create_func)();
+ if (its_plugin) {
+ handles_[its_plugin->get_plugin_type()][plugin_name] = handle;
+ switch (its_plugin->get_plugin_type()) {
+ case plugin_type_e::APPLICATION_PLUGIN:
+ if (its_plugin->get_plugin_version()
+ == VSOMEIP_APPLICATION_PLUGIN_VERSION) {
+ add_plugin(its_plugin, plugin_name);
+ } else {
+ VSOMEIP_ERROR << "Plugin version mismatch. "
+ << "Ignoring application plugin "
+ << its_plugin->get_plugin_name();
+ }
+ break;
+ case plugin_type_e::PRE_CONFIGURATION_PLUGIN:
+ if (its_plugin->get_plugin_version()
+ == VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION) {
+ add_plugin(its_plugin, plugin_name);
+ } else {
+ VSOMEIP_ERROR << "Plugin version mismatch. Ignoring "
+ << "pre-configuration plugin "
+ << its_plugin->get_plugin_name();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+std::shared_ptr<plugin> plugin_manager_impl::get_plugin(plugin_type_e _type, std::string _name) {
+ std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
+ auto its_type = plugins_.find(_type);
+ if (its_type != plugins_.end()) {
+ auto its_name = its_type->second.find(_name);
+ if (its_name != its_type->second.end()) {
+ return its_name->second;
+ }
+ }
+ return load_plugin(_name, _type, 1);
+}
+
+std::shared_ptr<plugin> plugin_manager_impl::load_plugin(const std::string& _library,
+ plugin_type_e _type, uint32_t _version) {
+ void* handle = load_library(_library);
+ plugin_init_func its_init_func = reinterpret_cast<plugin_init_func>(
+ load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL));
+ if (its_init_func) {
+ create_plugin_func its_create_func = (*its_init_func)();
+ if (its_create_func) {
+ handles_[_type][_library] = handle;
+ auto its_plugin = (*its_create_func)();
+ if (its_plugin) {
+ if (its_plugin->get_plugin_type() == _type
+ && its_plugin->get_plugin_version() == _version) {
+ add_plugin(its_plugin, _library);
+ return its_plugin;
+ } else {
+ VSOMEIP_ERROR << "Plugin version mismatch. Ignoring plugin "
+ << its_plugin->get_plugin_name();
+ }
+ }
+ }
+ }
+ return nullptr;
+}
+
+bool plugin_manager_impl::unload_plugin(plugin_type_e _type) {
+ std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
+ const auto found_handle = handles_.find(_type);
+ if (found_handle != handles_.end()) {
+ for (const auto& its_name : found_handle->second) {
+#ifdef _WIN32
+ FreeLibrary((HMODULE)its_name.second);
+#else
+ if (dlclose(its_name.second)) {
+ VSOMEIP_ERROR << "Unloading failed: (" << dlerror() << ")";
+ }
+#endif
+ }
+ } else {
+ VSOMEIP_ERROR << "plugin_manager_impl::unload_plugin didn't find plugin"
+ << " type:" << (int)_type;
+ return false;
+ }
+ return plugins_.erase(_type);
+}
+
+void plugin_manager_impl::add_plugin(const std::shared_ptr<plugin> &_plugin, const std::string& _name) {
+ plugins_[_plugin->get_plugin_type()][_name] = _plugin;
+}
+
+void * plugin_manager_impl::load_library(const std::string &_path) {
+#ifdef _WIN32
+ return LoadLibrary(_path.c_str());
+#else
+ return dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
+#endif
+}
+
+void * plugin_manager_impl::load_symbol(void * _handle,
+ const std::string &_symbol) {
+ void * its_symbol = 0;
+#ifdef _WIN32
+ HINSTANCE hDLL = (HINSTANCE)_handle;
+ if (hDLL != NULL) {
+
+ typedef UINT(CALLBACK* LPFNDLLFUNC1)(DWORD, UINT);
+
+ LPFNDLLFUNC1 lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, _symbol.c_str());
+ if (!lpfnDllFunc1) {
+ FreeLibrary(hDLL);
+ std::cerr << "Loading symbol \"" << _symbol << "\" failed (" << GetLastError() << ")" << std::endl;
+ }
+ else {
+ its_symbol = lpfnDllFunc1;
+ }
+ }
+#else
+ if (0 != _handle) {
+ its_symbol = dlsym(_handle, _symbol.c_str());
+ const char *dlsym_error = dlerror();
+ if (dlsym_error) {
+ VSOMEIP_INFO << "Cannot load symbol : " << _symbol << " : " << dlsym_error;
+ dlclose(_handle);
+ }
+ } else {
+ VSOMEIP_ERROR << "Loading failed: (" << dlerror() << ")";
+ }
+#endif
+ return (its_symbol);
+}
+
+} // namespace vsomeip_v3