2007-11-10 Marek Habersack <mhabersack@novell.com>
authorMarek Habersack <grendel@twistedcode.net>
Sat, 10 Nov 2007 02:05:07 +0000 (02:05 -0000)
committerMarek Habersack <grendel@twistedcode.net>
Sat, 10 Nov 2007 02:05:07 +0000 (02:05 -0000)
* 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
mcs/tools/mconfig/Mono.MonoConfig/DefaultConfigFileNodeHandler.cs
mcs/tools/mconfig/Mono.MonoConfig/DefaultNodeHandler.cs
mcs/tools/mconfig/Mono.MonoConfig/FeatureAction.cs [new file with mode: 0644]
mcs/tools/mconfig/Mono.MonoConfig/FeatureNode.cs
mcs/tools/mconfig/Mono.MonoConfig/FeatureNodeHandler.cs
mcs/tools/mconfig/Mono.MonoConfig/Helpers.cs
mcs/tools/mconfig/mconfig.cs
mcs/tools/mconfig/mconfig.exe.sources

index a20d87c0bcbb9efaba1a45592aef6073da0d87f0..90948f4b47d9e2120b8396214b9696b60848d25a 100644 (file)
@@ -1,3 +1,18 @@
+2007-11-10  Marek Habersack  <mhabersack@novell.com>
+
+       * 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  <mhabersack@novell.com>
 
        * Mono.MonoConfig/FeatureNodeHandler.cs: added support for feature
index 87948cbd0a1333c40de96bdde788323cb2ab6c32..05a64c6f8423076d015d69af94fc99b983338d5c 100644 (file)
@@ -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 <FeatureTarget> (Helpers.GetRequiredNonEmptyAttribute (nav, "target"), "target");
                        fileName = Helpers.GetOptionalAttribute (nav, "fileName");
                        
                        if (String.IsNullOrEmpty (fileName))
index 08cd51b1f9e876e399923b6a1f5adef4b9fa692f..9a2058555889237cc002c449ec14e7d25887cb32 100644 (file)
@@ -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 <FeatureTarget>  (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 (file)
index 0000000..38c4640
--- /dev/null
@@ -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 <ActionType> (val, "type");
+
+                       val = Helpers.GetRequiredNonEmptyAttribute (nav, "when");
+                       when = Helpers.ConvertEnum <ActionWhen> (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 ()
+               {
+               }
+       }
+}
index 46250a7b192780fee69f6d247a6d1d3c017fca08..30074ab55f1ecf3dd76e85eaf7e8b75b88cef4a3 100644 (file)
 //
 using System;
 using System.Collections.Generic;
-using System.IO;
 
 namespace Mono.MonoConfig
 {
        public class FeatureNode
        {
                List <FeatureBlock> blocks;
+               List <FeatureAction> actionsBefore;
+               List <FeatureAction> actionsAfter;
                string description;
-
+               
                public List <FeatureBlock> Blocks {
                        get {
                                if (blocks != null)
@@ -53,11 +54,22 @@ namespace Mono.MonoConfig
                                return String.Empty;
                        }
                }
+
+               public List <FeatureAction> ActionsBefore {
+                       get { return actionsBefore; }
+               }
+
+               public List <FeatureAction> ActionsAfter {
+                       get { return actionsAfter; }
+               }
                
-               public FeatureNode (List <FeatureBlock> blocks, string description)
+               public FeatureNode (List <FeatureBlock> blocks, string description,
+                                   List <FeatureAction> actionsBefore, List <FeatureAction> actionsAfter)
                {
                        this.blocks = blocks;
                        this.description = description;
+                       this.actionsBefore = actionsBefore;
+                       this.actionsAfter = actionsAfter;
                }
        }
 }
index a2bdfb4ffd0f282e0450ca986f23decfa723c758..0ee3a698b5297988c9556845f09f8f8737b02a40 100644 (file)
@@ -39,19 +39,23 @@ namespace Mono.MonoConfig
                string name;
                FeatureTarget target;
                List <FeatureBlock> blocks;
+               List <FeatureAction> actionsBefore;
+               List <FeatureAction> actionsAfter;
                Dictionary <string, FeatureNode> storage;
                StringBuilder description;
                
                public FeatureNodeHandler ()
                {
                        blocks = new List <FeatureBlock> ();
+                       actionsBefore = new List <FeatureAction> ();
+                       actionsAfter = new List <FeatureAction> ();
                        description = new StringBuilder ();
                }
                
                public void ReadConfiguration (XPathNavigator nav)
                {
                        name = Helpers.GetRequiredNonEmptyAttribute (nav, "name");
-                       target = Helpers.ConvertTarget (Helpers.GetRequiredNonEmptyAttribute (nav, "target"));
+                       target = Helpers.ConvertEnum <FeatureTarget> (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 <FeatureBlock> blocksClone = new List <FeatureBlock> (blocks.Count);
+                       List <FeatureAction> abc = new List <FeatureAction> (actionsBefore.Count);
+                       List <FeatureAction> aac = new List <FeatureAction> (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 <FeatureAction> 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 <FeatureBlock> 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 <FeatureAction> 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)
                {
index d68d3d78c61dbaaaece55c906d8efe02cd58b335..7755511a7871288cbdc6b1e2f87530be09d11e41 100644 (file)
@@ -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 <EnumType> (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)
                {
index 65ac73784e0b83e099c443238e1697db7f916a66..b149adef57df9b122cc705fbfc804f9c120ade2f 100644 (file)
@@ -192,7 +192,7 @@ namespace Mono.MonoConfig
                                                RequiredParameterMissing (argName);
                                        
                                        try {
-                                               Target = Helpers.ConvertTarget (argParam);
+                                               Target = Helpers.ConvertEnum <FeatureTarget> (argParam, "target");
                                        } catch (Exception ex) {
                                                OptionParameterError (argName, ex.Message);
                                        }
index 80221ce2e33ff75c463e4244bc3eac5b0752cb0e..70051b0bf666e814a3e359b0da547fb56933c06a 100644 (file)
@@ -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