* GenerateResource.cs (CompileResourceFile): Check File.Exists
[mono.git] / mcs / class / Microsoft.Build.Tasks / Microsoft.Build.Tasks / GenerateResource.cs
1 //
2 // GenerateResource.cs: Task that generates the resources.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //   Paolo Molaro (lupus@ximian.com)
7 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 //
9 // (C) 2005 Marek Sieradzki
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 #if NET_2_0
31
32 using System;
33 using System.Text;
34 using System.IO;
35 using System.Collections;
36 using System.Collections.Generic;
37 using System.Resources;
38 using System.Reflection;
39 using Microsoft.Build.Framework;
40 using Microsoft.Build.Utilities;
41 using Mono.XBuild.Tasks.GenerateResourceInternal;
42
43 namespace Microsoft.Build.Tasks {
44         public sealed class GenerateResource : TaskExtension {
45         
46                 ITaskItem[]     filesWritten;
47                 bool            neverLockTypeAssemblies;
48                 ITaskItem[]     outputResources;
49                 bool            publicClass;
50                 ITaskItem[]     references;
51                 ITaskItem[]     sources;
52                 ITaskItem       stateFile;
53                 string          stronglyTypedClassName;
54                 string          stronglyTypedFilename;
55                 string          stronglyTypedLanguage;
56                 string          stronglyTypedNamespace;
57                 bool            useSourcePath;
58                 
59                 public GenerateResource ()
60                 {
61                         useSourcePath = false;
62                 }
63
64                 public override bool Execute ()
65                 {
66                         if (sources.Length == 0)
67                                 return true;
68
69                         bool result = true;
70                         List  <ITaskItem> temporaryFilesWritten = new List <ITaskItem> ();
71                         if (outputResources == null) {
72                                 foreach (ITaskItem source in sources) {
73                                         string sourceFile = source.ItemSpec;
74                                         string outputFile = Path.ChangeExtension (sourceFile, "resources");
75
76                                         result &= CompileResourceFile (sourceFile, outputFile);
77
78                                         ITaskItem newItem = new TaskItem (source);
79                                         source.ItemSpec = outputFile;
80
81                                         temporaryFilesWritten.Add (newItem);
82                                 }
83                         } else {
84                                 if (sources.Length != outputResources.Length) {
85                                         Log.LogError ("Sources count is different than OutputResources count.");
86                                         return false;
87                                 }
88
89                                 for (int i = 0; i < sources.Length; i ++) {
90                                         if (String.IsNullOrEmpty (outputResources [i].ItemSpec)) {
91                                                 Log.LogError ("Filename of output can not be empty.");
92                                                 result = false;
93                                                 continue;
94                                         }
95
96                                         result &= CompileResourceFile (sources [i].ItemSpec, outputResources [i].ItemSpec);
97                                         temporaryFilesWritten.Add (outputResources [i]);
98                                 }
99                         }
100                         
101                         filesWritten = temporaryFilesWritten.ToArray ();
102
103                         return result;
104                 }
105                 
106 #if false
107                 private IResourceReader GetReader (Stream stream, string name)
108                 {
109                         string format = Path.GetExtension (name);
110                         switch (format.ToLower ()) {
111                         case ".po":
112                                 return new PoResourceReader (stream);
113                         case ".txt":
114                         case ".text":
115                                 return new TxtResourceReader (stream);
116                         case ".resources":
117                                 return new ResourceReader (stream);
118                         case ".resx":
119                                 ResXResourceReader reader = new ResXResourceReader (stream);
120
121                                 // set correct basepath to resolve relative paths in file refs
122                                 if (useSourcePath)
123                                         reader.BasePath = Path.GetDirectoryName (Path.GetFullPath (name));
124
125                                 return reader;
126                         default:
127                                 throw new Exception ("Unknown format in file " + name);
128                         }
129                 }
130                 
131                 private IResourceWriter GetWriter (Stream stream, string name)
132                 {
133                         string format = Path.GetExtension (name);
134                         switch (format.ToLower ()) {
135                         case ".po":
136                                 return new PoResourceWriter (stream);
137                         case ".txt":
138                         case ".text":
139                                 return new TxtResourceWriter (stream);
140                         case ".resources":
141                                 return new ResourceWriter (stream);
142                         case ".resx":
143                                 return new System.Resources.ResXResourceWriter (stream);
144                         default:
145                                 throw new Exception ("Unknown format in file " + name);
146                         }
147                 }
148 #endif
149                 
150                 private bool CompileResourceFile (string sname, string dname )
151                 {
152                         if (!File.Exists (sname)) {
153                                 Log.LogError ("Resource file '{0}' not found.", sname);
154                                 return false;
155                         }
156
157                         if (File.GetLastWriteTime (sname) <= File.GetLastWriteTime (dname)) {
158                                 Log.LogMessage (MessageImportance.Low,
159                                                 "Resource file '{0}' is newer than the source file '{1}', skipping.",
160                                                 dname, sname);
161                                 return true;
162                         }
163
164                         Resgen resgen = new Resgen ();
165                         resgen.BuildEngine = this.BuildEngine;
166                         resgen.UseSourcePath = true;
167
168                         resgen.SourceFile = sname;
169                         resgen.OutputFile = dname;
170
171                         return resgen.Execute ();
172                 }
173
174                 [Output]
175                 public ITaskItem[] FilesWritten {
176                         get {
177                                 return filesWritten;
178                         }
179                 }
180
181                 [MonoTODO]
182                 public bool NeverLockTypeAssemblies {
183                         get {
184                                 return neverLockTypeAssemblies;
185                         }
186                         set {
187                                 neverLockTypeAssemblies = value;
188                         }
189                 }
190
191                 [Output]
192                 public ITaskItem[] OutputResources {
193                         get {
194                                 return outputResources;
195                         }
196                         set {
197                                 outputResources = value;
198                         }
199                 }
200                 
201                 public bool PublicClass {
202                         get { return publicClass; }
203                         set { publicClass = value; }
204                 }
205
206                 public ITaskItem[] References {
207                         get {
208                                 return references;
209                         }
210                         set {
211                                 references = value;
212                         }
213                 }
214
215                 [Required]
216                 public ITaskItem[] Sources {
217                         get {
218                                 return sources;
219                         }
220                         set {
221                                 sources = value;
222                         }
223                 }
224
225                 public ITaskItem StateFile {
226                         get {
227                                 return stateFile;
228                         }
229                         set {
230                                 stateFile = value;
231                         }
232                 }
233
234                 [Output]
235                 public string StronglyTypedClassName {
236                         get {
237                                 return stronglyTypedClassName;
238                         }
239                         set {
240                                 stronglyTypedClassName = value;
241                         }
242                 }
243
244                 [Output]
245                 public string StronglyTypedFileName {
246                         get {
247                                 return stronglyTypedFilename;
248                         }
249                         set {
250                                 stronglyTypedFilename = value;
251                         }
252                 }
253
254                 public string StronglyTypedLanguage {
255                         get {
256                                 return stronglyTypedLanguage;
257                         }
258                         set {
259                                 stronglyTypedLanguage = value;
260                         }
261                 }
262
263                 public string StronglyTypedNamespace {
264                         get {
265                                 return stronglyTypedNamespace;
266                         }
267                         set {
268                                 stronglyTypedNamespace = value;
269                         }
270                 }
271
272                 public bool UseSourcePath {
273                         get {
274                                 return useSourcePath;
275                         }
276                         set {
277                                 useSourcePath = value;
278                         }
279                 }
280         }
281
282         class Resgen : ToolTaskExtension
283         {
284                 public Resgen ()
285                 {
286                 }
287
288                 protected internal override void AddCommandLineCommands (
289                                                  CommandLineBuilderExtension commandLine)
290                 {
291                         if (UseSourcePath)
292                                 commandLine.AppendSwitch ("/useSourcePath");
293
294                         commandLine.AppendSwitch (String.Format ("/compile {0}{1}", SourceFile,
295                                                 OutputFile != null ? "," + OutputFile : ""));
296                 }
297
298                 public override bool Execute ()
299                 {
300                         EnvironmentOverride ["MONO_IOMAP"] = "drive";
301                         return base.Execute ();
302                 }
303
304                 protected override string GenerateFullPathToTool ()
305                 {
306                         return Path.Combine (ToolPath, ToolExe);
307                 }
308
309                 protected override MessageImportance StandardOutputLoggingImportance {
310                         get { return MessageImportance.Low; }
311                 }
312
313                 protected override string ToolName {
314                         get { return Utilities.RunningOnWindows ? "resgen2.bat" : "resgen2"; }
315                 }
316
317                 public string SourceFile { get; set; }
318                 public string OutputFile { get; set; }
319
320                 public bool UseSourcePath { get; set; }
321         }
322 }
323
324 #endif