mirror of https://github.com/Icinga/icinga2.git
parent
08b1808397
commit
973db46d40
|
@ -37,6 +37,7 @@ set(config_SOURCES
|
|||
applyrule.cpp
|
||||
configcompilercontext.cpp configcompiler.cpp configitembuilder.cpp
|
||||
configitem.cpp ${FLEX_config_lexer_OUTPUTS} ${BISON_config_parser_OUTPUTS}
|
||||
configwriter.cpp
|
||||
expression.cpp objectrule.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software Foundation *
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include "config/configwriter.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
ConfigWriter::ConfigWriter(const String& fileName)
|
||||
: m_FP(fileName.CStr(), std::ofstream::out | std::ostream::trunc)
|
||||
{ }
|
||||
|
||||
void ConfigWriter::EmitBoolean(bool val)
|
||||
{
|
||||
m_FP << (val ? "true" : "false");
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitNumber(double val)
|
||||
{
|
||||
m_FP << val;
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitString(const String& val)
|
||||
{
|
||||
m_FP << "\"" << EscapeIcingaString(val) << "\"";
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitEmpty(void)
|
||||
{
|
||||
m_FP << "null";
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitArray(const Array::Ptr& val)
|
||||
{
|
||||
m_FP << "[ ";
|
||||
EmitArrayItems(val);
|
||||
m_FP << " ]";
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitArrayItems(const Array::Ptr& val)
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
ObjectLock olock(val);
|
||||
BOOST_FOREACH(const Value& item, val) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
m_FP << ", ";
|
||||
|
||||
EmitValue(0, item);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitScope(int indentLevel, const Dictionary::Ptr& val, const Array::Ptr& imports)
|
||||
{
|
||||
m_FP << "{";
|
||||
|
||||
if (imports && imports->GetLength() > 0) {
|
||||
ObjectLock xlock(imports);
|
||||
BOOST_FOREACH(const Value& import, imports) {
|
||||
m_FP << "\n";
|
||||
EmitIndent(indentLevel);
|
||||
m_FP << "import \"" << import << "\"";
|
||||
}
|
||||
|
||||
m_FP << "\n";
|
||||
}
|
||||
|
||||
ObjectLock olock(val);
|
||||
BOOST_FOREACH(const Dictionary::Pair& kv, val) {
|
||||
m_FP << "\n";
|
||||
EmitIndent(indentLevel);
|
||||
EmitIdentifier(kv.first, true);
|
||||
m_FP << " = ";
|
||||
EmitValue(indentLevel + 1, kv.second);
|
||||
}
|
||||
|
||||
m_FP << "\n";
|
||||
EmitIndent(indentLevel - 1);
|
||||
m_FP << "}";
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitValue(int indentLevel, const Value& val)
|
||||
{
|
||||
if (val.IsObjectType<Array>())
|
||||
EmitArray(val);
|
||||
else if (val.IsObjectType<Dictionary>())
|
||||
EmitScope(indentLevel, val);
|
||||
else if (val.IsString())
|
||||
EmitString(val);
|
||||
else if (val.IsNumber())
|
||||
EmitNumber(val);
|
||||
else if (val.IsBoolean())
|
||||
EmitBoolean(val);
|
||||
else if (val.IsEmpty())
|
||||
EmitEmpty();
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitRaw(const String& val)
|
||||
{
|
||||
m_FP << val;
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitIndent(int indentLevel)
|
||||
{
|
||||
for (int i = 0; i < indentLevel; i++)
|
||||
m_FP << "\t";
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitIdentifier(const String& identifier, bool inAssignment)
|
||||
{
|
||||
static std::set<String> keywords;
|
||||
if (keywords.empty()) {
|
||||
keywords.insert("object");
|
||||
keywords.insert("template");
|
||||
keywords.insert("include");
|
||||
keywords.insert("include_recursive");
|
||||
keywords.insert("library");
|
||||
keywords.insert("null");
|
||||
keywords.insert("true");
|
||||
keywords.insert("false");
|
||||
keywords.insert("const");
|
||||
keywords.insert("var");
|
||||
keywords.insert("this");
|
||||
keywords.insert("globals");
|
||||
keywords.insert("locals");
|
||||
keywords.insert("use");
|
||||
keywords.insert("apply");
|
||||
keywords.insert("to");
|
||||
keywords.insert("where");
|
||||
keywords.insert("import");
|
||||
keywords.insert("assign");
|
||||
keywords.insert("ignore");
|
||||
keywords.insert("function");
|
||||
keywords.insert("return");
|
||||
keywords.insert("break");
|
||||
keywords.insert("continue");
|
||||
keywords.insert("for");
|
||||
keywords.insert("if");
|
||||
keywords.insert("else");
|
||||
keywords.insert("while");
|
||||
}
|
||||
|
||||
if (keywords.find(identifier) != keywords.end()) {
|
||||
m_FP << "@" << identifier;
|
||||
return;
|
||||
}
|
||||
|
||||
boost::regex expr("^[a-zA-Z_][a-zA-Z0-9\\_]*$");
|
||||
boost::smatch what;
|
||||
if (boost::regex_search(identifier.GetData(), what, expr))
|
||||
m_FP << identifier;
|
||||
else if (inAssignment)
|
||||
EmitString(identifier);
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid identifier"));
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitConfigItem(const String& type, const String& name, bool isTemplate,
|
||||
const Array::Ptr& imports, const Dictionary::Ptr& attrs)
|
||||
{
|
||||
if (isTemplate)
|
||||
m_FP << "template ";
|
||||
else
|
||||
m_FP << "object ";
|
||||
|
||||
EmitIdentifier(type, false);
|
||||
m_FP << " ";
|
||||
EmitString(name);
|
||||
m_FP << " ";
|
||||
EmitScope(1, attrs, imports);
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitComment(const String& text)
|
||||
{
|
||||
m_FP << "/* " << text << " */\n";
|
||||
}
|
||||
|
||||
void ConfigWriter::EmitFunctionCall(const String& name, const Array::Ptr& arguments)
|
||||
{
|
||||
EmitIdentifier(name, false);
|
||||
m_FP << "(";
|
||||
EmitArrayItems(arguments);
|
||||
m_FP << ")";
|
||||
}
|
||||
|
||||
String ConfigWriter::EscapeIcingaString(const String& str)
|
||||
{
|
||||
String result = str;
|
||||
boost::algorithm::replace_all(result, "\\", "\\\\");
|
||||
boost::algorithm::replace_all(result, "\n", "\\n");
|
||||
boost::algorithm::replace_all(result, "\t", "\\t");
|
||||
boost::algorithm::replace_all(result, "\r", "\\r");
|
||||
boost::algorithm::replace_all(result, "\b", "\\b");
|
||||
boost::algorithm::replace_all(result, "\f", "\\f");
|
||||
boost::algorithm::replace_all(result, "\"", "\\\"");
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License *
|
||||
* as published by the Free Software Foundation; either version 2 *
|
||||
* of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the Free Software Foundation *
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef CONFIGWRITER_H
|
||||
#define CONFIGWRITER_H
|
||||
|
||||
#include "config/i2-config.hpp"
|
||||
#include "base/object.hpp"
|
||||
#include "base/array.hpp"
|
||||
#include "base/dictionary.hpp"
|
||||
#include <fstream>
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
/**
|
||||
* A configuration writer.
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
class I2_CONFIG_API ConfigWriter : public Object {
|
||||
public:
|
||||
DECLARE_PTR_TYPEDEFS(ConfigWriter);
|
||||
|
||||
ConfigWriter(const String& fileName);
|
||||
|
||||
void EmitBoolean(bool val);
|
||||
void EmitNumber(double val);
|
||||
void EmitString(const String& val);
|
||||
void EmitEmpty(void);
|
||||
void EmitArray(const Array::Ptr& val);
|
||||
void EmitArrayItems(const Array::Ptr& val);
|
||||
void EmitDictionary(const Dictionary::Ptr& val);
|
||||
void EmitScope(int indentLevel, const Dictionary::Ptr& val, const Array::Ptr& imports = Array::Ptr());
|
||||
void EmitValue(int indentLevel, const Value& val);
|
||||
void EmitRaw(const String& val);
|
||||
void EmitIndent(int indentLevel);
|
||||
|
||||
void EmitIdentifier(const String& identifier, bool inAssignment);
|
||||
void EmitConfigItem(const String& type, const String& name, bool isTemplate,
|
||||
const Array::Ptr& imports, const Dictionary::Ptr& attrs);
|
||||
|
||||
void EmitComment(const String& text);
|
||||
void EmitFunctionCall(const String& name, const Array::Ptr& arguments);
|
||||
|
||||
private:
|
||||
std::ofstream m_FP;
|
||||
|
||||
static String EscapeIcingaString(const String& str);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* CONFIGWRITER_H */
|
Loading…
Reference in New Issue