diff --git a/ATxCommon/Serializables/ServiceConfig.cs b/ATxCommon/Serializables/ServiceConfig.cs index acc1bc8a88b3355f256b95146b8ec9037ba06538..601240e90517253329de561b60c7d5d1ce248ff1 100644 --- a/ATxCommon/Serializables/ServiceConfig.cs +++ b/ATxCommon/Serializables/ServiceConfig.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Configuration; using System.IO; using System.Xml; +using System.Xml.Linq; using System.Xml.Serialization; using NLog; @@ -33,15 +34,38 @@ namespace ATxCommon.Serializables throw new SettingsPropertyIsReadOnlyException("The config file must not be written by the service!"); } - public static ServiceConfig Deserialize(string file) { - Log.Debug("Trying to read service configuration XML file: [{0}]", file); - var serializer = new XmlSerializer(typeof(ServiceConfig)); + /// <summary> + /// Load the host specific and the common XML configuration files, combine them and + /// deserialize them into a ServiceConfig object. The host specific configuration file's + /// name is defined as the hostname with an ".xml" suffix. + /// </summary> + /// <param name="path">The path to the configuration files.</param> + /// <returns>A ServiceConfig object with validated settings.</returns> + public static ServiceConfig Deserialize(string path) { ServiceConfig config; - using (var reader = XmlReader.Create(file)) { + + var commonFile = Path.Combine(path, "config.common.xml"); + var specificFile = Path.Combine(path, Environment.MachineName + ".xml"); + + // for parsing the configuration from two separate files we are using the default + // behaviour of the .NET XmlSerializer on duplicates: only the first occurrence is + // used, all other ones are silentley being discarded - this way we simply append the + // contents of the common config file to the host-specific and deserialize then: + var common = XElement.Load(commonFile); + Log.Debug("Loaded common configuration XML file: [{0}]", commonFile); + var combined = XElement.Load(specificFile); + Log.Debug("Loaded host specific configuration XML file: [{0}]", specificFile); + combined.Add(common.Nodes()); + Log.Trace("Combined XML structure:\n\n{0}\n\n", combined); + + using (var reader = XmlReader.Create(new StringReader(combined.ToString()))) { + Log.Debug("Trying to parse combined XML."); + var serializer = new XmlSerializer(typeof(ServiceConfig)); config = (ServiceConfig) serializer.Deserialize(reader); } + ValidateConfiguration(config); - Log.Debug("Finished deserializing service configuration XML file."); + Log.Debug("Successfully parsed and validated configuration XML."); return config; } diff --git a/ATxConfigTest/AutoTxConfigTest.cs b/ATxConfigTest/AutoTxConfigTest.cs index 679659e9ad476f889ca3d26b60c647a3dabf35e8..641af12570bb37ed275e44a817748ea537bffa43 100644 --- a/ATxConfigTest/AutoTxConfigTest.cs +++ b/ATxConfigTest/AutoTxConfigTest.cs @@ -21,7 +21,7 @@ namespace ATxConfigTest Layout = @"${date:format=yyyy-MM-dd HH\:mm\:ss} [${level}] (${logger}) ${message}", }; logConfig.AddTarget("console", consoleTarget); - var logRuleConsole = new LoggingRule("*", LogLevel.Debug, consoleTarget); + var logRuleConsole = new LoggingRule("*", LogLevel.Trace, consoleTarget); logConfig.LoggingRules.Add(logRuleConsole); LogManager.Configuration = logConfig; @@ -29,13 +29,12 @@ namespace ATxConfigTest if (args.Length > 0) baseDir = args[0]; - var configPath = Path.Combine(baseDir, "configuration.xml"); var statusPath = Path.Combine(baseDir, "status.xml"); try { string msg; - Console.WriteLine($"\nTrying to parse configuration file [{configPath}]...\n"); - _config = ServiceConfig.Deserialize(configPath); + Console.WriteLine($"\nTrying to parse configuration files from [{baseDir}]...\n"); + _config = ServiceConfig.Deserialize(baseDir); msg = "------------------ configuration settings ------------------"; Console.WriteLine($"{msg}\n{_config.Summary()}{msg}\n");