/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * The following features are not currently implemented * - Deprecated values * - Make filename and config file contents unicode-safe * - Config redirection/environment substitution * * - getInts (comma separated)) * - getStrings (comma separated)) * - getIntegerRange * - getSocketAddr * - getTimeDuration * - getBytes (e.g. 1M or 1G) * - hex values */ #include "configuration.h" #include #include #include #include #include namespace hdfs { /* * Configuration class */ Configuration::Configuration() {} bool is_valid_bool(const std::string& raw) { if (!strcasecmp(raw.c_str(), "true")) { return true; } if (!strcasecmp(raw.c_str(), "false")) { return true; } return false; } bool str_to_bool(const std::string& raw) { if (!strcasecmp(raw.c_str(), "true")) { return true; } return false; } optional Configuration::Load(const std::string& xmlData) { Configuration result; return result.OverlayResourceString(xmlData); } optional Configuration::OverlayResourceString( const std::string& xmlData) const { if (xmlData.size() == 0) { return optional(); } int length = xmlData.size(); std::vector raw_bytes; raw_bytes.reserve(length + 1); std::copy(xmlData.begin(), xmlData.end(), std::back_inserter(raw_bytes)); raw_bytes.push_back('\0'); ConfigMap map(raw_values_); bool success = UpdateMapWithResource(map, raw_bytes); if (success) { return optional(Configuration(map)); } else { return optional(); } } bool Configuration::UpdateMapWithResource(ConfigMap& map, std::vector& raw_bytes) { rapidxml::xml_document<> dom; dom.parse(&raw_bytes[0]); /* File must contain a single stanza */ auto config_node = dom.first_node("configuration", 0, false); if (!config_node) { return false; } /* Walk all of the nodes, ignoring the rest */ for (auto property_node = config_node->first_node("property", 0, false); property_node; property_node = property_node->next_sibling("property", 0, false)) { auto name_node = property_node->first_node("name", 0, false); auto value_node = property_node->first_node("value", 0, false); if (name_node && value_node) { auto mapValue = map.find(name_node->value()); if (mapValue != map.end() && mapValue->second.final) { continue; } map[name_node->value()] = value_node->value(); auto final_node = property_node->first_node("final", 0, false); if (final_node && is_valid_bool(final_node->value())) { map[name_node->value()].final = str_to_bool(final_node->value()); } } auto name_attr = property_node->first_attribute("name", 0, false); auto value_attr = property_node->first_attribute("value", 0, false); if (name_attr && value_attr) { auto mapValue = map.find(name_attr->value()); if (mapValue != map.end() && mapValue->second.final) { continue; } map[name_attr->value()] = value_attr->value(); auto final_attr = property_node->first_attribute("final", 0, false); if (final_attr && is_valid_bool(final_attr->value())) { map[name_attr->value()].final = str_to_bool(final_attr->value()); } } } return true; } optional Configuration::Get(const std::string& key) const { auto found = raw_values_.find(key); if (found != raw_values_.end()) { return std::experimental::make_optional(found->second.value); } else { return optional(); } } std::string Configuration::GetWithDefault( const std::string& key, const std::string& default_value) const { return Get(key).value_or(default_value); } optional Configuration::GetInt(const std::string& key) const { auto raw = Get(key); if (raw) { errno = 0; char* end = nullptr; auto result = std::experimental::make_optional(strtol(raw->c_str(), &end, 10)); if (end == raw->c_str()) { /* strtoll will set end to input if no conversion was done */ return optional(); } if (errno == ERANGE) { return optional(); } return result; } else { return optional(); } } int64_t Configuration::GetIntWithDefault(const std::string& key, int64_t default_value) const { return GetInt(key).value_or(default_value); } optional Configuration::GetDouble(const std::string& key) const { auto raw = Get(key); if (raw) { errno = 0; char* end = nullptr; auto result = std::experimental::make_optional(strtod(raw->c_str(), &end)); if (end == raw->c_str()) { /* strtod will set end to input if no conversion was done */ return optional(); } if (errno == ERANGE) { return optional(); } return result; } else { return optional(); } } double Configuration::GetDoubleWithDefault(const std::string& key, double default_value) const { return GetDouble(key).value_or(default_value); } optional Configuration::GetBool(const std::string& key) const { auto raw = Get(key); if (!raw) { return optional(); } if (!strcasecmp(raw->c_str(), "true")) { return std::experimental::make_optional(true); } if (!strcasecmp(raw->c_str(), "false")) { return std::experimental::make_optional(false); } return optional(); } bool Configuration::GetBoolWithDefault(const std::string& key, bool default_value) const { return GetBool(key).value_or(default_value); } }