summaryrefslogtreecommitdiff
path: root/lib/manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/manager.cpp')
-rw-r--r--lib/manager.cpp192
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: