From 0273afcd6a73824d2413ae53fbceb4f15586eba7 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Sat, 10 Nov 2007 02:05:07 +0000 Subject: [PATCH] 2007-11-10 Marek Habersack * Mono.MonoConfig/Helpers.cs: added a method for breaking long text lines to fit them within the console window. * Mono.MonoConfig/FeatureNode.cs: added support for feature actions. * Mono.MonoConfig/FeatureNodeHandler.cs: added support for feature actions. * Mono.MonoConfig/FeatureAction.cs: added * mconfig.exe.sources: added Mono.MonoConfig/FeatureAction.cs svn path=/trunk/mcs/; revision=89395 --- mcs/tools/mconfig/ChangeLog | 15 ++ .../DefaultConfigFileNodeHandler.cs | 2 +- .../Mono.MonoConfig/DefaultNodeHandler.cs | 2 +- .../mconfig/Mono.MonoConfig/FeatureAction.cs | 188 ++++++++++++++++++ .../mconfig/Mono.MonoConfig/FeatureNode.cs | 18 +- .../Mono.MonoConfig/FeatureNodeHandler.cs | 90 ++++++--- mcs/tools/mconfig/Mono.MonoConfig/Helpers.cs | 36 +++- mcs/tools/mconfig/mconfig.cs | 2 +- mcs/tools/mconfig/mconfig.exe.sources | 1 + 9 files changed, 312 insertions(+), 42 deletions(-) create mode 100644 mcs/tools/mconfig/Mono.MonoConfig/FeatureAction.cs diff --git a/mcs/tools/mconfig/ChangeLog b/mcs/tools/mconfig/ChangeLog index a20d87c0bcb..90948f4b47d 100644 --- a/mcs/tools/mconfig/ChangeLog +++ b/mcs/tools/mconfig/ChangeLog @@ -1,3 +1,18 @@ +2007-11-10 Marek Habersack + + * Mono.MonoConfig/Helpers.cs: added a method for breaking long + text lines to fit them within the console window. + + * Mono.MonoConfig/FeatureNode.cs: added support for feature + actions. + + * Mono.MonoConfig/FeatureNodeHandler.cs: added support for feature + actions. + + * Mono.MonoConfig/FeatureAction.cs: added + + * mconfig.exe.sources: added Mono.MonoConfig/FeatureAction.cs + 2007-11-09 Marek Habersack * Mono.MonoConfig/FeatureNodeHandler.cs: added support for feature diff --git a/mcs/tools/mconfig/Mono.MonoConfig/DefaultConfigFileNodeHandler.cs b/mcs/tools/mconfig/Mono.MonoConfig/DefaultConfigFileNodeHandler.cs index 87948cbd0a1..05a64c6f842 100644 --- a/mcs/tools/mconfig/Mono.MonoConfig/DefaultConfigFileNodeHandler.cs +++ b/mcs/tools/mconfig/Mono.MonoConfig/DefaultConfigFileNodeHandler.cs @@ -114,7 +114,7 @@ namespace Mono.MonoConfig public void ReadConfiguration (XPathNavigator nav) { name = Helpers.GetRequiredNonEmptyAttribute (nav, "name"); - target = Helpers.ConvertTarget (Helpers.GetRequiredNonEmptyAttribute (nav, "target")); + target = Helpers.ConvertEnum (Helpers.GetRequiredNonEmptyAttribute (nav, "target"), "target"); fileName = Helpers.GetOptionalAttribute (nav, "fileName"); if (String.IsNullOrEmpty (fileName)) diff --git a/mcs/tools/mconfig/Mono.MonoConfig/DefaultNodeHandler.cs b/mcs/tools/mconfig/Mono.MonoConfig/DefaultNodeHandler.cs index 08cd51b1f9e..9a205855588 100644 --- a/mcs/tools/mconfig/Mono.MonoConfig/DefaultNodeHandler.cs +++ b/mcs/tools/mconfig/Mono.MonoConfig/DefaultNodeHandler.cs @@ -64,7 +64,7 @@ namespace Mono.MonoConfig public void ReadConfiguration (XPathNavigator nav) { section = Helpers.GetRequiredNonEmptyAttribute (nav, "section"); - target = Helpers.ConvertTarget (Helpers.GetRequiredNonEmptyAttribute (nav, "target")); + target = Helpers.ConvertEnum (Helpers.GetRequiredNonEmptyAttribute (nav, "target"), "target"); XPathNodeIterator iter = nav.Select ("./text()"); StringBuilder sb = new StringBuilder (); diff --git a/mcs/tools/mconfig/Mono.MonoConfig/FeatureAction.cs b/mcs/tools/mconfig/Mono.MonoConfig/FeatureAction.cs new file mode 100644 index 00000000000..38c4640e30f --- /dev/null +++ b/mcs/tools/mconfig/Mono.MonoConfig/FeatureAction.cs @@ -0,0 +1,188 @@ +// +// Authors: +// Marek Habersack (mhabersack@novell.com) +// +// (C) 2007 Novell, Inc +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.XPath; + +namespace Mono.MonoConfig +{ + public enum ActionType + { + Message, + ShellScript, + Exec + } + + public enum ActionWhen + { + Before, + After + } + + public class FeatureAction + { + ActionType type; + ActionWhen when; + string command; + string commandArguments; + string message; + string script; + + public ActionWhen When { + get { return when; } + } + + public FeatureAction (XPathNavigator nav) + { + string val = Helpers.GetRequiredNonEmptyAttribute (nav, "type"); + type = Helpers.ConvertEnum (val, "type"); + + val = Helpers.GetRequiredNonEmptyAttribute (nav, "when"); + when = Helpers.ConvertEnum (val, "when"); + + XPathNodeIterator iter; + StringBuilder sb = new StringBuilder (); + + switch (type) { + case ActionType.Message: + case ActionType.ShellScript: + iter = nav.Select ("./text()"); + while (iter.MoveNext ()) + sb.Append (iter.Current.Value); + if (type == ActionType.Message) + message = sb.ToString (); + else + script = sb.ToString (); + break; + + case ActionType.Exec: + command = Helpers.GetRequiredNonEmptyAttribute (nav, "command"); + commandArguments = Helpers.GetOptionalAttribute (nav, "commndArguments"); + break; + } + } + + public void Execute () + { + switch (type) { + case ActionType.Message: + ExecuteMessage (); + break; + + case ActionType.ShellScript: + ExecuteShellScript (); + break; + + case ActionType.Exec: + ExecuteExec (); + break; + } + } + + void ExecuteMessage () + { + if (String.IsNullOrEmpty (message)) + return; + + string[] lines = message.Split ('\n'); + string line; + int maxLineWidth = Console.WindowWidth; + StringBuilder sb = new StringBuilder (); + + foreach (string l in lines) { + if (l.Length == 0) { + sb.Append ("\n"); + continue; + } + + line = l.Trim (); + if (line.Length > maxLineWidth) + sb.AppendFormat ("{0}\n", Helpers.BreakLongLine (line, String.Empty, maxLineWidth)); + else + sb.AppendFormat ("{0}{1}\n", String.Empty, line); + } + Console.WriteLine (sb.ToString ()); + } + + void ExecuteShellScript () + { + if (String.IsNullOrEmpty (script)) + return; + + string script_temp = Path.GetTempFileName (); + StreamWriter s = null; + try { + s = new StreamWriter (script_temp); + s.Write (script); + + Process p = new Process (); + ProcessStartInfo pinfo = p.StartInfo; + + pinfo.UseShellExecute = false; + pinfo.RedirectStandardOutput = true; + pinfo.RedirectStandardError = true; + pinfo.FileName = "/bin/bash"; + pinfo.Arguments = script_temp; + p.Start (); + + string stdout = p.StandardOutput.ReadToEnd (); + string stderr = p.StandardError.ReadToEnd (); + p.WaitForExit (); + + if (p.ExitCode != 0) { + Console.Error.Write (stderr); + throw new ApplicationException ( + String.Format ("Script signalled failure code: {0}", p.ExitCode)); + } + + Console.Write (stdout); + p.Close (); + } catch (Exception ex) { + Console.WriteLine (ex); + throw new ApplicationException ("Error executing feature shell action.", ex); + } finally { + if (s != null) + s.Close (); + try { + File.Delete (script_temp); + } catch (Exception) { + // ignore + } + } + } + + void ExecuteExec () + { + } + } +} diff --git a/mcs/tools/mconfig/Mono.MonoConfig/FeatureNode.cs b/mcs/tools/mconfig/Mono.MonoConfig/FeatureNode.cs index 46250a7b192..30074ab55f1 100644 --- a/mcs/tools/mconfig/Mono.MonoConfig/FeatureNode.cs +++ b/mcs/tools/mconfig/Mono.MonoConfig/FeatureNode.cs @@ -27,15 +27,16 @@ // using System; using System.Collections.Generic; -using System.IO; namespace Mono.MonoConfig { public class FeatureNode { List blocks; + List actionsBefore; + List actionsAfter; string description; - + public List Blocks { get { if (blocks != null) @@ -53,11 +54,22 @@ namespace Mono.MonoConfig return String.Empty; } } + + public List ActionsBefore { + get { return actionsBefore; } + } + + public List ActionsAfter { + get { return actionsAfter; } + } - public FeatureNode (List blocks, string description) + public FeatureNode (List blocks, string description, + List actionsBefore, List actionsAfter) { this.blocks = blocks; this.description = description; + this.actionsBefore = actionsBefore; + this.actionsAfter = actionsAfter; } } } diff --git a/mcs/tools/mconfig/Mono.MonoConfig/FeatureNodeHandler.cs b/mcs/tools/mconfig/Mono.MonoConfig/FeatureNodeHandler.cs index a2bdfb4ffd0..0ee3a698b52 100644 --- a/mcs/tools/mconfig/Mono.MonoConfig/FeatureNodeHandler.cs +++ b/mcs/tools/mconfig/Mono.MonoConfig/FeatureNodeHandler.cs @@ -39,19 +39,23 @@ namespace Mono.MonoConfig string name; FeatureTarget target; List blocks; + List actionsBefore; + List actionsAfter; Dictionary storage; StringBuilder description; public FeatureNodeHandler () { blocks = new List (); + actionsBefore = new List (); + actionsAfter = new List (); description = new StringBuilder (); } public void ReadConfiguration (XPathNavigator nav) { name = Helpers.GetRequiredNonEmptyAttribute (nav, "name"); - target = Helpers.ConvertTarget (Helpers.GetRequiredNonEmptyAttribute (nav, "target")); + target = Helpers.ConvertEnum (Helpers.GetRequiredNonEmptyAttribute (nav, "target"), "target"); XPathNodeIterator iter = nav.Select ("blocks/block[string-length (@name) > 0]"); while (iter.MoveNext ()) @@ -65,6 +69,25 @@ namespace Mono.MonoConfig continue; description.Append (val); } + + FeatureAction action; + iter = nav.Select ("actions/action[string-length (@type) > 0 and string-length (@when) > 0]"); + while (iter.MoveNext ()) { + action = new FeatureAction (iter.Current); + switch (action.When) { + case ActionWhen.Before: + actionsBefore.Add (action); + break; + + case ActionWhen.After: + actionsAfter.Add (action); + break; + + default: + throw new ApplicationException ( + String.Format ("Unknown 'when' attribute: {0}", action.When)); + } + } } public void StoreConfiguration () @@ -72,8 +95,13 @@ namespace Mono.MonoConfig AssertStorage (); List blocksClone = new List (blocks.Count); + List abc = new List (actionsBefore.Count); + List aac = new List (actionsAfter.Count); + blocksClone.AddRange (blocks); - FeatureNode fn = new FeatureNode (blocksClone, description.ToString ()); + abc.AddRange (actionsBefore); + aac.AddRange (actionsAfter); + FeatureNode fn = new FeatureNode (blocksClone, description.ToString (), abc, aac); if (storage.ContainsKey (name)) storage [name] = fn; // allow for silent override @@ -81,6 +109,8 @@ namespace Mono.MonoConfig storage.Add (name, fn); blocks.Clear (); + actionsBefore.Clear (); + actionsAfter.Clear (); description.Length = 0; } @@ -124,6 +154,16 @@ namespace Mono.MonoConfig StringBuilder ret = new StringBuilder (); ret.AppendFormat ("{0} (Target: {1})", name, lfb [0].Target); + List al = fn.ActionsBefore; + if (al != null && al.Count > 0) + ret.AppendFormat ("; {0} actions before", al.Count); + + al = fn.ActionsAfter; + if (al != null && al.Count > 0) + ret.AppendFormat ("; {0} actions after", al.Count); + + ret.Append ("\n"); + string desc = fn.Description; if (String.IsNullOrEmpty (desc)) return ret.ToString (); @@ -141,41 +181,13 @@ namespace Mono.MonoConfig line = l.Trim (); if (line.Length > maxLineWidth) - ret.AppendFormat ("{0}\n", BreakLongLine (line, indent, maxLineWidth)); + ret.AppendFormat ("{0}\n", Helpers.BreakLongLine (line, indent, maxLineWidth)); else ret.AppendFormat ("{0}{1}\n", indent, line); } return ret.ToString (); } - - string BreakLongLine (string line, string indent, int maxLineWidth) - { - StringBuilder sb = new StringBuilder (); - - int lineLen = line.Length; - int segments = lineLen / maxLineWidth; - int segmentStart = 0; - int segmentLen = maxLineWidth - 1; - int idx; - - while (segments-- >= 0) { - idx = line.LastIndexOf (' ', segmentStart + segmentLen); - if (idx > 0) - segmentLen = idx - segmentStart; - else - idx = segmentLen - 1; - - sb.AppendFormat ("{0}{1}\n", indent, line.Substring (segmentStart, segmentLen)); - segmentStart = idx + 1; - if (lineLen - segmentStart > maxLineWidth) - segmentLen = maxLineWidth; - else - segmentLen = lineLen - segmentStart - 1; - } - - return sb.ToString (); - } public bool HasFeature (string featureName) { @@ -208,7 +220,8 @@ namespace Mono.MonoConfig List blocks = fn.Blocks; if (blocks == null || blocks.Count == 0) throw new ApplicationException (String.Format ("Definition of feature '{0}' is empty", featureName)); - + + RunActions (fn.ActionsBefore); XmlDocument doc = new XmlDocument (); if (File.Exists (configFilePath)) @@ -218,8 +231,21 @@ namespace Mono.MonoConfig AddFeatureBlock (doc, block, target, defaults, configBlocks); Helpers.SaveXml (doc, configFilePath); + RunActions (fn.ActionsAfter); } + void RunActions (List actions) + { + if (actions == null || actions.Count == 0) + return; + + foreach (FeatureAction action in actions) { + if (action == null) + continue; + action.Execute (); + } + } + void AddFeatureBlock (XmlDocument doc, FeatureBlock block, FeatureTarget target, IDefaultContainer[] defaults, IConfigBlockContainer[] configBlocks) { diff --git a/mcs/tools/mconfig/Mono.MonoConfig/Helpers.cs b/mcs/tools/mconfig/Mono.MonoConfig/Helpers.cs index d68d3d78c61..7755511a787 100644 --- a/mcs/tools/mconfig/Mono.MonoConfig/Helpers.cs +++ b/mcs/tools/mconfig/Mono.MonoConfig/Helpers.cs @@ -38,16 +38,44 @@ namespace Mono.MonoConfig { public const string FakeRootName = "F_a_K_e_R_o_O_t_M_o_N_o_C_o_N_f_I_g_N_o_D_e"; - public static FeatureTarget ConvertTarget (string value) + public static EnumType ConvertEnum (string value, string attrName) { try { - EnumConverter cvt = new EnumConverter (typeof (FeatureTarget)); - return (FeatureTarget) cvt.ConvertFromInvariantString (value); + EnumConverter cvt = new EnumConverter (typeof (EnumType)); + return (EnumType) cvt.ConvertFromInvariantString (value); } catch (Exception) { throw new ApplicationException ( - String.Format ("Failed to parse the 'target' attribute '{0}'", value)); + String.Format ("Failed to parse the '{0}' attribute '{1}'", attrName, value)); } } + + public static string BreakLongLine (string line, string indent, int maxLineWidth) + { + StringBuilder sb = new StringBuilder (); + + int lineLen = line.Length; + int segments = lineLen / maxLineWidth; + int segmentStart = 0; + int segmentLen = maxLineWidth - 1; + int idx; + + while (segments-- >= 0) { + idx = line.LastIndexOf (' ', segmentStart + segmentLen); + if (idx > 0) + segmentLen = idx - segmentStart; + else + idx = segmentLen - 1; + + sb.AppendFormat ("{0}{1}\n", indent, line.Substring (segmentStart, segmentLen)); + segmentStart = idx + 1; + if (lineLen - segmentStart > maxLineWidth) + segmentLen = maxLineWidth; + else + segmentLen = lineLen - segmentStart - 1; + } + + return sb.ToString (); + } public static string GetRequiredNonEmptyAttribute (XPathNavigator node, string name) { diff --git a/mcs/tools/mconfig/mconfig.cs b/mcs/tools/mconfig/mconfig.cs index 65ac73784e0..b149adef57d 100644 --- a/mcs/tools/mconfig/mconfig.cs +++ b/mcs/tools/mconfig/mconfig.cs @@ -192,7 +192,7 @@ namespace Mono.MonoConfig RequiredParameterMissing (argName); try { - Target = Helpers.ConvertTarget (argParam); + Target = Helpers.ConvertEnum (argParam, "target"); } catch (Exception ex) { OptionParameterError (argName, ex.Message); } diff --git a/mcs/tools/mconfig/mconfig.exe.sources b/mcs/tools/mconfig/mconfig.exe.sources index 80221ce2e33..70051b0bf66 100644 --- a/mcs/tools/mconfig/mconfig.exe.sources +++ b/mcs/tools/mconfig/mconfig.exe.sources @@ -5,6 +5,7 @@ Mono.MonoConfig/ConfigBlockNodeHandler.cs Mono.MonoConfig/Configuration.cs Mono.MonoConfig/DefaultConfigFileNodeHandler.cs Mono.MonoConfig/DefaultNodeHandler.cs +Mono.MonoConfig/FeatureAction.cs Mono.MonoConfig/FeatureBlock.cs Mono.MonoConfig/FeatureNode.cs Mono.MonoConfig/FeatureNodeHandler.cs -- 2.25.1