/// <summary> /// Generates the node list. /// </summary> /// <param name="configs">The configs.</param> private static List <Node <string> > GenerateNodeList(RenderConfig renderConfig, IRenderConfigLogger log) { //Create list of all nodes, without dependencies log.LogMessage("Generating Node List..."); List <Node <string> > nodes = CreateInitialNodeList(renderConfig); foreach (Configuration config in renderConfig.Configurations) { //Split the dependencies, and then for each of them find a node in nodeList, and add as a dependency if (!String.IsNullOrEmpty(config.Depends)) { string[] dependencies = config.Depends.Split(',', ';'); foreach (string depends in dependencies) { Node <string> dependencyNode = SearchForNodeByIdentity(nodes, depends.Trim()); if (dependencyNode == null) { throw new ApplicationException("Error in configuration, cannot resolve dependency " + depends); } else { SearchForNodeByIdentity(nodes, config.Name).Dependencies.Add(dependencyNode); } } } } return(nodes); }
/// <summary> /// Deserializes and Included files, and adds them as Configuration objects. /// </summary> /// <param name="configs">The configs.</param> private void DeserializeAndAddIncludes(RenderConfig configs) { XmlSerializer configSerializer = new XmlSerializer(typeof(Configuration)); foreach (Include include in configs.Includes) { string includeFile = include.file; if (!File.Exists(includeFile)) { FileInfo configFile = new FileInfo(config.ConfigFile); includeFile = Path.Combine(configFile.Directory.FullName, include.file); } if (File.Exists(includeFile)) { log.LogMessage("Attempting to include file: " + include.file); try { XmlDocument includeXml = new XmlDocument(); includeXml.Load(includeFile); XmlNodeList nodes = includeXml.SelectNodes(@"//Configuration"); if (nodes.Count > 0) { log.LogMessage(string.Concat(include.file, " contained ", nodes.Count, " Configuration Nodes")); foreach (XmlNode node in nodes) { using (XmlReader nodeReader = XmlReader.Create(new StringReader(node.OuterXml.ToString()))) { configs.Configurations.Add((Configuration)configSerializer.Deserialize(nodeReader)); } } } else { log.LogError(string.Concat("Could not find any Configuration nodes in ", include.file)); } } catch (ApplicationException i) { log.LogError("Could not load include file: " + include.file); throw new ApplicationException("Could not load include file: " + include.file, i); } } else { log.LogError("Could not find include file: " + include.file); throw new ApplicationException("Could not find include file: " + include.file); } } }
/// <summary> /// Creates the config process stack. /// </summary> /// <param name="configs">The configs.</param> /// <param name="dependencyStack">The dependency stack.</param> /// <returns></returns> private Queue <Configuration> CreateConfigProcessQueue(RenderConfig renderConfig, Stack <Node <string> > dependencyStack) { Queue <Configuration> configQueue = new Queue <Configuration>(); while (dependencyStack.Count > 0) { Node <string> node = dependencyStack.Pop(); foreach (Configuration c in renderConfig.Configurations) { if (c.Name == node.Identity) { configQueue.Enqueue(c); } } } return(configQueue); }
/// <summary> /// Creates the initial node list. /// </summary> /// <param name="configs">The configs.</param> private static List <Node <string> > CreateInitialNodeList(RenderConfig renderConfig) { List <Node <string> > nodes = new List <Node <string> >(); foreach (Configuration config in renderConfig.Configurations) { if (SearchForNodeByIdentity(nodes, config.Name) != null) { throw new ApplicationException("Configuration exists in file twice"); } else { Node <string> node = new Node <string>(config.Name); nodes.Add(node); } } return(nodes); }
/// <summary> /// Renders the configuration specified. /// </summary> /// <returns></returns> public bool Render() { LogUtilities.LogSettings(config, log); nodeList = new List <Node <string> >(); Boolean returnCode = true; if (File.Exists(config.ConfigFile)) { log.LogMessage("Reading in configuration file..."); RenderConfig renderConfig = ReadConfigurationFile(); if (renderConfig != null) { //HACK We should be using a deep copy so that all this becomes "variableStack = dependencyStack.Clone();" //Get the list of nodes nodeList = GenerateNodeList(renderConfig, log); if (SearchForNodeByIdentity(nodeList, config.Configuration) == null) { throw new ApplicationException("Could not find Configuration : " + config.Configuration); } List <Node <string> > n2 = GenerateNodeList(renderConfig, log); //Generate the dependency path DepthFirstSearch <string> dfs = new DepthFirstSearch <string>(nodeList); DepthFirstSearch <string> dfs2 = new DepthFirstSearch <string>(n2); dependencyStack = dfs.GetDependencyPath(config.Configuration); //HACK Need to write a deep copy Queue Clone to get rid of this... variableStack = dfs2.GetDependencyPath(config.Configuration); } if (Directory.Exists(config.OutputDirectory)) { if (config.DeleteOutputDirectory) { log.LogMessage("Deleting and recreating output directory..."); Directory.Delete(config.OutputDirectory, true); Directory.CreateDirectory(config.OutputDirectory); } } else { log.LogMessage("Creating output directory..."); Directory.CreateDirectory(config.OutputDirectory); } //Create a queue of mods to run and a queue of EnvironmentVariables to implement //Variables have to be put in place before the mods... log.LogMessage("Building dependency queue..."); Queue <Configuration> configsToRun = CreateConfigProcessQueue(renderConfig, dependencyStack); //HACK This is ugly, needs a deep copy here.... Queue <Configuration> envQueue = CreateConfigProcessQueue(renderConfig, variableStack); while (envQueue.Count > 0) { Configuration varConfig = envQueue.Dequeue(); //First, we need to get all the Variables and create them. foreach (EnvironmentVariable variable in varConfig.EnvironmentVariables) { Environment.SetEnvironmentVariable(variable.variable, variable.Value); } } while (configsToRun.Count > 0) { Configuration currentConfig = configsToRun.Dequeue(); log.LogMessage(MessageImportance.High, "Running modification: " + currentConfig.Name); if (currentConfig.TargetFiles != null) { if (!currentConfig.Apply(config, log)) { log.LogError("Failed to apply configuration: " + currentConfig.Name); returnCode = false; } } } } else { log.LogError("Could not find configuration file: " + config.ConfigFile); returnCode = false; } //Let 'em know if (returnCode) { log.LogMessage(MessageImportance.High, "Configuration rendered!"); } else { log.LogError("Failed to render configuration."); } return(returnCode); }
/// <summary> /// Deserializes and Included files, and adds them as Configuration objects. /// </summary> /// <param name="configs">The configs.</param> private void DeserializeAndAddIncludes(RenderConfig configs) { XmlSerializer configSerializer = new XmlSerializer(typeof(Configuration)); foreach (Include include in configs.Includes) { string includeFile = include.file; if (!File.Exists(includeFile)) { FileInfo configFile = new FileInfo(config.ConfigFile); includeFile = Path.Combine(configFile.Directory.FullName, include.file); } if (File.Exists(includeFile)) { log.LogMessage("Attempting to include file: " + include.file); try { XmlDocument includeXml = new XmlDocument(); includeXml.Load(includeFile); XmlNodeList nodes = includeXml.SelectNodes(@"//Configuration"); if (nodes.Count > 0) { log.LogMessage(string.Concat(include.file, " contained ",nodes.Count," Configuration Nodes")); foreach (XmlNode node in nodes) { using (XmlReader nodeReader = XmlReader.Create(new StringReader(node.OuterXml.ToString()))) { configs.Configurations.Add((Configuration)configSerializer.Deserialize(nodeReader)); } } } else { log.LogError(string.Concat("Could not find any Configuration nodes in ",include.file)); } } catch (ApplicationException i) { log.LogError("Could not load include file: " + include.file); throw new ApplicationException("Could not load include file: " + include.file, i); } } else { log.LogError("Could not find include file: " + include.file); throw new ApplicationException("Could not find include file: " + include.file); } } }
/// <summary> /// Creates the initial node list. /// </summary> /// <param name="configs">The configs.</param> private static List<Node<string>> CreateInitialNodeList(RenderConfig renderConfig) { List<Node<string>> nodes = new List<Node<string>>(); foreach (Configuration config in renderConfig.Configurations) { if (SearchForNodeByIdentity(nodes, config.Name) != null) { throw new ApplicationException("Configuration exists in file twice"); } else { Node<string> node = new Node<string>(config.Name); nodes.Add(node); } } return nodes; }
/// <summary> /// Generates the node list. /// </summary> /// <param name="configs">The configs.</param> private static List<Node<string>> GenerateNodeList(RenderConfig renderConfig, IRenderConfigLogger log) { //Create list of all nodes, without dependencies log.LogMessage("Generating Node List..."); List<Node<string>> nodes = CreateInitialNodeList(renderConfig); foreach (Configuration config in renderConfig.Configurations) { //Split the dependencies, and then for each of them find a node in nodeList, and add as a dependency if (!String.IsNullOrEmpty(config.Depends)) { string[] dependencies = config.Depends.Split(',', ';'); foreach (string depends in dependencies) { Node<string> dependencyNode = SearchForNodeByIdentity(nodes, depends.Trim()); if (dependencyNode == null) { throw new ApplicationException("Error in configuration, cannot resolve dependency " + depends); } else { SearchForNodeByIdentity(nodes, config.Name).Dependencies.Add(dependencyNode); } } } } return nodes; }
/// <summary> /// Creates the config process stack. /// </summary> /// <param name="configs">The configs.</param> /// <param name="dependencyStack">The dependency stack.</param> /// <returns></returns> private Queue<Configuration> CreateConfigProcessQueue(RenderConfig renderConfig, Stack<Node<string>> dependencyStack) { Queue<Configuration> configQueue = new Queue<Configuration>(); while (dependencyStack.Count > 0) { Node<string> node = dependencyStack.Pop(); foreach (Configuration c in renderConfig.Configurations) { if (c.Name == node.Identity) { configQueue.Enqueue(c); } } } return configQueue; }