#include "plugin.h" #include #include #include #include #include namespace dll = boost::dll; namespace fs = std::filesystem; using namespace std::string_literals; PluginLoader::PluginLoader(Config& config): m_config{config} { } void PluginLoader::load_plugins() { const auto& plugin_directories{m_config.PluginDirectories()}; for (const auto& dir: plugin_directories) { for (auto& path: fs::recursive_directory_iterator(dir)) { if (path.is_regular_file() && path.path().extension() == ".so"s) { dll::fs::path lib_path{path.path()}; try { boost::shared_ptr plugin = dll::import(lib_path, "webserver_plugin", dll::load_mode::append_decorations); if (plugin) { if (plugin->version() != webserver_plugin_interface::interface_version) throw std::runtime_error("Bad interface version for "s + path.path().generic_string() + ": "s + std::to_string(plugin->version()) + " vs. "s + std::to_string(webserver_plugin_interface::interface_version)); std::string name{plugin->name()}; if (m_plugins.find(name) != m_plugins.end()) throw std::runtime_error("Plugin already exists: "s + name); std::cout << "Found plugin: " << name << " (" << path.path().string() << "), "; if (m_config.PluginIsConfigured(name)) { std::cout << "loading."; m_plugins.emplace(plugin->name(), plugin); } else { std::cout << "ignored (not configured)."; } std::cout << std::endl; } else std::cout << "Can't load plugin from " << path.path().generic_string() << std::endl; } catch (const std::exception& ex) { std::cout << "Can't load plugin from " << path.path().generic_string() << ": " << ex.what() << std::endl; } } } } } // validate config regarding plugins bool PluginLoader::validate_config() { const auto& sites{m_config.Sites()}; for (const auto& site: sites) { for (const auto& path: site.second.paths) { // path must contain target and plugin auto it {path.params.find("target")}; if (it == path.params.end()) { std::cout << "Path " << path.requested << " for site " << site.first << " is missing target specification." << std::endl; return false; } it = path.params.find("plugin"); if (it == path.params.end()) { std::cout << "Path " << path.requested << " for site " << site.first << " is missing plugin specification." << std::endl; return false; } std::string plugin {it->second}; // check if plugin exists if (m_plugins.find(plugin) == m_plugins.end()) { std::cout << "Configured plugin " << plugin << " not found" << std::endl; return false; } } } return true; } plugins_container_type& PluginLoader::get_plugins() { return m_plugins; }