[System.Net] Add support for .pac proxy config scripts on mac
[mono.git] / mcs / class / Microsoft.Build.Tasks / Microsoft.Build.Tasks / Exec.cs
1 //
2 // Exec.cs: Task that executes commands.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //   Ankit Jain (jankit@novell.com)
7 //
8 // (C) 2005 Marek Sieradzki
9 // Copyright 2009 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 using System;
31 using System.Collections;
32 using System.Collections.Specialized;
33 using System.Diagnostics;
34 using System.IO;
35 using System.Text;
36 using System.Text.RegularExpressions;
37 using System.Threading;
38 using Microsoft.Build.Framework;
39 using Microsoft.Build.Utilities;
40
41 namespace Microsoft.Build.Tasks {
42         public class Exec : ToolTaskExtension {
43         
44                 string          command;
45                 bool            ignoreExitCode;
46                 ITaskItem[]     outputs;
47                 string          stdErrEncoding;
48                 string          stdOutEncoding;
49                 string          workingDirectory;
50                 string scriptFile;
51
52 #if NET_4_0
53                 Func<string, bool> errorMatcher, warningMatcher;
54 #endif
55                 
56                 public Exec ()
57                 {
58                         ignoreExitCode = false;
59                 }
60                 
61                 protected internal override void AddCommandLineCommands (CommandLineBuilderExtension commandLine)
62                 {
63                         if (IsRunningOnWindows)
64                                 commandLine.AppendSwitch ("/q /c");
65
66                         if (!String.IsNullOrEmpty (command)) {
67                                 scriptFile = Path.GetTempFileName ();
68                                 if (IsRunningOnWindows)
69                                         scriptFile = scriptFile + ".bat";
70                                 using (StreamWriter sw = new StreamWriter (scriptFile)) {
71                                         sw.Write (command);
72                                 }
73                                 commandLine.AppendFileNameIfNotNull (scriptFile);
74                         }
75                         base.AddCommandLineCommands (commandLine);
76                 }
77
78                 protected override int ExecuteTool (string pathToTool,
79                                                     string responseFileCommands,
80                                                     string commandLineCommands)
81                 {
82                         try {
83 #if NET_4_0
84                                 errorMatcher = GetTryMatchRegexFunc (CustomErrorRegularExpression, true);
85                                 warningMatcher = GetTryMatchRegexFunc (CustomWarningRegularExpression, false);
86 #endif
87                                 return base.ExecuteTool (pathToTool, responseFileCommands, commandLineCommands);
88                         } finally {
89                                 if (scriptFile != null)
90                                         DeleteTempFile (scriptFile);
91                         }
92                 }
93
94                 [MonoTODO]
95                 protected override string GenerateFullPathToTool ()
96                 {
97                         return IsRunningOnWindows ? "cmd.exe" : "sh";
98                 }
99                 
100                 protected override string GetWorkingDirectory ()
101                 {
102                         return workingDirectory;
103                 }
104                 
105                 protected override bool HandleTaskExecutionErrors ()
106                 {
107                         if (ExitCode != 0)
108                                 Log.LogError ("Command '{0}' exited with code: {1}.", Command, ExitCode);
109
110                         return ExitCode == 0 || ignoreExitCode;
111                 }
112                 
113                 [MonoTODO]
114                 protected override void LogPathToTool (string toolName,
115                                                        string pathToTool)
116                 {
117                 }
118                 
119                 [MonoTODO]
120                 protected override void LogToolCommand (string message)
121                 {
122                         Log.LogMessage (MessageImportance.Normal, "Executing: " + command);
123                 }
124                 
125                 protected override void LogEventsFromTextOutput (string singleLine, MessageImportance importance)
126                 {
127 #if NET_4_0
128                         if (IgnoreStandardErrorWarningFormat ||
129                                 (!errorMatcher (singleLine) && !warningMatcher (singleLine)))
130 #endif
131                                 Log.LogMessage (importance, singleLine);
132                 }
133
134 #if NET_4_0
135                 // @is_error_type - log as errors, else warnings
136                 Func<string, bool> GetTryMatchRegexFunc (string regex_str, bool is_error_type)
137                 {
138                         bool is_bad = false;
139                         Regex regex = null;
140                         return (singleLine) => {
141                                 if (String.IsNullOrEmpty (regex_str) || is_bad)
142                                         return false;
143
144                                 try {
145                                         if (regex == null)
146                                                 regex = new Regex (regex_str, RegexOptions.Compiled);
147                                 } catch (ArgumentException ae) {
148                                         Log.LogError ("The regular expression specified for '{0}' is invalid : {1}",
149                                                         is_error_type ? "errors" : "warnings", ae.Message);
150                                         Log.LogMessage (MessageImportance.Low, "The regular expression specified for '{0}' is invalid : {1}",
151                                                         is_error_type ? "errors" : "warnings", ae.ToString ());
152
153                                         is_bad = true;
154                                         return false;
155                                 }
156
157                                 if (!regex.Match (singleLine).Success)
158                                         return false;
159
160                                 if (is_error_type)
161                                         Log.LogError (singleLine);
162                                 else
163                                         Log.LogWarning (singleLine);
164                                 return true;
165                         };
166                 }
167 #endif
168
169                 [MonoTODO]
170                 protected override bool ValidateParameters ()
171                 {
172                         return true;
173                 }
174                 
175                 [Required]
176                 public string Command {
177                         get { return command; }
178                         set {
179                                 command = value;
180                                 if (Path.DirectorySeparatorChar == '/')
181                                         command = command.Replace ("\r\n", "\n");
182                         }
183                 }
184
185                 public bool IgnoreExitCode {
186                         get { return ignoreExitCode; }
187                         set { ignoreExitCode = value; }
188                 }
189
190                 [Output]
191                 public ITaskItem[] Outputs {
192                         get { return outputs; }
193                         set { outputs = value; }
194                 }
195
196                 protected override Encoding StandardErrorEncoding {
197                         get { return base.StandardErrorEncoding; }
198                 }
199                 
200                 protected override MessageImportance StandardErrorLoggingImportance {
201                         get { return base.StandardErrorLoggingImportance; }
202                 }
203
204                 protected override Encoding StandardOutputEncoding {
205                         get { return base.StandardOutputEncoding; }
206                 }
207                 
208                 protected override MessageImportance StandardOutputLoggingImportance {
209                         get { return base.StandardOutputLoggingImportance; }
210                 }
211
212 #if NET_4_0
213                 public bool IgnoreStandardErrorWarningFormat { get; set; }
214
215                 public string CustomErrorRegularExpression { get; set; }
216
217                 public string CustomWarningRegularExpression { get; set; }
218 #endif
219                 
220                 [MonoTODO]
221                 [Output]
222                 public string StdOutEncoding {
223                         get { return stdOutEncoding; }
224                         set { stdOutEncoding = value; }
225                 }
226                 
227                 [MonoTODO]
228                 [Output]
229                 public string StdErrEncoding {
230                         get { return stdErrEncoding; }
231                         set { stdErrEncoding = value; }
232                 }
233                 
234                 [MonoTODO]
235                 protected override string ToolName {
236                         get { return String.Empty; }
237                 }
238
239                 public string WorkingDirectory {
240                         get { return workingDirectory; }
241                         set { workingDirectory = value; }
242                 }
243
244                 static bool IsRunningOnWindows {
245                         get {
246                                 PlatformID pid = Environment.OSVersion.Platform;
247                                 return ((int) pid != 128 && (int) pid != 4 && (int) pid != 6);
248                         }
249                 }
250
251         }
252 }