return DynamicType::GetByName(GetTypeNameV());
}
-DebugInfo DynamicObject::GetDebugInfo(void) const
-{
- return m_DebugInfo;
-}
-
-void DynamicObject::SetDebugInfo(const DebugInfo& di)
-{
- m_DebugInfo = di;
-}
-
bool DynamicObject::IsActive(void) const
{
return GetActive();
intrusive_ptr<DynamicType> GetType(void) const;
- DebugInfo GetDebugInfo(void) const;
- void SetDebugInfo(const DebugInfo& di);
-
bool IsActive(void) const;
bool IsPaused(void) const;
private:
static DynamicObject::Ptr GetObject(const String& type, const String& name);
static void RestoreObject(const String& message, int attributeTypes);
-
- DebugInfo m_DebugInfo;
};
#define DECLARE_OBJECTNAME(klass) \
};
}}}
-abstract class DynamicObject
+abstract class DynamicObjectBase
+{ };
+
+code {{{
+class I2_BASE_API DynamicObjectBase : public ObjectImpl<DynamicObjectBase>
+{
+public:
+ inline DebugInfo GetDebugInfo(void) const
+ {
+ return m_DebugInfo;
+ }
+
+ void SetDebugInfo(const DebugInfo& di)
+ {
+ m_DebugInfo = di;
+ }
+
+private:
+ DebugInfo m_DebugInfo;
+};
+}}}
+
+abstract class DynamicObject : DynamicObjectBase
{
[config, internal] String __name (Name);
- [config] String name (ShortName) {
+ [config] String "name" (ShortName) {
get {{{
if (m_ShortName.IsEmpty())
return GetName();
}}}
};
[config, internal, get_protected] String type (TypeNameV);
- [config] String zone (ZoneName);
+ [config] name(Zone) zone (ZoneName);
[config, internal, get_protected] Array::Ptr templates;
[get_protected] bool active;
[get_protected] bool paused {
******************************************************************************/
#include "base/exception.hpp"
+#include "base/dynamicobject.hpp"
#include <boost/thread/tss.hpp>
#ifdef HAVE_CXXABI_H
String message = ex.what();
+ const ValidationError *vex = dynamic_cast<const ValidationError *>(&ex);
+
if (message.IsEmpty())
result << boost::diagnostic_information(ex);
else
ShowCodeFragment(result, dex->GetDebugInfo());
}
+ if (vex) {
+ DebugInfo di;
+
+ DynamicObject::Ptr dobj = dynamic_pointer_cast<DynamicObject>(vex->GetObject());
+ if (dobj)
+ di = dobj->GetDebugInfo();
+
+ Dictionary::Ptr currentHint = vex->GetDebugHint();
+ Array::Ptr messages;
+
+ BOOST_FOREACH(const String& attr, vex->GetAttributePath()) {
+ Dictionary::Ptr props = currentHint->Get("properties");
+
+ if (!props)
+ break;
+
+ currentHint = props->Get(attr);
+
+ if (!currentHint)
+ break;
+
+ messages = currentHint->Get("messages");
+ }
+
+ if (messages && messages->GetLength() > 0) {
+ Array::Ptr message = messages->Get(messages->GetLength() - 1);
+
+ di.Path = message->Get(1);
+ di.FirstLine = message->Get(2);
+ di.FirstColumn = message->Get(3);
+ di.LastLine = message->Get(4);
+ di.LastColumn = message->Get(5);
+ }
+
+ if (!di.Path.IsEmpty()) {
+ result << "\nLocation:\n";
+ ShowCodeFragment(result, di);
+ }
+ }
+
const user_error *uex = dynamic_cast<const user_error *>(&ex);
const posix_error *pex = dynamic_cast<const posix_error *>(&ex);
return m_Message;
}
+ValidationError::ValidationError(const intrusive_ptr<ObjectImpl<DynamicObject> >& object, const std::vector<String>& attributePath, const String& message)
+ : m_Object(object), m_AttributePath(attributePath), m_Message(message)
+{
+ String path;
+
+ BOOST_FOREACH(const String& attribute, attributePath) {
+ if (!path.IsEmpty())
+ path += " -> ";
+
+ path += "'" + attribute + "'";
+ }
+
+ Type::Ptr type = object->GetReflectionType();
+ m_What = "Validation failed for object '" + object->GetName() + "' of type '" + type->GetName() + "'";
+
+ if (!path.IsEmpty())
+ m_What += "; Attribute " + path;
+
+ m_What += ": " + message;
+}
+
+ValidationError::~ValidationError(void) throw()
+{ }
+
+const char *ValidationError::what(void) const throw()
+{
+ return m_What.CStr();
+}
+
+intrusive_ptr<ObjectImpl<DynamicObject> > ValidationError::GetObject(void) const
+{
+ return m_Object;
+}
+
+std::vector<String> ValidationError::GetAttributePath(void) const
+{
+ return m_AttributePath;
+}
+
+String ValidationError::GetMessage(void) const
+{
+ return m_Message;
+}
+
+void ValidationError::SetDebugHint(const Dictionary::Ptr& dhint)
+{
+ m_DebugHint = dhint;
+}
+
+Dictionary::Ptr ValidationError::GetDebugHint(void) const
+{
+ return m_DebugHint;
+}
+
#include "base/context.hpp"
#include "base/utility.hpp"
#include "base/debuginfo.hpp"
+#include "base/dictionary.hpp"
#include <sstream>
#include <boost/exception/errinfo_api_function.hpp>
#include <boost/exception/errinfo_errno.hpp>
bool m_IncompleteExpr;
};
+class DynamicObject;
+template<> class ObjectImpl<DynamicObject>;
+
+/*
+ * @ingroup base
+ */
+class I2_BASE_API ValidationError : virtual public user_error
+{
+public:
+ ValidationError(const intrusive_ptr<ObjectImpl<DynamicObject> >& object, const std::vector<String>& attributePath, const String& message);
+ ~ValidationError(void) throw();
+
+ virtual const char *what(void) const throw();
+
+ intrusive_ptr<ObjectImpl<DynamicObject> > GetObject(void) const;
+ std::vector<String> GetAttributePath(void) const;
+ String GetMessage(void) const;
+
+ void SetDebugHint(const Dictionary::Ptr& dhint);
+ Dictionary::Ptr GetDebugHint(void) const;
+
+private:
+ intrusive_ptr<ObjectImpl<DynamicObject> > m_Object;
+ std::vector<String> m_AttributePath;
+ String m_Message;
+ String m_What;
+ Dictionary::Ptr m_DebugHint;
+};
+
I2_BASE_API StackTrace *GetLastExceptionStack(void);
I2_BASE_API void SetLastExceptionStack(const StackTrace& trace);
class FileLogger : StreamLogger
{
- [config] String path;
+ [config, required] String path;
};
}
#include "base/objectlock.hpp"
#include "base/dynamictype.hpp"
#include "base/application.hpp"
-#include "base/exception.hpp"
#include <boost/foreach.hpp>
#include <boost/regex.hpp>
#include <algorithm>
Field TypeType::GetFieldInfo(int id) const
{
if (id == 0)
- return Field(0, "Object", "prototype", 0);
+ return Field(0, "Object", "prototype", NULL, 0);
throw std::runtime_error("Invalid field ID.");
}
FAConfig = 2,
FAState = 4,
FAInternal = 64,
+ FARequired = 512
};
class Type;
int ID;
const char *TypeName;
const char *Name;
+ const char *RefTypeName;
int Attributes;
- Field(int id, const char *type, const char *name, int attributes)
- : ID(id), TypeName(type), Name(name), Attributes(attributes)
+ Field(int id, const char *type, const char *name, const char *reftype, int attributes)
+ : ID(id), TypeName(type), Name(name), RefTypeName(reftype), Attributes(attributes)
{ }
};
TAAbstract = 1
};
+class ValidationUtils
+{
+public:
+ virtual bool ValidateName(const String& type, const String& name) const = 0;
+};
+
class I2_BASE_API Type : public Object
{
public:
mkclass_target(checkercomponent.ti checkercomponent.thpp)
-mkembedconfig_target(checker-type.conf checker-type.cpp)
-
set(checker_SOURCES
- checkercomponent.cpp checkercomponent.thpp checker-type.cpp
+ checkercomponent.cpp checkercomponent.thpp
)
if(ICINGA2_UNITY_BUILD)
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type CheckerComponent {
-}
#include "base/unixsocket.hpp"
#include "base/utility.hpp"
#include "base/networkstream.hpp"
+#include "base/exception.hpp"
#include <iostream>
#ifdef HAVE_EDITLINE
#include "cli/editline.hpp"
#include "cli/repositoryutility.hpp"
#include "cli/clicommand.hpp"
-#include "config/configtype.hpp"
-#include "config/configcompiler.hpp"
#include "base/logger.hpp"
#include "base/application.hpp"
#include "base/convert.hpp"
}
}
-class RepositoryTypeRuleUtilities : public TypeRuleUtilities
+class RepositoryValidationUtils : public ValidationUtils
{
public:
- virtual bool ValidateName(const String& type, const String& name, String *hint) const
+ virtual bool ValidateName(const String& type, const String& name) const
{
return true;
}
change->Set("command", "add");
change->Set("attrs", attrs);
+ Type::Ptr utype = Type::GetByName(type);
+ ASSERT(utype);
+
if (check_config) {
- ConfigType::Ptr ctype = ConfigType::GetByName(type);
-
- if (!ctype)
- Log(LogCritical, "cli")
- << "No validation type available for '" << type << "'.";
- else {
- Dictionary::Ptr vattrs = attrs->ShallowClone();
- vattrs->Set("__name", vattrs->Get("name"));
- vattrs->Remove("name");
- vattrs->Remove("import");
- vattrs->Set("type", type);
-
- Type::Ptr dtype = Type::GetByName(type);
-
- Object::Ptr object = dtype->Instantiate();
- Deserialize(object, vattrs, false, FAConfig);
-
- try {
- RepositoryTypeRuleUtilities utils;
- ctype->ValidateItem(name, object, DebugInfo(), &utils);
- } catch (const ScriptError& ex) {
- Log(LogCritical, "config", DiagnosticInformation(ex));
- return false;
- }
+ try {
+ Object::Ptr object = utype->Instantiate();
+ Deserialize(object, attrs, false, FAConfig);
+
+ RepositoryValidationUtils utils;
+ static_pointer_cast<DynamicObject>(object)->Validate(FAConfig, utils);
+ } catch (const ScriptError& ex) {
+ Log(LogCritical, "config", DiagnosticInformation(ex));
+ return false;
}
}
mkclass_target(externalcommandlistener.ti externalcommandlistener.thpp)
mkclass_target(statusdatawriter.ti statusdatawriter.thpp)
-mkembedconfig_target(compat-type.conf compat-type.cpp)
-
set(compat_SOURCES
checkresultreader.cpp checkresultreader.thpp compatlogger.cpp
compatlogger.thpp externalcommandlistener.cpp externalcommandlistener.thpp
- statusdatawriter.cpp statusdatawriter.thpp compat-type.cpp
+ statusdatawriter.cpp statusdatawriter.thpp
)
if(ICINGA2_UNITY_BUILD)
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type StatusDataWriter {
- %attribute %string "status_path",
- %attribute %string "objects_path",
- %attribute %number "update_interval"
-}
-
-%type ExternalCommandListener {
- %attribute %string "command_path"
-}
-
-%type CompatLogger {
- %validator "ValidateRotationMethod",
-
- %attribute %string "log_dir",
- %attribute %string "rotation_method"
-}
-
-%type CheckResultReader {
- %attribute %string "spool_dir"
-}
#include "base/convert.hpp"
#include "base/application.hpp"
#include "base/utility.hpp"
-#include "base/function.hpp"
#include "base/statsfunction.hpp"
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
using namespace icinga;
REGISTER_TYPE(CompatLogger);
-REGISTER_SCRIPTFUNCTION(ValidateRotationMethod, &CompatLogger::ValidateRotationMethod);
REGISTER_STATSFUNCTION(CompatLoggerStats, &CompatLogger::StatsFunc);
ScheduleNextRotation();
}
-void CompatLogger::ValidateRotationMethod(const String& location, const CompatLogger::Ptr& object)
+void CompatLogger::ValidateRotationMethod(const String& value, const ValidationUtils& utils)
{
- String rotation_method = object->GetRotationMethod();
+ ObjectImpl<CompatLogger>::ValidateRotationMethod(value, utils);
- if (rotation_method != "HOURLY" && rotation_method != "DAILY" &&
- rotation_method != "WEEKLY" && rotation_method != "MONTHLY" && rotation_method != "NONE") {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Rotation method '" + rotation_method + "' is invalid.", object->GetDebugInfo()));
+ if (value != "HOURLY" && value != "DAILY" &&
+ value != "WEEKLY" && value != "MONTHLY" && value != "NONE") {
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("rotation_method"), "Rotation method '" + value + "' is invalid."));
}
}
-
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
- static void ValidateRotationMethod(const String& location, const CompatLogger::Ptr& object);
+ virtual void ValidateRotationMethod(const String& value, const ValidationUtils& utils) override;
protected:
virtual void Start(void);
add_flex_bison_dependency(config_lexer config_parser)
-mkembedconfig_target(base-type.conf base-type.cpp)
-
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
set(config_SOURCES
- applyrule.cpp base-type.conf base-type.cpp
+ applyrule.cpp
configcompilercontext.cpp configcompiler.cpp configitembuilder.cpp
configitem.cpp ${FLEX_config_lexer_OUTPUTS} ${BISON_config_parser_OUTPUTS}
- configtype.cpp expression.cpp objectrule.cpp typerule.cpp typerulelist.cpp
+ expression.cpp objectrule.cpp
)
if(ICINGA2_UNITY_BUILD)
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type DynamicObject {
- %require "__name",
- %attribute %string "__name",
-
- %attribute %string "name",
-
- %require "type",
- %attribute %string "type",
-
- %attribute %name(Zone) "zone",
-
- %attribute %array "templates" {
- %attribute %string "*"
- },
-}
-
-%type Logger {
- %attribute %string "severity"
-}
-
-%type FileLogger %inherits Logger {
- %require "path",
- %attribute %string "path"
-}
-
-%type SyslogLogger %inherits Logger {
-}
******************************************************************************/
#include "config/configcompiler.hpp"
-#include "config/typerule.hpp"
#include "config/expression.hpp"
+#include "base/exception.hpp"
using namespace icinga;
[ \t] /* ignore whitespace */
<INITIAL>{
-%type return T_TYPE;
-%dictionary { yylval->type = TypeDictionary; return T_TYPE_DICTIONARY; }
-%array { yylval->type = TypeArray; return T_TYPE_ARRAY; }
-%number { yylval->type = TypeNumber; return T_TYPE_NUMBER; }
-%string { yylval->type = TypeString; return T_TYPE_STRING; }
-%scalar { yylval->type = TypeScalar; return T_TYPE_SCALAR; }
-%any { yylval->type = TypeAny; return T_TYPE_ANY; }
-%function { yylval->type = TypeFunction; return T_TYPE_FUNCTION; }
-%name { yylval->type = TypeName; return T_TYPE_NAME; }
-%validator { return T_VALIDATOR; }
-%require { return T_REQUIRE; }
-%attribute { return T_ATTRIBUTE; }
-%inherits return T_INHERITS;
object return T_OBJECT;
template return T_TEMPLATE;
include return T_INCLUDE;
#include "config/i2-config.hpp"
#include "config/configitembuilder.hpp"
#include "config/configcompiler.hpp"
-#include "config/typerule.hpp"
-#include "config/typerulelist.hpp"
#include "config/expression.hpp"
#include "config/applyrule.hpp"
#include "config/objectrule.hpp"
bool boolean;
icinga::Expression *expr;
icinga::DictExpression *dexpr;
- icinga::Value *variant;
CombinedSetOp csop;
- icinga::TypeSpecifier type;
std::vector<String> *slist;
std::vector<std::pair<Expression *, EItemInfo> > *llist;
std::vector<Expression *> *elist;
%token T_LOCALS "locals (T_LOCALS)"
%token T_CONST "const (T_CONST)"
%token T_USE "use (T_USE)"
-%token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)"
-%token <type> T_TYPE_ARRAY "array (T_TYPE_ARRAY)"
-%token <type> T_TYPE_NUMBER "number (T_TYPE_NUMBER)"
-%token <type> T_TYPE_STRING "string (T_TYPE_STRING)"
-%token <type> T_TYPE_SCALAR "scalar (T_TYPE_SCALAR)"
-%token <type> T_TYPE_ANY "any (T_TYPE_ANY)"
-%token <type> T_TYPE_FUNCTION "function (T_TYPE_FUNCTION)"
-%token <type> T_TYPE_NAME "name (T_TYPE_NAME)"
-%token T_VALIDATOR "%validator (T_VALIDATOR)"
-%token T_REQUIRE "%require (T_REQUIRE)"
-%token T_ATTRIBUTE "%attribute (T_ATTRIBUTE)"
-%token T_TYPE "type (T_TYPE)"
%token T_OBJECT "object (T_OBJECT)"
%token T_TEMPLATE "template (T_TEMPLATE)"
%token T_INCLUDE "include (T_INCLUDE)"
%type <elist> rterm_items_inner
%type <slist> identifier_items
%type <slist> identifier_items_inner
-%type <variant> typerulelist
%type <csop> combined_set_op
-%type <type> type
%type <llist> statements
%type <llist> lterm_items
%type <llist> lterm_items_inner
| T_STRING
;
-type: T_TYPE identifier
- {
- String name = String($2);
- free($2);
-
- context->m_Type = ConfigType::GetByName(name);
-
- if (!context->m_Type) {
- context->m_Type = new ConfigType(name, @$);
- context->m_Type->Register();
- }
- }
- type_inherits_specifier typerulelist
- {
- TypeRuleList::Ptr ruleList = *$5;
- delete $5;
-
- context->m_Type->GetRuleList()->AddRules(ruleList);
- context->m_Type->GetRuleList()->AddRequires(ruleList);
-
- BOOST_FOREACH(const String& validator, ruleList->GetValidators()) {
- context->m_Type->GetRuleList()->AddValidator(validator);
- }
- }
- ;
-
-typerulelist: '{'
- {
- context->m_OpenBraces++;
- context->m_RuleLists.push(new TypeRuleList());
- }
- typerules
- '}'
- {
- context->m_OpenBraces--;
- $$ = new Value(context->m_RuleLists.top());
- context->m_RuleLists.pop();
- }
- ;
-
-typerules: typerules_inner
- | typerules_inner sep
-
-typerules_inner: /* empty */
- | typerule
- | typerules_inner sep typerule
- ;
-
-typerule: T_REQUIRE T_STRING
- {
- context->m_RuleLists.top()->AddRequire($2);
- free($2);
- }
- | T_VALIDATOR T_STRING
- {
- context->m_RuleLists.top()->AddValidator($2);
- free($2);
- }
- | T_ATTRIBUTE type T_STRING
- {
- TypeRule rule($2, String(), $3, TypeRuleList::Ptr(), @$);
- free($3);
-
- context->m_RuleLists.top()->AddRule(rule);
- }
- | T_ATTRIBUTE T_TYPE_NAME '(' identifier ')' T_STRING
- {
- TypeRule rule($2, $4, $6, TypeRuleList::Ptr(), @$);
- free($4);
- free($6);
-
- context->m_RuleLists.top()->AddRule(rule);
- }
- | T_ATTRIBUTE type T_STRING typerulelist
- {
- TypeRule rule($2, String(), $3, *$4, @$);
- free($3);
- delete $4;
- context->m_RuleLists.top()->AddRule(rule);
- }
- ;
-
-type_inherits_specifier: /* empty */
- | T_INHERITS identifier
- {
- context->m_Type->SetParent($2);
- free($2);
- }
- ;
-
-type: T_TYPE_DICTIONARY
- | T_TYPE_ARRAY
- | T_TYPE_NUMBER
- | T_TYPE_STRING
- | T_TYPE_SCALAR
- | T_TYPE_ANY
- | T_TYPE_FUNCTION
- | T_TYPE_NAME
- ;
-
object:
{
context->m_ObjectAssign.push(true);
if (seen_assign) {
if (!ObjectRule::IsValidSourceType(type))
- BOOST_THROW_EXCEPTION(ScriptError("object rule 'assign' cannot be used for type '" + type + "'", DebugInfoRange(@2, @3)));
+ BOOST_THROW_EXCEPTION(ScriptError("object rule 'assign' cannot be used for type '" + type + "'", DebugInfoRange(@2, @4)));
if (ignore) {
Expression *rex = new LogicalNegateExpression(ignore, DebugInfoRange(@2, @5));
| T_SET_BINARY_OR
;
-lterm: type
- {
- $$ = MakeLiteral(); // ASTify this
- }
- | library
+lterm: library
{
$$ = MakeLiteral(); // ASTify this
}
#include "config/i2-config.hpp"
#include "config/expression.hpp"
-#include "config/configtype.hpp"
#include "base/debuginfo.hpp"
#include "base/registry.hpp"
#include "base/initialize.hpp"
std::ostringstream m_LexBuffer;
CompilerDebugInfo m_LocationBegin;
- std::stack<TypeRuleList::Ptr> m_RuleLists;
- ConfigType::Ptr m_Type;
-
std::stack<bool> m_Apply;
std::stack<bool> m_ObjectAssign;
std::stack<bool> m_SeenAssign;
#include "config/configcompilercontext.hpp"
#include "config/applyrule.hpp"
#include "config/objectrule.hpp"
-#include "config/configtype.hpp"
#include "base/application.hpp"
#include "base/dynamictype.hpp"
#include "base/objectlock.hpp"
return m_Filter;
}
+class DefaultValidationUtils : public ValidationUtils
+{
+public:
+ virtual bool ValidateName(const String& type, const String& name) const override
+ {
+ return ConfigItem::GetObject(type, name) != ConfigItem::Ptr();
+ }
+};
+
/**
* Commits the configuration item by creating a DynamicObject
* object.
persistentItem->Set("type", GetType());
persistentItem->Set("name", GetName());
persistentItem->Set("properties", Serialize(dobj, FAConfig));
- persistentItem->Set("debug_hints", debugHints.ToDictionary());
+
+ Dictionary::Ptr dhint = debugHints.ToDictionary();
+ persistentItem->Set("debug_hints", dhint);
Array::Ptr di = new Array();
di->Add(m_DebugInfo.Path);
ConfigCompilerContext::GetInstance()->WriteObject(persistentItem);
persistentItem.reset();
- ConfigType::Ptr ctype = ConfigType::GetByName(GetType());
-
- if (ctype) {
- TypeRuleUtilities utils;
- ctype->ValidateItem(GetName(), dobj, GetDebugInfo(), &utils);
+ try {
+ DefaultValidationUtils utils;
+ dobj->Validate(FAConfig, utils);
+ } catch (ValidationError& ex) {
+ ex.SetDebugHint(dhint);
+ throw;
}
+ dhint.reset();
+
dobj->Register();
m_Object = dobj;
+++ /dev/null
-/******************************************************************************
- * 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/configtype.hpp"
-#include "config/vmops.hpp"
-#include "base/objectlock.hpp"
-#include "base/convert.hpp"
-#include "base/singleton.hpp"
-#include "base/function.hpp"
-#include <boost/foreach.hpp>
-
-using namespace icinga;
-
-ConfigType::ConfigType(const String& name, const DebugInfo& debuginfo)
- : m_Name(name), m_RuleList(new TypeRuleList()), m_DebugInfo(debuginfo)
-{ }
-
-String ConfigType::GetName(void) const
-{
- return m_Name;
-}
-
-String ConfigType::GetParent(void) const
-{
- return m_Parent;
-}
-
-void ConfigType::SetParent(const String& parent)
-{
- m_Parent = parent;
-}
-
-TypeRuleList::Ptr ConfigType::GetRuleList(void) const
-{
- return m_RuleList;
-}
-
-DebugInfo ConfigType::GetDebugInfo(void) const
-{
- return m_DebugInfo;
-}
-
-void ConfigType::AddParentRules(std::vector<TypeRuleList::Ptr>& ruleLists, const ConfigType::Ptr& item)
-{
- ConfigType::Ptr parent;
- if (item->m_Parent.IsEmpty()) {
- if (item->GetName() != "DynamicObject")
- parent = ConfigType::GetByName("DynamicObject");
- } else {
- parent = ConfigType::GetByName(item->m_Parent);
- }
-
- if (parent) {
- AddParentRules(ruleLists, parent);
- ruleLists.push_back(parent->m_RuleList);
- }
-}
-
-void ConfigType::ValidateItem(const String& name, const Object::Ptr& object, const DebugInfo& debugInfo, const TypeRuleUtilities *utils)
-{
- String location = "Object '" + name + "' (Type: '" + GetName() + "')";
-
- if (!debugInfo.Path.IsEmpty())
- location += " at " + debugInfo.Path + ":" + Convert::ToString(debugInfo.FirstLine);
-
- std::vector<String> locations;
- locations.push_back(location);
-
- std::vector<TypeRuleList::Ptr> ruleLists;
- AddParentRules(ruleLists, this);
- ruleLists.push_back(m_RuleList);
-
- ValidateObject(object, ruleLists, locations, utils);
-}
-
-String ConfigType::LocationToString(const std::vector<String>& locations)
-{
- bool first = true;
- String stack;
- BOOST_FOREACH(const String& location, locations) {
- if (!first)
- stack += " -> ";
- else
- first = false;
-
- stack += location;
- }
-
- return stack;
-}
-
-void ConfigType::ValidateAttribute(const String& key, const Value& value,
- const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,
- const TypeRuleUtilities *utils)
-{
- TypeValidationResult overallResult = ValidationUnknownField;
- std::vector<TypeRuleList::Ptr> subRuleLists;
- String hint;
-
- locations.push_back("Key " + key);
-
- BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {
- TypeRuleList::Ptr subRuleList;
- TypeValidationResult result = ruleList->ValidateAttribute(key, value, &subRuleList, &hint, utils);
-
- if (subRuleList)
- subRuleLists.push_back(subRuleList);
-
- if (overallResult == ValidationOK)
- continue;
-
- if (result == ValidationOK) {
- overallResult = result;
- continue;
- }
-
- if (result == ValidationInvalidType)
- overallResult = result;
- }
-
- if (overallResult == ValidationUnknownField)
- BOOST_THROW_EXCEPTION(ScriptError("Unknown attribute: " + LocationToString(locations)));
- else if (overallResult == ValidationInvalidType) {
- String message = "Invalid value: " + LocationToString(locations);
-
- if (!hint.IsEmpty())
- message += ": " + hint;
-
- BOOST_THROW_EXCEPTION(ScriptError(message));
- }
-
- if (!subRuleLists.empty() && value.IsObject() && !value.IsObjectType<Array>())
- ValidateObject(value, subRuleLists, locations, utils);
- else if (!subRuleLists.empty() && value.IsObjectType<Array>())
- ValidateArray(value, subRuleLists, locations, utils);
-
- locations.pop_back();
-}
-
-void ConfigType::ValidateObject(const Object::Ptr& object,
- const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,
- const TypeRuleUtilities *utils)
-{
- BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {
- BOOST_FOREACH(const String& require, ruleList->GetRequires()) {
- locations.push_back("Attribute '" + require + "'");
-
- Value value = VMOps::GetField(object, require);
-
- if (value.IsEmpty())
- BOOST_THROW_EXCEPTION(ScriptError("Required attribute is missing: " + LocationToString(locations)));
-
- locations.pop_back();
- }
-
- BOOST_FOREACH(const String& validator, ruleList->GetValidators()) {
- Function::Ptr func = ScriptGlobal::Get(validator, &Empty);
-
- if (!func)
- BOOST_THROW_EXCEPTION(std::invalid_argument("Validator function '" + validator + "' does not exist."));
-
- std::vector<Value> arguments;
- arguments.push_back(LocationToString(locations));
- arguments.push_back(object);
-
- func->Invoke(arguments);
- }
- }
-
- Dictionary::Ptr dictionary = dynamic_pointer_cast<Dictionary>(object);
-
- if (dictionary) {
- ObjectLock olock(dictionary);
-
- BOOST_FOREACH(const Dictionary::Pair& kv, dictionary) {
- ValidateAttribute(kv.first, kv.second, ruleLists, locations, utils);
- }
- } else {
- Type::Ptr type = object->GetReflectionType();
-
- if (!type)
- return;
-
- for (int i = 0; i < type->GetFieldCount(); i++) {
- Field field = type->GetFieldInfo(i);
-
- if (!(field.Attributes & FAConfig))
- continue;
-
- ValidateAttribute(field.Name, object->GetField(i), ruleLists, locations, utils);
- }
- }
-}
-
-void ConfigType::ValidateArray(const Array::Ptr& array,
- const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,
- const TypeRuleUtilities *utils)
-{
- BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {
- BOOST_FOREACH(const String& require, ruleList->GetRequires()) {
- size_t index = Convert::ToLong(require);
-
- locations.push_back("Attribute '" + require + "'");
-
- if (array->GetLength() < index)
- BOOST_THROW_EXCEPTION(ScriptError("Required array index is missing: " + LocationToString(locations)));
-
- locations.pop_back();
- }
-
- BOOST_FOREACH(const String& validator, ruleList->GetValidators()) {
- Function::Ptr func = ScriptGlobal::Get(validator, &Empty);
-
- if (!func)
- BOOST_THROW_EXCEPTION(std::invalid_argument("Validator function '" + validator + "' does not exist."));
-
- std::vector<Value> arguments;
- arguments.push_back(LocationToString(locations));
- arguments.push_back(array);
-
- func->Invoke(arguments);
- }
- }
-
- ObjectLock olock(array);
-
- int index = 0;
- String key;
- BOOST_FOREACH(const Value& value, array) {
- key = Convert::ToString(index);
- index++;
-
- ValidateAttribute(key, value, ruleLists, locations, utils);
- }
-}
-
-void ConfigType::Register(void)
-{
- ConfigTypeRegistry::GetInstance()->Register(GetName(), this);
-}
-
-ConfigType::Ptr ConfigType::GetByName(const String& name)
-{
- return ConfigTypeRegistry::GetInstance()->GetItem(name);
-}
-
-ConfigTypeRegistry::ItemMap ConfigType::GetTypes(void)
-{
- return ConfigTypeRegistry::GetInstance()->GetItems();
-}
-
-ConfigTypeRegistry *ConfigTypeRegistry::GetInstance(void)
-{
- return Singleton<ConfigTypeRegistry>::GetInstance();
-}
+++ /dev/null
-/******************************************************************************\r
- * Icinga 2 *\r
- * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) *\r
- * *\r
- * This program is free software; you can redistribute it and/or *\r
- * modify it under the terms of the GNU General Public License *\r
- * as published by the Free Software Foundation; either version 2 *\r
- * of the License, or (at your option) any later version. *\r
- * *\r
- * This program is distributed in the hope that it will be useful, *\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *\r
- * GNU General Public License for more details. *\r
- * *\r
- * You should have received a copy of the GNU General Public License *\r
- * along with this program; if not, write to the Free Software Foundation *\r
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *\r
- ******************************************************************************/\r
-\r
-#ifndef CONFIGTYPE_H\r
-#define CONFIGTYPE_H\r
-\r
-#include "config/i2-config.hpp"\r
-#include "config/typerulelist.hpp"\r
-#include "config/typerule.hpp"\r
-#include "config/configitem.hpp"\r
-#include "base/array.hpp"\r
-#include "base/registry.hpp"\r
-\r
-namespace icinga\r
-{\r
-\r
-/**\r
- * A configuration type. Used to validate config objects.\r
- *\r
- * @ingroup config\r
- */\r
-class I2_CONFIG_API ConfigType : public Object {\r
-public:\r
- DECLARE_PTR_TYPEDEFS(ConfigType);\r
-\r
- ConfigType(const String& name, const DebugInfo& debuginfo);\r
-\r
- String GetName(void) const;\r
-\r
- String GetParent(void) const;\r
- void SetParent(const String& parent);\r
-\r
- TypeRuleList::Ptr GetRuleList(void) const;\r
-\r
- DebugInfo GetDebugInfo(void) const;\r
-\r
- void ValidateItem(const String& name, const Object::Ptr& object,\r
- const DebugInfo& debugInfo, const TypeRuleUtilities *utils);\r
-\r
- void Register(void);\r
- static ConfigType::Ptr GetByName(const String& name);\r
- static Registry<ConfigType, ConfigType::Ptr>::ItemMap GetTypes(void);\r
-\r
-private:\r
- String m_Name; /**< The type name. */\r
- String m_Parent; /**< The parent type. */\r
-\r
- TypeRuleList::Ptr m_RuleList;\r
- DebugInfo m_DebugInfo; /**< Debug information. */\r
-\r
- static void ValidateAttribute(const String& key, const Value& value,\r
- const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,\r
- const TypeRuleUtilities *utils);\r
- static void ValidateObject(const Object::Ptr& object,\r
- const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,\r
- const TypeRuleUtilities *utils);\r
- static void ValidateArray(const Array::Ptr& array,\r
- const std::vector<TypeRuleList::Ptr>& ruleLists, std::vector<String>& locations,\r
- const TypeRuleUtilities *utils);\r
-\r
- static String LocationToString(const std::vector<String>& locations);\r
-\r
- static void AddParentRules(std::vector<TypeRuleList::Ptr>& ruleLists, const ConfigType::Ptr& item);\r
-};\r
-\r
-class I2_CONFIG_API ConfigTypeRegistry : public Registry<ConfigTypeRegistry, ConfigType::Ptr>\r
-{\r
-public:\r
- static ConfigTypeRegistry *GetInstance(void);\r
-};\r
-\r
-}\r
-\r
-#endif /* CONFIGTYPE_H */\r
+++ /dev/null
-/******************************************************************************
- * 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/typerule.hpp"
-#include "config/configitem.hpp"
-#include "base/convert.hpp"
-#include "base/utility.hpp"
-#include "base/dictionary.hpp"
-#include "base/array.hpp"
-
-using namespace icinga;
-
-TypeRule::TypeRule(TypeSpecifier type, const String& nameType,
- const String& namePattern, const TypeRuleList::Ptr& subRules,
- const DebugInfo& debuginfo)
- : m_Type(type), m_NameType(nameType), m_NamePattern(namePattern), m_SubRules(subRules), m_DebugInfo(debuginfo)
-{ }
-
-TypeRuleList::Ptr TypeRule::GetSubRules(void) const
-{
- return m_SubRules;
-}
-
-bool TypeRule::MatchName(const String& name) const
-{
- return (Utility::Match(m_NamePattern, name));
-}
-
-bool TypeRule::MatchValue(const Value& value, String *hint, const TypeRuleUtilities *utils) const
-{
- ConfigItem::Ptr item;
-
- if (value.IsEmpty())
- return true;
-
- switch (m_Type) {
- case TypeAny:
- return true;
-
- case TypeString:
- /* fall through; any scalar can be converted to a string */
- case TypeScalar:
- return value.IsScalar();
-
- case TypeNumber:
- try {
- Convert::ToDouble(value);
- } catch (...) {
- return false;
- }
-
- return true;
-
- case TypeDictionary:
- return value.IsObjectType<Dictionary>();
-
- case TypeArray:
- return value.IsObjectType<Array>();
-
- case TypeFunction:
- return value.IsObjectType<Function>();
-
- case TypeName:
- if (!value.IsScalar())
- return false;
-
- return utils->ValidateName(m_NameType, value, hint);
-
- default:
- return false;
- }
-}
-
-bool TypeRuleUtilities::ValidateName(const String& type, const String& name, String *hint) const
-{
- if (name.IsEmpty())
- return true;
-
- ConfigItem::Ptr item = ConfigItem::GetObject(type, name);
-
- if (!item) {
- *hint = "Object '" + name + "' of type '" + type + "' does not exist.";
- return false;
- }
-
- if (item->IsAbstract()) {
- *hint = "Object '" + name + "' of type '" + type + "' must not be a template.";
- return false;
- }
-
- return true;
-}
+++ /dev/null
-/******************************************************************************
- * 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 TYPERULE_H
-#define TYPERULE_H
-
-#include "config/i2-config.hpp"
-#include "config/typerulelist.hpp"
-#include "base/debuginfo.hpp"
-
-namespace icinga
-{
-
-/**
- * Utilities for type rules.
- *
- * @ingroup config
- */
-class I2_CONFIG_API TypeRuleUtilities
-{
-public:
- virtual bool ValidateName(const String& type, const String& name, String *hint) const;
-};
-
-/**
- * The allowed type for a type rule.
- *
- * @ingroup config
- */
-enum TypeSpecifier
-{
- TypeAny,
- TypeScalar,
- TypeNumber,
- TypeString,
- TypeDictionary,
- TypeArray,
- TypeFunction,
- TypeName
-};
-
-/**
- * A configuration type rule.
- *
- * @ingroup config
- */
-struct I2_CONFIG_API TypeRule
-{
-public:
- TypeRule(TypeSpecifier type, const String& nameType,
- const String& namePattern, const TypeRuleList::Ptr& subRules,
- const DebugInfo& debuginfo);
-
- TypeRuleList::Ptr GetSubRules(void) const;
-
- bool MatchName(const String& name) const;
- bool MatchValue(const Value& value, String *hint, const TypeRuleUtilities *utils) const;
-
-private:
- TypeSpecifier m_Type;
- String m_NameType;
- String m_NamePattern;
- TypeRuleList::Ptr m_SubRules;
- DebugInfo m_DebugInfo;
-};
-
-}
-
-#endif /* TYPERULE_H */
+++ /dev/null
-/******************************************************************************
- * 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/typerulelist.hpp"
-#include "config/typerule.hpp"
-#include <boost/foreach.hpp>
-
-using namespace icinga;
-
-/**
- * Adds a validator method for a rule list.
- *
- * @param validator The validator.
- */
-void TypeRuleList::AddValidator(const String& validator)
-{
- m_Validators.push_back(validator);
-}
-
-/**
- * Retrieves the validator methods.
- *
- * @returns The validator methods.
- */
-std::vector<String> TypeRuleList::GetValidators(void) const
-{
- return m_Validators;
-}
-
-/**
- * Adds an attribute to the list of required attributes.
- *
- * @param attr The new required attribute.
- */
-void TypeRuleList::AddRequire(const String& attr)
-{
- m_Requires.push_back(attr);
-}
-
-/**
- * Retrieves the list of required attributes.
- *
- * @returns The list of required attributes.
- */
-std::vector<String> TypeRuleList::GetRequires(void) const
-{
- return m_Requires;
-}
-
-/**
- * Adds all requires from the specified rule list.
- *
- * @param ruleList The rule list to copy requires from.
- */
-void TypeRuleList::AddRequires(const TypeRuleList::Ptr& ruleList)
-{
- BOOST_FOREACH(const String& require, ruleList->m_Requires) {
- AddRequire(require);
- }
-}
-
-/**
- * Adds a rule to a rule list.
- *
- * @param rule The rule that should be added.
- */
-void TypeRuleList::AddRule(const TypeRule& rule)
-{
- m_Rules.push_back(rule);
-}
-
-/**
- * Adds all rules from the specified rule list.
- *
- * @param ruleList The rule list to copy rules from.
- */
-void TypeRuleList::AddRules(const TypeRuleList::Ptr& ruleList)
-{
- BOOST_FOREACH(const TypeRule& rule, ruleList->m_Rules) {
- AddRule(rule);
- }
-}
-
-/**
- * Returns the number of rules currently contained in the list.
- *
- * @returns The length of the list.
- */
-size_t TypeRuleList::GetLength(void) const
-{
- return m_Rules.size();
-}
-
-/**
- * Validates a field.
- *
- * @param name The name of the attribute.
- * @param value The value of the attribute.
- * @param[out] subRules The list of sub-rules for the matching rule.
- * @param[out] hint A hint describing the validation failure.
- * @returns The validation result.
- */
-TypeValidationResult TypeRuleList::ValidateAttribute(const String& name,
- const Value& value, TypeRuleList::Ptr *subRules, String *hint,
- const TypeRuleUtilities *utils) const
-{
- bool foundField = false;
- BOOST_FOREACH(const TypeRule& rule, m_Rules) {
- if (!rule.MatchName(name))
- continue;
-
- foundField = true;
-
- if (rule.MatchValue(value, hint, utils)) {
- *subRules = rule.GetSubRules();
- return ValidationOK;
- }
- }
-
- if (foundField)
- return ValidationInvalidType;
- else
- return ValidationUnknownField;
-}
+++ /dev/null
-/******************************************************************************
- * 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 TYPERULELIST_H
-#define TYPERULELIST_H
-
-#include "config/i2-config.hpp"
-#include "base/value.hpp"
-#include <vector>
-
-namespace icinga
-{
-
-struct TypeRule;
-class TypeRuleUtilities;
-
-/**
- * @ingroup config
- */
-enum TypeValidationResult
-{
- ValidationOK,
- ValidationInvalidType,
- ValidationUnknownField
-};
-
-/**
- * A list of configuration type rules.
- *
- * @ingroup config
- */
-class I2_CONFIG_API TypeRuleList : public Object
-{
-public:
- DECLARE_PTR_TYPEDEFS(TypeRuleList);
-
- void AddValidator(const String& validator);
- std::vector<String> GetValidators(void) const;
-
- void AddRequire(const String& attr);
- void AddRequires(const TypeRuleList::Ptr& ruleList);
- std::vector<String> GetRequires(void) const;
-
- void AddRule(const TypeRule& rule);
- void AddRules(const TypeRuleList::Ptr& ruleList);
-
- TypeValidationResult ValidateAttribute(const String& name, const Value& value,
- TypeRuleList::Ptr *subRules, String *hint, const TypeRuleUtilities *utils) const;
-
- size_t GetLength(void) const;
-
-private:
- std::vector<String> m_Validators;
- std::vector<String> m_Requires;
- std::vector<TypeRule> m_Rules;
-};
-
-}
-
-#endif /* TYPERULELIST_H */
try {
context->SetField(fid, value);
} catch (const boost::bad_lexical_cast&) {
- BOOST_THROW_EXCEPTION(ScriptError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'", debugInfo));
+ Field fieldInfo = type->GetFieldInfo(fid);
+ Type::Ptr ftype = Type::GetByName(fieldInfo.TypeName);
+ BOOST_THROW_EXCEPTION(ScriptError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "', expected '" + ftype->GetName() + "'", debugInfo));
} catch (const std::bad_cast&) {
- BOOST_THROW_EXCEPTION(ScriptError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'", debugInfo));
+ Field fieldInfo = type->GetFieldInfo(fid);
+ Type::Ptr ftype = Type::GetByName(fieldInfo.TypeName);
+ BOOST_THROW_EXCEPTION(ScriptError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "', expected '" + ftype->GetName() + "'", debugInfo));
}
}
mkclass_target(dbconnection.ti dbconnection.thpp)
-mkembedconfig_target(db_ido-type.conf db_ido-type.cpp)
mkembedconfig_target(db_ido-itl.conf db_ido-itl.cpp)
set(db_ido_SOURCES
commanddbobject.cpp dbconnection.cpp dbconnection.thpp dbconnection.thpp
- db_ido-type.cpp db_ido-itl.cpp dbevents.cpp dbobject.cpp dbquery.cpp
+ db_ido-itl.cpp dbevents.cpp dbobject.cpp dbquery.cpp
dbreference.cpp dbtype.cpp dbvalue.cpp endpointdbobject.cpp hostdbobject.cpp
hostgroupdbobject.cpp idochecktask.cpp servicedbobject.cpp
servicegroupdbobject.cpp timeperioddbobject.cpp userdbobject.cpp
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type DbConnection {
- %validator "ValidateFailoverTimeout"
-
- %attribute %string "table_prefix",
-
- %attribute %dictionary "cleanup" {
- %attribute %number "acknowledgements_age",
- %attribute %number "commenthistory_age",
- %attribute %number "contactnotifications_age",
- %attribute %number "contactnotificationmethods_age",
- %attribute %number "downtimehistory_age",
- %attribute %number "eventhandlers_age",
- %attribute %number "externalcommands_age",
- %attribute %number "flappinghistory_age",
- %attribute %number "hostchecks_age",
- %attribute %number "logentries_age",
- %attribute %number "notifications_age",
- %attribute %number "processevents_age",
- %attribute %number "statehistory_age",
- %attribute %number "servicechecks_age",
- %attribute %number "systemcommands_age",
- },
-
- %attribute %number "categories",
-
- %attribute %number "enable_ha",
-
- %attribute %number "failover_timeout",
-}
#include "base/objectlock.hpp"
#include "base/utility.hpp"
#include "base/logger.hpp"
-#include "base/function.hpp"
#include "base/exception.hpp"
#include <boost/foreach.hpp>
using namespace icinga;
REGISTER_TYPE(DbConnection);
-REGISTER_SCRIPTFUNCTION(ValidateFailoverTimeout, &DbConnection::ValidateFailoverTimeout);
Timer::Ptr DbConnection::m_ProgramStatusTimer;
boost::once_flag DbConnection::m_OnceFlag = BOOST_ONCE_INIT;
}
}
-void DbConnection::ValidateFailoverTimeout(const String& location, const DbConnection::Ptr& object)
+void DbConnection::ValidateFailoverTimeout(double value, const ValidationUtils& utils)
{
- if (object->GetFailoverTimeout() < 60) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Failover timeout minimum is 60s.", object->GetDebugInfo()));
- }
+ ObjectImpl<DbConnection>::ValidateFailoverTimeout(value, utils);
+
+ if (value < 60)
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("failover_timeout"), "Failover timeout minimum is 60s."));
}
void DbConnection::IncreaseQueryCount(void)
int GetQueryCount(RingBuffer::SizeType span) const;
virtual int GetPendingQueryCount(void) const = 0;
- static void ValidateFailoverTimeout(const String& location, const DbConnection::Ptr& object);
+ virtual void ValidateFailoverTimeout(double value, const ValidationUtils& utils) override;
protected:
virtual void OnConfigLoaded(void);
};
};
+
+validator DbConnection {
+ Dictionary cleanup {
+ Number acknowledgements_age;
+ Number commenthistory_age;
+ Number contactnotifications_age;
+ Number contactnotificationmethods_age;
+ Number downtimehistory_age;
+ Number eventhandlers_age;
+ Number externalcommands_age;
+ Number flappinghistory_age;
+ Number hostchecks_age;
+ Number logentries_age;
+ Number notifications_age;
+ Number processevents_age;
+ Number statehistory_age;
+ Number servicechecks_age;
+ Number systemcommands_age;
+ };
+};
+
}
if(MYSQL_FOUND)
mkclass_target(idomysqlconnection.ti idomysqlconnection.thpp)
- mkembedconfig_target(db_ido_mysql-type.conf db_ido_mysql-type.cpp)
-
set(db_ido_mysql_SOURCES
- idomysqlconnection.cpp idomysqlconnection.thpp db_ido_mysql-type.cpp
+ idomysqlconnection.cpp idomysqlconnection.thpp
)
if(ICINGA2_UNITY_BUILD)
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type IdoMysqlConnection %inherits DbConnection {
- %attribute %string "host",
- %attribute %number "port",
-
- %attribute %string "socket_path",
-
- %attribute %string "user",
- %attribute %string "password",
-
- %attribute %string "database",
-
- %attribute %string "instance_name",
- %attribute %string "instance_description"
-}
if(PostgreSQL_FOUND)
mkclass_target(idopgsqlconnection.ti idopgsqlconnection.thpp)
- mkembedconfig_target(db_ido_pgsql-type.conf db_ido_pgsql-type.cpp)
-
link_directories(${PostgreSQL_LIBRARY_DIRS})
include_directories(${PostgreSQL_INCLUDE_DIRS})
set(db_ido_pgsql_SOURCES
- idopgsqlconnection.cpp idopgsqlconnection.thpp db_ido_pgsql-type.cpp
+ idopgsqlconnection.cpp idopgsqlconnection.thpp
)
if(ICINGA2_UNITY_BUILD)
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type IdoPgsqlConnection %inherits DbConnection {
- %attribute %string "host",
- %attribute %number "port",
-
- %attribute %string "user",
- %attribute %string "password",
-
- %attribute %string "database",
-
- %attribute %string "instance_name",
- %attribute %string "instance_description"
-}
mkclass_target(demo.ti demo.thpp)
-mkembedconfig_target(demo-type.conf demo-type.cpp)
-
set(demo_SOURCES
- demo.cpp demo.thpp demo-type.cpp
+ demo.cpp demo.thpp
)
if(ICINGA2_UNITY_BUILD)
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type Demo {
-}
mkclass_target(hello.ti hello.thpp)
-mkembedconfig_target(hello-type.conf hello-type.cpp)
mkembedconfig_target(hello-app.conf hello-app.cpp)
set(hello_SOURCES
- hello.cpp hello.thpp hello-type.cpp hello-app.cpp
+ hello.cpp hello.thpp hello-app.cpp
)
if(ICINGA2_UNITY_BUILD)
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type Hello {
-}
mkclass_target(usergroup.ti usergroup.thpp)
mkclass_target(user.ti user.thpp)
-mkembedconfig_target(icinga-type.conf icinga-type.cpp)
mkembedconfig_target(icinga-app.conf icinga-app.cpp)
set(icinga_SOURCES
notification.thpp notification-apply.cpp objectutils.cpp perfdatavalue.cpp perfdatavalue.thpp pluginutility.cpp scheduleddowntime.cpp
scheduleddowntime.thpp scheduleddowntime-apply.cpp service-apply.cpp checkable-check.cpp checkable-comment.cpp
service.cpp service.thpp servicegroup.cpp servicegroup.thpp checkable-notification.cpp timeperiod.cpp timeperiod.thpp
- user.cpp user.thpp usergroup.cpp usergroup.thpp icinga-type.cpp icinga-app.cpp
+ user.cpp user.thpp usergroup.cpp usergroup.thpp icinga-app.cpp
)
if(ICINGA2_UNITY_BUILD)
#include "icinga/checkable.hpp"
#include "base/objectlock.hpp"
#include "base/utility.hpp"
-#include "base/function.hpp"
#include "base/exception.hpp"
#include <boost/foreach.hpp>
#include <boost/bind/apply.hpp>
using namespace icinga;
REGISTER_TYPE(Checkable);
-REGISTER_SCRIPTFUNCTION(ValidateCheckableCheckInterval, &Checkable::ValidateCheckInterval);
boost::signals2::signal<void (const Checkable::Ptr&, bool, const MessageOrigin&)> Checkable::OnEnablePerfdataChanged;
boost::signals2::signal<void (const Checkable::Ptr&, const String&, const String&, AcknowledgementType, bool, double, const MessageOrigin&)> Checkable::OnAcknowledgementSet;
return Endpoint::GetByName(GetCommandEndpointRaw());
}
-void Checkable::ValidateCheckInterval(const String& location, const Checkable::Ptr& object)
+void Checkable::ValidateCheckIntervalRaw(double value, const ValidationUtils& utils)
{
- if (object->GetCheckInterval() <= 0) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": check_interval must be greater than 0.", object->GetDebugInfo()));
- }
+ ObjectImpl<Checkable>::ValidateCheckIntervalRaw(value, utils);
+
+ if (value <= 0)
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("check_interval"), "Interval must be greater than 0."));
}
void RemoveReverseDependency(const intrusive_ptr<Dependency>& dep);
std::set<intrusive_ptr<Dependency> > GetReverseDependencies(void) const;
- static void ValidateCheckInterval(const String& location, const Checkable::Ptr& object);
+ virtual void ValidateCheckIntervalRaw(double value, const ValidationUtils& utils) override;
protected:
virtual void Start(void);
[config] Array::Ptr groups {
default {{{ return new Array(); }}}
};
- [config, protected] String check_command (CheckCommandRaw);
+ [config, protected, required] name(CheckCommand) check_command (CheckCommandRaw);
[config] int max_check_attempts (MaxCheckAttemptsRaw) {
default {{{ return 3; }}}
};
- [config, protected] String check_period (CheckPeriodRaw);
+ [config, protected] name(TimePeriod) check_period (CheckPeriodRaw);
[config] double check_interval (CheckIntervalRaw) {
default {{{ return 5 * 60; }}}
};
[config] double retry_interval (RetryIntervalRaw) {
default {{{ return 60; }}}
};
- [config] String event_command (EventCommandRaw);
+ [config] name(EventCommand) event_command (EventCommandRaw);
[config] bool volatile;
[config] double flapping_threshold {
default {{{ return 30; }}}
[state] Value override_max_check_attempts;
[state] Value override_check_period;
- [config] String command_endpoint (CommandEndpointRaw);
+ [config] name(Endpoint) command_endpoint (CommandEndpointRaw);
};
}
#include "icinga/command.hpp"
#include "icinga/macroprocessor.hpp"
-#include "base/function.hpp"
#include "base/exception.hpp"
#include "base/objectlock.hpp"
#include <boost/foreach.hpp>
using namespace icinga;
REGISTER_TYPE(Command);
-REGISTER_SCRIPTFUNCTION(ValidateCommandAttributes, &Command::ValidateAttributes);
-REGISTER_SCRIPTFUNCTION(ValidateCommandArguments, &Command::ValidateArguments);
-REGISTER_SCRIPTFUNCTION(ValidateEnvironmentVariables, &Command::ValidateEnvironmentVariables);
int Command::GetModifiedAttributes(void) const
{
}
}
-void Command::ValidateAttributes(const String& location, const Command::Ptr& object)
+void Command::Validate(int types, const ValidationUtils& utils)
{
- if (object->GetArguments() != Empty && !object->GetCommandLine().IsObjectType<Array>()) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Attribute 'command' must be an array if the 'arguments' attribute is set.", object->GetDebugInfo()));
- }
-}
+ ObjectImpl<Command>::Validate(types, utils);
-void Command::ValidateArguments(const String& location, const Command::Ptr& object)
-{
- Dictionary::Ptr arguments = object->GetArguments();
+ Dictionary::Ptr arguments = GetArguments();
- if (!arguments)
+ if (!(types & FAConfig))
return;
- ObjectLock olock(arguments);
- BOOST_FOREACH(const Dictionary::Pair& kv, arguments) {
- const Value& arginfo = kv.second;
- Value argval;
+ if (arguments) {
+ if (!GetCommandLine().IsObjectType<Array>())
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("command"), "Attribute 'command' must be an array if the 'arguments' attribute is set."));
- if (arginfo.IsObjectType<Dictionary>()) {
- Dictionary::Ptr argdict = arginfo;
+ ObjectLock olock(arguments);
+ BOOST_FOREACH(const Dictionary::Pair& kv, arguments) {
+ const Value& arginfo = kv.second;
+ Value argval;
- if (argdict->Contains("value")) {
- String argvalue = argdict->Get("value");
+ if (arginfo.IsObjectType<Dictionary>()) {
+ Dictionary::Ptr argdict = arginfo;
- if (!MacroProcessor::ValidateMacroString(argvalue)) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + argvalue + "'.", object->GetDebugInfo()));
+ if (argdict->Contains("value")) {
+ String argvalue = argdict->Get("value");
+
+ if (!MacroProcessor::ValidateMacroString(argvalue))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("arguments")(kv.first)("value"), "Validation failed: Closing $ not found in macro format string '" + argvalue + "'."));
}
- }
- if (argdict->Contains("set_if")) {
- String argsetif = argdict->Get("set_if");
+ if (argdict->Contains("set_if")) {
+ String argsetif = argdict->Get("set_if");
- if (!MacroProcessor::ValidateMacroString(argsetif)) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + argsetif + "'.", object->GetDebugInfo()));
+ if (!MacroProcessor::ValidateMacroString(argsetif))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("arguments")(kv.first)("set_if"), "Closing $ not found in macro format string '" + argsetif + "'."));
}
- }
- } else if (arginfo.IsObjectType<Function>()) {
- continue; /* we cannot evaluate macros in functions */
- } else {
- argval = arginfo;
+ } else if (arginfo.IsObjectType<Function>()) {
+ continue; /* we cannot evaluate macros in functions */
+ } else {
+ argval = arginfo;
- if (argval.IsEmpty())
- continue;
+ if (argval.IsEmpty())
+ continue;
- String argstr = argval;
+ String argstr = argval;
- if (!MacroProcessor::ValidateMacroString(argstr)) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + argstr + "'.", object->GetDebugInfo()));
+ if (!MacroProcessor::ValidateMacroString(argstr))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("arguments")(kv.first), "Closing $ not found in macro format string '" + argstr + "'."));
}
}
}
-}
-
-void Command::ValidateEnvironmentVariables(const String& location, const Command::Ptr& object)
-{
- Dictionary::Ptr env = object->GetEnv();
- if (!env)
- return;
+ Dictionary::Ptr env = GetEnv();
- ObjectLock olock(env);
- BOOST_FOREACH(const Dictionary::Pair& kv, env) {
- const Value& envval = kv.second;
+ if (env) {
+ ObjectLock olock(env);
+ BOOST_FOREACH(const Dictionary::Pair& kv, env) {
+ const Value& envval = kv.second;
- if (!envval.IsString() || envval.IsEmpty())
- continue;
+ if (!envval.IsString() || envval.IsEmpty())
+ continue;
- if (!MacroProcessor::ValidateMacroString(envval)) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + envval + "'.", object->GetDebugInfo()));
+ if (!MacroProcessor::ValidateMacroString(envval))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("env")(kv.first), "Closing $ not found in macro format string '" + envval + "'."));
}
}
}
//virtual Dictionary::Ptr Execute(const Object::Ptr& context) = 0;
- static void ValidateAttributes(const String& location, const Command::Ptr& object);
- static void ValidateArguments(const String& location, const Command::Ptr& object);
- static void ValidateEnvironmentVariables(const String& location, const Command::Ptr& object);
+ virtual void Validate(int types, const ValidationUtils& utils) override;
int GetModifiedAttributes(void) const;
void SetModifiedAttributes(int flags, const MessageOrigin& origin = MessageOrigin());
{
[config] Value command (CommandLine);
[config] Value arguments;
- [config] Value timeout {
+ [config] int timeout {
default {{{ return 60; }}}
};
[config] Dictionary::Ptr env;
- [config] Function::Ptr execute;
+ [config, required] Function::Ptr execute;
+};
+
+validator Command {
+ String command;
+ Function command;
+ Array command {
+ String "*";
+ Function "*";
+ };
+
+ Dictionary arguments {
+ String "*";
+ Dictionary "*" {
+ String key;
+ String value;
+ Function value;
+ String description;
+ Number "required";
+ Number skip_key;
+ Number repeat_key;
+ String set_if;
+ Function set_if;
+ Number order;
+ };
+ };
+
+ Dictionary env {
+ String "*";
+ Function "*";
+ };
};
}
using namespace icinga;
REGISTER_TYPE(CustomVarObject);
-REGISTER_SCRIPTFUNCTION(ValidateCustomAttributes, &CustomVarObject::ValidateCustomAttributes);
boost::signals2::signal<void (const CustomVarObject::Ptr&, const Dictionary::Ptr& vars, const MessageOrigin&)> CustomVarObject::OnVarsChanged;
return vars_override->Contains(name);
}
-void CustomVarObject::ValidateCustomAttributes(const String& location, const CustomVarObject::Ptr& object)
+void CustomVarObject::ValidateVarsRaw(const Dictionary::Ptr& value, const ValidationUtils& utils)
{
- Dictionary::Ptr vars = object->GetVars();
-
- if (!vars)
+ if (!value)
return;
/* string, array, dictionary */
- ObjectLock olock(vars);
- BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+ ObjectLock olock(value);
+ BOOST_FOREACH(const Dictionary::Pair& kv, value) {
const Value& varval = kv.second;
if (varval.IsObjectType<Dictionary>()) {
if (kv_var.second.IsEmpty())
continue;
- if (!MacroProcessor::ValidateMacroString(kv_var.second)) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + kv_var.second + "'.", object->GetDebugInfo()));
- }
+ if (!MacroProcessor::ValidateMacroString(kv_var.second))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("vars")(kv.first)(kv_var.first), "Closing $ not found in macro format string '" + kv_var.second + "'."));
}
} else if (varval.IsObjectType<Array>()) {
/* check all array entries */
continue;
if (!MacroProcessor::ValidateMacroString(arrval)) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + arrval + "'.", object->GetDebugInfo()));
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("vars")(kv.first), "Closing $ not found in macro format string '" + arrval + "'."));
}
}
} else {
String varstr = varval;
- if (!MacroProcessor::ValidateMacroString(varstr)) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + varstr + "'.", object->GetDebugInfo()));
- }
+ if (!MacroProcessor::ValidateMacroString(varstr))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of<String>("vars")(kv.first), "Closing $ not found in macro format string '" + varstr + "'."));
}
}
}
static boost::signals2::signal<void (const CustomVarObject::Ptr&, const Dictionary::Ptr& vars, const MessageOrigin&)> OnVarsChanged;
- static void ValidateCustomAttributes(const String& location, const CustomVarObject::Ptr& object);
+ virtual void ValidateVarsRaw(const Dictionary::Ptr& value, const ValidationUtils& utils) override;
Dictionary::Ptr GetVars(void) const;
void SetVars(const Dictionary::Ptr& vars, const MessageOrigin& origin = MessageOrigin());
#include "icinga/dependency.hpp"
#include "icinga/service.hpp"
#include "base/logger.hpp"
-#include "base/function.hpp"
#include "base/exception.hpp"
#include <boost/foreach.hpp>
using namespace icinga;
REGISTER_TYPE(Dependency);
-REGISTER_SCRIPTFUNCTION(ValidateDependencyFilters, &Dependency::ValidateFilters);
String DependencyNameComposer::MakeName(const String& shortName, const Object::Ptr& context) const
{
return TimePeriod::GetByName(GetPeriodRaw());
}
-void Dependency::ValidateFilters(const String& location, const Dependency::Ptr& object)
+void Dependency::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils)
{
- int sfilter = FilterArrayToInt(object->GetStates(), 0);
+ ObjectImpl<Dependency>::ValidateStates(value, utils);
- if (object->GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": State filter is invalid for host dependency.", object->GetDebugInfo()));
- }
+ int sfilter = FilterArrayToInt(value, 0);
- if (!object->GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": State filter is invalid for service dependency.", object->GetDebugInfo()));
- }
+ if (GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0)
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("states"), "State filter is invalid for host dependency."));
+
+ if (!GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0)
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("states"), "State filter is invalid for service dependency."));
}
static void RegisterApplyRuleHandler(void);
- static void ValidateFilters(const String& location, const Dependency::Ptr& object);
+ virtual void ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) override;
static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
load_after Host;
load_after Service;
- [config] String child_host_name;
+ [config, required] name(Host) child_host_name;
[config] String child_service_name;
- [config] String parent_host_name;
+ [config, required] name(Host) parent_host_name;
[config] String parent_service_name;
- [config] String period (PeriodRaw);
+ [config] name(TimePeriod) period (PeriodRaw);
[config] Array::Ptr states;
int state_filter_real (StateFilter);
};
};
+validator Dependency {
+ Array states {
+ Number "*";
+ };
+};
+
}
#include "icinga/hostgroup.hpp"
#include "icinga/pluginutility.hpp"
#include "icinga/scheduleddowntime.hpp"
-#include "base/exception.hpp"
#include "base/objectlock.hpp"
#include "base/convert.hpp"
#include "base/utility.hpp"
};
+validator Host {
+ Array groups {
+ name(HostGroup) "*";
+ };
+};
+
}
[config] String action_url;
};
+validator HostGroup {
+ Array groups {
+ name(HostGroup) "*";
+ };
+};
+
}
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type IcingaApplication {
-}
-
-%type IcingaStatusWriter {
- %attribute %string "status_path",
- %attribute %number "update_interval"
-}
-
-%type CustomVarObject {
- %validator "ValidateCustomAttributes",
- %attribute %dictionary "vars",
-}
-
-%type Checkable %inherits CustomVarObject {
- %validator "ValidateCheckableCheckInterval",
-
- %attribute %string "display_name",
-
- %require "check_command",
- %attribute %name(CheckCommand) "check_command",
- %attribute %number "max_check_attempts",
- %attribute %name(TimePeriod) "check_period",
- %attribute %number "check_interval",
- %attribute %number "retry_interval",
-
- %attribute %number "enable_notifications",
- %attribute %number "enable_active_checks",
- %attribute %number "enable_passive_checks",
- %attribute %number "enable_event_handler",
-
- %attribute %name(EventCommand) "event_command",
-
- %attribute %number "enable_flapping",
- %attribute %number "flapping_threshold",
-
- %attribute %number "enable_perfdata",
-
- %attribute %number "volatile",
-
- %attribute %string "notes",
- %attribute %string "notes_url",
- %attribute %string "action_url",
- %attribute %string "icon_image",
- %attribute %string "icon_image_alt",
-
- %attribute %name(Endpoint) "command_endpoint",
-}
-
-%type Host %inherits Checkable {
- %attribute %string "display_name",
- %attribute %array "groups" {
- %attribute %name(HostGroup) "*"
- },
-
- %attribute %string "address",
- %attribute %string "address6",
-}
-
-%type HostGroup %inherits CustomVarObject {
- %attribute %string "display_name"
-
- %attribute %array "groups" {
- %attribute %name(HostGroup) "*"
- },
-
- %attribute %string "notes",
- %attribute %string "notes_url",
- %attribute %string "action_url",
-}
-
-%type Service %inherits Checkable {
- %require "host_name",
- %attribute %name(Host) "host_name",
-
- %attribute %string "name",
-
- %attribute %array "groups" {
- %attribute %name(ServiceGroup) "*"
- },
-}
-
-%type ServiceGroup %inherits CustomVarObject {
- %attribute %string "display_name"
-
- %attribute %array "groups" {
- %attribute %name(ServiceGroup) "*"
- },
-
- %attribute %string "notes",
- %attribute %string "notes_url",
- %attribute %string "action_url",
-}
-
-%type Notification %inherits CustomVarObject {
- %validator "ValidateNotificationFilters"
- %validator "ValidateNotificationUsers"
-
- %require "host_name",
- %attribute %name(Host) "host_name",
- %attribute %string "service_name",
-
- %attribute %string "name",
-
- %attribute %array "users" {
- %attribute %name(User) "*"
- },
- %attribute %array "user_groups" {
- %attribute %name(UserGroup) "*"
- },
-
- %attribute %dictionary "times" {
- %attribute %number "begin",
- %attribute %number "end",
- },
-
- %require "command",
- %attribute %name(NotificationCommand) "command",
-
- %attribute %number "interval",
- %attribute %name(TimePeriod) "period",
-
- %attribute %array "types" {
- %attribute %number "*"
- },
- %attribute %array "states" {
- %attribute %number "*"
- },
-
- %attribute %name(Endpoint) "command_endpoint",
-}
-
-%type User %inherits CustomVarObject {
- %validator "ValidateUserFilters"
-
- %attribute %string "display_name",
-
- %attribute %array "groups" {
- %attribute %name(UserGroup) "*"
- },
-
- %attribute %number "enable_notifications",
- %attribute %array "types" {
- %attribute %number "*"
- },
- %attribute %array "states" {
- %attribute %number "*"
- },
- %attribute %name(TimePeriod) "period",
-
- %attribute %string "email",
- %attribute %string "pager",
-}
-
-%type UserGroup %inherits CustomVarObject {
- %attribute %string "display_name",
-
- %attribute %array "groups" {
- %attribute %name(UserGroup) "*"
- },
-}
-
-%type TimePeriod %inherits CustomVarObject {
- %validator "ValidateTimePeriodRanges",
-
- %attribute %string "display_name",
-
- %require "update",
- %attribute %function "update",
-
-/* %if (methods.update == "LegacyTimePeriod") { */
-// %require "ranges",
- %attribute %dictionary "ranges" {
- %attribute %string "*"
- }
-/* } */
-}
-
-%type Command %inherits CustomVarObject {
- %validator "ValidateCommandAttributes",
- %validator "ValidateCommandArguments",
- %validator "ValidateEnvironmentVariables",
-
- %require "execute",
- %attribute %function "execute",
-
-/* %if (methods.execute == "PluginNotification" || methods.execute == "PluginCheck" || methods.execute == "PluginEvent") { */
-// %require "command",
- %attribute %string "command",
- %attribute %function "command",
- %attribute %array "command" {
- %attribute %string "*"
- %attribute %function "*",
- },
- %attribute %dictionary "arguments" {
- %attribute %string "*",
- %attribute %dictionary "*" {
- %attribute %string "key"
- %attribute %string "value"
- %attribute %function "value"
- %attribute %string "description"
- %attribute %number "required"
- %attribute %number "skip_key"
- %attribute %number "repeat_key"
- %attribute %string "set_if"
- %attribute %function "set_if"
- %attribute %number "order"
- }
- },
- %attribute %dictionary "env" {
- %attribute %string "*"
- %attribute %function "*"
- },
- %attribute %number "timeout"
-/* } */
-}
-
-%type CheckCommand %inherits Command {
-
-}
-
-%type NotificationCommand %inherits Command {
-
-}
-
-%type EventCommand %inherits Command {
-
-}
-
-%type ScheduledDowntime %inherits CustomVarObject {
- %validator "ValidateScheduledDowntimeRanges",
-
- %require "host_name",
- %attribute %name(Host) "host_name",
- %attribute %string "service_name",
-
- %attribute %string "name",
-
- %require "author",
- %attribute %string "author",
-
- %require "comment",
- %attribute %string "comment",
-
- %attribute %number "duration",
- %attribute %number "fixed",
-
- %require "ranges",
- %attribute %dictionary "ranges" {
- %attribute %string "*"
- },
-}
-
-%type Dependency %inherits CustomVarObject {
- %validator "ValidateDependencyFilters"
-
- %require "parent_host_name",
- %attribute %name(Host) "parent_host_name",
- %attribute %string "parent_service_name",
-
- %require "child_host_name",
- %attribute %name(Host) "child_host_name",
- %attribute %string "child_service_name",
-
- %attribute %string "name",
-
- %attribute %name(TimePeriod) "period",
-
- %attribute %array "states" {
- %attribute %number "*"
- },
- %attribute %number "ignore_soft_states",
- %attribute %number "disable_checks",
- %attribute %number "disable_notifications"
-}
#include "base/exception.hpp"
#include "base/initialize.hpp"
#include "base/scriptglobal.hpp"
-#include "base/function.hpp"
#include <boost/foreach.hpp>
using namespace icinga;
REGISTER_TYPE(Notification);
-REGISTER_SCRIPTFUNCTION(ValidateNotificationFilters, &Notification::ValidateFilters);
-REGISTER_SCRIPTFUNCTION(ValidateNotificationUsers, &Notification::ValidateUsers);
INITIALIZE_ONCE(&Notification::StaticInitialize);
boost::signals2::signal<void (const Notification::Ptr&, double, const MessageOrigin&)> Notification::OnNextNotificationChanged;
<< "Not sending notifications for notification object '" << GetName() << "': before escalation range";
/* we need to adjust the next notification time
- * to now + begin delaying the first notification
- */
+ * to now + begin delaying the first notification
+ */
double nextProposedNotification = now + times->Get("begin") + 1.0;
if (GetNextNotification() > nextProposedNotification)
SetNextNotification(nextProposedNotification);
}
}
-void Notification::ValidateUsers(const String& location, const Notification::Ptr& object)
+void Notification::Validate(int types, const ValidationUtils& utils)
{
- Array::Ptr users = object->GetUsersRaw();
- Array::Ptr groups = object->GetUserGroupsRaw();
+ ObjectImpl<Notification>::Validate(types, utils);
- if ((!users || users->GetLength() == 0) && (!groups || groups->GetLength() == 0)) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": No users/user_groups specified.", object->GetDebugInfo()));
- }
+ if (!(types & FAConfig))
+ return;
+
+ Array::Ptr users = GetUsersRaw();
+ Array::Ptr groups = GetUserGroupsRaw();
+
+ if ((!users || users->GetLength() == 0) && (!groups || groups->GetLength() == 0))
+ BOOST_THROW_EXCEPTION(ValidationError(this, std::vector<String>(), "Validation failed: No users/user_groups specified."));
}
-void Notification::ValidateFilters(const String& location, const Notification::Ptr& object)
+void Notification::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils)
{
- int sfilter = FilterArrayToInt(object->GetStates(), 0);
+ ObjectImpl<Notification>::ValidateStates(value, utils);
- if (object->GetServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": State filter is invalid.", object->GetDebugInfo()));
- }
+ int sfilter = FilterArrayToInt(value, 0);
- if (!object->GetServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": State filter is invalid.", object->GetDebugInfo()));
- }
+ if (GetServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0)
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("states"), "State filter is invalid."));
- int tfilter = FilterArrayToInt(object->GetTypes(), 0);
+ if (!GetServiceName().IsEmpty() && (sfilter & ~(StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0)
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("types"), "State filter is invalid."));
+}
+
+void Notification::ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils)
+{
+ ObjectImpl<Notification>::ValidateTypes(value, utils);
+
+ int tfilter = FilterArrayToInt(value, 0);
if ((tfilter & ~(1 << NotificationDowntimeStart | 1 << NotificationDowntimeEnd | 1 << NotificationDowntimeRemoved |
1 << NotificationCustom | 1 << NotificationAcknowledgement | 1 << NotificationProblem | 1 << NotificationRecovery |
- 1 << NotificationFlappingStart | 1 << NotificationFlappingEnd)) != 0) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Type filter is invalid.", object->GetDebugInfo()));
- }
+ 1 << NotificationFlappingStart | 1 << NotificationFlappingEnd)) != 0)
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("types"), "Type filter is invalid."));
}
Endpoint::Ptr Notification::GetCommandEndpoint(void) const
{
return Endpoint::GetByName(GetCommandEndpointRaw());
}
-
static void RegisterApplyRuleHandler(void);
- static void ValidateUsers(const String& location, const Notification::Ptr& object);
- static void ValidateFilters(const String& location, const Notification::Ptr& object);
+ virtual void Validate(int types, const ValidationUtils& utils) override;
+
+ virtual void ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) override;
+ virtual void ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) override;
static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
load_after Host;
load_after Service;
- [config, protected] String command (CommandRaw);
+ [config, protected, required] name(NotificationCommand) command (CommandRaw);
[config] double interval {
default {{{ return 1800; }}}
};
- [config] String period (PeriodRaw);
+ [config] name(TimePeriod) period (PeriodRaw);
[config, protected] Array::Ptr users (UsersRaw);
[config, protected] Array::Ptr user_groups (UserGroupsRaw);
[config] Dictionary::Ptr times;
int type_filter_real (TypeFilter);
[config] Array::Ptr states;
int state_filter_real (StateFilter);
- [config, protected] String host_name;
+ [config, protected, required] name(Host) host_name;
[config, protected] String service_name;
[state] Array::Ptr notified_users {
[state, set_protected] Value notification_number;
[state] double last_problem_notification;
- [config] String command_endpoint (CommandEndpointRaw);
+ [config] name(Endpoint) command_endpoint (CommandEndpointRaw);
+};
+
+validator Notification {
+ Array users {
+ name(User) "*";
+ };
+
+ Array user_groups {
+ name(UserGroup) "*";
+ };
+
+ Dictionary times {
+ Number begin;
+ Number end;
+ };
+
+ Array types {
+ Number "*";
+ };
+
+ Array states {
+ Number "*";
+ };
};
}
using namespace icinga;
REGISTER_TYPE(ScheduledDowntime);
-REGISTER_SCRIPTFUNCTION(ValidateScheduledDowntimeRanges, &ScheduledDowntime::ValidateRanges);
INITIALIZE_ONCE(&ScheduledDowntime::StaticInitialize);
downtime->SetConfigOwner(GetName());
}
-void ScheduledDowntime::ValidateRanges(const String& location, const ScheduledDowntime::Ptr& object)
+void ScheduledDowntime::ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils)
{
- Dictionary::Ptr ranges = object->GetRanges();
-
- if (!ranges)
+ if (!value)
return;
/* create a fake time environment to validate the definitions */
tm reference = Utility::LocalTime(refts);
Array::Ptr segments = new Array();
- ObjectLock olock(ranges);
- BOOST_FOREACH(const Dictionary::Pair& kv, ranges) {
+ ObjectLock olock(value);
+ BOOST_FOREACH(const Dictionary::Pair& kv, value) {
try {
tm begin_tm, end_tm;
int stride;
LegacyTimePeriod::ParseTimeRange(kv.first, &begin_tm, &end_tm, &stride, &reference);
} catch (std::exception&) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Invalid time specification.", object->GetDebugInfo()));
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("ranges"), "Invalid time specification: " + kv.first));
}
try {
LegacyTimePeriod::ProcessTimeRanges(kv.second, &reference, segments);
} catch (std::exception&) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Invalid time range definition.", object->GetDebugInfo()));
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("ranges"), "Invalid time range definition: " + kv.first));
}
}
}
static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
- static void ValidateRanges(const String& location, const ScheduledDowntime::Ptr& object);
+ virtual void ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils) override;
protected:
virtual void OnAllConfigLoaded(void);
load_after Host;
load_after Service;
- [config, protected] String host_name;
+ [config, protected, required] name(Host) host_name;
[config, protected] String service_name;
- [config] String author;
- [config] String comment;
+ [config, required] String author;
+ [config, required] String comment;
[config] double duration;
[config] bool fixed {
default {{{ return true; }}}
};
- [config] Dictionary::Ptr ranges;
+ [config, required] Dictionary::Ptr ranges;
+};
+
+validator ScheduledDowntime {
+ Dictionary ranges {
+ String "*";
+ };
};
}
return m_DisplayName;
}}}
};
- [config] String host_name;
+ [config, required] name(Host) host_name;
[enum, no_storage] ServiceState "state" {
get {{{
return GetStateRaw();
};
};
+validator Service {
+ Array groups {
+ name(ServiceGroup) "*";
+ };
+};
+
}
[config] String action_url;
};
+validator ServiceGroup {
+ Array groups {
+ name(ServiceGroup) "*";
+ };
+};
+
}
using namespace icinga;
REGISTER_TYPE(TimePeriod);
-REGISTER_SCRIPTFUNCTION(ValidateTimePeriodRanges, &TimePeriod::ValidateRanges);
static Timer::Ptr l_UpdateTimer;
Log(LogDebug, "TimePeriod", "---");
}
-void TimePeriod::ValidateRanges(const String& location, const TimePeriod::Ptr& object)
+void TimePeriod::ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils)
{
- Dictionary::Ptr ranges = object->GetRanges();
-
- if (!ranges)
+ if (!value)
return;
/* create a fake time environment to validate the definitions */
tm reference = Utility::LocalTime(refts);
Array::Ptr segments = new Array();
- ObjectLock olock(ranges);
- BOOST_FOREACH(const Dictionary::Pair& kv, ranges) {
+ ObjectLock olock(value);
+ BOOST_FOREACH(const Dictionary::Pair& kv, value) {
try {
tm begin_tm, end_tm;
int stride;
LegacyTimePeriod::ParseTimeRange(kv.first, &begin_tm, &end_tm, &stride, &reference);
} catch (std::exception&) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Invalid time specification.", object->GetDebugInfo()));
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("ranges"), "Invalid time specification: " + kv.first));
}
try {
LegacyTimePeriod::ProcessTimeRanges(kv.second, &reference, segments);
} catch (std::exception&) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Invalid time range definition.", object->GetDebugInfo()));
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("ranges"), "Invalid time range definition: " + kv.second));
}
}
}
bool IsInside(double ts) const;
double FindNextTransition(double begin);
- static void ValidateRanges(const String& location, const TimePeriod::Ptr& object);
+ virtual void ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils) override;
private:
void AddSegment(double s, double end);
}}}
};
[config] Dictionary::Ptr ranges;
- [config] Function::Ptr update;
+ [config, required] Function::Ptr update;
[state] Value valid_begin;
[state] Value valid_end;
[state] Array::Ptr segments;
};
};
+validator TimePeriod {
+ Dictionary ranges {
+ String "*";
+ };
+};
+
}
#include "icinga/usergroup.hpp"
#include "icinga/notification.hpp"
#include "icinga/usergroup.hpp"
-#include "base/function.hpp"
#include "base/objectlock.hpp"
#include "base/exception.hpp"
#include <boost/foreach.hpp>
using namespace icinga;
REGISTER_TYPE(User);
-REGISTER_SCRIPTFUNCTION(ValidateUserFilters, &User::ValidateFilters);
boost::signals2::signal<void (const User::Ptr&, bool, const MessageOrigin&)> User::OnEnableNotificationsChanged;
return TimePeriod::GetByName(GetPeriodRaw());
}
-void User::ValidateFilters(const String& location, const User::Ptr& object)
+void User::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils)
{
- int sfilter = FilterArrayToInt(object->GetStates(), 0);
+ ObjectImpl<User>::ValidateStates(value, utils);
+
+ int sfilter = FilterArrayToInt(value, 0);
if ((sfilter & ~(StateFilterUp | StateFilterDown | StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": State filter is invalid.", object->GetDebugInfo()));
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("states"), "State filter is invalid."));
}
+}
- int tfilter = FilterArrayToInt(object->GetTypes(), 0);
+void User::ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils)
+{
+ int tfilter = FilterArrayToInt(value, 0);
if ((tfilter & ~(1 << NotificationDowntimeStart | 1 << NotificationDowntimeEnd | 1 << NotificationDowntimeRemoved |
1 << NotificationCustom | 1 << NotificationAcknowledgement | 1 << NotificationProblem | 1 << NotificationRecovery |
1 << NotificationFlappingStart | 1 << NotificationFlappingEnd)) != 0) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Type filter is invalid.", object->GetDebugInfo()));
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("types"), "Type filter is invalid."));
}
}
/* Notifications */
TimePeriod::Ptr GetPeriod(void) const;
- static void ValidateFilters(const String& location, const User::Ptr& attrs);
+ virtual void ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) override;
+ virtual void ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) override;
bool GetEnableNotifications(void) const;
void SetEnableNotifications(bool enabled, const MessageOrigin& origin = MessageOrigin());
[config] Array::Ptr groups {
default {{{ return new Array(); }}}
};
- [config] String period (PeriodRaw);
+ [config] name(TimePeriod) period (PeriodRaw);
[config] Array::Ptr types;
int type_filter_real (TypeFilter);
[config] Array::Ptr states;
[state] double last_notification;
};
+validator User {
+ Array groups {
+ name(UserGroup) "*";
+ };
+
+ Array types {
+ Number "*";
+ };
+
+ Array states {
+ Number "*";
+ };
+};
+
}
[config] Array::Ptr groups;
};
+validator UserGroup {
+ Array groups {
+ name(UserGroup) "*";
+ };
+};
+
}
mkclass_target(livestatuslistener.ti livestatuslistener.thpp)
-mkembedconfig_target(livestatus-type.conf livestatus-type.cpp)
-
set(livestatus_SOURCES
aggregator.cpp andfilter.cpp attributefilter.cpp
avgaggregator.cpp column.cpp combinerfilter.cpp commandstable.cpp
minaggregator.cpp negatefilter.cpp orfilter.cpp
servicegroupstable.cpp servicestable.cpp statehisttable.cpp
statustable.cpp stdaggregator.cpp sumaggregator.cpp table.cpp
- timeperiodstable.cpp livestatus-type.cpp
+ timeperiodstable.cpp
)
if(ICINGA2_UNITY_BUILD)
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type LivestatusListener {
- %validator "ValidateSocketType",
-
- %attribute %string "socket_type",
-
- %attribute %string "socket_path",
- %attribute %string "bind_host",
- %attribute %string "bind_port",
-
- %attribute %string "compat_log_path",
-}
using namespace icinga;
REGISTER_TYPE(LivestatusListener);
-REGISTER_SCRIPTFUNCTION(ValidateSocketType, &LivestatusListener::ValidateSocketType);
static int l_ClientsConnected = 0;
static int l_Connections = 0;
}
-void LivestatusListener::ValidateSocketType(const String& location, const LivestatusListener::Ptr& object)
+void LivestatusListener::ValidateSocketType(const String& value, const ValidationUtils& utils)
{
- String socket_type = object->GetSocketType();
+ ObjectImpl<LivestatusListener>::ValidateSocketType(value, utils);
- if (socket_type != "unix" && socket_type != "tcp") {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Socket type '" + socket_type + "' is invalid.", object->GetDebugInfo()));
- }
+ if (value != "unix" && value != "tcp")
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("socket_type"), "Socket type '" + value + "' is invalid."));
}
static int GetClientsConnected(void);
static int GetConnections(void);
- static void ValidateSocketType(const String& location, const LivestatusListener::Ptr& object);
+ virtual void ValidateSocketType(const String& value, const ValidationUtils& utils) override;
protected:
virtual void Start(void);
mkclass_target(notificationcomponent.ti notificationcomponent.thpp)
-mkembedconfig_target(notification-type.conf notification-type.cpp)
-
set(notification_SOURCES
- notificationcomponent.cpp notificationcomponent.thpp notification-type.cpp
+ notificationcomponent.cpp notificationcomponent.thpp
)
if(ICINGA2_UNITY_BUILD)
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type NotificationComponent {
- %attribute %number "enable_ha"
-}
mkclass_target(opentsdbwriter.ti opentsdbwriter.thpp)
mkclass_target(perfdatawriter.ti perfdatawriter.thpp)
-mkembedconfig_target(perfdata-type.conf perfdata-type.cpp)
-
set(perfdata_SOURCES
- gelfwriter.cpp gelfwriter.thpp graphitewriter.cpp graphitewriter.thpp opentsdbwriter.cpp opentsdbwriter.thpp perfdatawriter.cpp perfdatawriter.thpp perfdata-type.cpp
+ gelfwriter.cpp gelfwriter.thpp graphitewriter.cpp graphitewriter.thpp opentsdbwriter.cpp opentsdbwriter.thpp perfdatawriter.cpp perfdatawriter.thpp
)
if(ICINGA2_UNITY_BUILD)
using namespace icinga;
REGISTER_TYPE(GraphiteWriter);
-REGISTER_SCRIPTFUNCTION(ValidateNameTemplates, &GraphiteWriter::ValidateNameTemplates);
REGISTER_STATSFUNCTION(GraphiteWriterStats, &GraphiteWriter::StatsFunc);
return EscapeMetric(value);
}
-void GraphiteWriter::ValidateNameTemplates(const String& location, const GraphiteWriter::Ptr& object)
+void GraphiteWriter::ValidateHostNameTemplate(const String& value, const ValidationUtils& utils)
{
- if (!MacroProcessor::ValidateMacroString(object->GetHostNameTemplate())) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + object->GetHostNameTemplate() + "'.", object->GetDebugInfo()));
- }
+ ObjectImpl<GraphiteWriter>::ValidateHostNameTemplate(value, utils);
- if (!MacroProcessor::ValidateMacroString(object->GetServiceNameTemplate())) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + object->GetServiceNameTemplate() + "'.", object->GetDebugInfo()));
- }
+ if (!MacroProcessor::ValidateMacroString(value))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("host_name_template"), "Closing $ not found in macro format string '" + value + "'."));
+}
+
+void GraphiteWriter::ValidateServiceNameTemplate(const String& value, const ValidationUtils& utils)
+{
+ ObjectImpl<GraphiteWriter>::ValidateServiceNameTemplate(value, utils);
+
+ if (!MacroProcessor::ValidateMacroString(value))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("service_name_template"), "Closing $ not found in macro format string '" + value + "'."));
}
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
- static void ValidateNameTemplates(const String& location, const GraphiteWriter::Ptr& object);
+ virtual void ValidateHostNameTemplate(const String& value, const ValidationUtils& utils) override;
+ virtual void ValidateServiceNameTemplate(const String& value, const ValidationUtils& utils) override;
protected:
virtual void Start(void);
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
-%type PerfdataWriter {
- %validator "ValidateFormatTemplates",
-
- %attribute %string "host_perfdata_path",
- %attribute %string "service_perfdata_path",
- %attribute %string "host_temp_path",
- %attribute %string "service_temp_path",
- %attribute %string "host_format_template",
- %attribute %string "service_format_template",
- %attribute %number "rotation_interval"
-}
-
-%type GraphiteWriter {
- %validator "ValidateNameTemplates",
-
- %attribute %string "host",
- %attribute %string "port",
- %attribute %string "host_name_template",
- %attribute %string "service_name_template"
-}
-
-%type GelfWriter {
- %attribute %string "host",
- %attribute %string "port",
- %attribute %string "source"
-}
-
-%type OpenTsdbWriter {
- %attribute %string "host",
- %attribute %string "port",
-}
using namespace icinga;
REGISTER_TYPE(PerfdataWriter);
-REGISTER_SCRIPTFUNCTION(ValidateFormatTemplates, &PerfdataWriter::ValidateFormatTemplates);
REGISTER_STATSFUNCTION(PerfdataWriterStats, &PerfdataWriter::StatsFunc);
RotateFile(m_HostOutputFile, GetHostTempPath(), GetHostPerfdataPath());
}
-void PerfdataWriter::ValidateFormatTemplates(const String& location, const PerfdataWriter::Ptr& object)
+void PerfdataWriter::ValidateHostFormatTemplate(const String& value, const ValidationUtils& utils)
{
- if (!MacroProcessor::ValidateMacroString(object->GetHostFormatTemplate())) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + object->GetHostFormatTemplate() + "'.", object->GetDebugInfo()));
- }
+ ObjectImpl<PerfdataWriter>::ValidateHostFormatTemplate(value, utils);
- if (!MacroProcessor::ValidateMacroString(object->GetServiceFormatTemplate())) {
- BOOST_THROW_EXCEPTION(ScriptError("Validation failed for " +
- location + ": Closing $ not found in macro format string '" + object->GetHostFormatTemplate() + "'.", object->GetDebugInfo()));
- }
+ if (!MacroProcessor::ValidateMacroString(value))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("host_format_template"), "Closing $ not found in macro format string '" + value + "'."));
+}
+
+void PerfdataWriter::ValidateServiceFormatTemplate(const String& value, const ValidationUtils& utils)
+{
+ ObjectImpl<PerfdataWriter>::ValidateServiceFormatTemplate(value, utils);
+
+ if (!MacroProcessor::ValidateMacroString(value))
+ BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of("service_format_template"), "Closing $ not found in macro format string '" + value + "'."));
}
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
- static void ValidateFormatTemplates(const String& location, const PerfdataWriter::Ptr& object);
+ virtual void ValidateHostFormatTemplate(const String& value, const ValidationUtils& utils) override;
+ virtual void ValidateServiceFormatTemplate(const String& value, const ValidationUtils& utils) override;
protected:
virtual void Start(void);
mkclass_target(endpoint.ti endpoint.thpp)
mkclass_target(zone.ti zone.thpp)
-mkembedconfig_target(remote-type.conf remote-type.cpp)
-
set(remote_SOURCES
apiclient.cpp apiclient-heartbeat.cpp apifunction.cpp apilistener.cpp apilistener-sync.cpp
apilistener.thpp authority.cpp endpoint.cpp endpoint.thpp jsonrpc.cpp
- messageorigin.cpp remote-type.cpp zone.cpp zone.thpp
+ messageorigin.cpp zone.cpp zone.thpp
)
if(ICINGA2_UNITY_BUILD)
class ApiListener : DynamicObject
{
- [config] String cert_path;
- [config] String key_path;
- [config] String ca_path;
+ [config, required] String cert_path;
+ [config, required] String key_path;
+ [config, required] String ca_path;
[config] String crl_path;
[config] String bind_host;
+++ /dev/null
-/******************************************************************************
- * 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. *
- ******************************************************************************/
-
- %type ApiListener {
- %require "cert_path",
- %attribute %string "cert_path",
-
- %require "key_path",
- %attribute %string "key_path",
-
- %require "ca_path",
- %attribute %string "ca_path",
-
- %attribute %string "crl_path",
-
- %attribute %string "bind_host",
- %attribute %string "bind_port",
-
- %attribute %number "accept_config",
- %attribute %number "accept_commands",
-
- %attribute %string "ticket_salt"
-}
-
-%type Endpoint {
- %attribute %string "host",
- %attribute %string "port",
-
- %attribute %number "log_duration"
-}
-
-%type Zone {
- %attribute %name(Zone) "parent",
-
- %attribute %array "endpoints" {
- %attribute %name(Endpoint) "*"
- },
-
- %attribute %number "global"
-}
class Zone : DynamicObject
{
- [config] String parent (ParentRaw);
+ [config] name(Zone) parent (ParentRaw);
[config] Array::Ptr endpoints (EndpointsRaw);
[config] bool global;
};
+validator Zone {
+ Array endpoints {
+ name(Endpoint) "*";
+ };
+};
+
}
******************************************************************************/
#include "config/configcompiler.hpp"
+#include "base/exception.hpp"
#include <boost/test/unit_test.hpp>
using namespace icinga;
******************************************************************************/
#include "livestatus/livestatusquery.hpp"
-#include "config/configtype.hpp"
#include "config/configcompiler.hpp"
+#include "config/configitem.hpp"
#include "base/application.hpp"
-#include "base/debug.hpp"
-#include "base/objectlock.hpp"
-#include "base/console.hpp"
-#include "base/serializer.hpp"
#include "base/stdiostream.hpp"
#include "base/json.hpp"
#include "base/loader.hpp"
#include <boost/test/unit_test.hpp>
#include <fstream>
-
using namespace icinga;
struct GlobalConfigFixture {
protected { yylval->num = FAGetProtected | FASetProtected; return T_FIELD_ATTRIBUTE; }
internal { yylval->num = FAInternal; return T_FIELD_ATTRIBUTE; }
no_storage { yylval->num = FANoStorage; return T_FIELD_ATTRIBUTE; }
+validator { return T_VALIDATOR; }
+required { return T_REQUIRED; }
+name { return T_NAME; }
default { yylval->num = FTDefault; return T_FIELD_ACCESSOR_TYPE; }
get { yylval->num = FTGet; return T_FIELD_ACCESSOR_TYPE; }
set { yylval->num = FTSet; return T_FIELD_ACCESSOR_TYPE; }
%union {
char *text;
int num;
+ FieldType *type;
Field *field;
std::vector<Field> *fields;
Klass *klass;
FieldAccessor *fieldaccessor;
std::vector<FieldAccessor> *fieldaccessors;
+ Rule *rule;
+ std::vector<Rule> *rules;
+ Validator *validator;
}
%token T_INCLUDE "include (T_INCLUDE)"
%token T_CODE "code (T_CODE)"
%token T_LOAD_AFTER "load_after (T_LOAD_AFTER)"
%token T_NAMESPACE "namespace (T_NAMESPACE)"
+%token T_VALIDATOR "validator (T_VALIDATOR)"
+%token T_REQUIRED "required (T_REQUIRED)"
+%token T_NAME "name (T_NAME)"
%token T_STRING "string (T_STRING)"
%token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)"
%token T_FIELD_ATTRIBUTE "field_attribute (T_FIELD_ATTRIBUTE)"
%type <text> angle_include
%type <text> code
%type <num> T_FIELD_ATTRIBUTE
+%type <num> field_attribute
%type <num> field_attributes
%type <num> field_attribute_list
%type <num> T_FIELD_ACCESSOR_TYPE
%type <num> T_CLASS_ATTRIBUTE
%type <num> class_attribute_list
+%type <type> field_type
%type <field> class_field
%type <fields> class_fields
%type <klass> class
%type <fieldaccessors> field_accessor_list
%type <fieldaccessors> field_accessors
%type <fieldaccessor> field_accessor
+%type <rule> validator_rule
+%type <rules> validator_rules
+%type <validator> validator
%{
} catch (const std::exception& ex) {
std::cerr << "Exception: " << ex.what();
}
+
+ HandleMissingValidators();
}
#define scanner (context->GetScanner())
context->HandleClass(*$1, yylloc);
delete $1;
}
+ | validator
+ {
+ context->HandleValidator(*$1, yylloc);
+ delete $1;
+ }
| namespace
| code
{
}
;
-class_field: field_attribute_list identifier identifier alternative_name_specifier field_accessor_list ';'
+field_type: identifier
+ {
+ $$ = new FieldType();
+ $$->IsName = false;
+ $$->TypeName = $1;
+ free($1);
+ }
+ | T_NAME '(' identifier ')'
+ {
+ $$ = new FieldType();
+ $$->IsName = true;
+ $$->TypeName = $3;
+ free($3);
+ }
+ ;
+
+class_field: field_attribute_list field_type identifier alternative_name_specifier field_accessor_list ';'
{
Field *field = new Field();
if ((field->Attributes & (FAConfig | FAState)) == 0)
field->Attributes |= FAEphemeral;
- field->Type = $2;
- std::free($2);
+ field->Type = *$2;
+ delete $2;
field->Name = $3;
std::free($3);
}
;
+field_attribute: T_FIELD_ATTRIBUTE
+ {
+ $$ = $1;
+ }
+ | T_REQUIRED
+ {
+ $$ = FARequired;
+ }
+ ;
+
field_attributes: /* empty */
{
$$ = 0;
}
- | field_attributes ',' T_FIELD_ATTRIBUTE
+ | field_attributes ',' field_attribute
{
$$ = $1 | $3;
}
- | T_FIELD_ATTRIBUTE
+ | field_attribute
{
$$ = $1;
}
}
;
+validator_rules: /* empty */
+ {
+ $$ = new std::vector<Rule>();
+ }
+ | validator_rules validator_rule
+ {
+ $$->push_back(*$2);
+ delete $2;
+ }
+ ;
+
+validator_rule: T_NAME '(' T_IDENTIFIER ')' identifier ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = 0;
+ $$->IsName = true;
+ $$->Type = $3;
+ std::free($3);
+ $$->Pattern = $5;
+ std::free($5);
+ }
+ | T_IDENTIFIER identifier ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = 0;
+ $$->IsName = false;
+ $$->Type = $1;
+ std::free($1);
+ $$->Pattern = $2;
+ std::free($2);
+ }
+ | T_NAME '(' T_IDENTIFIER ')' identifier '{' validator_rules '}' ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = 0;
+ $$->IsName = true;
+ $$->Type = $3;
+ std::free($3);
+ $$->Pattern = $5;
+ std::free($5);
+ $$->Rules = *$7;
+ delete $7;
+ }
+ | T_IDENTIFIER identifier '{' validator_rules '}' ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = 0;
+ $$->IsName = false;
+ $$->Type = $1;
+ std::free($1);
+ $$->Pattern = $2;
+ std::free($2);
+ $$->Rules = *$4;
+ delete $4;
+ }
+ | T_REQUIRED identifier ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = RARequired;
+ $$->IsName = false;
+ $$->Type = "";
+ $$->Pattern = $2;
+ std::free($2);
+ }
+ ;
+
+validator: T_VALIDATOR T_IDENTIFIER '{' validator_rules '}' ';'
+ {
+ $$ = new Validator();
+
+ $$->Name = $2;
+ std::free($2);
+
+ $$->Rules = *$4;
+ delete $4;
+ }
+ ;
+
identifier: T_IDENTIFIER
| T_STRING
{
#include "classcompiler.hpp"
#include <iostream>
+#include <sstream>
#include <fstream>
#include <stdexcept>
#include <map>
+#include <set>
#include <vector>
#include <cstring>
#ifndef _WIN32
void ClassCompiler::HandleNamespaceEnd(const ClassDebugInfo&)
{
+ HandleMissingValidators();
+
std::cout << "}" << std::endl;
}
for (it = str.begin(); it != str.end(); it++) {
if (current >= len)
- break;
+ break;
char c = *it;
- hash = c + (hash << 6) + (hash << 16) - hash;
+ hash = c + (hash << 6) + (hash << 16) - hash;
- current++;
- }
+ current++;
+ }
- return hash;
+ return hash;
}
static int TypePreference(const std::string& type)
static bool FieldLayoutCmp(const Field& a, const Field& b)
{
- return TypePreference(a.Type) < TypePreference(b.Type);
+ return TypePreference(a.Type.GetRealType()) < TypePreference(b.Type.GetRealType());
}
static bool FieldTypeCmp(const Field& a, const Field& b)
{
- return a.Type < b.Type;
+ return a.Type.GetRealType() < b.Type.GetRealType();
}
void ClassCompiler::OptimizeStructLayout(std::vector<Field>& fields)
size_t num = 0;
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
- std::string ftype = it->Type;
+ std::string ftype = it->Type.GetRealType();
+
+ if (ftype == "bool" || ftype == "int" || ftype == "double")
+ ftype = "Number";
if (ftype == "int" || ftype == "double")
ftype = "Number";
if (it->Attributes & FAEnum)
ftype = "Number";
+ std::string nameref;
+
+ if (it->Type.IsName)
+ nameref = "\"" + it->Type.TypeName + "\"";
+ else
+ nameref = "NULL";
+
std::cout << "\t\t\t" << "case " << num << ":" << std::endl
- << "\t\t\t\t" << "return Field(" << num << ", \"" << ftype << "\", \"" << it->Name << "\", " << it->Attributes << ");" << std::endl;
+ << "\t\t\t\t" << "return Field(" << num << ", \"" << ftype << "\", \"" << it->Name << "\", " << nameref << ", " << it->Attributes << ");" << std::endl;
num++;
}
std::cout << "};" << std::endl << std::endl;
+ std::cout << std::endl;
+
/* ObjectImpl */
std::cout << "template<>" << std::endl
<< "class ObjectImpl<" << klass.Name << ">"
<< " : public " << (klass.Parent.empty() ? "Object" : klass.Parent) << std::endl
<< "{" << std::endl
<< "public:" << std::endl
- << "\t" << "DECLARE_PTR_TYPEDEFS(ObjectImpl<" << klass.Name << ">);" << std::endl;
+ << "\t" << "DECLARE_PTR_TYPEDEFS(ObjectImpl<" << klass.Name << ">);" << std::endl << std::endl;
+
+ /* Validate */
+ std::cout << "\t" << "virtual void Validate(int types, const ValidationUtils& utils)" << std::endl
+ << "\t" << "{" << std::endl;
+
+ if (!klass.Parent.empty())
+ std::cout << "\t\t" << klass.Parent << "::Validate(types, utils);" << std::endl << std::endl;
+
+ for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
+ std::cout << "\t\t" << "if (" << (it->Attributes & (FAEphemeral|FAConfig|FAState)) << " & types)" << std::endl
+ << "\t\t\t" << "Validate" << it->GetFriendlyName() << "(Get" << it->GetFriendlyName() << "(), utils);" << std::endl;
+ }
+
+ std::cout << "\t" << "}" << std::endl << std::endl;
+
+ for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
+ std::cout << "\t" << "inline void SimpleValidate" << it->GetFriendlyName() << "(" << it->Type.GetArgumentType() << " value, const ValidationUtils& utils)" << std::endl
+ << "\t" << "{" << std::endl;
+
+ const Field& field = *it;
+
+ if ((field.Attributes & (FARequired)) || field.Type.IsName) {
+ if (field.Attributes & FARequired) {
+ if (field.Type.GetRealType().find("::Ptr") != std::string::npos)
+ std::cout << "\t\t" << "if (!value)" << std::endl;
+ else
+ std::cout << "\t\t" << "if (value.IsEmpty())" << std::endl;
+
+ std::cout << "\t\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of(\"" << field.Name << "\"), \"Attribute must not be empty.\"));" << std::endl << std::endl;
+ }
+
+ if (field.Type.IsName) {
+ std::cout << "\t\t" << "String ref = value;" << std::endl
+ << "\t\t" << "if (!ref.IsEmpty() && !utils.ValidateName(\"" << field.Type.TypeName << "\", ref))" << std::endl
+ << "\t\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(this, boost::assign::list_of(\"" << field.Name << "\"), \"Object '\" + ref + \"' of type '" << field.Type.TypeName
+ << "' does not exist.\"));" << std::endl;
+ }
+ }
+
+ std::cout << "\t" << "}" << std::endl << std::endl;
+ }
if (!klass.Fields.empty()) {
/* constructor */
if (!klass.Parent.empty())
std::cout << "\t\t" << "int real_id = id - TypeImpl<" << klass.Parent << ">::StaticGetFieldCount(); " << std::endl
- << "\t\t" << "if (real_id < 0) { " << klass.Parent << "::SetField(id, value); return; }" << std::endl;
+ << "\t\t" << "if (real_id < 0) { " << klass.Parent << "::SetField(id, value); return; }" << std::endl;
std::cout << "\t\t" << "switch (";
<< "\t\t\t\t" << "Set" << it->GetFriendlyName() << "(";
if (it->Attributes & FAEnum)
- std::cout << "static_cast<" << it->Type << ">(static_cast<int>(";
+ std::cout << "static_cast<" << it->Type.GetRealType() << ">(static_cast<int>(";
std::cout << "value";
prot = "public";
std::cout << prot << ":" << std::endl
- << "\t" << "virtual " << it->Type << " Get" << it->GetFriendlyName() << "(void) const";
+ << "\t" << "virtual " << it->Type.GetRealType() << " Get" << it->GetFriendlyName() << "(void) const";
if (it->PureGetAccessor) {
std::cout << " = 0;" << std::endl;
prot = "public";
std::cout << prot << ":" << std::endl
- << "\t" << "virtual void Set" << it->GetFriendlyName() << "(";
-
- if (it->Type == "bool" || it->Type == "double" || it->Type == "int")
- std::cout << it->Type;
- else
- std::cout << "const " << it->Type << "&";
-
- std::cout << " value)" << std::endl;
+ << "\t" << "virtual void Set" << it->GetFriendlyName() << "(" << it->Type.GetArgumentType() << " value)" << std::endl;
if (it->PureSetAccessor) {
std::cout << " = 0;" << std::endl;
/* default */
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
- std::string prot;
+ std::string realType = it->Type.GetRealType();
std::cout << "private:" << std::endl
- << "\t" << it->Type << " GetDefault" << it->GetFriendlyName() << "(void) const" << std::endl
+ << "\t" << realType << " GetDefault" << it->GetFriendlyName() << "(void) const" << std::endl
<< "\t" << "{" << std::endl;
if (it->DefaultAccessor.empty())
- std::cout << "\t\t" << "return " << it->Type << "();" << std::endl;
+ std::cout << "\t\t" << "return " << realType << "();" << std::endl;
else
std::cout << it->DefaultAccessor << std::endl;
std::cout << "\t" << "}" << std::endl;
}
+ /* validators */
+ for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
+ std::cout << "protected:" << std::endl
+ << "\t" << "virtual void Validate" << it->GetFriendlyName() << "(" << it->Type.GetArgumentType() << " value, const ValidationUtils& utils);" << std::endl;
+ }
+
/* instance variables */
std::cout << "private:" << std::endl;
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
if (!(it->Attributes & FANoStorage))
- std::cout << "\t" << it->Type << " m_" << it->GetFriendlyName() << ";" << std::endl;
+ std::cout << "\t" << it->Type.GetRealType() << " m_" << it->GetFriendlyName() << ";" << std::endl;
}
}
std::cout << "\t" << "friend class " << klass.TypeBase << ";" << std::endl;
std::cout << "};" << std::endl << std::endl;
+
+ for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
+ m_MissingValidators[std::make_pair(klass.Name, it->GetFriendlyName())] = *it;
+ }
+}
+
+enum ValidatorType
+{
+ ValidatorField,
+ ValidatorArray,
+ ValidatorDictionary
+};
+
+static void CodeGenValidator(const std::string& name, const std::string& klass, const std::vector<Rule>& rules, const std::string& field, const FieldType& fieldType, ValidatorType validatorType)
+{
+ std::cout << "inline void TIValidate" << name << "(const intrusive_ptr<ObjectImpl<" << klass << "> >& object, ";
+
+ if (validatorType != ValidatorField)
+ std::cout << "const String& key, ";
+
+ bool static_known_attribute = false;
+
+ std::cout << fieldType.GetArgumentType() << " value, std::vector<String>& location, const ValidationUtils& utils)" << std::endl
+ << "{" << std::endl;
+
+ if (validatorType == ValidatorField) {
+ static_known_attribute = true;
+
+ bool required = false;
+
+ for (std::vector<Rule>::size_type i = 0; i < rules.size(); i++) {
+ const Rule& rule = rules[i];
+
+ if ((rule.Attributes & RARequired) && rule.Pattern == field) {
+ required = true;
+ break;
+ }
+ }
+
+ if (fieldType.GetRealType() != "int" && fieldType.GetRealType() != "double") {
+ if (fieldType.GetRealType() == "Value" || fieldType.GetRealType() == "String")
+ std::cout << "\t" << "if (value.IsEmpty())" << std::endl;
+ else
+ std::cout << "\t" << "if (!value)" << std::endl;
+
+ if (required)
+ std::cout << "BOOST_THROW_EXCEPTION(ValidationError(this, location, \"This attribute must not be empty.\"));" << std::endl;
+ else
+ std::cout << "\t\t" << "return;" << std::endl;
+
+ std::cout << std::endl;
+ }
+ }
+
+ if (!static_known_attribute)
+ std::cout << "\t" << "bool known_attribute = false;" << std::endl;
+
+ bool type_check = false;
+
+ for (std::vector<Rule>::size_type i = 0; i < rules.size(); i++) {
+ const Rule& rule = rules[i];
+
+ if (rule.Attributes & RARequired)
+ continue;
+
+ if (validatorType == ValidatorField && rule.Pattern != field)
+ continue;
+
+ std::cout << "\t" << "do {" << std::endl;
+
+ if (validatorType != ValidatorField) {
+ if (rule.Pattern != "*") {
+ if (rule.Pattern.find_first_of("*?") != std::string::npos)
+ std::cout << "\t\t" << "if (!Utility::Match(\"" << rule.Pattern << "\", key))" << std::endl;
+ else
+ std::cout << "\t\t" << "if (key != \"" << rule.Pattern << "\")" << std::endl;
+
+ std::cout << "\t\t\t" << "break;" << std::endl;
+ } else
+ static_known_attribute = true;
+
+ if (!static_known_attribute)
+ std::cout << "\t\t" << "known_attribute = true;" << std::endl;
+ }
+
+ if (rule.IsName) {
+ std::cout << "\t\t" << "if (value.IsScalar()) {" << std::endl
+ << "\t\t\t" << "if (utils.ValidateName(\"" << rule.Type << "\", value))" << std::endl
+ << "\t\t\t\t" << "return;" << std::endl
+ << "\t\t\t" << "else" << std::endl
+ << "\t\t\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(object, location, \"Object '\" + value + \"' of type '" << rule.Type << "' does not exist.\"));" << std::endl
+ << "\t\t" << "}" << std::endl;
+ }
+
+ if (fieldType.GetRealType() == "Value") {
+ if (rule.Type == "String")
+ std::cout << "\t\t" << "if (value.IsScalar())" << std::endl
+ << "\t\t\t" << "return;" << std::endl;
+ else if (rule.Type == "Number") {
+ std::cout << "\t\t" << "try {" << std::endl
+ << "\t\t\t" << "Convert::ToDouble(value);" << std::endl
+ << "\t\t\t" << "return;" << std::endl
+ << "\t\t" << "} catch (...) { }" << std::endl;
+ }
+ }
+
+ if (rule.Type == "Dictionary" || rule.Type == "Array" || rule.Type == "Function") {
+ if (fieldType.GetRealType() == "Value") {
+ std::cout << "\t\t" << "if (value.IsObjectType<" << rule.Type << ">()) {" << std::endl;
+ type_check = true;
+ } else if (fieldType.GetRealType() != rule.Type + "::Ptr") {
+ std::cout << "\t\t" << "if (dynamic_pointer_cast<" << rule.Type << ">(value)) {" << std::endl;
+ type_check = true;
+ }
+
+ if (!rule.Rules.empty()) {
+ bool indent = false;
+
+ if (rule.Type == "Dictionary") {
+ if (type_check)
+ std::cout << "\t\t\t" << "Dictionary::Ptr dict = value;" << std::endl;
+ else
+ std::cout << "\t\t" << "const Dictionary::Ptr& dict = value;" << std::endl;
+
+ std::cout << (type_check ? "\t" : "") << "\t\t" << "ObjectLock olock(dict);" << std::endl
+ << (type_check ? "\t" : "") << "\t\t" << "BOOST_FOREACH(const Dictionary::Pair& kv, dict) {" << std::endl
+ << (type_check ? "\t" : "") << "\t\t\t" << "const String& akey = kv.first;" << std::endl
+ << (type_check ? "\t" : "") << "\t\t\t" << "const Value& avalue = kv.second;" << std::endl;
+ indent = true;
+ } else if (rule.Type == "Array") {
+ if (type_check)
+ std::cout << "\t\t\t" << "Array::Ptr arr = value;" << std::endl;
+ else
+ std::cout << "\t\t" << "const Array::Ptr& arr = value;" << std::endl;
+
+ std::cout << (type_check ? "\t" : "") << "\t\t" << "Array::SizeType anum = 0;" << std::endl
+ << (type_check ? "\t" : "") << "\t\t" << "ObjectLock olock(arr);" << std::endl
+ << (type_check ? "\t" : "") << "\t\t" << "BOOST_FOREACH(const Value& avalue, arr) {" << std::endl
+ << (type_check ? "\t" : "") << "\t\t\t" << "String akey = Convert::ToString(anum);" << std::endl;
+ indent = true;
+ } else {
+ std::cout << (type_check ? "\t" : "") << "\t\t" << "String akey = \"\";" << std::endl
+ << (type_check ? "\t" : "") << "\t\t" << "const Value& avalue = value;" << std::endl;
+ }
+
+ std::string subvalidator_prefix;
+
+ if (validatorType == ValidatorField)
+ subvalidator_prefix = klass;
+ else
+ subvalidator_prefix = name;
+
+ std::cout << (type_check ? "\t" : "") << (indent ? "\t" : "") << "\t\t" << "location.push_back(akey);" << std::endl
+ << (type_check ? "\t" : "") << (indent ? "\t" : "") << "\t\t" << "TIValidate" << subvalidator_prefix << "_" << i << "(object, akey, avalue, location, utils);" << std::endl;
+
+ if (rule.Type == "Array")
+ std::cout << (type_check ? "\t" : "") << "\t\t\t" << "anum++;" << std::endl;
+
+ if (rule.Type == "Dictionary" || rule.Type == "Array")
+ std::cout << (type_check ? "\t" : "") << "\t\t" << "}" << std::endl;
+
+ for (std::vector<Rule>::size_type i = 0; i < rule.Rules.size(); i++) {
+ const Rule& srule = rule.Rules[i];
+
+ if ((srule.Attributes & RARequired) == 0)
+ continue;
+
+ if (rule.Type == "Dictionary") {
+ std::cout << (type_check ? "\t" : "") << "\t\t" << "if (dict.Get(\"" << srule.Pattern << "\").IsEmpty())" << std::endl
+ << (type_check ? "\t" : "") << "\t\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(this, location, \"Required dictionary item '" << srule.Pattern << "' is not set.\"));" << std::endl;
+ } else if (rule.Type == "Array") {
+ int index = -1;
+ std::stringstream idxbuf;
+ idxbuf << srule.Pattern;
+ idxbuf >> index;
+
+ if (index == -1) {
+ std::cerr << "Invalid index for 'required' keyword: " << srule.Pattern;
+ std::exit(1);
+ }
+
+ std::cout << (type_check ? "\t" : "") << "\t\t" << "if (arr.GetLength() < " << (index + 1) << ")" << std::endl
+ << (type_check ? "\t" : "") << "\t\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(this, location, \"Required index '" << index << "' is not set.\"));" << std::endl;
+ }
+ }
+
+ std::cout << (type_check ? "\t" : "") << (indent ? "\t" : "") << "\t\t" << "location.pop_back();" << std::endl;
+ }
+
+ std::cout << (type_check ? "\t" : "") << "\t\t" << "return;" << std::endl;
+
+ if (fieldType.GetRealType() == "Value" || fieldType.GetRealType() != rule.Type + "::Ptr")
+ std::cout << "\t\t" << "}" << std::endl;
+ }
+
+ std::cout << "\t" << "} while (0);" << std::endl << std::endl;
+ }
+
+ if (type_check || validatorType != ValidatorField) {
+ if (!static_known_attribute)
+ std::cout << "\t" << "if (!known_attribute)" << std::endl
+ << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(object, location, \"Invalid attribute: \" + key));" << std::endl
+ << "\t" << "else" << std::endl;
+
+ std::cout << (!static_known_attribute ? "\t" : "") << "\t" << "BOOST_THROW_EXCEPTION(ValidationError(object, boost::assign::list_of(";
+
+ if (validatorType == ValidatorField)
+ std::cout << "\"" << field << "\"";
+ else
+ std::cout << "key";
+
+ std::cout << "), \"Invalid type.\"));" << std::endl;
+ }
+
+ std::cout << "}" << std::endl << std::endl;
+}
+
+static void CodeGenValidatorSubrules(const std::string& name, const std::string& klass, const std::vector<Rule>& rules)
+{
+ for (std::vector<Rule>::size_type i = 0; i < rules.size(); i++) {
+ const Rule& rule = rules[i];
+
+ if (rule.Attributes & RARequired)
+ continue;
+
+ if (!rule.Rules.empty()) {
+ ValidatorType subtype;
+
+ if (rule.Type == "Array")
+ subtype = ValidatorArray;
+ else if (rule.Type == "Dictionary")
+ subtype = ValidatorDictionary;
+ else {
+ std::cerr << "Invalid sub-validator type: " << rule.Type << std::endl;
+ std::exit(EXIT_FAILURE);
+ }
+
+ std::ostringstream namebuf;
+ namebuf << name << "_" << i;
+
+ CodeGenValidatorSubrules(namebuf.str(), klass, rule.Rules);
+
+ FieldType ftype;
+ ftype.IsName = false;
+ ftype.TypeName = "Value";
+ CodeGenValidator(namebuf.str(), klass, rule.Rules, rule.Pattern, ftype, subtype);
+ }
+ }
+}
+
+void ClassCompiler::HandleValidator(const Validator& validator, const ClassDebugInfo&)
+{
+ CodeGenValidatorSubrules(validator.Name, validator.Name, validator.Rules);
+
+ for (std::map<std::pair<std::string, std::string>, Field>::const_iterator it = m_MissingValidators.begin(); it != m_MissingValidators.end(); it++)
+ CodeGenValidator(it->first.first + it->first.second, it->first.first, validator.Rules, it->second.Name, it->second.Type, ValidatorField);
+
+ for (std::map<std::pair<std::string, std::string>, Field>::const_iterator it = m_MissingValidators.begin(); it != m_MissingValidators.end(); it++) {
+ std::cout << "inline void ObjectImpl<" << it->first.first << ">::Validate" << it->first.second << "(" << it->second.Type.GetArgumentType() << " value, const ValidationUtils& utils)" << std::endl
+ << "{" << std::endl
+ << "\t" << "SimpleValidate" << it->first.second << "(value, utils);" << std::endl
+ << "\t" << "std::vector<String> location;" << std::endl
+ << "\t" << "location.push_back(\"" << it->second.Name << "\");" << std::endl
+ << "\t" << "TIValidate" << it->first.first << it->first.second << "(this, value, location, utils);" << std::endl
+ << "}" << std::endl << std::endl;
+ }
+
+ m_MissingValidators.clear();
+}
+
+void ClassCompiler::HandleMissingValidators(void)
+{
+ for (std::map<std::pair<std::string, std::string>, Field>::const_iterator it = m_MissingValidators.begin(); it != m_MissingValidators.end(); it++) {
+ std::cout << "inline void ObjectImpl<" << it->first.first << ">::Validate" << it->first.second << "(" << it->second.Type.GetArgumentType() << " value, const ValidationUtils& utils)" << std::endl
+ << "{" << std::endl
+ << "\t" << "SimpleValidate" << it->first.second << "(value, utils);" << std::endl
+ << "}" << std::endl << std::endl;
+ }
+
+ m_MissingValidators.clear();
}
void ClassCompiler::CompileFile(const std::string& path)
return CompileStream(path, &stream);
}
-std::string ClassCompiler::BaseName(const std::string& path)
+std::string ClassCompiler::BaseName(const std::string& path)
{
char *dir = strdup(path.c_str());
std::string result;
<< "#include \"base/value.hpp\"" << std::endl
<< "#include \"base/array.hpp\"" << std::endl
<< "#include \"base/dictionary.hpp\"" << std::endl
+ << "#include \"base/convert.hpp\"" << std::endl
+ << "#include \"base/exception.hpp\"" << std::endl
+ << "#include \"base/objectlock.hpp\"" << std::endl
<< "#include \"base/utility.hpp\"" << std::endl << std::endl
+ << "#include <boost/foreach.hpp>" << std::endl
+ << "#include <boost/assign/list_of.hpp>" << std::endl
<< "#ifdef _MSC_VER" << std::endl
<< "#pragma warning( push )" << std::endl
<< "#pragma warning( disable : 4244 )" << std::endl
#include <istream>
#include <vector>
#include <algorithm>
+#include <map>
namespace icinga
{
FASetProtected = 32,
FAInternal = 64,
FANoStorage = 128,
- FALoadDependency = 256
+ FALoadDependency = 256,
+ FARequired = 512
+};
+
+struct FieldType
+{
+ bool IsName;
+ std::string TypeName;
+
+ inline std::string GetRealType(void) const
+ {
+ if (IsName)
+ return "String";
+ else
+ return TypeName;
+ }
+
+ inline std::string GetArgumentType(void) const
+ {
+ std::string realType = GetRealType();
+
+ if (realType == "bool" || realType == "double" || realType == "int")
+ return realType;
+ else
+ return "const " + realType + "&";
+ }
};
struct Field
{
int Attributes;
- std::string Type;
+ FieldType Type;
std::string Name;
std::string AlternativeName;
std::string GetAccessor;
: Attributes(0), PureGetAccessor(false), PureSetAccessor(false)
{ }
- std::string GetFriendlyName(void) const
+ inline std::string GetFriendlyName(void) const
{
if (!AlternativeName.empty())
return AlternativeName;
std::vector<std::string> LoadDependencies;
};
+enum RuleAttribute
+{
+ RARequired = 1
+};
+
+struct Rule
+{
+ int Attributes;
+ bool IsName;
+ std::string Type;
+ std::string Pattern;
+
+ std::vector<Rule> Rules;
+};
+
+struct Validator
+{
+ std::string Name;
+ std::vector<Rule> Rules;
+};
+
class ClassCompiler
{
public:
void HandleInclude(const std::string& path, const ClassDebugInfo& locp);
void HandleAngleInclude(const std::string& path, const ClassDebugInfo& locp);
void HandleClass(const Klass& klass, const ClassDebugInfo& locp);
+ void HandleValidator(const Validator& validator, const ClassDebugInfo& locp);
void HandleNamespaceBegin(const std::string& name, const ClassDebugInfo& locp);
void HandleNamespaceEnd(const ClassDebugInfo& locp);
void HandleCode(const std::string& code, const ClassDebugInfo& locp);
+ void HandleMissingValidators(void);
static void CompileFile(const std::string& path);
static void CompileStream(const std::string& path, std::istream *stream);
std::istream *m_Input;
void *m_Scanner;
+ std::map<std::pair<std::string, std::string>, Field> m_MissingValidators;
+
static unsigned long SDBM(const std::string& str, size_t len);
static std::string BaseName(const std::string& path);
static std::string FileNameToGuardName(const std::string& path);