| /* |
| * 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. |
| */ |
| |
| #include <unistd.h> |
| #include <cstring> |
| #include <string> |
| #include <limits> |
| #include "xml_parser.h" |
| |
| using std::string; |
| |
| namespace hawq { |
| namespace test { |
| |
| XmlConfig::XmlConfig(string p) : |
| path(p) { |
| parse(); |
| } |
| |
| bool XmlConfig::open() { |
| if (access(path.c_str(), R_OK)) { |
| return false; |
| } |
| |
| doc = xmlReadFile(path.c_str(), nullptr, 0); |
| if (doc == nullptr) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| void XmlConfig::closeNotSave() { |
| xmlFreeDoc(doc); |
| } |
| |
| void XmlConfig::closeAndSave() { |
| xmlSaveFormatFile(path.c_str(), doc, 0); |
| xmlFreeDoc(doc); |
| } |
| |
| bool XmlConfig::parse() { |
| LIBXML_TEST_VERSION kv |
| .clear(); |
| |
| if (!open()) { |
| return false; |
| } |
| try { |
| readConfigItems(doc); |
| closeNotSave(); |
| return true; |
| } catch (...) { |
| closeNotSave(); |
| return false; |
| } |
| } |
| |
| void XmlConfig::readConfigItems(xmlDocPtr doc) { |
| xmlNodePtr root, curNode; |
| root = xmlDocGetRootElement(doc); |
| if (root == nullptr || strcmp((const char *) root->name, "configuration")) { |
| return ; |
| } |
| // for each property |
| for (curNode = root->children; curNode != nullptr; curNode = curNode->next) { |
| if (curNode->type != XML_ELEMENT_NODE) { |
| continue; |
| } |
| if (strcmp((const char *) curNode->name, "property")) { |
| return; |
| } |
| readConfigItem(curNode->children); |
| } |
| } |
| |
| void XmlConfig::readConfigItem(xmlNodePtr root) { |
| string key, value, scope; |
| xmlNodePtr curNode; |
| bool hasName = false, hasValue = false, hasScope = false; |
| for (curNode = root; curNode != nullptr; curNode = curNode->next) { |
| if (curNode->type != XML_ELEMENT_NODE) { |
| continue; |
| } |
| if (!hasName && !strcmp((const char *) curNode->name, "name")) { |
| if (curNode->children != nullptr |
| && XML_TEXT_NODE == curNode->children->type) { |
| key = (const char *) curNode->children->content; |
| hasName = true; |
| } |
| } else if (!hasValue && !strcmp((const char *) curNode->name, "value")) { |
| if (curNode->children != nullptr |
| && XML_TEXT_NODE == curNode->children->type) { |
| value = (const char *) curNode->children->content; |
| hasValue = true; |
| } |
| } else { |
| continue; |
| } |
| } |
| if (hasName && hasValue) { |
| kv[key] = value; |
| return; |
| } else if (hasName && hasValue) { |
| return; |
| } else if (hasName && hasScope) { |
| return; |
| } else if (hasName) { |
| return; |
| } |
| } |
| |
| bool XmlConfig::setString(const string &key, |
| const string &value, |
| bool save) { |
| bool result = false; |
| |
| if (save) { |
| if (!open()) { |
| return false; |
| } |
| } |
| try { |
| result = writeConfigItem(doc, key, value); |
| if (save) { |
| closeAndSave(); |
| } |
| } catch (...) { |
| if (save) { |
| closeNotSave(); |
| } |
| } |
| return result; |
| } |
| |
| bool XmlConfig::setString(const string &key, |
| const string &value) { |
| return setString(key, value, true); |
| } |
| |
| bool XmlConfig::writeConfigItem(xmlDocPtr doc, |
| const string &key, |
| const string &value) { |
| xmlNodePtr root, curNode, curNodeChild, findNode; |
| root = xmlDocGetRootElement(doc); |
| bool findkey = false; |
| if (root == nullptr || strcmp((const char *) root->name, "configuration")) { |
| return false; |
| } |
| // for each property |
| for (curNode = root->children; curNode != nullptr; curNode = curNode->next) { |
| if (curNode->type != XML_ELEMENT_NODE) { |
| continue; |
| } |
| if (strcmp((const char *) curNode->name, "property")) { |
| return false; |
| } |
| curNodeChild = curNode->children; |
| for (curNodeChild = curNode->children; curNodeChild != nullptr; curNodeChild = curNodeChild->next) { |
| if (curNodeChild->type != XML_ELEMENT_NODE) { |
| continue; |
| } |
| if (!strcmp((const char *) curNodeChild->name, "name")) { |
| if (curNodeChild->children != nullptr |
| && XML_TEXT_NODE == curNodeChild->children->type |
| && !strcmp((const char *) curNodeChild->children->content, key.c_str())) { |
| findNode = curNode; |
| findkey = true; |
| } else { |
| if (findkey) { |
| xmlNewTextChild(findNode, NULL, BAD_CAST "value", BAD_CAST value.c_str()); |
| return true; |
| } |
| } |
| } else if (!strcmp((const char *) curNodeChild->name, "value")) { |
| if (findkey |
| && curNodeChild->children != nullptr |
| && XML_TEXT_NODE == curNodeChild->children->type) { |
| xmlNodeSetContent(curNodeChild->children, (xmlChar*) const_cast<char*>(value.c_str())); |
| return true; |
| } |
| } else { |
| continue; |
| } |
| } |
| } |
| |
| xmlNodePtr newNode = xmlNewNode(NULL, BAD_CAST "property"); |
| xmlAddChild(root, newNode); |
| xmlNewTextChild(newNode, NULL, BAD_CAST "name", BAD_CAST key.c_str()); |
| xmlNewTextChild(newNode, NULL, BAD_CAST "value", BAD_CAST value.c_str()); |
| return true; |
| } |
| |
| const string XmlConfig::getString(const char *key) { |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return ""; |
| } |
| return it->second; |
| } |
| |
| const string XmlConfig::getString(const char *key, const char *def) { |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return string(def); |
| } else { |
| return it->second; |
| } |
| } |
| |
| const string XmlConfig::getString(const string & key) { |
| return getString(key.c_str()); |
| } |
| |
| const string XmlConfig::getString(const string & key, |
| const string & def) { |
| return getString(key.c_str(), def.c_str()); |
| } |
| |
| int64_t XmlConfig::getInt64(const char *key) { |
| int64_t retval; |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return 0; |
| } |
| retval = strToInt64(it->second.c_str()); |
| return retval; |
| } |
| |
| int64_t XmlConfig::getInt64(const char *key, int64_t def) { |
| int64_t retval; |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return def; |
| } |
| retval = strToInt64(it->second.c_str()); |
| return retval; |
| } |
| |
| int32_t XmlConfig::getInt32(const char *key) { |
| int32_t retval; |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return 0; |
| } |
| retval = strToInt32(it->second.c_str()); |
| return retval; |
| } |
| |
| int32_t XmlConfig::getInt32(const char *key, int32_t def) { |
| int32_t retval; |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return def; |
| } |
| retval = strToInt32(it->second.c_str()); |
| return retval; |
| } |
| |
| double XmlConfig::getDouble(const char *key) { |
| double retval; |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return 0.0; |
| } |
| retval = strToDouble(it->second.c_str()); |
| return retval; |
| } |
| |
| double XmlConfig::getDouble(const char *key, double def) { |
| double retval; |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return def; |
| } |
| retval = strToDouble(it->second.c_str()); |
| return retval; |
| } |
| |
| bool XmlConfig::getBool(const char *key) { |
| bool retval; |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return false; |
| } |
| retval = strToBool(it->second.c_str()); |
| return retval; |
| } |
| |
| bool XmlConfig::getBool(const char *key, bool def) { |
| bool retval; |
| XmlConfigMapIterator it = kv.find(key); |
| if (kv.end() == it) { |
| return def; |
| } |
| retval = strToBool(it->second.c_str()); |
| return retval; |
| } |
| |
| int64_t XmlConfig::strToInt64(const char *str) { |
| int64_t retval; |
| char *end = nullptr; |
| retval = strtoll(str, &end, 0); |
| return retval; |
| } |
| |
| int32_t XmlConfig::strToInt32(const char *str) { |
| int32_t retval; |
| char *end = nullptr; |
| retval = strtoll(str, &end, 0); |
| return retval; |
| } |
| |
| bool XmlConfig::strToBool(const char *str) { |
| bool retval = false; |
| if (!strcasecmp(str, "true") || !strcmp(str, "1")) { |
| retval = true; |
| } else if (!strcasecmp(str, "false") || !strcmp(str, "0")) { |
| retval = false; |
| } else { |
| return false; |
| } |
| return retval; |
| } |
| |
| double XmlConfig::strToDouble(const char *str) { |
| double retval; |
| char *end = nullptr; |
| retval = strtod(str, &end); |
| return retval; |
| } |
| |
| } // namespace test |
| } // namespace hawq |