diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-04-04 13:21:59 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-04-04 13:21:59 +0200 |
commit | 95d5acc8c7e60255b19e7084e374eb26cc5d0ba3 (patch) | |
tree | d2ebf474c5076341a30cdeb8035f1843db240d16 | |
parent | 2be63668af1cadf846ae2d44a0fd5c909ceaf47e (diff) |
Versioned plugins
-rw-r--r-- | plugin.cpp | 48 | ||||
-rw-r--r-- | plugin.h | 18 | ||||
-rw-r--r-- | plugin_interface.h | 3 | ||||
-rw-r--r-- | webserver.cpp | 8 |
4 files changed, 67 insertions, 10 deletions
@@ -1,21 +1,22 @@ #include "plugin.h" #include <boost/dll/import.hpp> -#include <boost/shared_ptr.hpp> #include <boost/filesystem.hpp> #include <iostream> #include <filesystem> -#include "plugin_interface.h" - namespace dll = boost::dll; namespace fs = std::filesystem; using namespace std::string_literals; -void load_plugins(Config& config) +PluginLoader::PluginLoader(Config& config): m_config{config} +{ +} + +void PluginLoader::load_plugins() { - const auto& plugin_directories{config.PluginDirectories()}; + const auto& plugin_directories{m_config.PluginDirectories()}; for (const auto& dir: plugin_directories) { for (auto& path: fs::recursive_directory_iterator(dir)) { @@ -23,14 +24,45 @@ void load_plugins(Config& config) dll::fs::path lib_path{path.path()}; + try { boost::shared_ptr<webserver_plugin_interface> plugin = dll::import<webserver_plugin_interface>(lib_path, "webserver_plugin", dll::load_mode::append_decorations); - if (!plugin) - throw std::runtime_error("Can't load plugin"); + 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::cout << "Plugin: " << plugin->generate_page("a") << std::endl; + if (m_plugins.contains(plugin->name())) + throw std::runtime_error("Plugin already exists: "s + plugin->name()); + + m_plugins.emplace(plugin->name(), plugin); + + std::cout << "Found plugin: " << plugin->name() << 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; + } } } } } +bool PluginLoader::validate_config() +{ + const auto& sites{m_config.Sites()}; + + for (const auto& site: sites) { + for (const auto& path: site.paths) { + if (path.type == Plugin) { + std::string plugin {path.params.at("plugin")}; + + if (!m_plugins.contains(plugin)) { + std::cout << "Configured plugin " << plugin << " not found" << std::endl; + return false; + } + } + } + } + return true; +} + @@ -1,5 +1,21 @@ #pragma once #include "config.h" +#include "plugin_interface.h" -void load_plugins(Config& config); +#include <boost/shared_ptr.hpp> + +#include <memory> +#include <unordered_map> + +class PluginLoader +{ + Config& m_config; + std::unordered_map<std::string, boost::shared_ptr<webserver_plugin_interface>> m_plugins; + +public: + PluginLoader(Config& config); + + void load_plugins(); // Load all plugins from configured paths + bool validate_config(); // Check if all configured plugins exist +}; diff --git a/plugin_interface.h b/plugin_interface.h index 72da0b9..e67d20a 100644 --- a/plugin_interface.h +++ b/plugin_interface.h @@ -6,6 +6,9 @@ class BOOST_SYMBOL_VISIBLE webserver_plugin_interface { public: + static const int interface_version {1}; + virtual int version() { return interface_version; } + virtual std::string name() = 0; virtual std::string generate_page(std::string path) = 0; virtual ~webserver_plugin_interface(){} }; diff --git a/webserver.cpp b/webserver.cpp index 2574272..3f7a2a3 100644 --- a/webserver.cpp +++ b/webserver.cpp @@ -33,7 +33,13 @@ int main(int argc, char* argv[]) try { Config config{config_filename}; - load_plugins(config); + + PluginLoader plugin_loader(config); + plugin_loader.load_plugins(); + + if (!plugin_loader.validate_config()) + throw std::runtime_error("Couldn't find all configured plugins."); + return http_server(argc, argv); } catch (const std::exception& ex) { std::cout << "Error: " << ex.what() << std::endl; |