]> granicus.if.org Git - icinga2/commitdiff
Generate C++ code for type validators
authorGunnar Beutner <gunnar@beutner.name>
Sun, 30 Nov 2014 22:32:13 +0000 (23:32 +0100)
committerGunnar Beutner <gunnar@beutner.name>
Fri, 27 Mar 2015 06:59:27 +0000 (07:59 +0100)
fixes #7709
fixes #8867

96 files changed:
lib/base/dynamicobject.cpp
lib/base/dynamicobject.hpp
lib/base/dynamicobject.ti
lib/base/exception.cpp
lib/base/exception.hpp
lib/base/filelogger.ti
lib/base/scriptutils.cpp
lib/base/type.cpp
lib/base/type.hpp
lib/checker/CMakeLists.txt
lib/checker/checker-type.conf [deleted file]
lib/cli/consolecommand.cpp
lib/cli/repositoryutility.cpp
lib/compat/CMakeLists.txt
lib/compat/compat-type.conf [deleted file]
lib/compat/compatlogger.cpp
lib/compat/compatlogger.hpp
lib/config/CMakeLists.txt
lib/config/base-type.conf [deleted file]
lib/config/config_lexer.ll
lib/config/config_parser.yy
lib/config/configcompiler.hpp
lib/config/configitem.cpp
lib/config/configtype.cpp [deleted file]
lib/config/configtype.hpp [deleted file]
lib/config/typerule.cpp [deleted file]
lib/config/typerule.hpp [deleted file]
lib/config/typerulelist.cpp [deleted file]
lib/config/typerulelist.hpp [deleted file]
lib/config/vmops.hpp
lib/db_ido/CMakeLists.txt
lib/db_ido/db_ido-type.conf [deleted file]
lib/db_ido/dbconnection.cpp
lib/db_ido/dbconnection.hpp
lib/db_ido/dbconnection.ti
lib/db_ido_mysql/CMakeLists.txt
lib/db_ido_mysql/db_ido_mysql-type.conf [deleted file]
lib/db_ido_pgsql/CMakeLists.txt
lib/db_ido_pgsql/db_ido_pgsql-type.conf [deleted file]
lib/demo/CMakeLists.txt
lib/demo/demo-type.conf [deleted file]
lib/hello/CMakeLists.txt
lib/hello/hello-type.conf [deleted file]
lib/icinga/CMakeLists.txt
lib/icinga/checkable.cpp
lib/icinga/checkable.hpp
lib/icinga/checkable.ti
lib/icinga/command.cpp
lib/icinga/command.hpp
lib/icinga/command.ti
lib/icinga/customvarobject.cpp
lib/icinga/customvarobject.hpp
lib/icinga/dependency.cpp
lib/icinga/dependency.hpp
lib/icinga/dependency.ti
lib/icinga/host.cpp
lib/icinga/host.ti
lib/icinga/hostgroup.ti
lib/icinga/icinga-type.conf [deleted file]
lib/icinga/notification.cpp
lib/icinga/notification.hpp
lib/icinga/notification.ti
lib/icinga/scheduleddowntime.cpp
lib/icinga/scheduleddowntime.hpp
lib/icinga/scheduleddowntime.ti
lib/icinga/service.ti
lib/icinga/servicegroup.ti
lib/icinga/timeperiod.cpp
lib/icinga/timeperiod.hpp
lib/icinga/timeperiod.ti
lib/icinga/user.cpp
lib/icinga/user.hpp
lib/icinga/user.ti
lib/icinga/usergroup.ti
lib/livestatus/CMakeLists.txt
lib/livestatus/livestatus-type.conf [deleted file]
lib/livestatus/livestatuslistener.cpp
lib/livestatus/livestatuslistener.hpp
lib/notification/CMakeLists.txt
lib/notification/notification-type.conf [deleted file]
lib/perfdata/CMakeLists.txt
lib/perfdata/graphitewriter.cpp
lib/perfdata/graphitewriter.hpp
lib/perfdata/perfdata-type.conf [deleted file]
lib/perfdata/perfdatawriter.cpp
lib/perfdata/perfdatawriter.hpp
lib/remote/CMakeLists.txt
lib/remote/apilistener.ti
lib/remote/remote-type.conf [deleted file]
lib/remote/zone.ti
test/config-ops.cpp
test/livestatus.cpp
tools/mkclass/class_lexer.ll
tools/mkclass/class_parser.yy
tools/mkclass/classcompiler.cpp
tools/mkclass/classcompiler.hpp

index 7176cab980f54c5f3a3df9db1f3815c083c2f5c7..e29e51022e63611a44a359e554c8d3544e66f280 100644 (file)
@@ -56,16 +56,6 @@ DynamicType::Ptr DynamicObject::GetType(void) const
        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();
index c7d3649bf901a9acda4a1f0fcd3af4622a0ff318..7ea7f4fa17fd7bc3e0a359886e4e6e4333b96be7 100644 (file)
@@ -52,9 +52,6 @@ public:
 
        intrusive_ptr<DynamicType> GetType(void) const;
 
-       DebugInfo GetDebugInfo(void) const;
-       void SetDebugInfo(const DebugInfo& di);
-
        bool IsActive(void) const;
        bool IsPaused(void) const;
 
@@ -97,8 +94,6 @@ protected:
 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)                                              \
index b541820ad84fef5aa642c8b02bc842e24a067a57..df8bdb1543105de9d909d01a6011534dbbde27e2 100644 (file)
@@ -33,10 +33,32 @@ public:
 };
 }}}
 
-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();
@@ -45,7 +67,7 @@ abstract class DynamicObject
                }}}
        };
        [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 {
index c34ab587b7648c2c25d798e9cb7a29f3b5da4113..a68e0da59281d0d13ec139058ae92904d82b400a 100644 (file)
@@ -18,6 +18,7 @@
  ******************************************************************************/
 
 #include "base/exception.hpp"
+#include "base/dynamicobject.hpp"
 #include <boost/thread/tss.hpp>
 
 #ifdef HAVE_CXXABI_H
@@ -136,6 +137,8 @@ String icinga::DiagnosticInformation(const std::exception& ex, bool verbose, Sta
 
        String message = ex.what();
 
+       const ValidationError *vex = dynamic_cast<const ValidationError *>(&ex);
+
        if (message.IsEmpty())
                result << boost::diagnostic_information(ex);
        else
@@ -148,6 +151,46 @@ String icinga::DiagnosticInformation(const std::exception& ex, bool verbose, Sta
                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);
 
@@ -270,3 +313,57 @@ const char *posix_error::what(void) const throw()
        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;
+}
+
index 3270a332b2f474ac2039b1e835d443e2482cf908..15f449f123c0574fd266b0e16bed724bfee3b290 100644 (file)
@@ -26,6 +26,7 @@
 #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>
@@ -64,6 +65,35 @@ private:
        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);
 
index d341088a3e6da81c607bf743e1218b7055959686..eb579cf1820b577e3fe4b14905658ba4093cc70c 100644 (file)
@@ -24,7 +24,7 @@ namespace icinga
 
 class FileLogger : StreamLogger
 {
-       [config] String path;
+       [config, required] String path;
 };
 
 }
index cf48089030d4efe1095edf7c5fb5fb40d8c7708d..b6b9df8c6827da9c87aa531d5cbd0f536675154b 100644 (file)
@@ -26,7 +26,6 @@
 #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>
index 95bc97412c75276046bfc4ab4cf7533651d447c1..dd2fcd68e11e003d4836532b453793dd268c474d 100644 (file)
@@ -137,7 +137,7 @@ int TypeType::GetFieldId(const String& name) const
 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.");
 }
index 1c123fb1b313ca75a733a3dd09515b64074a57cc..b636ecc7f9871cf9103485495b82cfb29ee133eb 100644 (file)
@@ -37,6 +37,7 @@ enum FieldAttribute
        FAConfig = 2,
        FAState = 4,
        FAInternal = 64,
+       FARequired = 512
 }; 
 
 class Type;
@@ -46,10 +47,11 @@ struct Field
        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)
        { }
 };
 
@@ -58,6 +60,12 @@ enum TypeAttribute
        TAAbstract = 1
 };
 
+class ValidationUtils
+{
+public:
+       virtual bool ValidateName(const String& type, const String& name) const = 0;
+};
+
 class I2_BASE_API Type : public Object
 {
 public:
index 5463c79128a914ab5e7075711fc541e656cb7bea..d8f422dfb02f3d4ce34ff697beb0432716953f3f 100644 (file)
 
 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)
diff --git a/lib/checker/checker-type.conf b/lib/checker/checker-type.conf
deleted file mode 100644 (file)
index f86a57f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/******************************************************************************
- * 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 {
-}
index 23471c49dbce16939249a02ac5b4d49a280fef0f..b5845b681320903db6e1b3c7de07e0fab1a36088 100644 (file)
@@ -26,6 +26,7 @@
 #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"
index 3cccc73684697b10a5d038ba57bc584f34dc45d0..d7b0e0ecd655842d24f6435bb96af026e453e90e 100644 (file)
@@ -19,8 +19,6 @@
 
 #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"
@@ -189,10 +187,10 @@ void RepositoryUtility::PrintChangeLog(std::ostream& fp)
        }
 }
 
-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;
        }
@@ -228,31 +226,19 @@ bool RepositoryUtility::AddObject(const std::vector<String>& object_paths, const
        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;
                }
        }
 
index 163d777791ddfb7e0d88e508e449daa9f15716eb..60a4d9a1e0cde9a55ab105f7f783c48ffeb59fa7 100644 (file)
@@ -20,12 +20,10 @@ mkclass_target(compatlogger.ti compatlogger.thpp)
 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)
diff --git a/lib/compat/compat-type.conf b/lib/compat/compat-type.conf
deleted file mode 100644 (file)
index 7782ff9..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/******************************************************************************
- * 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"
-}
index 4d88edbaa3128cf2ee1cdf0b490ba7413ba1c1a4..c5cc9b424291c590e01f53e18b426ff445021e3d 100644 (file)
@@ -32,7 +32,6 @@
 #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>
@@ -40,7 +39,6 @@
 using namespace icinga;
 
 REGISTER_TYPE(CompatLogger);
-REGISTER_SCRIPTFUNCTION(ValidateRotationMethod, &CompatLogger::ValidateRotationMethod);
 
 REGISTER_STATSFUNCTION(CompatLoggerStats, &CompatLogger::StatsFunc);
 
@@ -561,14 +559,12 @@ void CompatLogger::RotationTimerHandler(void)
        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."));
        }
 }
-
index 24ae233c287848b5defe86c38572608e3a69aa61..b0fc5dc79423369d9af3531ea2f9b0298bee50d9 100644 (file)
@@ -41,7 +41,7 @@ public:
 
        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);
index 1a54fc9864717d6dbe8da32940f93488c723fd5f..ab9d8092754d1422c986142757b191788ef8cfc3 100644 (file)
@@ -31,15 +31,13 @@ endif()
 
 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)
diff --git a/lib/config/base-type.conf b/lib/config/base-type.conf
deleted file mode 100644 (file)
index 2b38c73..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/******************************************************************************
- * 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 {
-}
index 25310d6505f0e0a1f8116dcdede21dc1ffb5d7cf..dc0a7eed5c688d76e7e5f7e17fd64d93138c6846 100644 (file)
@@ -19,8 +19,8 @@
  ******************************************************************************/
 
 #include "config/configcompiler.hpp"
-#include "config/typerule.hpp"
 #include "config/expression.hpp"
+#include "base/exception.hpp"
 
 using namespace icinga;
 
@@ -167,19 +167,6 @@ do {                                                       \
 [ \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;
index f84d4d5e56d1a8cc4a1f985e0400b4c797dd3399..b262f75943af84c471a2debe69256894bf210aca 100644 (file)
@@ -23,8 +23,6 @@
 #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"
@@ -92,9 +90,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
        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;
@@ -149,18 +145,6 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
 %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)"
@@ -190,9 +174,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
 %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
@@ -352,106 +334,6 @@ identifier: T_IDENTIFIER
        | 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);
@@ -483,7 +365,7 @@ object:
 
                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));
@@ -544,11 +426,7 @@ combined_set_op: T_SET
        | T_SET_BINARY_OR
        ;
 
-lterm: type
-       {
-               $$ = MakeLiteral(); // ASTify this
-       }
-       | library
+lterm: library
        {
                $$ = MakeLiteral(); // ASTify this
        }
index 6f4cdb4fa2ba5b1195daf414145de9a537efd538..981c447440f90fb90772d5b539fc2cdee79f397c 100644 (file)
@@ -22,7 +22,6 @@
 
 #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"
@@ -124,9 +123,6 @@ public:
        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;
index b5ed42731b37b23d387433673ba235f0d469e8d0..373ced031ab0c4a9b43ad1b7470dfd760b6bc94f 100644 (file)
@@ -21,7 +21,6 @@
 #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"
@@ -135,6 +134,15 @@ boost::shared_ptr<Expression> ConfigItem::GetFilter(void) const
        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.
@@ -210,7 +218,9 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
        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);
@@ -223,13 +233,16 @@ DynamicObject::Ptr ConfigItem::Commit(bool discard)
        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;
diff --git a/lib/config/configtype.cpp b/lib/config/configtype.cpp
deleted file mode 100644 (file)
index 03f0c69..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/******************************************************************************
- * 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();
-}
diff --git a/lib/config/configtype.hpp b/lib/config/configtype.hpp
deleted file mode 100644 (file)
index d4a6356..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/******************************************************************************\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
diff --git a/lib/config/typerule.cpp b/lib/config/typerule.cpp
deleted file mode 100644 (file)
index 513d666..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/******************************************************************************
- * 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;
-}
diff --git a/lib/config/typerule.hpp b/lib/config/typerule.hpp
deleted file mode 100644 (file)
index a4fe8fa..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/******************************************************************************
- * 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 */
diff --git a/lib/config/typerulelist.cpp b/lib/config/typerulelist.cpp
deleted file mode 100644 (file)
index eb67bf5..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/******************************************************************************
- * 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;
-}
diff --git a/lib/config/typerulelist.hpp b/lib/config/typerulelist.hpp
deleted file mode 100644 (file)
index c96f11f..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/******************************************************************************
- * 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 */
index 9d7307cddf679e7b71a5173a4e61f8098d3bd979..a0f3845bd75cc75bcb856de554a8760c8657d052 100644 (file)
@@ -317,9 +317,13 @@ public:
                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));
                }
        }
 
index fcc74ea60c9b3a2e8339de295e4c156c0b3773a9..0cec9ea024b927a8e3048a7ae4b63f21bcd9a1c0 100644 (file)
 
 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
diff --git a/lib/db_ido/db_ido-type.conf b/lib/db_ido/db_ido-type.conf
deleted file mode 100644 (file)
index 331b891..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/******************************************************************************
- * 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",
-}
index 2baa0175fbbce78e16e8e6803e3124e3a809c526..fe8e011b184a0e93d305a58fedb178932226749c 100644 (file)
 #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;
@@ -440,12 +438,12 @@ void DbConnection::PrepareDatabase(void)
        }
 }
 
-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)
index 2437442587a679f4adb6a7d5a157907104393334..e31660967e5e7aa3a2a9badeff756773fc0e7b0b 100644 (file)
@@ -74,7 +74,7 @@ public:
        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);
index 498490e03b96bb801dcf39d7bfcb991d40c7876e..51c98456f60882f90f1ae62b990c21998b8a834b 100644 (file)
@@ -56,4 +56,25 @@ abstract class DbConnection : DynamicObject
        };
 };
 
+
+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;
+       };
+};
+
 }
index 9f382fa5eb9d8f3225df5f822451c805b4547f56..61d57232a07bda1e1f2ffb3524304aa8fac76107 100644 (file)
@@ -20,10 +20,8 @@ find_package(MySQL)
 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)
diff --git a/lib/db_ido_mysql/db_ido_mysql-type.conf b/lib/db_ido_mysql/db_ido_mysql-type.conf
deleted file mode 100644 (file)
index 829be8f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/******************************************************************************
- * 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"
-}
index 985532c1edc986ae49955d43dab45c4c38594a50..06da5143dcbb5b0385bbed1c9354d2642bfee5c9 100644 (file)
@@ -20,13 +20,11 @@ find_package(PostgreSQL)
 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)
diff --git a/lib/db_ido_pgsql/db_ido_pgsql-type.conf b/lib/db_ido_pgsql/db_ido_pgsql-type.conf
deleted file mode 100644 (file)
index b0d6abc..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/******************************************************************************
- * 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"
-}
index fb41b88a989bbeaeb092574eac8a30214821aaf4..2484d356acd556b8c93a1048d02f31d86147fc55 100644 (file)
 
 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)
diff --git a/lib/demo/demo-type.conf b/lib/demo/demo-type.conf
deleted file mode 100644 (file)
index 6cec1b8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/******************************************************************************
- * 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 {
-}
index 4e5e4a7797a18b03f90dca5d789a2ded2fe4a18a..d9ff7017ad4d60fe335c2b0ca4370cf804072b48 100644 (file)
 
 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)
diff --git a/lib/hello/hello-type.conf b/lib/hello/hello-type.conf
deleted file mode 100644 (file)
index c17a093..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/******************************************************************************
- * 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 {
-}
index 14cd7095a807d3ec448172bab27ba2ca653b69d0..10648c885730af9337b59c5716c6ef6e80cbb325 100644 (file)
@@ -38,7 +38,6 @@ mkclass_target(timeperiod.ti timeperiod.thpp)
 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
@@ -52,7 +51,7 @@ 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)
index c023ae42f90ac8526dc2c2dd63b35ff05ab55be0..27b5c3628537cac82d9a9233b33060c99b154078 100644 (file)
@@ -20,7 +20,6 @@
 #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>
@@ -28,7 +27,6 @@
 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;
@@ -263,10 +261,10 @@ Endpoint::Ptr Checkable::GetCommandEndpoint(void) const
        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."));
 }
index 96a43830ce2933dcbc3600cec13988079bba02a6..41c9187c4de5a48aa15f6f47c49250cac1051242 100644 (file)
@@ -277,7 +277,7 @@ public:
        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);
index f0e61594e27245f5ca4e830cd7567c348460891d..6c868300e46a0c4e4a04caa14b4149e289b1f3c3 100644 (file)
@@ -43,18 +43,18 @@ abstract class Checkable : CustomVarObject
        [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; }}}
@@ -147,7 +147,7 @@ abstract class Checkable : CustomVarObject
        [state] Value override_max_check_attempts;
        [state] Value override_check_period;
 
-       [config] String command_endpoint (CommandEndpointRaw);
+       [config] name(Endpoint) command_endpoint (CommandEndpointRaw);
 };
 
 }
index 6d6bafcd4cbb7aa9cd60771c5ae27dd93f5789e7..0641e1d57460649cbab3e86a1090785819ead6b6 100644 (file)
@@ -19,7 +19,6 @@
 
 #include "icinga/command.hpp"
 #include "icinga/macroprocessor.hpp"
-#include "base/function.hpp"
 #include "base/exception.hpp"
 #include "base/objectlock.hpp"
 #include <boost/foreach.hpp>
@@ -27,9 +26,6 @@
 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
 {
@@ -49,81 +45,68 @@ void Command::SetModifiedAttributes(int flags, const MessageOrigin& origin)
        }
 }
 
-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 + "'."));
                }
        }
 }
index 4a23c461973ea3d5c75b7f4daa92ddb586735118..4b85452d863de98a416392f8ebbf26fde171dcfb 100644 (file)
@@ -39,9 +39,7 @@ public:
 
        //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());
index 84267ab1e6d1f2f0d5faa706e339609e42395717..3d3c53066aec745153de3cf9e38e8f000162becc 100644 (file)
@@ -27,11 +27,41 @@ abstract class Command : CustomVarObject
 {
        [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 "*";
+       };
 };
 
 }
index 929139897974fe5e9dccee38340f6df312ee8c5d..8388cea293a5119b357257c4ad3d0a3541f9dbb4 100644 (file)
@@ -28,7 +28,6 @@
 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;
 
@@ -68,16 +67,14 @@ bool CustomVarObject::IsVarOverridden(const String& name) const
        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>()) {
@@ -89,10 +86,8 @@ void CustomVarObject::ValidateCustomAttributes(const String& location, const Cus
                                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 */
@@ -104,8 +99,7 @@ void CustomVarObject::ValidateCustomAttributes(const String& location, const Cus
                                        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 {
@@ -114,10 +108,8 @@ void CustomVarObject::ValidateCustomAttributes(const String& location, const Cus
 
                        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 + "'."));
                }
        }
 }
index 36f97dd93079dd1b081d48e0ab348df852307259..b87d637a327f765e9a0751c23781b96c8bc21502 100644 (file)
@@ -61,7 +61,7 @@ public:
 
        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());
index 214b16dfbe627f98069ee2330453ae4cb3d3c670..d935a8f03db1f0008b059389532cbd00da176016 100644 (file)
 #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
 {
@@ -198,17 +196,15 @@ TimePeriod::Ptr Dependency::GetPeriod(void) 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."));
 }
index 6635cb3022a8f96c71daa86004f93e42485a89d3..2b38a32a34d885b6472e489899ac9147e1816040 100644 (file)
@@ -51,7 +51,7 @@ public:
 
        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);
index d89e046f1b8cae9e82fcc519949f1b3e13691f24..7107e065a9339eff2e1304bbc9cc9e7a34efa0f8 100644 (file)
@@ -36,13 +36,13 @@ class Dependency : CustomVarObject < DependencyNameComposer
        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);
@@ -57,4 +57,10 @@ class Dependency : CustomVarObject < DependencyNameComposer
        };
 };
 
+validator Dependency {
+       Array states {
+               Number "*";
+       };
+};
+
 }
index 8f6caec568323a756456fb0ded2cc286c6e77aa0..4e7083a20b638b16902ada114911572a7c293df8 100644 (file)
@@ -22,7 +22,6 @@
 #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"
index bf570f86c2a373c407d8f644ccf221473d5d84bc..670f0b3173b35454174c0642067737195df0982d 100644 (file)
@@ -49,4 +49,10 @@ class Host : Checkable
 
 };
 
+validator Host {
+       Array groups {
+               name(HostGroup) "*";
+       };
+};
+
 }
index a0a8b78395d1aa403ab1f97e5bbae0fba0f7ab86..637f19a14049ac38352a0071990e3c2ac6081869 100644 (file)
@@ -39,4 +39,10 @@ class HostGroup : CustomVarObject
        [config] String action_url;
 };
 
+validator HostGroup {
+       Array groups {
+               name(HostGroup) "*";
+       };
+};
+
 }
diff --git a/lib/icinga/icinga-type.conf b/lib/icinga/icinga-type.conf
deleted file mode 100644 (file)
index 049eadc..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-/******************************************************************************
- * 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"
-}
index afce5c1e886796b5f01958a4dca478b1e82be40b..af2732d000f313f460ff1dd104b898297b97a43d 100644 (file)
 #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;
@@ -256,8 +253,8 @@ void Notification::BeginExecuteNotification(NotificationType type, const CheckRe
                                    << "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);
@@ -628,43 +625,46 @@ String Notification::NotificationHostStateToString(HostState state)
        }
 }
 
-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());
 }
-
index 0a8f41770132a86fbfa81ee4d760606505a1cbbe..62915f1f20115de98274bd36ee3add62cd836375 100644 (file)
@@ -110,8 +110,10 @@ public:
 
        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);
index dbb19a1d0a21133254f3b1ea7e7d0336ab12e679..1f26d1b32f91ccc899dd538a5752be2b154fe8e2 100644 (file)
@@ -35,11 +35,11 @@ class Notification : CustomVarObject < NotificationNameComposer
        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;
@@ -47,7 +47,7 @@ class Notification : CustomVarObject < NotificationNameComposer
        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 {
@@ -59,7 +59,30 @@ class Notification : CustomVarObject < NotificationNameComposer
        [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 "*";
+       };
 };
 
 }
index 446e252812f0eb3e2d7ccb6c83370e6198232721..4deacdd9ad0fb8ddc2dfc4d2a877b4c59d7a050f 100644 (file)
@@ -34,7 +34,6 @@
 using namespace icinga;
 
 REGISTER_TYPE(ScheduledDowntime);
-REGISTER_SCRIPTFUNCTION(ValidateScheduledDowntimeRanges, &ScheduledDowntime::ValidateRanges);
 
 INITIALIZE_ONCE(&ScheduledDowntime::StaticInitialize);
 
@@ -181,11 +180,9 @@ void ScheduledDowntime::CreateNextDowntime(void)
        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 */
@@ -193,22 +190,20 @@ void ScheduledDowntime::ValidateRanges(const String& location, const ScheduledDo
        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));
                }
        }
 }
index a4f5273d34ecf19d3cd851083f11c946dccec586..5eac7c6a8ba42162b6eabbfc2f12d192a2167ac1 100644 (file)
@@ -53,7 +53,7 @@ public:
        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);
index e2a68c57900f60fd450a2374f9a0825d342808e9..06f84ef1b01e23dfb4ed424f27f40f114ca87305 100644 (file)
@@ -35,18 +35,24 @@ class ScheduledDowntime : CustomVarObject < ScheduledDowntimeNameComposer
        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 "*";
+       };
 };
 
 }
index 8f524006d48b749250a01ee96af3182d15bcdefd..a516fac7ea059f62e37766ff25b3d83a91ebdbff 100644 (file)
@@ -45,7 +45,7 @@ class Service : Checkable < ServiceNameComposer
                                return m_DisplayName;
                }}}
        };
-       [config] String host_name;
+       [config, required] name(Host) host_name;
        [enum, no_storage] ServiceState "state" {
                get {{{
                        return GetStateRaw();
@@ -63,4 +63,10 @@ class Service : Checkable < ServiceNameComposer
        };
 };
 
+validator Service {
+       Array groups {
+               name(ServiceGroup) "*";
+       };
+};
+
 }
index 9830c13fcc0c2200bb14bddad4d76eec51c24241..258864ba9fecb29be86345f0abfeed9529ccc8e8 100644 (file)
@@ -39,4 +39,10 @@ class ServiceGroup : CustomVarObject
        [config] String action_url;
 };
 
+validator ServiceGroup {
+       Array groups {
+               name(ServiceGroup) "*";
+       };
+};
+
 }
index 825e52e7cf0be99b44acbe7db87985bbf450b46a..07dcbe39916f3d7afbebcd435343ae1a7afe5f7f 100644 (file)
@@ -30,7 +30,6 @@
 using namespace icinga;
 
 REGISTER_TYPE(TimePeriod);
-REGISTER_SCRIPTFUNCTION(ValidateTimePeriodRanges, &TimePeriod::ValidateRanges);
 
 static Timer::Ptr l_UpdateTimer;
 
@@ -306,11 +305,9 @@ void TimePeriod::Dump(void)
        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 */
@@ -318,22 +315,20 @@ void TimePeriod::ValidateRanges(const String& location, const TimePeriod::Ptr& o
        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));
                }
        }
 }
index e4482f299f6b3ce251fa995a9bceff2649d71296..843808155830a78e709d7fbe2549901c5540768b 100644 (file)
@@ -48,7 +48,7 @@ public:
        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);
index 50a9506323cefd825cad9e86153f6865f175b8e8..c1db4b4d469520a3576f5755ef02661ec91fac78 100644 (file)
@@ -34,7 +34,7 @@ class TimePeriod : CustomVarObject
                }}}
        };
        [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;
@@ -43,4 +43,10 @@ class TimePeriod : CustomVarObject
        };
 };
 
+validator TimePeriod {
+       Dictionary ranges {
+               String "*";
+       };
+};
+
 }
index a7e46163885cf2f68da0355c5bf966629e4cc8f7..cb68b6cf552bc1d7c296e0105a022b95c5212d35 100644 (file)
@@ -21,7 +21,6 @@
 #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>
@@ -29,7 +28,6 @@
 using namespace icinga;
 
 REGISTER_TYPE(User);
-REGISTER_SCRIPTFUNCTION(ValidateUserFilters, &User::ValidateFilters);
 
 boost::signals2::signal<void (const User::Ptr&, bool, const MessageOrigin&)> User::OnEnableNotificationsChanged;
 
@@ -101,22 +99,25 @@ TimePeriod::Ptr User::GetPeriod(void) const
        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."));
        }
 }
 
index 4b42c82dfdcfc7e08d50b3ec024cb0a63df743af..f4e9137c67d635c21550c69932029377d1a72717 100644 (file)
@@ -44,7 +44,8 @@ public:
        /* 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());
index 5685255bb89d3fec5337871567dbd329141260ec..cf00e725a5813b19d4c5533892b86201c565d3f4 100644 (file)
@@ -36,7 +36,7 @@ class User : CustomVarObject
        [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;
@@ -53,4 +53,18 @@ class User : CustomVarObject
        [state] double last_notification;
 };
 
+validator User {
+       Array groups {
+               name(UserGroup) "*";
+       };
+
+       Array types {
+               Number "*";
+       };
+
+       Array states {
+               Number "*";
+       };
+};
+
 }
index bf3f3216c4c1876b8ebd129b357c89afbebeefdf..7e45b9524b126dc67ab13c6425de65a471aec5cf 100644 (file)
@@ -36,4 +36,10 @@ class UserGroup : CustomVarObject
        [config] Array::Ptr groups;
 };
 
+validator UserGroup {
+       Array groups {
+               name(UserGroup) "*";
+       };
+};
+
 }
index 07a4ce8eab95038df72dc6e7cfe989cfe22c461f..fb7033b7287dc14ac54c579f359caa6603b2d5f6 100644 (file)
@@ -17,8 +17,6 @@
 
 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
@@ -30,7 +28,7 @@ set(livestatus_SOURCES
   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)
diff --git a/lib/livestatus/livestatus-type.conf b/lib/livestatus/livestatus-type.conf
deleted file mode 100644 (file)
index 5acab91..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/******************************************************************************
- * 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",
-}
index 83e2948adcdf3bff3f1d460b66792acf18575d5f..800fa271381a45858d1e4ad418ea2bff38430d4f 100644 (file)
@@ -35,7 +35,6 @@
 using namespace icinga;
 
 REGISTER_TYPE(LivestatusListener);
-REGISTER_SCRIPTFUNCTION(ValidateSocketType, &LivestatusListener::ValidateSocketType);
 
 static int l_ClientsConnected = 0;
 static int l_Connections = 0;
@@ -213,12 +212,10 @@ void LivestatusListener::ClientHandler(const Socket::Ptr& client)
 }
 
 
-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."));
 }
index 334e34b58e9ddd4b322fe09a87cc9f00311eb3cc..6886866a3df8c674087e168f33dc95a35602b1ce 100644 (file)
@@ -45,7 +45,7 @@ public:
        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);
index 84276ef126bdce67b097efe36cd21eddc64c7540..dca75ba540be2f40304e4548edd55eaf46e6737e 100644 (file)
 
 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)
diff --git a/lib/notification/notification-type.conf b/lib/notification/notification-type.conf
deleted file mode 100644 (file)
index 6267220..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/******************************************************************************
- * 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"
-}
index 8ea16b4cfa7310ef229d07e967705e676006d7af..b6c2cd9185b4dda615566cc18a3e23ddef476947 100644 (file)
@@ -20,10 +20,8 @@ mkclass_target(graphitewriter.ti graphitewriter.thpp)
 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)
index cf6f42298b6ef20619b040a2e4a3210754ed4258..7304e62259645a639ac9ef0270d8409bbf929f6d 100644 (file)
@@ -43,7 +43,6 @@
 using namespace icinga;
 
 REGISTER_TYPE(GraphiteWriter);
-REGISTER_SCRIPTFUNCTION(ValidateNameTemplates, &GraphiteWriter::ValidateNameTemplates);
 
 REGISTER_STATSFUNCTION(GraphiteWriterStats, &GraphiteWriter::StatsFunc);
 
@@ -232,15 +231,18 @@ Value GraphiteWriter::EscapeMacroMetric(const Value& value)
                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 + "'."));
 }
index dc9392b4d050478c66615ffbb03c20e85e58a19e..e20c88f221ec55345db086d1839d208ed1f6dd49 100644 (file)
@@ -43,7 +43,8 @@ public:
 
        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);
diff --git a/lib/perfdata/perfdata-type.conf b/lib/perfdata/perfdata-type.conf
deleted file mode 100644 (file)
index a07cd29..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/******************************************************************************
- * 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",
-}
index a92b4844631f072034bfbcabd411608634124251..368889fcbb3804a9a307456f446a0830df8f7f50 100644 (file)
@@ -34,7 +34,6 @@
 using namespace icinga;
 
 REGISTER_TYPE(PerfdataWriter);
-REGISTER_SCRIPTFUNCTION(ValidateFormatTemplates, &PerfdataWriter::ValidateFormatTemplates);
 
 REGISTER_STATSFUNCTION(PerfdataWriterStats, &PerfdataWriter::StatsFunc);
 
@@ -140,15 +139,18 @@ void PerfdataWriter::RotationTimerHandler(void)
        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 + "'."));
 }
index 7edd334a94ad31b08820c3bba6b17d445119c173..aa58c7a1bcf3c3dcd34cf18f864d3ad63da27004 100644 (file)
@@ -42,7 +42,8 @@ public:
 
        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);
index 6e8194d6d02c4c2335dc54466c69bcd6af76b784..9965474aaa1883404ebcb5e0fb0283248fcea3c7 100644 (file)
@@ -19,12 +19,10 @@ mkclass_target(apilistener.ti apilistener.thpp)
 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)
index c968eb33eb47abb5e23a7f36f05005222a10f3e1..489511dd59342421d1d3264912d1aa5860ab5db2 100644 (file)
@@ -25,9 +25,9 @@ namespace icinga
 
 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;
diff --git a/lib/remote/remote-type.conf b/lib/remote/remote-type.conf
deleted file mode 100644 (file)
index 371a974..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/******************************************************************************
- * 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"
-}
index e21e21bd27db3e1fe4ad633c284f9cad7fe494f7..37df1c6e7d31f4fcddd404d0aaa8e0ba7e7e0a25 100644 (file)
@@ -24,9 +24,15 @@ namespace icinga
 
 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) "*";
+       };
+};
+
 }
index 6468e31774f8308c8daa11cb381a173a33a5d0cd..227abe4b1ba0d6ae0c129d8becef61c13ebd248e 100644 (file)
@@ -18,6 +18,7 @@
  ******************************************************************************/
 
 #include "config/configcompiler.hpp"
+#include "base/exception.hpp"
 #include <boost/test/unit_test.hpp>
 
 using namespace icinga;
index 9c79dff24599f3f3b5d2753f82ed04b1d0d8619e..f50cfc8ce22ae16847f51f331593f4a5185e46fa 100644 (file)
  ******************************************************************************/
 
 #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"
@@ -32,7 +28,6 @@
 #include <boost/test/unit_test.hpp>
 #include <fstream>
 
-
 using namespace icinga;
 
 struct GlobalConfigFixture {
index 7c59cf62c4ff0f0f7cb650aeb55664f7aeab38bf..c7873c9d7f7cf0c61704a9c96c76a32492782a81 100644 (file)
@@ -143,6 +143,9 @@ set_protected                       { yylval->num = FASetProtected; return T_FIELD_ATTRIBUTE; }
 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; }
index 559a9b2c59dcca261d9e238d445b8564503c9b3a..ab1f07d6c62323ec535243d878db5879b7965124 100644 (file)
@@ -45,11 +45,15 @@ using namespace icinga;
 %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)"
@@ -57,6 +61,9 @@ using namespace icinga;
 %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)"
@@ -77,17 +84,22 @@ using namespace icinga;
 %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
 
 %{
 
@@ -110,6 +122,8 @@ void ClassCompiler::Compile(void)
        } catch (const std::exception& ex) {
                std::cerr << "Exception: " << ex.what();
        }
+
+       HandleMissingValidators();
 }
 
 #define scanner (context->GetScanner())
@@ -137,6 +151,11 @@ statement: include
                context->HandleClass(*$1, yylloc);
                delete $1;
        }
+       | validator
+       {
+               context->HandleValidator(*$1, yylloc);
+               delete $1;
+       }
        | namespace
        | code
        {
@@ -250,7 +269,23 @@ class_fields: /* empty */
        }
        ;
 
-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();
 
@@ -259,8 +294,8 @@ class_field: field_attribute_list identifier identifier alternative_name_specifi
                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);
@@ -321,15 +356,25 @@ field_attribute_list: /* empty */
        }
        ;
 
+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;
        }
@@ -368,6 +413,84 @@ field_accessor: T_FIELD_ACCESSOR_TYPE T_STRING
        }
        ;
 
+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
        {
index fa0c8d395496a681899ab86bdaec1c855a604bf0..d700cfd523c88e00de84f592c17b73708ff94a0b 100644 (file)
 
 #include "classcompiler.hpp"
 #include <iostream>
+#include <sstream>
 #include <fstream>
 #include <stdexcept>
 #include <map>
+#include <set>
 #include <vector>
 #include <cstring>
 #ifndef _WIN32
@@ -77,6 +79,8 @@ void ClassCompiler::HandleNamespaceBegin(const std::string& name, const ClassDeb
 
 void ClassCompiler::HandleNamespaceEnd(const ClassDebugInfo&)
 {
+       HandleMissingValidators();
+
        std::cout << "}" << std::endl;
 }
 
@@ -94,16 +98,16 @@ unsigned long ClassCompiler::SDBM(const std::string& str, size_t len = std::stri
 
        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)
@@ -124,12 +128,12 @@ 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)
@@ -297,7 +301,10 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
 
                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";
@@ -310,8 +317,15 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
                        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++;
                }
 
@@ -362,13 +376,56 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
 
        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 */
@@ -389,7 +446,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
 
                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 (";
 
@@ -406,7 +463,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
                                          << "\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";
                        
@@ -465,7 +522,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
                                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;
@@ -494,14 +551,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
                                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;
@@ -519,26 +569,32 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
 
                /* 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;
                }
        }
 
@@ -549,6 +605,286 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
                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)
@@ -562,7 +898,7 @@ 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;
@@ -610,7 +946,12 @@ void ClassCompiler::CompileStream(const std::string& path, std::istream *stream)
                          << "#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
index bb53c745a8bd7775bc5e69bb2fae475115c23b2c..697f32f490287d2f5a80e7e1493b588eec9a1095 100644 (file)
@@ -24,6 +24,7 @@
 #include <istream>
 #include <vector>
 #include <algorithm>
+#include <map>
 
 namespace icinga
 {
@@ -66,13 +67,38 @@ enum FieldAttribute
        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;
@@ -85,7 +111,7 @@ struct Field
                : Attributes(0), PureGetAccessor(false), PureSetAccessor(false)
        { }
 
-       std::string GetFriendlyName(void) const
+       inline std::string GetFriendlyName(void) const
        {
                if (!AlternativeName.empty())
                        return AlternativeName;
@@ -130,6 +156,27 @@ struct Klass
        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:
@@ -150,9 +197,11 @@ 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);
@@ -164,6 +213,8 @@ private:
        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);