diff options
Diffstat (limited to 'lib/manager.cpp')
-rw-r--r-- | lib/manager.cpp | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/lib/manager.cpp b/lib/manager.cpp new file mode 100644 index 0000000..0b497c9 --- /dev/null +++ b/lib/manager.cpp @@ -0,0 +1,192 @@ +/** + * @file manager.cpp + * + * @brief Settings manager implementation. + * + * @author Ossama Othman @<ossama.othman@@intel.com@> + * + * @copyright @par + * Copyright 2012, 2013 Intel Corporation All Rights Reserved. + * @par + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * @par + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * @par + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + + +#include "config.hpp" +#include "manager.hpp" +#include <settingsd/plugin.hpp> +#include <settingsd/response_callback.hpp> +#include <settingsd/json_glib_traits.hpp> +#include <settingsd/smart_ptr.hpp> + +#include <gmodule.h> + +#include <boost/filesystem.hpp> + + +ivi::settings::manager::manager(std::string const & dir) + : loaders_() + , settings_() +{ + load_settings(dir); +} + +ivi::settings::manager::~manager() +{ +} + +bool +ivi::settings::manager::register_setting(std::unique_ptr<plugin> p) +{ + std::string const & id = p->id(); + + auto const result = + settings_.insert(std::make_pair(id, std::move(p))); + + if (!result.second) + std::cerr << "Settings plugin registration for \"" + << id << "\" failed." << std::endl; + + return result.second; +} + +void +ivi::settings::manager::load_settings(std::string const & dir) +{ + if (dir.length() == 0) + throw std::logic_error("Zero length settings plugin directory path."); + + namespace fs = boost::filesystem; + + // Find all settings plugins in the plugin directory. + fs::path settings_dir(dir); + + if (fs::is_directory(settings_dir)) { + // Iterate over directory entries, create settings instances + // for each settings plugin, and store in settings map. + + fs::directory_iterator const end; + for (fs::directory_iterator i(settings_dir); i != end; ++i) { + try { + fs::path const & plugin_path = (*i).path(); + + // Verify that the plugin is actually a file with the + // appropriate extension (e.g. ".so"). + // + // Note that the .extension() method returns a string like + // ".so" whereas G_MODULE_SUFFIX is preprocessor symbol/string + // like "so". We prepend a period to G_MODULE_SUFFIX using + // standard string literal concatenation. + if (!fs::is_regular_file(plugin_path) + || plugin_path.extension() != "." G_MODULE_SUFFIX) + continue; + + std::string const & plugin_name = plugin_path.string(); + + std::unique_ptr<loader> plugin(new loader(plugin_name, *this)); + + loaders_.push_back(std::move(plugin)); + } + catch (std::logic_error & e) { + /** + * @todo I really hate catching an exception like this, but I + * really don't want to resort to a construct/init() + * style of object initialization. Fix. + */std::cerr << "Error loading plugin: " << e.what() << "\n"; + } + } + + if (settings_.size() == 0) { + std::cerr << "Settings plugin directory \"" + << dir << "\" has no plugins.\n"; + } else { + std::cerr << "Registered settings plugins: \n"; + for (auto const & i : settings_) + std::cerr << "\t" << i.first << '\n'; + } + } else { + std::cerr << "Settings plugin directory \"" + << dir << "\" does not exist.\n"; + } +} + +void +ivi::settings::manager::dispatch(std::string request, + struct libwebsocket * wsi) +{ + if (request.empty()) { + response_callback response(wsi, std::string(), std::string()); + response.send_error("Empty settings request."); + } + + smart_ptr<JsonParser> const parser(json_parser_new()); + json_parser_load_from_data(parser.get(), request.c_str(), -1, nullptr); + + JsonReader * const reader = json_reader_new(json_parser_get_root(parser.get())); + smart_ptr<JsonReader> const safe_reader(reader); + + // Retrieve setting name and transcation ID from the JSON request + // string. + char const * type = nullptr; + if (json_reader_read_member(reader, "type")) { + type = json_reader_get_string_value(reader); + } + json_reader_end_member(reader); + + /** + * @todo Allow transaction ID to be null? + */ + char const * transaction_id = ""; + if (json_reader_read_member(reader, "transactionid")) { + transaction_id = json_reader_get_string_value(reader); + } + json_reader_end_member(reader); + + response_callback response(wsi, + type == nullptr ? "" : type, + transaction_id); + + std::string error; + if (type != nullptr) { + // Dispatch the request to the corresponding settings plugin. + auto i = settings_.find(type); + if (i != settings_.end()) + (*i).second->handle_request(request, response); + else { + error = + std::string("Settings type \"") + + type + "\" not supported."; + + response.send_error(error); + } + } else { + error = + "Settings type not specified in request.\n" + "Supported plugins:\n"; + + for (auto const & i : settings_) + error += "\t" + i.first + "\n"; + + response.send_error(error); + } +} + + +// Local Variables: +// mode:c++ +// c-basic-offset:2 +// indent-tabs-mode: nil +// End: |