--- /dev/null
+#ifndef __PLUGIN_MANAGER_H__
+#define __PLUGIN_MANAGER_H__
+
+#include <vector>
+
+#include "PluginData.h"
+#include "PluginProxy.h"
+#include "module/AbstractModule.h"
+
+namespace nncc
+{
+namespace contrib
+{
+namespace module
+{
+namespace plugin
+{
+
+class PluginManagerException : public foundation::Exception
+{
+public:
+ PluginManagerException() = delete;
+ explicit PluginManagerException(const std::string &info);
+ PluginManagerException(Exception &e, const std::string &info);
+};
+
+class PluginManager
+{
+public:
+ static const std::string paramPluginPath;
+ static const std::string paramVerboseLoading;
+ static const std::string paramPluginHelp;
+
+ PluginManager();
+
+ void setConfig(std::shared_ptr<config::DataList> conf);
+ void loadPlugins(std::vector<AbstractModule *> &modules);
+ static PluginManager &getInstance();
+ void help() const;
+
+ friend std::ostream &operator<<(std::ostream &st, const PluginManager &mod);
+
+private:
+ std::vector<std::string> getPluginPathList();
+
+ void applyParam(const std::string &name);
+ void applyParam(const std::string &name, const std::string &value);
+
+ std::vector<AbstractModule *> _modules;
+
+ std::vector<std::shared_ptr<PluginProxy>> _plugins;
+ std::shared_ptr<config::DataList> _config;
+ std::string _pluginsPath;
+ std::vector<config::PluginParam> _supportedParams;
+ bool _showPluginInfo;
+};
+
+} // namespace plugin
+} // namespace module
+} // namespace contrib
+} // namespace nncc
+
+#endif // __PLUGIN_MANAGER_H__
--- /dev/null
+#include <iostream>
+#include <dlfcn.h>
+#include <dirent.h>
+#include <cstring>
+
+#include "module/plugin/PluginProxy.h"
+#include "module/plugin/PluginSession.h"
+#include "module/plugin/PluginManager.h"
+
+#include "PluginException.h"
+#include "ConfigException.h"
+
+namespace nncc
+{
+namespace contrib
+{
+namespace module
+{
+namespace plugin
+{
+
+const std::string PluginManager::paramPluginPath = "plugins-path";
+const std::string PluginManager::paramVerboseLoading = "plugins-verbose";
+const std::string PluginManager::paramPluginHelp = "plugins-help";
+
+std::vector<std::string> PluginManager::getPluginPathList() {
+ std::vector<std::string> pluginPathList;
+ std::vector<std::string> dirList;
+
+ // Push first path
+ dirList.clear();
+ dirList.push_back(_pluginsPath);
+
+ while (!dirList.empty()) {
+ const auto curPluginsPath = dirList.back();
+ dirList.pop_back();
+
+ DIR *dir;
+ struct dirent *ent;
+ if ((dir = opendir(curPluginsPath.c_str())) != nullptr) {
+ while ((ent = readdir(dir)) != nullptr) {
+ if ((ent->d_type == DT_DIR) && (std::string(ent->d_name) != ".") &&
+ (std::string(ent->d_name) != "..")) {
+ std::string f = curPluginsPath + std::string("/") + std::string(ent->d_name);
+ dirList.push_back(f);
+ } else if (strstr(ent->d_name, ".so") != nullptr) {
+ std::string f = curPluginsPath + std::string("/") + std::string(ent->d_name);
+ pluginPathList.push_back(f);
+ }
+ }
+ closedir(dir);
+ } else {
+ // could not open directory
+ // TODO add some log
+ }
+ }
+ return pluginPathList;
+}
+
+void PluginManager::loadPlugins(std::vector<AbstractModule *> &modules) {
+ std::cout << "Current plugin path is <" << _pluginsPath << ">" << std::endl;
+ auto plugins = getPluginPathList();
+
+ for (const auto &pluginPath : plugins) {
+ try {
+ auto pl = PluginProxy::create(pluginPath);
+ auto plInst = pl->getPluginInstance();
+ std::shared_ptr<config::AbstractSession> session = std::make_shared<config::PluginSession>();
+ plInst->setSession(session);
+ plInst->fillSession();
+
+ if (_showPluginInfo)
+ std::cout << "plugin <" + pluginPath + ">: {" << std::endl
+ << "name <" + pl->getPluginName() + "> " << std::endl
+ << dynamic_cast<config::PluginSession &>(*session) << std::endl
+ << "}" << std::endl;
+
+ _plugins.push_back(pl);
+ }
+ catch (PluginException &e) {
+ if (_showPluginInfo)
+ std::cout << "plugin <" + pluginPath << ">: {" << std::endl
+ << "bad plugin :" << e.what() << std::endl
+ << "}" << std::endl;
+ }
+ catch (config::DataException &eOp) {
+ std::cout << "bad plugin info <" + pluginPath << ">:" << eOp.what() << std::endl;
+ }
+ }
+
+ if (_plugins.empty())
+ throw PluginManagerException("No plugins found");
+
+ // Fill modules by plugins
+ for (auto &pl : _plugins) {
+ for (auto m : modules) {
+ auto session =
+ dynamic_cast<config::PluginSession *>(pl->getPluginInstance()->getSession().get());
+ if (m->getModuleType() == session->getPluginType()) {
+ m->registerPlugin(pl);
+ break;
+ }
+ }
+ }
+
+ for (auto m : modules) {
+ std::cout << *m;
+ }
+}
+
+std::ostream &operator<<(std::ostream &st, const PluginManager &mod) {
+ for (const auto &pl : mod._plugins)
+ st << pl << std::endl;
+ return st;
+}
+
+PluginManager &PluginManager::getInstance() {
+ static PluginManager instance;
+ return instance;
+}
+
+void PluginManager::setConfig(std::shared_ptr<config::DataList> conf) {
+ try {
+ _config = conf;
+ auto plist = config::DataList::intersection(*conf, _supportedParams);
+
+ for (auto &p : plist->getElements()) {
+ if (p.second.hasValue())
+ applyParam(p.second.getName(), p.second.getValue());
+ else
+ applyParam(p.second.getName());
+ }
+ }
+ catch (ConfigException &e) {
+ throw PluginManagerException(e, "config error");
+ }
+ catch (PluginException &e) {
+ throw PluginManagerException(e, "plugin error");
+ }
+}
+
+void PluginManager::applyParam(const std::string &name) {
+ if (name == paramPluginHelp) {
+ help();
+ } else if (name == paramVerboseLoading) {
+ _showPluginInfo = true;
+ } else {
+ std::string info =
+ "[ERR]" + std::string(__func__) + " <" + name + ">" + " WRONG SINGLE PARAMETER";
+ throw ConfigException(info);
+ }
+}
+
+void PluginManager::applyParam(const std::string &name, const std::string &value) {
+ std::cout << __func__ << " <" + name + "> = " + value << std::endl;
+ if (name == paramPluginPath) {
+ _pluginsPath = value;
+ } else {
+ help();
+ std::string info =
+ "[ERR]" + std::string(__func__) + " <" + name + "> = " + value + " WRONG PARAMETER";
+ throw ConfigException(info);
+ }
+}
+
+void PluginManager::help() const {
+ std::cout << "HELP" << std::endl;
+
+ for (auto &p : _supportedParams)
+ if (!p.isOptional())
+ std::cout << "--" << p.getName() << " ";
+
+ for (auto &p : _supportedParams)
+ if (p.isOptional())
+ std::cout << "[--" << p.getName() << "] ";
+ std::cout << std::endl;
+
+ for (auto &p : _supportedParams)
+ std::cout << p << std::endl;
+}
+
+PluginManager::PluginManager() : _config(nullptr), _showPluginInfo(false) {
+ _supportedParams = {{paramPluginPath, "[path]", true},
+ {paramVerboseLoading, "[show found plugins info]", true},
+ {paramPluginHelp, "[help]", true}};
+}
+
+PluginManagerException::PluginManagerException(const std::string &info) : Exception(info) {}
+
+PluginManagerException::PluginManagerException(Exception &e, const std::string &info)
+ : Exception(e, info) {
+}
+
+} // namespace plugin
+} // namespace module
+} // namespace contrib
+} // namespace nncc