Mercurial > irccd
view libirccd/irccd/daemon/plugin_service.cpp @ 628:27587ff92a64
Misc: update copyrights
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 09 Jan 2018 14:06:40 +0100 |
parents | 986ed3a7575d |
children |
line wrap: on
line source
/* * plugin_service.cpp -- plugin service * * Copyright (c) 2013-2018 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <irccd/config.hpp> #include <irccd/string_util.hpp> #include <irccd/system.hpp> #include "irccd.hpp" #include "logger.hpp" #include "plugin_service.hpp" namespace irccd { namespace { template <typename Map> Map to_map(const config& conf, const std::string& section) { Map ret; for (const auto& opt : conf.doc().get(section)) ret.emplace(opt.key(), opt.value()); return ret; } } // !namespace plugin_service::plugin_service(irccd& irccd) noexcept : irccd_(irccd) { } plugin_service::~plugin_service() { for (const auto& plugin : plugins_) { try { plugin->on_unload(irccd_); } catch (const std::exception& ex) { irccd_.log().warning() << "plugin: " << plugin->name() << ": " << ex.what() << std::endl; } } } bool plugin_service::has(const std::string& name) const noexcept { return std::count_if(plugins_.cbegin(), plugins_.cend(), [&] (const auto& plugin) { return plugin->name() == name; }) > 0; } std::shared_ptr<plugin> plugin_service::get(const std::string& name) const noexcept { auto it = std::find_if(plugins_.begin(), plugins_.end(), [&] (const auto& plugin) { return plugin->name() == name; }); if (it == plugins_.end()) return nullptr; return *it; } std::shared_ptr<plugin> plugin_service::require(const std::string& name) const { auto plugin = get(name); if (!plugin) throw plugin_error(plugin_error::not_found, name); return plugin; } void plugin_service::add(std::shared_ptr<plugin> plugin) { plugins_.push_back(std::move(plugin)); } void plugin_service::add_loader(std::unique_ptr<plugin_loader> loader) { loaders_.push_back(std::move(loader)); } plugin_config plugin_service::config(const std::string& id) { return to_map<plugin_config>(irccd_.config(), string_util::sprintf("plugin.%s", id)); } plugin_formats plugin_service::formats(const std::string& id) { return to_map<plugin_formats>(irccd_.config(), string_util::sprintf("format.%s", id)); } plugin_paths plugin_service::paths(const std::string& id) { auto defaults = to_map<plugin_paths>(irccd_.config(), "paths"); auto paths = to_map<plugin_paths>(irccd_.config(), string_util::sprintf("paths.%s", id)); // Fill defaults paths. if (!defaults.count("cache")) defaults.emplace("cache", sys::cachedir() + "/plugin/" + id); if (!defaults.count("data")) paths.emplace("data", sys::datadir() + "/plugin/" + id); if (!defaults.count("config")) paths.emplace("config", sys::sysconfigdir() + "/plugin/" + id); // Now fill missing fields. if (!paths.count("cache")) paths.emplace("cache", defaults["cache"]); if (!paths.count("data")) paths.emplace("data", defaults["data"]); if (!paths.count("config")) paths.emplace("config", defaults["config"]); return paths; } std::shared_ptr<plugin> plugin_service::open(const std::string& id, const std::string& path) { for (const auto& loader : loaders_) { auto plugin = loader->open(id, path); if (plugin) return plugin; } return nullptr; } std::shared_ptr<plugin> plugin_service::find(const std::string& id) { for (const auto& loader : loaders_) { auto plugin = loader->find(id); if (plugin) return plugin; } return nullptr; } void plugin_service::load(std::string name, std::string path) { if (has(name)) throw plugin_error(plugin_error::already_exists, name); std::shared_ptr<plugin> plugin; if (path.empty()) plugin = find(name); else plugin = open(name, std::move(path)); if (!plugin) throw plugin_error(plugin_error::not_found, name); plugin->set_config(config(name)); plugin->set_formats(formats(name)); plugin->set_paths(paths(name)); exec(plugin, &plugin::on_load, irccd_); add(std::move(plugin)); } void plugin_service::reload(const std::string& name) { auto plugin = get(name); if (!plugin) throw plugin_error(plugin_error::not_found, name); exec(plugin, &plugin::on_reload, irccd_); } void plugin_service::unload(const std::string& name) { auto it = std::find_if(plugins_.begin(), plugins_.end(), [&] (const auto& plugin) { return plugin->name() == name; }); if (it == plugins_.end()) throw plugin_error(plugin_error::not_found, name); // Erase first, in case of throwing. auto save = *it; plugins_.erase(it); exec(save, &plugin::on_unload, irccd_); } void plugin_service::load(const class config& cfg) noexcept { for (const auto& option : cfg.section("plugins")) { if (!string_util::is_identifier(option.key())) continue; auto name = option.key(); auto p = get(name); // Reload the plugin if already loaded. if (p) { p->set_config(config(name)); p->set_formats(formats(name)); p->set_paths(paths(name)); } else { try { load(name, option.value()); } catch (const std::exception& ex) { irccd_.log().warning(ex.what()); } } } } } // !irccd