4 * @brief Settings manager implementation.
6 * @author Ossama Othman @<ossama.othman@@intel.com@>
9 * Copyright 2012, 2013 Intel Corporation All Rights Reserved.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation;
14 * version 2.1 of the License.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301 USA
29 #include "manager.hpp"
30 #include <settingsd/plugin.hpp>
31 #include <settingsd/response_callback.hpp>
32 #include <settingsd/json_glib_traits.hpp>
33 #include <settingsd/unique_ptr.hpp>
37 #include <boost/filesystem.hpp>
40 ivi::settings::manager::manager(std::string const & dir)
49 ivi::settings::manager::~manager()
54 ivi::settings::manager::register_setting(std::unique_ptr<plugin> p)
56 std::string const & id = p->id();
59 settings_.insert(std::make_pair(id, std::move(p)));
62 std::cerr << "Settings plugin registration for \""
63 << id << "\" failed." << std::endl;
69 ivi::settings::manager::load_settings(std::string const & dir)
71 if (dir.length() == 0)
72 throw std::invalid_argument("Zero length settings plugin "
75 namespace fs = boost::filesystem;
77 // Find all settings plugins in the plugin directory.
78 fs::path settings_dir(dir);
80 if (fs::is_directory(settings_dir)) {
81 // Iterate over directory entries, create settings instances
82 // for each settings plugin, and store in settings map.
84 fs::directory_iterator const end;
85 for (fs::directory_iterator i(settings_dir); i != end; ++i) {
87 fs::path const & plugin_path = (*i).path();
89 // Verify that the plugin is actually a file with the
90 // appropriate extension (e.g. ".so").
92 // Note that the .extension() method returns a string like
93 // ".so" whereas G_MODULE_SUFFIX is preprocessor symbol/string
94 // like "so". We prepend a period to G_MODULE_SUFFIX using
95 // standard string literal concatenation.
96 if (!fs::is_regular_file(plugin_path)
97 || plugin_path.extension() != "." G_MODULE_SUFFIX)
100 std::string const & plugin_name = plugin_path.string();
102 std::unique_ptr<loader> plugin(new loader(plugin_name, *this));
104 loaders_.push_back(std::move(plugin));
106 catch (std::exception & e) {
108 * @todo I really hate catching an exception like this, but I
109 * really don't want to resort to a construct/init()
110 * style of object initialization. Fix.
112 std::cerr << "Error loading plugin: " << e.what() << "\n";
115 std::cerr << "Ignoring unknown exception thrown from plugin.\n";
119 if (settings_.size() == 0) {
120 throw std::invalid_argument("Settings plugin directory \""
121 + dir + "\" has no plugins.");
123 std::cerr << "Registered settings plugins:\n";
124 for (auto const & i : settings_)
125 std::cerr << "\t" << i.first << '\n';
128 throw std::invalid_argument("Settings plugin directory \""
129 + dir + "\" does not exist.");
134 ivi::settings::manager::dispatch(std::string request,
137 if (request.empty()) {
138 response_callback response(wsi, std::string(), std::string());
139 response.send_error("Empty settings request.");
143 unique_ptr<JsonParser> const parser(json_parser_new());
144 json_parser_load_from_data(parser.get(), request.c_str(), -1, nullptr);
146 JsonReader * const reader =
147 json_reader_new(json_parser_get_root(parser.get()));
148 unique_ptr<JsonReader> const safe_reader(reader);
150 // Retrieve setting name and transcation ID from the JSON request
152 char const * type = nullptr;
153 if (json_reader_read_member(reader, "type")) {
154 type = json_reader_get_string_value(reader);
156 json_reader_end_member(reader);
159 * @todo Allow transaction ID to be null?
161 char const * transaction_id = "";
162 if (json_reader_read_member(reader, "transactionid")) {
163 transaction_id = json_reader_get_string_value(reader);
165 json_reader_end_member(reader);
167 response_callback response(wsi,
168 type == nullptr ? "" : type,
172 if (type != nullptr) {
173 // Dispatch the request to the corresponding settings plugin.
174 auto i = settings_.find(type);
175 if (i != settings_.end())
176 (*i).second->handle_request(request, response);
179 std::string("Settings type \"")
180 + type + "\" not supported.";
182 response.send_error(error);
186 "Settings type not specified in request.\n"
187 "Supported plugins:\n";
189 for (auto const & i : settings_)
190 error += "\t" + i.first + "\n";
192 response.send_error(error);
197 ivi::settings::manager::subscribe_client(libwebsocket * wsi)
199 std::lock_guard<std::mutex> lock(mutex_);
201 send_callbacks_.emplace_back(wsi);
205 ivi::settings::manager::unsubscribe_client(libwebsocket * wsi)
207 std::lock_guard<std::mutex> lock(mutex_);
209 auto const end = send_callbacks_.end();
210 for (auto i = send_callbacks_.begin(); i != end; ++i)
212 send_callbacks_.erase(i);
216 ivi::settings::manager::send_event(
217 unique_ptr<JsonBuilder> const & builder) const
221 std::lock_guard<std::mutex> lock(mutex_);
223 for (auto c : send_callbacks_)
224 if (!c.send_payload("event", builder))
234 // indent-tabs-mode: nil