| 1 | #include "StdAfx.h"
|
|---|
| 2 |
|
|---|
| 3 | #include "settings_manager_impl.h"
|
|---|
| 4 |
|
|---|
| 5 | #include <settings/settings_ini.hpp>
|
|---|
| 6 | #include <settings/settings_dummy.hpp>
|
|---|
| 7 | #include <settings/settings_http.hpp>
|
|---|
| 8 | #ifdef WIN32
|
|---|
| 9 | #include <settings/settings_old.hpp>
|
|---|
| 10 | #include <settings/settings_registry.hpp>
|
|---|
| 11 | #endif
|
|---|
| 12 |
|
|---|
| 13 | #include <settings/client/settings_proxy.hpp>
|
|---|
| 14 | #include <settings/client/settings_client.hpp>
|
|---|
| 15 | #include <file_helpers.hpp>
|
|---|
| 16 | #include <config.h>
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 | static settings_manager::NSCSettingsImpl* settings_impl = NULL;
|
|---|
| 20 |
|
|---|
| 21 | namespace settings_manager {
|
|---|
| 22 | // Alias to make handling "compatible" with old syntax
|
|---|
| 23 |
|
|---|
| 24 | inline NSCSettingsImpl* internal_get() {
|
|---|
| 25 | if (settings_impl == NULL)
|
|---|
| 26 | throw settings::settings_exception(_T("Settings has not been initiated!"));
|
|---|
| 27 | return settings_impl;
|
|---|
| 28 | }
|
|---|
| 29 | nscapi::settings_helper::settings_impl_interface_ptr get_proxy() {
|
|---|
| 30 | return nscapi::settings_helper::settings_impl_interface_ptr(new settings_client::settings_proxy(internal_get()));
|
|---|
| 31 | }
|
|---|
| 32 | settings::instance_ptr get_settings() {
|
|---|
| 33 | return internal_get()->get();
|
|---|
| 34 | }
|
|---|
| 35 | settings::instance_ptr get_settings_no_wait() {
|
|---|
| 36 | return internal_get()->get_no_wait();
|
|---|
| 37 | }
|
|---|
| 38 | settings::settings_core* get_core() {
|
|---|
| 39 | return internal_get();
|
|---|
| 40 | }
|
|---|
| 41 | void destroy_settings() {
|
|---|
| 42 | settings_manager::NSCSettingsImpl* old = settings_impl;
|
|---|
| 43 | settings_impl = NULL;
|
|---|
| 44 | delete old;
|
|---|
| 45 | }
|
|---|
| 46 |
|
|---|
| 47 | std::wstring NSCSettingsImpl::find_file(std::wstring file, std::wstring fallback) {
|
|---|
| 48 | // @todo: replace this with a proper parser!
|
|---|
| 49 | if (file.size() == 0)
|
|---|
| 50 | file = fallback;
|
|---|
| 51 | return provider_->expand_path(file);
|
|---|
| 52 | }
|
|---|
| 53 | std::wstring NSCSettingsImpl::expand_path(std::wstring file) {
|
|---|
| 54 | return provider_->expand_path(file);
|
|---|
| 55 | }
|
|---|
| 56 |
|
|---|
| 57 |
|
|---|
| 58 | //////////////////////////////////////////////////////////////////////////
|
|---|
| 59 | /// Create an instance of a given type.
|
|---|
| 60 | /// Used internally to create instances of various settings types.
|
|---|
| 61 | ///
|
|---|
| 62 | /// @param type the type to create
|
|---|
| 63 | /// @param context the context to use
|
|---|
| 64 | /// @return a new instance of given type.
|
|---|
| 65 | ///
|
|---|
| 66 | /// @author mickem
|
|---|
| 67 | settings::instance_raw_ptr NSCSettingsImpl::create_instance(std::wstring key) {
|
|---|
| 68 | net::wurl url = net::parse(key);
|
|---|
| 69 | if (url.protocol.empty()) {
|
|---|
| 70 | url = net::parse(key + _T("://"));
|
|---|
| 71 | get_logger()->debug(__FILE__, __LINE__, _T("No driver specified attemtping to fake one: ") + url.to_string());
|
|---|
| 72 | }
|
|---|
| 73 | get_logger()->debug(__FILE__, __LINE__, _T("Creating instance for: ") + url.to_string());
|
|---|
| 74 | if (url.host.empty() && url.path.empty())
|
|---|
| 75 | key = _T("");
|
|---|
| 76 | #ifdef WIN32
|
|---|
| 77 | if (url.protocol == _T("old")) {
|
|---|
| 78 | old_ = true;
|
|---|
| 79 | if (key.empty())
|
|---|
| 80 | key = DEFAULT_CONF_OLD_LOCATION;
|
|---|
| 81 | return settings::instance_raw_ptr(new settings::OLDSettings(this, key));
|
|---|
| 82 | }
|
|---|
| 83 | if (url.protocol == _T("registry")) {
|
|---|
| 84 | if (key.empty())
|
|---|
| 85 | key = DEFAULT_CONF_REG_LOCATION;
|
|---|
| 86 | return settings::instance_raw_ptr(new settings::REGSettings(this, key));
|
|---|
| 87 | }
|
|---|
| 88 | #endif
|
|---|
| 89 | if (url.protocol == _T("ini")) {
|
|---|
| 90 | if (key.empty())
|
|---|
| 91 | key = DEFAULT_CONF_INI_LOCATION;
|
|---|
| 92 | return settings::instance_raw_ptr(new settings::INISettings(this, key));
|
|---|
| 93 | }
|
|---|
| 94 | if (url.protocol == _T("dummy")) {
|
|---|
| 95 | return settings::instance_raw_ptr(new settings::settings_dummy(this, key));
|
|---|
| 96 | }
|
|---|
| 97 | if (url.protocol == _T("http")) {
|
|---|
| 98 | return settings::instance_raw_ptr(new settings::settings_http(this, key));
|
|---|
| 99 | }
|
|---|
| 100 | throw settings::settings_exception(_T("Undefined settings protocol: ") + url.protocol);
|
|---|
| 101 | }
|
|---|
| 102 |
|
|---|
| 103 | bool NSCSettingsImpl::check_file(std::wstring file, std::wstring tag, std::wstring &key) {
|
|---|
| 104 | std::wstring tmp = provider_->expand_path(file);
|
|---|
| 105 | if (file_helpers::checks::exists(tmp)) {
|
|---|
| 106 | key = tag;
|
|---|
| 107 | return true;
|
|---|
| 108 | }
|
|---|
| 109 | return false;
|
|---|
| 110 | }
|
|---|
| 111 |
|
|---|
| 112 | std::wstring NSCSettingsImpl::expand_context(std::wstring key) {
|
|---|
| 113 | #ifdef WIN32
|
|---|
| 114 | if (key == _T("old"))
|
|---|
| 115 | return DEFAULT_CONF_OLD_LOCATION;
|
|---|
| 116 | if (key == _T("registry"))
|
|---|
| 117 | return DEFAULT_CONF_REG_LOCATION;
|
|---|
| 118 | #endif
|
|---|
| 119 | if (key == _T("ini"))
|
|---|
| 120 | return DEFAULT_CONF_INI_LOCATION;
|
|---|
| 121 | if (key == _T("dummy"))
|
|---|
| 122 | return _T("dummy://");
|
|---|
| 123 | return key;
|
|---|
| 124 | }
|
|---|
| 125 |
|
|---|
| 126 | bool NSCSettingsImpl::context_exists(std::wstring key) {
|
|---|
| 127 | net::wurl url = net::parse(key);
|
|---|
| 128 | if (url.protocol.empty())
|
|---|
| 129 | url = net::parse(expand_context(key));
|
|---|
| 130 | #ifdef WIN32
|
|---|
| 131 | if (url.protocol == _T("old"))
|
|---|
| 132 | return settings::OLDSettings::context_exists(this, key);
|
|---|
| 133 | if (url.protocol == _T("registry"))
|
|---|
| 134 | return settings::REGSettings::context_exists(this, key);
|
|---|
| 135 | #endif
|
|---|
| 136 | if (url.protocol == _T("ini"))
|
|---|
| 137 | return settings::INISettings::context_exists(this, key);
|
|---|
| 138 | if (url.protocol == _T("dummy"))
|
|---|
| 139 | return true;
|
|---|
| 140 | if (url.protocol == _T("http"))
|
|---|
| 141 | return true;
|
|---|
| 142 | return false;
|
|---|
| 143 | }
|
|---|
| 144 |
|
|---|
| 145 | bool NSCSettingsImpl::has_boot_conf() {
|
|---|
| 146 | return file_helpers::checks::exists(boot_.string());
|
|---|
| 147 | }
|
|---|
| 148 |
|
|---|
| 149 | //////////////////////////////////////////////////////////////////////////
|
|---|
| 150 | /// Boot the settings subsystem from the given file (boot.ini).
|
|---|
| 151 | ///
|
|---|
| 152 | /// @param file the file to use when booting.
|
|---|
| 153 | ///
|
|---|
| 154 | /// @author mickem
|
|---|
| 155 | void NSCSettingsImpl::boot(std::wstring key) {
|
|---|
| 156 | std::list<std::wstring> order;
|
|---|
| 157 | if (!key.empty()) {
|
|---|
| 158 | order.push_back(key);
|
|---|
| 159 | }
|
|---|
| 160 | boot_ = provider_->expand_path(BOOT_CONF_LOCATION);
|
|---|
| 161 | if (file_helpers::checks::exists(boot_.string())) {
|
|---|
| 162 | get_logger()->debug(__FILE__, __LINE__, _T("Boot.ini found in: ") + boot_.string());
|
|---|
| 163 | for (int i=0;i<20;i++) {
|
|---|
| 164 | std::wstring v = get_boot_string(_T("settings"), strEx::itos(i), _T(""));
|
|---|
| 165 | if (!v.empty())
|
|---|
| 166 | order.push_back(expand_context(v));
|
|---|
| 167 | }
|
|---|
| 168 | }
|
|---|
| 169 | if (order.size() == 0) {
|
|---|
| 170 | get_logger()->debug(__FILE__, __LINE__, _T("No entries found looking in (adding default): ") + boot_.string());
|
|---|
| 171 | order.push_back(DEFAULT_CONF_OLD_LOCATION);
|
|---|
| 172 | order.push_back(DEFAULT_CONF_INI_LOCATION);
|
|---|
| 173 | }
|
|---|
| 174 | int i=0;
|
|---|
| 175 | std::wstring boot_order;
|
|---|
| 176 | BOOST_FOREACH(std::wstring k, order) {
|
|---|
| 177 | strEx::append_list(boot_order, k, _T(", "));
|
|---|
| 178 | }
|
|---|
| 179 | get_logger()->debug(__FILE__, __LINE__, _T("Boot order: ") + boot_order);
|
|---|
| 180 | BOOST_FOREACH(std::wstring k, order) {
|
|---|
| 181 | if (context_exists(k)) {
|
|---|
| 182 | get_logger()->debug(__FILE__, __LINE__, _T("Activating: ") + k);
|
|---|
| 183 | set_instance(k);
|
|---|
| 184 | return;
|
|---|
| 185 | }
|
|---|
| 186 | }
|
|---|
| 187 | if (!key.empty()) {
|
|---|
| 188 | get_logger()->info(__FILE__, __LINE__, _T("No valid settings found but one was given (using that): ") + key);
|
|---|
| 189 | set_instance(key);
|
|---|
| 190 | return;
|
|---|
| 191 | }
|
|---|
| 192 |
|
|---|
| 193 | get_logger()->debug(__FILE__, __LINE__, _T("No valid settings found (tried): ") + boot_order);
|
|---|
| 194 |
|
|---|
| 195 | std::wstring tgt = get_boot_string(_T("main"), _T("write"), _T(""));
|
|---|
| 196 | if (!tgt.empty()) {
|
|---|
| 197 | get_logger()->debug(__FILE__, __LINE__, _T("Creating new settings file: ") + tgt);
|
|---|
| 198 | set_instance(tgt);
|
|---|
| 199 | return;
|
|---|
| 200 | }
|
|---|
| 201 | get_logger()->err(__FILE__, __LINE__, std::wstring(_T("Settings contexts exausted, will create a new ")) + DEFAULT_CONF_INI_LOCATION);
|
|---|
| 202 | set_instance(DEFAULT_CONF_INI_LOCATION);
|
|---|
| 203 | }
|
|---|
| 204 |
|
|---|
| 205 | void NSCSettingsImpl::set_primary(std::wstring key) {
|
|---|
| 206 | std::list<std::wstring> order;
|
|---|
| 207 | for (int i=0;i<20;i++) {
|
|---|
| 208 | std::wstring v = get_boot_string(_T("settings"), strEx::itos(i), _T(""));
|
|---|
| 209 | if (!v.empty()) {
|
|---|
| 210 | order.push_back(expand_context(v));
|
|---|
| 211 | set_boot_string(_T("settings"), strEx::itos(i), _T(""));
|
|---|
| 212 | }
|
|---|
| 213 | }
|
|---|
| 214 | order.remove(key);
|
|---|
| 215 | order.push_front(key);
|
|---|
| 216 | int i=1;
|
|---|
| 217 | BOOST_FOREACH(std::wstring k, order) {
|
|---|
| 218 | set_boot_string(_T("settings"), strEx::itos(i++), k);
|
|---|
| 219 | }
|
|---|
| 220 | set_boot_string(_T("main"), _T("write"), key);
|
|---|
| 221 | }
|
|---|
| 222 |
|
|---|
| 223 |
|
|---|
| 224 | bool NSCSettingsImpl::create_context(std::wstring key) {
|
|---|
| 225 | try {
|
|---|
| 226 | change_context(key);
|
|---|
| 227 | } catch (settings::settings_exception e) {
|
|---|
| 228 | provider_->log_fatal_error(_T("Failed to initialize settings: ") + e.getError());
|
|---|
| 229 | return false;
|
|---|
| 230 | } catch (...) {
|
|---|
| 231 | provider_->log_fatal_error(_T("FATAL ERROR IN SETTINGS SUBSYTEM"));
|
|---|
| 232 | return false;
|
|---|
| 233 | }
|
|---|
| 234 | return true;
|
|---|
| 235 | }
|
|---|
| 236 |
|
|---|
| 237 | void NSCSettingsImpl::change_context(std::wstring context) {
|
|---|
| 238 | try {
|
|---|
| 239 | get_core()->migrate_to(context);
|
|---|
| 240 | set_primary(context);
|
|---|
| 241 | get_core()->boot(context);
|
|---|
| 242 | } catch (settings::settings_exception e) {
|
|---|
| 243 | provider_->log_fatal_error(_T("Failed to initialize settings: ") + e.getError());
|
|---|
| 244 | } catch (...) {
|
|---|
| 245 | provider_->log_fatal_error(_T("FATAL ERROR IN SETTINGS SUBSYTEM"));
|
|---|
| 246 | }
|
|---|
| 247 | }
|
|---|
| 248 |
|
|---|
| 249 | bool init_settings(provider_interface *provider, std::wstring context) {
|
|---|
| 250 | try {
|
|---|
| 251 | settings_impl = new NSCSettingsImpl(provider);
|
|---|
| 252 | get_core()->set_logger(provider->create_logger());
|
|---|
| 253 | get_core()->set_base(provider->expand_path(_T("${base-path}")));
|
|---|
| 254 | get_core()->boot(context);
|
|---|
| 255 | } catch (settings::settings_exception e) {
|
|---|
| 256 | provider->log_fatal_error(_T("Failed to initialize settings: ") + e.getError());
|
|---|
| 257 | return false;
|
|---|
| 258 | } catch (...) {
|
|---|
| 259 | provider->log_fatal_error(_T("FATAL ERROR IN SETTINGS SUBSYTEM"));
|
|---|
| 260 | return false;
|
|---|
| 261 | }
|
|---|
| 262 | return true;
|
|---|
| 263 | }
|
|---|
| 264 |
|
|---|
| 265 | void change_context(std::wstring context) {
|
|---|
| 266 | settings_impl->change_context(context);
|
|---|
| 267 | }
|
|---|
| 268 |
|
|---|
| 269 | bool has_boot_conf() {
|
|---|
| 270 | return settings_impl->has_boot_conf();
|
|---|
| 271 | }
|
|---|
| 272 | bool context_exists(std::wstring key) {
|
|---|
| 273 | return settings_impl->context_exists(key);
|
|---|
| 274 | }
|
|---|
| 275 | bool create_context(std::wstring key) {
|
|---|
| 276 | return settings_impl->create_context(key);
|
|---|
| 277 | }
|
|---|
| 278 |
|
|---|
| 279 |
|
|---|
| 280 | }
|
|---|