softwarecontainer  0.18.0-739e8d7 2017-05-04
mainconfigsource.cpp
1 /*
2  * Copyright (C) 2016-2017 Pelagicore AB
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
9  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
10  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
11  * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
12  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
13  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
14  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15  * SOFTWARE.
16  *
17  * For further information see LICENSE
18  */
19 
20 #include "mainconfigsource.h"
21 #include "config.h"
22 #include "configerror.h"
23 
24 
25 namespace softwarecontainer {
26 
27 MainConfigSource::MainConfigSource(std::unique_ptr<ConfigLoader> loader, TypeMap typeMapping):
28  m_loader(std::move(loader)),
29  m_typeMapping(std::move(typeMapping)),
30  m_configsByGroup(std::map<std::string, std::vector<std::string>>()),
31  m_stringConfigs(std::vector<StringConfig>()),
32  m_intConfigs(std::vector<IntConfig>()),
33  m_boolConfigs(std::vector<BoolConfig>())
34 {
35  log_debug() << "Initializing main config source";
36 
37  /*
38  * The order of the calls below is important as some calls modify members
39  * that subsequent calls uses. In general, all errors that can occur are turned
40  * into ConfigError of various kinds and thrown where the error happened.
41  * These exceptions are not caught and handled anywhere, they are propagated to
42  * the creator of MainConfigSource.
43  */
44 
45  loadConfig();
46  readLoadedConfig();
47  createConfigItems();
48 }
49 
50 std::vector<StringConfig> MainConfigSource::stringConfigs()
51 {
52  return m_stringConfigs;
53 }
54 
55 std::vector<IntConfig> MainConfigSource::intConfigs()
56 {
57  return m_intConfigs;
58 }
59 
60 std::vector<BoolConfig> MainConfigSource::boolConfigs()
61 {
62  return m_boolConfigs;
63 }
64 
65 void MainConfigSource::loadConfig()
66 {
67  try {
68  m_config = m_loader->loadConfig();
69  } catch (Glib::Error &error) {
70  throw ConfigFileError("Error loading main config file");
71  }
72 }
73 
74 void MainConfigSource::readLoadedConfig()
75 {
76  try {
77  std::vector<Glib::ustring> groups = m_config->get_groups();
78  for (auto &group : groups) {
79  std::vector<Glib::ustring> keys = m_config->get_keys(group);
80 
81  for (auto &key : keys) {
82  m_configsByGroup[group].push_back(key);
83  }
84  }
85  } catch (Glib::Error &error) {
86  throw ConfigFileError("Error reading main config file");
87  }
88 }
89 
90 void MainConfigSource::createConfigItems()
91 {
92  for (auto &configGroup : m_configsByGroup) {
93  auto group = configGroup.first;
94  auto keys = configGroup.second;
95 
96  for (auto &key : keys) {
97  ConfigType type = typeOf(group, key);
98  create(group, key, type);
99  }
100  }
101 }
102 
103 ConfigType MainConfigSource::typeOf(const std::string &group, const std::string &key)
104 {
105  try {
106  return m_typeMapping.at(std::make_pair(group, key));
107  } catch (std::exception &error) {
108  std::string message = "Unknown config " + group + "::" + key;
109  log_error() << message;
110  throw ConfigUnknownError(message);
111  }
112 }
113 
114 void MainConfigSource::create(const std::string &group, const std::string &key, ConfigType type)
115 {
116  switch (type) {
117  case ConfigType::String:
118  m_stringConfigs.push_back(createConfig<StringConfig, std::string>(group, key));
119  break;
120  case ConfigType::Integer:
121  m_intConfigs.push_back(createConfig<IntConfig, int>(group, key));
122  break;
123  case ConfigType::Boolean:
124  m_boolConfigs.push_back(createConfig<BoolConfig, bool>(group, key));
125  break;
126  default:
127  break;
128  }
129 }
130 
131 template<typename T, typename U>
132 T MainConfigSource::createConfig(const std::string &group, const std::string &name)
133 {
134  U value = getGlibValue<U>(group, name);
135  T config(group, name, value);
136  config.setSource(ConfigSourceType::Main);
137 
138  return config;
139 }
140 
141 template<>
142 std::string MainConfigSource::getGlibValue(const std::string &group, const std::string &key) const
143 {
144  try {
145  std::string value = m_config->get_string(Glib::ustring(group), Glib::ustring(key));
146  return value;
147  } catch (Glib::KeyFileError &error) {
148  std::string message = "Could not parse string value: \"" + error.what() + "\"";
149  log_error() << message;
150  throw ConfigFileError(message);
151  }
152 
153  throw ConfigInternalError();
154 }
155 
156 template<>
157 int MainConfigSource::getGlibValue(const std::string &group, const std::string &key) const
158 {
159  try {
160  int value = m_config->get_integer(Glib::ustring(group), Glib::ustring(key));
161  return value;
162  } catch (Glib::KeyFileError &error) {
163  std::string message = "Could not parse integer value: \"" + error.what() + "\"";
164  log_error() << message;
165  throw ConfigFileError(message);
166  }
167 
168  throw ConfigInternalError();
169 }
170 
171 template<>
172 bool MainConfigSource::getGlibValue(const std::string &group, const std::string &key) const
173 {
174  try {
175  bool value = m_config->get_boolean(Glib::ustring(group), Glib::ustring(key));
176  return value;
177  } catch (Glib::KeyFileError &error) {
178  std::string message = "Could not parse boolean value: \"" + error.what() + "\"";
179  log_error() << message;
180  throw ConfigFileError(message);
181  }
182 
183  throw ConfigInternalError();
184 }
185 
186 } // namespace softwarecontainer
An error occured in a Glib operation.
Definition: configerror.h:122
Represents a config item of type bool.
Definition: configitem.h:72
Represents a config item of type string.
Definition: configitem.h:46
ConfigType
Represents the type of a config value.
Definition: configtypes.h:32
A config is found which is not defined in ConfigDefinition.
Definition: configerror.h:104
MainConfigSource(std::unique_ptr< ConfigLoader > loader, TypeMap typeMapping)
Developers guide to adding a config item:
Represents a config item of type int.
Definition: configitem.h:59
An error occured which is an internal error in the config code.
Definition: configerror.h:56