blob: 1a47edc21780a4fe5fd1abb770e5525983cb4f88 [file] [log] [blame]
/*
* 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