1
0

configuration.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. /*
  19. * The following features are not currently implemented
  20. * - Deprecated values
  21. * - Make filename and config file contents unicode-safe
  22. * - Config redirection/environment substitution
  23. *
  24. * - getInts (comma separated))
  25. * - getStrings (comma separated))
  26. * - getIntegerRange
  27. * - getSocketAddr
  28. * - getTimeDuration
  29. * - getBytes (e.g. 1M or 1G)
  30. * - hex values
  31. */
  32. #include "configuration.h"
  33. #include <strings.h>
  34. #include <sstream>
  35. #include <map>
  36. #include <rapidxml/rapidxml.hpp>
  37. #include <rapidxml/rapidxml_utils.hpp>
  38. namespace hdfs {
  39. /*
  40. * Configuration class
  41. */
  42. Configuration::Configuration() {}
  43. bool is_valid_bool(const std::string& raw) {
  44. if (!strcasecmp(raw.c_str(), "true")) {
  45. return true;
  46. }
  47. if (!strcasecmp(raw.c_str(), "false")) {
  48. return true;
  49. }
  50. return false;
  51. }
  52. bool str_to_bool(const std::string& raw) {
  53. if (!strcasecmp(raw.c_str(), "true")) {
  54. return true;
  55. }
  56. return false;
  57. }
  58. optional<Configuration> Configuration::Load(const std::string& xmlData) {
  59. Configuration result;
  60. return result.OverlayResourceString(xmlData);
  61. }
  62. optional<Configuration> Configuration::OverlayResourceString(
  63. const std::string& xmlData) const {
  64. if (xmlData.size() == 0) {
  65. return optional<Configuration>();
  66. }
  67. int length = xmlData.size();
  68. std::vector<char> raw_bytes;
  69. raw_bytes.reserve(length + 1);
  70. std::copy(xmlData.begin(), xmlData.end(), std::back_inserter(raw_bytes));
  71. raw_bytes.push_back('\0');
  72. ConfigMap map(raw_values_);
  73. bool success = UpdateMapWithResource(map, raw_bytes);
  74. if (success) {
  75. return optional<Configuration>(Configuration(map));
  76. } else {
  77. return optional<Configuration>();
  78. }
  79. }
  80. bool Configuration::UpdateMapWithResource(ConfigMap& map,
  81. std::vector<char>& raw_bytes) {
  82. rapidxml::xml_document<> dom;
  83. dom.parse<rapidxml::parse_trim_whitespace>(&raw_bytes[0]);
  84. /* File must contain a single <configuration> stanza */
  85. auto config_node = dom.first_node("configuration", 0, false);
  86. if (!config_node) {
  87. return false;
  88. }
  89. /* Walk all of the <property> nodes, ignoring the rest */
  90. for (auto property_node = config_node->first_node("property", 0, false);
  91. property_node;
  92. property_node = property_node->next_sibling("property", 0, false)) {
  93. auto name_node = property_node->first_node("name", 0, false);
  94. auto value_node = property_node->first_node("value", 0, false);
  95. if (name_node && value_node) {
  96. auto mapValue = map.find(name_node->value());
  97. if (mapValue != map.end() && mapValue->second.final) {
  98. continue;
  99. }
  100. map[name_node->value()] = value_node->value();
  101. auto final_node = property_node->first_node("final", 0, false);
  102. if (final_node && is_valid_bool(final_node->value())) {
  103. map[name_node->value()].final = str_to_bool(final_node->value());
  104. }
  105. }
  106. auto name_attr = property_node->first_attribute("name", 0, false);
  107. auto value_attr = property_node->first_attribute("value", 0, false);
  108. if (name_attr && value_attr) {
  109. auto mapValue = map.find(name_attr->value());
  110. if (mapValue != map.end() && mapValue->second.final) {
  111. continue;
  112. }
  113. map[name_attr->value()] = value_attr->value();
  114. auto final_attr = property_node->first_attribute("final", 0, false);
  115. if (final_attr && is_valid_bool(final_attr->value())) {
  116. map[name_attr->value()].final = str_to_bool(final_attr->value());
  117. }
  118. }
  119. }
  120. return true;
  121. }
  122. optional<std::string> Configuration::Get(const std::string& key) const {
  123. auto found = raw_values_.find(key);
  124. if (found != raw_values_.end()) {
  125. return std::experimental::make_optional(found->second.value);
  126. } else {
  127. return optional<std::string>();
  128. }
  129. }
  130. std::string Configuration::GetWithDefault(
  131. const std::string& key, const std::string& default_value) const {
  132. return Get(key).value_or(default_value);
  133. }
  134. optional<int64_t> Configuration::GetInt(const std::string& key) const {
  135. auto raw = Get(key);
  136. if (raw) {
  137. errno = 0;
  138. char* end = nullptr;
  139. auto result =
  140. std::experimental::make_optional(strtol(raw->c_str(), &end, 10));
  141. if (end == raw->c_str()) {
  142. /* strtoll will set end to input if no conversion was done */
  143. return optional<int64_t>();
  144. }
  145. if (errno == ERANGE) {
  146. return optional<int64_t>();
  147. }
  148. return result;
  149. } else {
  150. return optional<int64_t>();
  151. }
  152. }
  153. int64_t Configuration::GetIntWithDefault(const std::string& key,
  154. int64_t default_value) const {
  155. return GetInt(key).value_or(default_value);
  156. }
  157. optional<double> Configuration::GetDouble(const std::string& key) const {
  158. auto raw = Get(key);
  159. if (raw) {
  160. errno = 0;
  161. char* end = nullptr;
  162. auto result = std::experimental::make_optional(strtod(raw->c_str(), &end));
  163. if (end == raw->c_str()) {
  164. /* strtod will set end to input if no conversion was done */
  165. return optional<double>();
  166. }
  167. if (errno == ERANGE) {
  168. return optional<double>();
  169. }
  170. return result;
  171. } else {
  172. return optional<double>();
  173. }
  174. }
  175. double Configuration::GetDoubleWithDefault(const std::string& key,
  176. double default_value) const {
  177. return GetDouble(key).value_or(default_value);
  178. }
  179. optional<bool> Configuration::GetBool(const std::string& key) const {
  180. auto raw = Get(key);
  181. if (!raw) {
  182. return optional<bool>();
  183. }
  184. if (!strcasecmp(raw->c_str(), "true")) {
  185. return std::experimental::make_optional(true);
  186. }
  187. if (!strcasecmp(raw->c_str(), "false")) {
  188. return std::experimental::make_optional(false);
  189. }
  190. return optional<bool>();
  191. }
  192. bool Configuration::GetBoolWithDefault(const std::string& key,
  193. bool default_value) const {
  194. return GetBool(key).value_or(default_value);
  195. }
  196. }