2007-11-10 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / tools / mconfig / Mono.MonoConfig / FeatureAction.cs
1 //
2 // Authors:
3 //   Marek Habersack (mhabersack@novell.com)
4 //
5 // (C) 2007 Novell, Inc
6 //
7
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections.Generic;
30 using System.ComponentModel;
31 using System.Diagnostics;
32 using System.IO;
33 using System.Text;
34 using System.Xml;
35 using System.Xml.XPath;
36
37 namespace Mono.MonoConfig
38 {
39         public enum ActionType
40         {
41                 Message,
42                 ShellScript,
43                 Exec
44         }
45
46         public enum ActionWhen
47         {
48                 Before,
49                 After
50         }
51         
52         public class FeatureAction
53         {
54                 ActionType type;
55                 ActionWhen when;
56                 string command;
57                 string commandArguments;
58                 string message;
59                 string script;
60                 
61                 public ActionWhen When {
62                         get { return when; }
63                 }
64                 
65                 public FeatureAction (XPathNavigator nav)
66                 {
67                         string val = Helpers.GetRequiredNonEmptyAttribute (nav, "type");
68                         type = Helpers.ConvertEnum <ActionType> (val, "type");
69
70                         val = Helpers.GetRequiredNonEmptyAttribute (nav, "when");
71                         when = Helpers.ConvertEnum <ActionWhen> (val, "when");
72
73                         XPathNodeIterator iter;
74                         StringBuilder sb = new StringBuilder ();
75                         
76                         switch (type) {
77                                 case ActionType.Message:
78                                 case ActionType.ShellScript:
79                                         iter = nav.Select ("./text()");
80                                         while (iter.MoveNext ())
81                                                 sb.Append (iter.Current.Value);
82                                         if (type == ActionType.Message)
83                                                 message = sb.ToString ();
84                                         else
85                                                 script = sb.ToString ();
86                                         break;
87                                         
88                                 case ActionType.Exec:
89                                         command = Helpers.GetRequiredNonEmptyAttribute (nav, "command");
90                                         commandArguments = Helpers.GetOptionalAttribute (nav, "commndArguments");
91                                         break;
92                         }
93                 }
94
95                 public void Execute ()
96                 {
97                         switch (type) {
98                                 case ActionType.Message:
99                                         ExecuteMessage ();
100                                         break;
101
102                                 case ActionType.ShellScript:
103                                         ExecuteShellScript ();
104                                         break;
105
106                                 case ActionType.Exec:
107                                         ExecuteExec ();
108                                         break;
109                         }
110                 }
111
112                 void ExecuteMessage ()
113                 {
114                         if (String.IsNullOrEmpty (message))
115                                 return;
116
117                         string[] lines = message.Split ('\n');
118                         string line;
119                         int maxLineWidth = Console.WindowWidth;
120                         StringBuilder sb = new StringBuilder ();
121                         
122                         foreach (string l in lines) {
123                                 if (l.Length == 0) {
124                                         sb.Append ("\n");
125                                         continue;
126                                 }
127                                 
128                                 line = l.Trim ();
129                                 if (line.Length > maxLineWidth)
130                                         sb.AppendFormat ("{0}\n", Helpers.BreakLongLine (line, String.Empty, maxLineWidth));
131                                 else
132                                         sb.AppendFormat ("{0}{1}\n", String.Empty, line);
133                         }
134                         Console.WriteLine (sb.ToString ());
135                 }
136
137                 void ExecuteShellScript ()
138                 {
139                         if (String.IsNullOrEmpty (script))
140                                 return;
141
142                         string script_temp = Path.GetTempFileName ();
143                         StreamWriter s = null;
144                         try {
145                                 s = new StreamWriter (script_temp);
146                                 s.Write (script);
147                                 
148                                 Process p = new Process ();
149                                 ProcessStartInfo pinfo = p.StartInfo;
150
151                                 pinfo.UseShellExecute = false;
152                                 pinfo.RedirectStandardOutput = true;
153                                 pinfo.RedirectStandardError = true;
154                                 pinfo.FileName = "/bin/bash";
155                                 pinfo.Arguments = script_temp;
156                                 p.Start ();
157
158                                 string stdout = p.StandardOutput.ReadToEnd ();
159                                 string stderr = p.StandardError.ReadToEnd ();
160                                 p.WaitForExit ();
161
162                                 if (p.ExitCode != 0) {
163                                         Console.Error.Write (stderr);
164                                         throw new ApplicationException (
165                                                 String.Format ("Script signalled failure code: {0}", p.ExitCode));
166                                 }
167                                 
168                                 Console.Write (stdout);
169                                 p.Close ();
170                         } catch (Exception ex) {
171                                 Console.WriteLine (ex);
172                                 throw new ApplicationException ("Error executing feature shell action.", ex);
173                         } finally {
174                                 if (s != null)
175                                         s.Close ();
176                                 try {
177                                         File.Delete (script_temp);
178                                 } catch (Exception) {
179                                         // ignore
180                                 }
181                         }
182                 }
183
184                 void ExecuteExec ()
185                 {
186                 }
187         }
188 }