]> granicus.if.org Git - icinga2/commitdiff
Validate config objects before trying to activate them.
authorGunnar Beutner <gunnar.beutner@netways.de>
Tue, 5 Feb 2013 12:06:42 +0000 (13:06 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 5 Feb 2013 12:06:42 +0000 (13:06 +0100)
Fixes #3619

19 files changed:
icinga-app/icinga.cpp
lib/base/value.cpp
lib/config/Makefile.am
lib/config/config.vcxproj
lib/config/config_parser.cc
lib/config/config_parser.yy
lib/config/configcompiler.cpp
lib/config/configcompiler.h
lib/config/configcompilercontext.cpp [new file with mode: 0644]
lib/config/configcompilercontext.h [new file with mode: 0644]
lib/config/configitem.cpp
lib/config/configitem.h
lib/config/configtype.cpp
lib/config/configtype.h
lib/config/i2-config.h
lib/config/typerule.cpp
lib/config/typerule.h
lib/config/typerulelist.cpp
lib/config/typerulelist.h

index e7f3104cd987fed29fafbf8c1c6d2fd1883bc633..3547b54ee7a79366ed0b064324976f3aef0857e2 100644 (file)
@@ -38,28 +38,35 @@ static bool g_ReloadConfig = false;
 static Timer::Ptr g_ReloadConfigTimer;
 #endif /* _WIN32 */
 
-static bool LoadConfigFiles(void)
+static bool LoadConfigFiles(bool validateOnly)
 {
-       set<ConfigItem::Ptr> allItems;
+       ConfigCompilerContext context;
 
-       try {
-               BOOST_FOREACH(const String& configPath, g_AppParams["config"].as<vector<String> >()) {
-                       vector<ConfigItem::Ptr> items;
-                       vector<ConfigType::Ptr> types;
+       ConfigCompilerContext::SetContext(&context);
+
+       BOOST_FOREACH(const String& configPath, g_AppParams["config"].as<vector<String> >()) {
+               ConfigCompiler::CompileFile(configPath);
+       }
 
-                       ConfigCompiler::CompileFile(configPath, &items, &types);
+       ConfigCompilerContext::SetContext(NULL);
 
-                       Logger::Write(LogInformation, "icinga-app", "Registering config types...");
-                       BOOST_FOREACH(const ConfigType::Ptr& type, types) {
-                               type->Commit();
-                       }
+       context.Validate();
+
+       bool hasError = false;
+
+       BOOST_FOREACH(const ConfigCompilerError& error, context.GetErrors()) {
+               if (error.Warning) {
+                       Logger::Write(LogWarning, "icinga-app", "Config warning: " + error.Message);
+               } else {
+                       hasError = true;
+                       Logger::Write(LogCritical, "icinga-app", "Config error: " + error.Message);
+               }
+       }
 
-                       Logger::Write(LogInformation, "icinga-app", "Executing config items...");
-                       BOOST_FOREACH(const ConfigItem::Ptr& item, items) {
-                               item->Commit();
-                       }
+       if (hasError)
+               return false;
 
-                       Logger::Write(LogInformation, "icinga-app", "Validating config items...");
+/*                     Logger::Write(LogInformation, "icinga-app", "Validating config items...");
                        DynamicType::Ptr type;
                        BOOST_FOREACH(tie(tuples::ignore, type), DynamicType::GetTypes()) {
                                ConfigType::Ptr ctype = ConfigType::GetByName(type->GetName());
@@ -74,32 +81,26 @@ static bool LoadConfigFiles(void)
                                BOOST_FOREACH(tie(tuples::ignore, object), type->GetObjects()) {
                                        ctype->ValidateObject(object);
                                }
-                       }
+                       }*/
 
-                       std::copy(items.begin(), items.end(), std::inserter(allItems, allItems.begin()));
-               }
+       context.ActivateItems();
 
-               BOOST_FOREACH(const ConfigItem::WeakPtr& witem, g_ConfigItems) {
-                       ConfigItem::Ptr item = witem.lock();
+       BOOST_FOREACH(const ConfigItem::WeakPtr& witem, g_ConfigItems) {
+               ConfigItem::Ptr item = witem.lock();
 
-                       /* Ignore this item if it's not active anymore */
-                       if (!item || ConfigItem::GetObject(item->GetType(), item->GetName()) != item)
-                               continue;
+               /* Ignore this item if it's not active anymore */
+               if (!item || ConfigItem::GetObject(item->GetType(), item->GetName()) != item)
+                       continue;
 
-                       /* Remove the object if it's not in the list of current items */
-                       if (allItems.find(item) == allItems.end())
-                               item->Unregister();
-               }
+               item->Unregister();
+       }
 
-               g_ConfigItems.clear();
-               std::copy(allItems.begin(), allItems.end(), std::back_inserter(g_ConfigItems));
+       g_ConfigItems.clear();
 
-               return true;
-       } catch (const exception& ex) {
-               Logger::Write(LogCritical, "icinga-app", "Configuration error: " + String(ex.what()));
-               return false;
-       }
+       vector<ConfigItem::Ptr> items = context.GetItems();
+       std::copy(items.begin(), items.end(), std::back_inserter(g_ConfigItems));
 
+       return true;
 }
 
 #ifndef _WIN32
@@ -107,7 +108,7 @@ static void ReloadConfigTimerHandler(void)
 {
        if (g_ReloadConfig) {
                Logger::Write(LogInformation, "icinga-app", "Received SIGHUP. Reloading config files.");
-               LoadConfigFiles();
+               LoadConfigFiles(false);
                g_ReloadConfig = false;
        }
 }
@@ -241,21 +242,23 @@ int main(int argc, char **argv)
 
        DynamicObject::BeginTx();
 
-       if (!LoadConfigFiles())
+       bool validateOnly = g_AppParams.count("validate");
+
+       if (!LoadConfigFiles(validateOnly))
                return EXIT_FAILURE;
 
        DynamicObject::FinishTx();
 
+       if (validateOnly) {
+               Logger::Write(LogInformation, "icinga-app", "Terminating as requested by --validate.");
+               return EXIT_SUCCESS;
+       }
+
        Application::Ptr app = Application::GetInstance();
 
        if (!app)
                throw_exception(runtime_error("Configuration must create an Application object."));
 
-       if (g_AppParams.count("validate")) {
-               Logger::Write(LogInformation, "icinga-app", "Terminating as requested by --validate.");
-               return EXIT_SUCCESS;
-       }
-
        if (g_AppParams.count("daemonize")) {
                Logger::Write(LogInformation, "icinga", "Daemonizing.");
                Utility::Daemonize();
index f74bb7f3a6e31bd222b2e3843e2e9a15d5ea8cae..a83a757396ccfc6f29a872f0b4ccddf2038094c8 100644 (file)
@@ -88,7 +88,7 @@ String Value::Serialize(void) const
 
        char *jsonString;
 
-       if (Application::GetInstance()->IsDebugging())
+       if (Application::IsDebugging())
                jsonString = cJSON_Print(json);
        else
                jsonString = cJSON_PrintUnformatted(json);
index 5a1ce8cd60a070b2baef392e97f570bb3ff2a50f..8737d31bd036ff63d8b6ec02cfb731384b11669b 100644 (file)
@@ -11,6 +11,8 @@ AM_YFLAGS = -d
 libconfig_la_SOURCES = \
        configcompiler.cpp \
        configcompiler.h \
+       configcompilercontext.cpp \
+       configcompilercontext.h \
        config_lexer.ll \
        config_parser.yy \
        i2-config.h \
index ded9a97b56f1f494b17c1e3fcc0f4dce79d68572..b111cf53dc8311add3301e5c03a93c6c836bbc3d 100644 (file)
@@ -20,6 +20,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="configcompiler.h" />
+    <ClInclude Include="configcompilercontext.h" />
     <ClInclude Include="configitem.h" />
     <ClInclude Include="configitembuilder.h" />
     <ClInclude Include="configtype.h" />
@@ -33,6 +34,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="configcompiler.cpp" />
+    <ClCompile Include="configcompilercontext.cpp" />
     <ClCompile Include="configitem.cpp" />
     <ClCompile Include="configitembuilder.cpp" />
     <ClCompile Include="configtype.cpp" />
index 8dbf738bf58de9cc7a1b019eda9510dc10f1c5b3..461744fdd891261164cf4d214951516096259a53 100644 (file)
@@ -246,7 +246,13 @@ static ConfigType::Ptr m_Type;
 
 void ConfigCompiler::Compile(void)
 {
-       yyparse(this);
+       assert(ConfigCompilerContext::GetContext() != NULL);
+
+       try {
+               yyparse(this);
+       } catch (const exception& ex) {
+               ConfigCompilerContext::GetContext()->AddError(false, ex.what());
+       }
 }
 
 #define scanner (context->GetScanner())
@@ -254,7 +260,7 @@ void ConfigCompiler::Compile(void)
 
 
 /* Line 343 of yacc.c  */
-#line 258 "config_parser.cc"
+#line 264 "config_parser.cc"
 
 #ifdef short
 # undef short
@@ -565,13 +571,13 @@ static const yytype_int8 yyrhs[] =
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   110,   110,   111,   114,   114,   114,   114,   117,   121,
-     126,   131,   132,   139,   138,   160,   163,   170,   169,   181,
-     182,   184,   185,   186,   189,   194,   202,   203,   209,   210,
-     211,   212,   213,   220,   225,   220,   244,   245,   248,   252,
-     258,   259,   262,   269,   270,   274,   273,   285,   286,   288,
-     289,   290,   293,   301,   315,   324,   325,   326,   327,   328,
-     334,   339,   343,   349,   350
+       0,   116,   116,   117,   120,   120,   120,   120,   123,   127,
+     132,   137,   138,   145,   144,   166,   169,   176,   175,   187,
+     188,   190,   191,   192,   195,   200,   208,   209,   215,   216,
+     217,   218,   219,   226,   231,   226,   250,   251,   254,   258,
+     264,   265,   268,   275,   276,   280,   279,   291,   292,   294,
+     295,   296,   299,   307,   321,   330,   331,   332,   333,   334,
+     340,   345,   349,   355,   356
 };
 #endif
 
@@ -1616,7 +1622,7 @@ yyreduce:
         case 8:
 
 /* Line 1806 of yacc.c  */
-#line 118 "config_parser.yy"
+#line 124 "config_parser.yy"
     {
                context->HandleInclude((yyvsp[(2) - (2)].text), false, yylloc);
        }
@@ -1625,7 +1631,7 @@ yyreduce:
   case 9:
 
 /* Line 1806 of yacc.c  */
-#line 122 "config_parser.yy"
+#line 128 "config_parser.yy"
     {
                context->HandleInclude((yyvsp[(2) - (2)].text), true, yylloc);
        }
@@ -1634,7 +1640,7 @@ yyreduce:
   case 10:
 
 /* Line 1806 of yacc.c  */
-#line 127 "config_parser.yy"
+#line 133 "config_parser.yy"
     {
                context->HandleLibrary((yyvsp[(2) - (2)].text));
        }
@@ -1643,7 +1649,7 @@ yyreduce:
   case 12:
 
 /* Line 1806 of yacc.c  */
-#line 133 "config_parser.yy"
+#line 139 "config_parser.yy"
     {
                (yyval.text) = (yyvsp[(1) - (1)].text);
        }
@@ -1652,17 +1658,17 @@ yyreduce:
   case 13:
 
 /* Line 1806 of yacc.c  */
-#line 139 "config_parser.yy"
+#line 145 "config_parser.yy"
     {
                String name = String((yyvsp[(3) - (3)].text));
-               m_Type = context->GetTypeByName(name);
+               m_Type = ConfigCompilerContext::GetContext()->GetType(name);
                
                if (!m_Type) {
                        if ((yyvsp[(1) - (3)].num))
                                throw_exception(invalid_argument("partial type definition for unknown type '" + name + "'"));
 
                        m_Type = boost::make_shared<ConfigType>(name, yylloc);
-                       context->AddType(m_Type);
+                       ConfigCompilerContext::GetContext()->AddType(m_Type);
                }
        }
     break;
@@ -1670,7 +1676,7 @@ yyreduce:
   case 14:
 
 /* Line 1806 of yacc.c  */
-#line 152 "config_parser.yy"
+#line 158 "config_parser.yy"
     {
                TypeRuleList::Ptr ruleList = *(yyvsp[(6) - (6)].variant);
                m_Type->GetRuleList()->AddRules(ruleList);
@@ -1681,7 +1687,7 @@ yyreduce:
   case 15:
 
 /* Line 1806 of yacc.c  */
-#line 160 "config_parser.yy"
+#line 166 "config_parser.yy"
     {
                (yyval.num) = 0;
        }
@@ -1690,7 +1696,7 @@ yyreduce:
   case 16:
 
 /* Line 1806 of yacc.c  */
-#line 164 "config_parser.yy"
+#line 170 "config_parser.yy"
     {
                (yyval.num) = 1;
        }
@@ -1699,7 +1705,7 @@ yyreduce:
   case 17:
 
 /* Line 1806 of yacc.c  */
-#line 170 "config_parser.yy"
+#line 176 "config_parser.yy"
     {
                m_RuleLists.push(boost::make_shared<TypeRuleList>());
        }
@@ -1708,7 +1714,7 @@ yyreduce:
   case 18:
 
 /* Line 1806 of yacc.c  */
-#line 175 "config_parser.yy"
+#line 181 "config_parser.yy"
     {
                (yyval.variant) = new Value(m_RuleLists.top());
                m_RuleLists.pop();
@@ -1718,7 +1724,7 @@ yyreduce:
   case 24:
 
 /* Line 1806 of yacc.c  */
-#line 190 "config_parser.yy"
+#line 196 "config_parser.yy"
     {
                TypeRule rule((yyvsp[(1) - (2)].type), (yyvsp[(2) - (2)].text), TypeRuleList::Ptr(), yylloc);
                m_RuleLists.top()->AddRule(rule);
@@ -1728,7 +1734,7 @@ yyreduce:
   case 25:
 
 /* Line 1806 of yacc.c  */
-#line 195 "config_parser.yy"
+#line 201 "config_parser.yy"
     {
                TypeRule rule((yyvsp[(1) - (3)].type), (yyvsp[(2) - (3)].text), *(yyvsp[(3) - (3)].variant), yylloc);
                delete (yyvsp[(3) - (3)].variant);
@@ -1739,7 +1745,7 @@ yyreduce:
   case 27:
 
 /* Line 1806 of yacc.c  */
-#line 204 "config_parser.yy"
+#line 210 "config_parser.yy"
     {
                m_Type->SetParent((yyvsp[(2) - (2)].text));
        }
@@ -1748,7 +1754,7 @@ yyreduce:
   case 32:
 
 /* Line 1806 of yacc.c  */
-#line 214 "config_parser.yy"
+#line 220 "config_parser.yy"
     {
                (yyval.type) = (yyvsp[(1) - (1)].type);
        }
@@ -1757,7 +1763,7 @@ yyreduce:
   case 33:
 
 /* Line 1806 of yacc.c  */
-#line 220 "config_parser.yy"
+#line 226 "config_parser.yy"
     {
                m_Abstract = false;
                m_Local = false;
@@ -1767,7 +1773,7 @@ yyreduce:
   case 34:
 
 /* Line 1806 of yacc.c  */
-#line 225 "config_parser.yy"
+#line 231 "config_parser.yy"
     {
                m_Item = boost::make_shared<ConfigItemBuilder>(yylloc);
                m_Item->SetType((yyvsp[(4) - (5)].text));
@@ -1778,7 +1784,7 @@ yyreduce:
   case 35:
 
 /* Line 1806 of yacc.c  */
-#line 231 "config_parser.yy"
+#line 237 "config_parser.yy"
     {
                ExpressionList::Ptr exprl = *(yyvsp[(8) - (8)].variant);
                delete (yyvsp[(8) - (8)].variant);
@@ -1787,7 +1793,7 @@ yyreduce:
                m_Item->SetLocal(m_Local);
                m_Item->SetAbstract(m_Abstract);
 
-               context->AddObject(m_Item->Compile());
+               ConfigCompilerContext::GetContext()->AddItem(m_Item->Compile());
                m_Item.reset();
        }
     break;
@@ -1795,7 +1801,7 @@ yyreduce:
   case 38:
 
 /* Line 1806 of yacc.c  */
-#line 249 "config_parser.yy"
+#line 255 "config_parser.yy"
     {
                m_Abstract = true;
        }
@@ -1804,7 +1810,7 @@ yyreduce:
   case 39:
 
 /* Line 1806 of yacc.c  */
-#line 253 "config_parser.yy"
+#line 259 "config_parser.yy"
     {
                m_Local = true;
        }
@@ -1813,7 +1819,7 @@ yyreduce:
   case 42:
 
 /* Line 1806 of yacc.c  */
-#line 263 "config_parser.yy"
+#line 269 "config_parser.yy"
     {
                m_Item->AddParent((yyvsp[(1) - (1)].text));
                free((yyvsp[(1) - (1)].text));
@@ -1823,7 +1829,7 @@ yyreduce:
   case 45:
 
 /* Line 1806 of yacc.c  */
-#line 274 "config_parser.yy"
+#line 280 "config_parser.yy"
     {
                m_ExpressionLists.push(boost::make_shared<ExpressionList>());
        }
@@ -1832,7 +1838,7 @@ yyreduce:
   case 46:
 
 /* Line 1806 of yacc.c  */
-#line 279 "config_parser.yy"
+#line 285 "config_parser.yy"
     {
                (yyval.variant) = new Value(m_ExpressionLists.top());
                m_ExpressionLists.pop();
@@ -1842,7 +1848,7 @@ yyreduce:
   case 52:
 
 /* Line 1806 of yacc.c  */
-#line 294 "config_parser.yy"
+#line 300 "config_parser.yy"
     {
                Expression expr((yyvsp[(1) - (3)].text), (yyvsp[(2) - (3)].op), *(yyvsp[(3) - (3)].variant), yylloc);
                free((yyvsp[(1) - (3)].text));
@@ -1855,7 +1861,7 @@ yyreduce:
   case 53:
 
 /* Line 1806 of yacc.c  */
-#line 302 "config_parser.yy"
+#line 308 "config_parser.yy"
     {
                Expression subexpr((yyvsp[(3) - (6)].text), (yyvsp[(5) - (6)].op), *(yyvsp[(6) - (6)].variant), yylloc);
                free((yyvsp[(3) - (6)].text));
@@ -1874,7 +1880,7 @@ yyreduce:
   case 54:
 
 /* Line 1806 of yacc.c  */
-#line 316 "config_parser.yy"
+#line 322 "config_parser.yy"
     {
                Expression expr((yyvsp[(1) - (1)].text), OperatorSet, (yyvsp[(1) - (1)].text), yylloc);
                free((yyvsp[(1) - (1)].text));
@@ -1886,7 +1892,7 @@ yyreduce:
   case 59:
 
 /* Line 1806 of yacc.c  */
-#line 329 "config_parser.yy"
+#line 335 "config_parser.yy"
     {
                (yyval.op) = (yyvsp[(1) - (1)].op);
        }
@@ -1895,7 +1901,7 @@ yyreduce:
   case 60:
 
 /* Line 1806 of yacc.c  */
-#line 335 "config_parser.yy"
+#line 341 "config_parser.yy"
     {
                (yyval.variant) = new Value((yyvsp[(1) - (1)].text));
                free((yyvsp[(1) - (1)].text));
@@ -1905,7 +1911,7 @@ yyreduce:
   case 61:
 
 /* Line 1806 of yacc.c  */
-#line 340 "config_parser.yy"
+#line 346 "config_parser.yy"
     {
                (yyval.variant) = new Value((yyvsp[(1) - (1)].num));
        }
@@ -1914,7 +1920,7 @@ yyreduce:
   case 62:
 
 /* Line 1806 of yacc.c  */
-#line 344 "config_parser.yy"
+#line 350 "config_parser.yy"
     {
                (yyval.variant) = new Value();
        }
@@ -1923,7 +1929,7 @@ yyreduce:
   case 64:
 
 /* Line 1806 of yacc.c  */
-#line 351 "config_parser.yy"
+#line 357 "config_parser.yy"
     {
                (yyval.variant) = (yyvsp[(1) - (1)].variant);
        }
@@ -1932,7 +1938,7 @@ yyreduce:
 
 
 /* Line 1806 of yacc.c  */
-#line 1936 "config_parser.cc"
+#line 1942 "config_parser.cc"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -2170,6 +2176,6 @@ yyreturn:
 
 
 /* Line 2067 of yacc.c  */
-#line 355 "config_parser.yy"
+#line 361 "config_parser.yy"
 
 
index 5c9a3a7f3530496b3b20183cf71dc2314d8b2a9e..b19d99a28e8350f5be0da4057a6cb6494cc9da41 100644 (file)
@@ -99,7 +99,13 @@ static ConfigType::Ptr m_Type;
 
 void ConfigCompiler::Compile(void)
 {
-       yyparse(this);
+       assert(ConfigCompilerContext::GetContext() != NULL);
+
+       try {
+               yyparse(this);
+       } catch (const exception& ex) {
+               ConfigCompilerContext::GetContext()->AddError(false, ex.what());
+       }
 }
 
 #define scanner (context->GetScanner())
@@ -138,14 +144,14 @@ identifier: T_IDENTIFIER
 type: partial_specifier T_TYPE identifier
        {
                String name = String($3);
-               m_Type = context->GetTypeByName(name);
+               m_Type = ConfigCompilerContext::GetContext()->GetType(name);
                
                if (!m_Type) {
                        if ($1)
                                throw_exception(invalid_argument("partial type definition for unknown type '" + name + "'"));
 
                        m_Type = boost::make_shared<ConfigType>(name, yylloc);
-                       context->AddType(m_Type);
+                       ConfigCompilerContext::GetContext()->AddType(m_Type);
                }
        }
        type_inherits_specifier typerulelist
@@ -236,7 +242,7 @@ object_inherits_specifier expressionlist
                m_Item->SetLocal(m_Local);
                m_Item->SetAbstract(m_Abstract);
 
-               context->AddObject(m_Item->Compile());
+               ConfigCompilerContext::GetContext()->AddItem(m_Item->Compile());
                m_Item.reset();
        }
        ;
index adb0ef08fcde02b59b654d0e0599fc74bf17b660..a7f178c56309c3d0f233530e2468a337f288cc09 100644 (file)
@@ -71,33 +71,6 @@ void *ConfigCompiler::GetScanner(void) const
        return m_Scanner;
 }
 
-/**
- * Retrieves the result from the compiler.
- *
- * @returns A list of configuration items.
- */
-vector<ConfigItem::Ptr> ConfigCompiler::GetResultObjects(void) const
-{
-       return m_ResultObjects;
-}
-
-/**
- * Retrieves the resulting type objects from the compiler.
- *
- * @returns A list of type objects.
- */
-vector<ConfigType::Ptr> ConfigCompiler::GetResultTypes(void) const
-{
-       vector<ConfigType::Ptr> types;
-       
-       ConfigType::Ptr type;
-       BOOST_FOREACH(tie(tuples::ignore, type), m_ResultTypes) {
-               types.push_back(type);
-       }
-       
-       return types;
-}
-
 /**
  * Retrieves the path for the input file.
  *
@@ -125,12 +98,7 @@ void ConfigCompiler::HandleInclude(const String& include, bool search, const Deb
        else
                path = Utility::DirName(GetPath()) + "/" + include;
 
-       vector<ConfigType::Ptr> types;
-       m_HandleInclude(path, search, &m_ResultObjects, &types, debuginfo);
-
-       BOOST_FOREACH(const ConfigType::Ptr& type, types) {
-               AddType(type);
-       }
+       m_HandleInclude(path, search, debuginfo);
 }
 
 /**
@@ -150,23 +118,12 @@ void ConfigCompiler::HandleLibrary(const String& library)
  * @param stream The input stream.
  * @returns Configuration items.
  */
-void ConfigCompiler::CompileStream(const String& path,
-    istream *stream, vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes)
+void ConfigCompiler::CompileStream(const String& path, istream *stream)
 {
        stream->exceptions(istream::badbit);
 
        ConfigCompiler ctx(path, stream);
        ctx.Compile();
-       
-       if (resultItems) {
-               vector<ConfigItem::Ptr> items = ctx.GetResultObjects();
-               std::copy(items.begin(), items.end(), std::back_inserter(*resultItems));
-       }
-
-       if (resultTypes) {      
-               vector<ConfigType::Ptr> types = ctx.GetResultTypes();
-               std::copy(types.begin(), types.end(), std::back_inserter(*resultTypes));
-       }
 }
 
 /**
@@ -175,8 +132,7 @@ void ConfigCompiler::CompileStream(const String& path,
  * @param path The path.
  * @returns Configuration items.
  */
-void ConfigCompiler::CompileFile(const String& path,
-    vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes)
+void ConfigCompiler::CompileFile(const String& path)
 {
        ifstream stream;
        stream.open(path.CStr(), ifstream::in);
@@ -186,7 +142,7 @@ void ConfigCompiler::CompileFile(const String& path,
 
        Logger::Write(LogInformation, "config", "Compiling config file: " + path);
 
-       return CompileStream(path, &stream, resultItems, resultTypes);
+       return CompileStream(path, &stream);
 }
 
 /**
@@ -196,11 +152,10 @@ void ConfigCompiler::CompileFile(const String& path,
  * @param text The text.
  * @returns Configuration items.
  */
-void ConfigCompiler::CompileText(const String& path, const String& text,
-    vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes)
+void ConfigCompiler::CompileText(const String& path, const String& text)
 {
        stringstream stream(text);
-       return CompileStream(path, &stream, resultItems, resultTypes);
+       return CompileStream(path, &stream);
 }
 
 /**
@@ -209,12 +164,10 @@ void ConfigCompiler::CompileText(const String& path, const String& text,
  *
  * @param include The path from the include directive.
  * @param search Whether to search include dirs.
- * @param resultItems The resulting items.
- * @param resultTypes The resulting types.
  * @param debuginfo Debug information.
  */
 void ConfigCompiler::HandleFileInclude(const String& include, bool search,
-    vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes, const DebugInfo& debuginfo)
+    const DebugInfo& debuginfo)
 {
        String includePath = include;
 
@@ -239,23 +192,13 @@ void ConfigCompiler::HandleFileInclude(const String& include, bool search,
 
        vector<ConfigItem::Ptr> items;
 
-       if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CompileFile, _1, resultItems, resultTypes))) {
+       if (!Utility::Glob(includePath, boost::bind(&ConfigCompiler::CompileFile, _1))) {
                stringstream msgbuf;
                msgbuf << "Include file '" + include + "' does not exist (or no files found for pattern): " << debuginfo;
                throw_exception(invalid_argument(msgbuf.str()));
        }
 }
 
-/**
- * Adds an object to the result.
- *
- * @param object The configuration item.
- */
-void ConfigCompiler::AddObject(const ConfigItem::Ptr& object)
-{
-       m_ResultObjects.push_back(object);
-}
-
 /**
  * Adds a directory to the list of include search dirs.
  *
@@ -268,19 +211,3 @@ void ConfigCompiler::AddIncludeSearchDir(const String& dir)
        m_IncludeSearchDirs.push_back(dir);
 }
 
-void ConfigCompiler::AddType(const ConfigType::Ptr& type)
-{
-       m_ResultTypes[type->GetName()] = type;
-}
-
-ConfigType::Ptr ConfigCompiler::GetTypeByName(const String& name) const
-{
-       map<String, ConfigType::Ptr>::const_iterator it;
-       
-       it = m_ResultTypes.find(name);
-       
-       if (it == m_ResultTypes.end())
-               return ConfigType::Ptr();
-       
-       return it->second;
-}
index 006e5443286cca2d2f8adbf7b3acfc3a0d0d5376..036b3e8b39674fc74c39897862ef9738914b0333 100644 (file)
@@ -32,8 +32,7 @@ namespace icinga
 class I2_CONFIG_API ConfigCompiler
 {
 public:
-       typedef function<void (const String&, bool, vector<ConfigItem::Ptr> *,
-           vector<ConfigType::Ptr> *, const DebugInfo&)> HandleIncludeFunc;
+       typedef function<void (const String&, bool, const DebugInfo&)> HandleIncludeFunc;
 
        ConfigCompiler(const String& path, istream *input = &cin,
            HandleIncludeFunc includeHandler = &ConfigCompiler::HandleFileInclude);
@@ -41,32 +40,21 @@ public:
 
        void Compile(void);
 
-       static void CompileStream(const String& path,
-           istream *stream, vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes);
-       static void CompileFile(const String& path, vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes);
-       static void CompileText(const String& path,
-           const String& text, vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes);
+       static void CompileStream(const String& path, istream *stream);
+       static void CompileFile(const String& path);
+       static void CompileText(const String& path, const String& text);
 
        static void AddIncludeSearchDir(const String& dir);
 
-       vector<ConfigItem::Ptr> GetResultObjects(void) const;
-       vector<ConfigType::Ptr> GetResultTypes(void) const;
-
        String GetPath(void) const;
 
        static void HandleFileInclude(const String& include, bool search,
-           vector<ConfigItem::Ptr> *resultItems, vector<ConfigType::Ptr> *resultTypes,
            const DebugInfo& debuginfo);
        
        /* internally used methods */
        void HandleInclude(const String& include, bool search, const DebugInfo& debuginfo);
        void HandleLibrary(const String& library);
        
-       void AddObject(const ConfigItem::Ptr& object);
-       void AddType(const ConfigType::Ptr& type);
-       
-       ConfigType::Ptr GetTypeByName(const String& name) const;
-       
        size_t ReadInput(char *buffer, size_t max_bytes);
        void *GetScanner(void) const;
 
@@ -77,8 +65,6 @@ private:
        HandleIncludeFunc m_HandleInclude;
 
        void *m_Scanner;
-       vector<ConfigItem::Ptr> m_ResultObjects;
-       map<String, ConfigType::Ptr> m_ResultTypes;
 
        static vector<String> m_IncludeSearchDirs;
 
diff --git a/lib/config/configcompilercontext.cpp b/lib/config/configcompilercontext.cpp
new file mode 100644 (file)
index 0000000..f973426
--- /dev/null
@@ -0,0 +1,128 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 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 "i2-config.h"
+
+using std::ifstream;
+
+using namespace icinga;
+
+ConfigCompilerContext *ConfigCompilerContext::m_Context = NULL;
+
+ConfigCompilerContext::ConfigCompilerContext(void)
+       : m_Flags(0)
+{ }
+
+void ConfigCompilerContext::AddItem(const ConfigItem::Ptr& item)
+{
+       m_Items.push_back(item);
+       m_ItemsMap[make_pair(item->GetType(), item->GetName())] = item;
+}
+
+ConfigItem::Ptr ConfigCompilerContext::GetItem(const String& type, const String& name) const
+{
+       map<pair<String, String>, ConfigItem::Ptr>::const_iterator it;
+
+       it = m_ItemsMap.find(make_pair(type, name));
+
+       if (it == m_ItemsMap.end())
+               return ConfigItem::Ptr();
+
+       return it->second;
+}
+
+vector<ConfigItem::Ptr> ConfigCompilerContext::GetItems(void) const
+{
+       return m_Items;
+}
+
+void ConfigCompilerContext::AddType(const ConfigType::Ptr& type)
+{
+       m_Types[type->GetName()] = type;
+}
+
+ConfigType::Ptr ConfigCompilerContext::GetType(const String& name) const
+{
+       map<String, ConfigType::Ptr>::const_iterator it;
+
+       it = m_Types.find(name);
+
+       if (it == m_Types.end())
+               return ConfigType::Ptr();
+
+       return it->second;
+}
+
+void ConfigCompilerContext::AddError(bool warning, const String& message)
+{
+       m_Errors.push_back(ConfigCompilerError(warning, message));
+}
+
+vector<ConfigCompilerError> ConfigCompilerContext::GetErrors(void) const
+{
+       return m_Errors;
+}
+
+void ConfigCompilerContext::SetFlags(int flags)
+{
+       m_Flags = flags;
+}
+
+int ConfigCompilerContext::GetFlags(void) const
+{
+       return m_Flags;
+}
+
+void ConfigCompilerContext::SetContext(ConfigCompilerContext *context)
+{
+       assert(m_Context == NULL || context == NULL);
+
+       m_Context = context;
+}
+
+ConfigCompilerContext *ConfigCompilerContext::GetContext(void)
+{
+       return m_Context;
+}
+
+void ConfigCompilerContext::Validate(void)
+{
+       SetContext(this);
+
+       BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) {
+               ConfigType::Ptr ctype = GetType(item->GetType());
+
+               if (!ctype)
+                       continue;
+
+               ctype->ValidateItem(item);
+       }
+
+       SetContext(NULL);
+}
+
+void ConfigCompilerContext::ActivateItems(void)
+{
+       assert(m_Context == NULL);
+
+       Logger::Write(LogInformation, "config", "Executing config items...");
+       BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) {
+               item->Commit();
+       }
+}
diff --git a/lib/config/configcompilercontext.h b/lib/config/configcompilercontext.h
new file mode 100644 (file)
index 0000000..de2e80a
--- /dev/null
@@ -0,0 +1,87 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 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 CONFIGCOMPILERCONTEXT_H
+#define CONFIGCOMPILERCONTEXT_H
+
+namespace icinga
+{
+
+/**
+ * @ingroup config
+ */
+enum ConfigCompilerFlag
+{
+        CompilerStrict = 1, /**< Treat warnings as errors. */
+        CompilerLinkExisting = 2 /**< Link objects to existing config items. */
+};
+
+struct ConfigCompilerError
+{
+       bool Warning;
+       String Message;
+
+       ConfigCompilerError(bool warning, const String& message)
+               : Warning(warning), Message(message)
+       { }
+};
+
+/*
+ * @ingroup config
+ */
+class ConfigCompilerContext
+{
+public:
+       ConfigCompilerContext(void);
+
+       void AddItem(const ConfigItem::Ptr& item);
+       ConfigItem::Ptr GetItem(const String& type, const String& name) const;
+       vector<ConfigItem::Ptr> GetItems(void) const;
+
+       void AddType(const ConfigType::Ptr& type);
+       ConfigType::Ptr GetType(const String& name) const;
+
+       void AddError(bool warning, const String& message);
+       vector<ConfigCompilerError> GetErrors(void) const;
+
+       void SetFlags(int flags);
+       int GetFlags(void) const;
+
+       void Validate(void);
+       void ActivateItems(void);
+
+       static void SetContext(ConfigCompilerContext *context);
+       static ConfigCompilerContext *GetContext(void);
+
+private:
+        int m_Flags;
+
+       vector<shared_ptr<ConfigItem> > m_Items;
+        map<pair<String, String>, shared_ptr<ConfigItem> > m_ItemsMap;
+
+        map<String, shared_ptr<ConfigType> > m_Types;
+
+        vector<ConfigCompilerError> m_Errors;
+
+       static ConfigCompilerContext *m_Context;
+};
+
+}
+
+#endif /* CONFIGCOMPILERCONTEXT_H */
index dd52515230e17d8dba791628aee48a58f7c558c2..77628afd0f505ef3f84c972c9c88f7ccf697c7d7 100644 (file)
@@ -92,6 +92,13 @@ vector<String> ConfigItem::GetParents(void) const
        return m_Parents;
 }
 
+Dictionary::Ptr ConfigItem::Link(void) const
+{
+       Dictionary::Ptr attrs = boost::make_shared<Dictionary>();
+       InternalLink(attrs);
+       return attrs;
+}
+
 /**
  * Calculates the object's properties based on parent objects and the object's
  * expression list.
@@ -99,7 +106,7 @@ vector<String> ConfigItem::GetParents(void) const
  * @param dictionary The dictionary that should be used to store the
  *                  properties.
  */
-void ConfigItem::CalculateProperties(const Dictionary::Ptr& dictionary) const
+void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const
 {
        BOOST_FOREACH(const String& name, m_Parents) {
                ConfigItem::Ptr parent = ConfigItem::GetObject(GetType(), name);
@@ -111,7 +118,7 @@ void ConfigItem::CalculateProperties(const Dictionary::Ptr& dictionary) const
                        throw_exception(domain_error(message.str()));
                }
 
-               parent->CalculateProperties(dictionary);
+               parent->InternalLink(dictionary);
        }
 
        m_ExpressionList->Execute(dictionary);
@@ -129,8 +136,7 @@ DynamicObject::Ptr ConfigItem::Commit(void)
 
        DynamicObject::Ptr dobj = m_DynamicObject.lock();
 
-       Dictionary::Ptr properties = boost::make_shared<Dictionary>();
-       CalculateProperties(properties);
+       Dictionary::Ptr properties = Link();
 
        /* Create a fake update in the format that
         * DynamicObject::ApplyUpdate expects. */
@@ -279,12 +285,27 @@ DynamicObject::Ptr ConfigItem::GetDynamicObject(void) const
 ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
 {
        ConfigItem::ItemMap::iterator it;
+
+       ConfigCompilerContext *context = ConfigCompilerContext::GetContext();
+
+       if (context) {
+               ConfigItem::Ptr item = context->GetItem(type, name);
+
+               if (item)
+                       return item;
+
+               /* ignore already active objects while we're in the compiler
+                * context and linking to existing items is disabled. */
+               if ((context->GetFlags() & CompilerLinkExisting) == 0)
+                       return ConfigItem::Ptr();
+       }
+
        it = m_Items.find(make_pair(type, name));
 
-       if (it == m_Items.end())
-               return ConfigItem::Ptr();
+       if (it != m_Items.end())
+               return it->second;
 
-       return it->second;
+       return ConfigItem::Ptr();
 }
 
 void ConfigItem::Dump(ostream& fp) const
index 2cc73c919fd254215373a8479583a2a5d2bf17e1..1bc3d8892796ad25f1cbd4b8479e84fb50e4d6ad 100644 (file)
@@ -54,6 +54,8 @@ public:
 
        DebugInfo GetDebugInfo(void) const;
 
+       Dictionary::Ptr Link(void) const;
+
        static ConfigItem::Ptr GetObject(const String& type,
            const String& name);
 
@@ -61,7 +63,7 @@ public:
        static boost::signal<void (const ConfigItem::Ptr&)> OnRemoved;
 
 private:
-       void CalculateProperties(const Dictionary::Ptr& dictionary) const;
+       void InternalLink(const Dictionary::Ptr& dictionary) const;
 
         void RegisterChild(const ConfigItem::Ptr& child);
         void UnregisterChild(const ConfigItem::Ptr& child);
index c4ff22b15e7bf6d1885fa74aa5ccc1db2a93955d..90b5eebfb15daaf92d31cb61d57abb2187b6d2d1 100644 (file)
@@ -21,8 +21,6 @@
 \r
 using namespace icinga;\r
 \r
-ConfigType::TypeMap ConfigType::m_Types;\r
-\r
 ConfigType::ConfigType(const String& name, const DebugInfo& debuginfo)\r
        : m_Name(name), m_RuleList(boost::make_shared<TypeRuleList>()), m_DebugInfo(debuginfo)\r
 { }\r
@@ -52,68 +50,77 @@ DebugInfo ConfigType::GetDebugInfo(void) const
        return m_DebugInfo;\r
 }\r
 \r
-void ConfigType::ValidateObject(const DynamicObject::Ptr& object) const\r
+void ConfigType::ValidateItem(const ConfigItem::Ptr& object) const\r
 {\r
-       DynamicObject::AttributeConstIterator it;\r
-       const DynamicObject::AttributeMap& attributes = object->GetAttributes();\r
-       \r
-       for (it = attributes.begin(); it != attributes.end(); it++) {\r
-               if ((it->second.Type & Attribute_Config) == 0)\r
-                       continue;\r
-\r
-               if (!ValidateAttribute(it->first, it->second.Data))\r
-                       Logger::Write(LogWarning, "config", "Configuration attribute '" + it->first +\r
-                           "' on object '" + object->GetName() + "' of type '" + object->GetType()->GetName() + "' is unknown or contains an invalid type.");\r
-       }\r
-}\r
+       Dictionary::Ptr attrs = object->Link();\r
 \r
-void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary, const TypeRuleList::Ptr& ruleList)\r
-{\r
-       String key;\r
-       Value value;\r
-       BOOST_FOREACH(tie(key, value), dictionary) {\r
-               // TODO: implement (#3619)\r
-       }\r
-}\r
+       vector<String> locations;\r
+       locations.push_back("Object '" + object->GetName() + "' (Type: '" + object->GetType() + "')");\r
 \r
-bool ConfigType::ValidateAttribute(const String& name, const Value& value) const\r
-{\r
        ConfigType::Ptr parent;\r
-       \r
        if (m_Parent.IsEmpty()) {\r
                if (GetName() != "DynamicObject")\r
-                       parent = ConfigType::GetByName("DynamicObject");\r
+                       parent = ConfigCompilerContext::GetContext()->GetType("DynamicObject");\r
        } else {\r
-               parent = ConfigType::GetByName(m_Parent);\r
+               parent = ConfigCompilerContext::GetContext()->GetType(m_Parent);\r
        }\r
-       \r
-       if (parent && parent->ValidateAttribute(name, value))\r
-           return true;\r
-       \r
-       TypeRuleList::Ptr subRules;\r
-\r
-       if (!m_RuleList->FindMatch(name, value, &subRules))\r
-               return false;\r
-       \r
-       if (subRules && value.IsObjectType<Dictionary>())\r
-               ValidateDictionary(value, subRules);\r
-\r
-       return true;\r
-}\r
 \r
-void ConfigType::Commit(void)\r
-{\r
-       m_Types[GetName()] = GetSelf();\r
+       vector<TypeRuleList::Ptr> ruleLists;\r
+       if (parent)\r
+               ruleLists.push_back(parent->m_RuleList);\r
+\r
+       ruleLists.push_back(m_RuleList);\r
+\r
+       ValidateDictionary(attrs, ruleLists, locations);\r
 }\r
 \r
-ConfigType::Ptr ConfigType::GetByName(const String& name)\r
+void ConfigType::ValidateDictionary(const Dictionary::Ptr& dictionary,\r
+    const vector<TypeRuleList::Ptr>& ruleLists, vector<String>& locations)\r
 {\r
-       ConfigType::TypeMap::iterator it;\r
-       \r
-       it = m_Types.find(name);\r
-       \r
-       if (it == m_Types.end())\r
-               return ConfigType::Ptr();\r
-\r
-       return it->second;\r
+       String key;\r
+       Value value;\r
+       BOOST_FOREACH(tie(key, value), dictionary) {\r
+               TypeValidationResult overallResult = ValidationUnknownField;\r
+               vector<TypeRuleList::Ptr> subRuleLists;\r
+\r
+               locations.push_back("Attribute '" + key + "'");\r
+\r
+               BOOST_FOREACH(const TypeRuleList::Ptr& ruleList, ruleLists) {\r
+                       TypeRuleList::Ptr subRuleList;\r
+                       TypeValidationResult result = ruleList->Validate(key, value, &subRuleList);\r
+\r
+                       if (subRuleList)\r
+                               subRuleLists.push_back(subRuleList);\r
+\r
+                       if (result == ValidationOK) {\r
+                               overallResult = result;\r
+                               break;\r
+                       }\r
+\r
+                       if (result == ValidationInvalidType)\r
+                               overallResult = result;\r
+               }\r
+\r
+               bool first = true;\r
+               String stack;\r
+               BOOST_FOREACH(const String& location, locations) {\r
+                       if (!first)\r
+                               stack += " -> ";\r
+                       else\r
+                               first = false;\r
+\r
+                       stack += location;\r
+               }\r
+\r
+               if (overallResult == ValidationUnknownField)\r
+                       ConfigCompilerContext::GetContext()->AddError(true, "Unknown attribute: " + stack);\r
+               else if (overallResult == ValidationInvalidType)\r
+                       ConfigCompilerContext::GetContext()->AddError(false, "Invalid type for attribute: " + stack);\r
+\r
+               if (subRuleLists.size() > 0 && value.IsObjectType<Dictionary>())\r
+                       ValidateDictionary(value, subRuleLists, locations);\r
+\r
+               locations.pop_back();\r
+       }\r
 }\r
+\r
index 08d2d9347dc4d55743a434d9c63d7c6e0fee9e54..f66c31c340d74b9048d07cfb154cfd63755e5c30 100644 (file)
@@ -23,6 +23,8 @@
 namespace icinga\r
 {\r
 \r
+struct ConfigCompilerContext;\r
+\r
 /**\r
  * A configuration type. Used to validate config objects.\r
  *\r
@@ -40,16 +42,12 @@ public:
        String GetParent(void) const;\r
        void SetParent(const String& parent);\r
 \r
-       void Commit(void);\r
-       \r
        TypeRuleList::Ptr GetRuleList(void) const;\r
 \r
        DebugInfo GetDebugInfo(void) const;\r
 \r
-       void ValidateObject(const DynamicObject::Ptr& object) const;\r
+       void ValidateItem(const ConfigItem::Ptr& object) const;\r
 \r
-       static ConfigType::Ptr GetByName(const String& name);\r
-       \r
 private:\r
        String m_Name; /**< The type name. */\r
        String m_Parent; /**< The parent type. */\r
@@ -57,11 +55,8 @@ private:
        TypeRuleList::Ptr m_RuleList;\r
        DebugInfo m_DebugInfo; /**< Debug information. */\r
 \r
-       typedef map<String, ConfigType::Ptr> TypeMap;\r
-       static TypeMap m_Types; /**< All registered configuration types. */\r
-\r
-       bool ValidateAttribute(const String& name, const Value& value) const;\r
-       static void ValidateDictionary(const Dictionary::Ptr& dictionary, const TypeRuleList::Ptr& ruleList);\r
+       static void ValidateDictionary(const Dictionary::Ptr& dictionary,\r
+           const vector<TypeRuleList::Ptr>& ruleLists, vector<String>& locations);\r
 \r
 };\r
 \r
index 468f1a92e32308446799218cdc06f93c58f8bf99..0a3eb71c365042805a9ba4bee5dbdcab685b6ae2 100644 (file)
@@ -48,11 +48,12 @@ using std::endl;
 #include "debuginfo.h"
 #include "typerulelist.h"
 #include "typerule.h"
-#include "configtype.h"
 #include "expression.h"
 #include "expressionlist.h"
 #include "configitem.h"
+#include "configtype.h"
 #include "configitembuilder.h"
 #include "configcompiler.h"
+#include "configcompilercontext.h"
 
 #endif /* I2CONFIG_H */
index 59a9ad8abaefd195874480db5fafc6181439cea4..156c21737ec242b8922249106bfb8d02d8addec7 100644 (file)
@@ -31,11 +31,13 @@ TypeRuleList::Ptr TypeRule::GetSubRules(void) const
        return m_SubRules;
 }
 
-bool TypeRule::Matches(const String& name, const Value& value) const
+bool TypeRule::MatchName(const String& name) const
 {
-       if (!Utility::Match(m_NamePattern, name))
-               return false;
+       return (Utility::Match(m_NamePattern, name));
+}
 
+bool TypeRule::MatchValue(const Value& value) const
+{
        if (value.IsEmpty())
                return true;
 
@@ -64,3 +66,4 @@ bool TypeRule::Matches(const String& name, const Value& value) const
                        assert(!"Type rule has invalid type specifier.");
        }
 }
+
index e95974f49dd4e8e39e9476892029cccdd85506c5..384bae68d6b7ab3bc317fc4d20b3bfc8accebd32 100644 (file)
@@ -50,7 +50,8 @@ public:
 \r
        TypeRuleList::Ptr GetSubRules(void) const;\r
        \r
-       bool Matches(const String& name, const Value& value) const;\r
+       bool MatchName(const String& name) const;\r
+       bool MatchValue(const Value& value) const;\r
 \r
 private:\r
        TypeSpecifier m_Type;\r
index d9d156dbdbddd9ff7761982b57fedeb1ed96d7e9..7df540d9e5ef7fe20bd87a8a8477bef021e72f21 100644 (file)
@@ -54,20 +54,31 @@ size_t TypeRuleList::GetLength(void) const
 }\r
 \r
 /**\r
- * Finds a matching rule.\r
+ * Validates a field.\r
  *\r
  * @param name The name of the attribute.\r
  * @param value The value of the attribute.\r
- * *@param[out] subRules The list of sub-rules for the matching rule.\r
+ * @param[out] subRules The list of sub-rules for the matching rule.\r
+ * @returns The validation result.\r
  */\r
-bool TypeRuleList::FindMatch(const String& name, const Value& value, TypeRuleList::Ptr *subRules)\r
+TypeValidationResult TypeRuleList::Validate(const String& name, const Value& value, TypeRuleList::Ptr *subRules) const\r
 {\r
+       bool foundField = false;\r
        BOOST_FOREACH(const TypeRule& rule, m_Rules) {\r
-               if (rule.Matches(name, value)) {\r
+               if (!rule.MatchName(name))\r
+                       continue;\r
+\r
+               foundField = true;\r
+\r
+               if (rule.MatchValue(value)) {\r
                        *subRules = rule.GetSubRules();\r
-                       return true;\r
+                       return ValidationOK;\r
                }\r
        }\r
-       \r
-       return false;\r
+\r
+       if (foundField)\r
+               return ValidationInvalidType;\r
+       else\r
+               return ValidationUnknownField;\r
 }\r
+\r
index 4ec128ed6dd41ec433f93a524299630fbede394f..b12d3af1a797d9cc201fbb629cc16f234ad3bc4e 100644 (file)
@@ -25,6 +25,16 @@ namespace icinga
 \r
 struct TypeRule;\r
 \r
+/**\r
+ * @ingroup config\r
+ */\r
+enum TypeValidationResult\r
+{\r
+       ValidationOK,\r
+       ValidationInvalidType,\r
+       ValidationUnknownField\r
+};\r
+\r
 /**\r
  * A list of configuration type rules.\r
  *\r
@@ -39,7 +49,7 @@ public:
        void AddRule(const TypeRule& rule);\r
        void AddRules(const TypeRuleList::Ptr& ruleList);\r
 \r
-       bool FindMatch(const String& name, const Value& value, TypeRuleList::Ptr *subRules);\r
+       TypeValidationResult Validate(const String& name, const Value& value, TypeRuleList::Ptr *subRules) const;\r
 \r
        size_t GetLength(void) const;\r
 \r