source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/Ildasm.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 13.5 KB
Line 
1/*
2 * Copyright 2003-2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17package org.apache.tools.ant.taskdefs.optional.dotnet;
18
19import org.apache.tools.ant.types.EnumeratedAttribute;
20import org.apache.tools.ant.BuildException;
21import org.apache.tools.ant.Task;
22import org.apache.tools.ant.Project;
23import org.apache.tools.ant.util.FileUtils;
24
25import java.io.File;
26
27/**
28 * Task to take a .NET or Mono -generated managed executable and turn it
29 * into ILASM assembly code. Useful when converting imported typelibs into
30 * assembler before patching and recompiling, as one has to do when doing
31 * advanced typelib work.
32 * <p>
33 * As well as generating the named output file, the ildasm program
34 * will also generate resource files <code>Icons.resources</code>
35 * <code>Message.resources</code> and a .res file whose filename stub is derived
36 * from the source in ways to obscure to determine.
37 * There is no way to control whether or not these files are created, or where they are created
38 * (they are created in the current directory; their names come from inside the
39 * executable and may be those used by the original developer). This task
40 * creates the resources in the directory specified by <code>resourceDir</code> if
41 * set, else in the same directory as the <code>destFile</code>.
42 *
43 * <p>
44 * This task requires the .NET SDK installed and ildasm on the path.
45 * To disassemble using alternate CLR systems, set the executable attribute
46 * to the name/path of the alternate implementation -one that must
47 * support all the classic ildasm commands.
48 *
49 * <p>
50 * Dependency logic: the task executes the command if the output file is missing
51 * or older than the source file. It does not take into account changes
52 * in the options of the task, or timestamp differences in resource files.
53 * When the underlying ildasm executable fails for some reason, it leaves the
54 * .il file in place with some error message. To prevent this from confusing
55 * the dependency logic, the file specified by the <code>dest</code>
56 * attribute is <i>always</i> deleted after an unsuccessful build.
57 * @ant.task category="dotnet"
58 */
59public class Ildasm extends Task {
60
61 /**
62 * source file (mandatory)
63 */
64 private File sourceFile;
65
66 /**
67 * dest file (mandatory)
68 */
69 private File destFile;
70 /**
71 * progress bar switch
72 */
73 private boolean progressBar = false;
74
75 /**
76 * what is our encoding
77 */
78 private String encoding;
79
80 /**
81 * /bytes flag for byte markup
82 */
83
84 private boolean bytes = false;
85
86 /**
87 * line numbers? /linenum
88 */
89 private boolean linenumbers = false;
90
91 /**
92 * /raweh flag for raw exception handling
93 */
94 private boolean rawExceptionHandling = false;
95
96 /**
97 * show the source; /source
98 */
99 private boolean showSource = false;
100
101 /**
102 * /quoteallnames to quote all names
103 */
104 private boolean quoteallnames = false;
105
106 /**
107 * /header for header information
108 */
109 private boolean header = false;
110
111 /**
112 * when false, sets the /noil attribute
113 * to suppress assembly info
114 */
115 private boolean assembler = true;
116
117 /**
118 * include metadata
119 * /tokens
120 */
121
122 private boolean metadata = false;
123
124 /**
125 * what visibility do we want.
126 *
127 */
128 private String visibility;
129
130 /**
131 * specific item to disassemble
132 */
133
134 private String item;
135
136 /**
137 * override for the executable
138 */
139 private String executable = "ildasm";
140
141 /**
142 * name of the directory for resources to be created. We cannot control
143 * their names, but we can say where they get created. If not set, the
144 * directory of the dest file is used
145 */
146 private File resourceDir;
147
148
149 /**
150 * Set the name of the directory for resources to be created. We cannot control
151 * their names, but we can say where they get created. If not set, the
152 * directory of the dest file is used
153 */
154 public void setResourceDir(File resourceDir) {
155 this.resourceDir = resourceDir;
156 }
157
158 /**
159 * override the name of the executable (normally ildasm) or set
160 * its full path. Do not set a relative path, as the ugly hacks
161 * needed to create resource files in the dest directory
162 * force us to change to this directory before running the application.
163 * i.e use &lt;property location&gt to create an absolute path from a
164 * relative one before setting this value.
165 * @param executable
166 */
167 public void setExecutable(String executable) {
168 this.executable = executable;
169 }
170
171 /**
172 * Select the output encoding: ascii, utf8 or unicode
173 * @param encoding
174 */
175 public void setEncoding(EncodingTypes encoding) {
176 this.encoding = encoding.getValue();
177 }
178
179 /**
180 * enable (default) or disable assembly language in the output
181 * @param assembler
182 */
183 public void setAssembler(boolean assembler) {
184 this.assembler = assembler;
185 }
186
187 /**
188 * enable or disable (default) the original bytes as comments
189 * @param bytes
190 */
191 public void setBytes(boolean bytes) {
192 this.bytes = bytes;
193 }
194
195 /**
196 * the output file (required)
197 * @param destFile
198 */
199 public void setDestFile(File destFile) {
200 this.destFile = destFile;
201 }
202
203 /**
204 * include header information; default false.
205 * @param header
206 */
207 public void setHeader(boolean header) {
208 this.header = header;
209 }
210
211 /**
212 * name a single item to decode; a class or a method
213 * e.g item="Myclass::method" or item="namespace1::namespace2::Myclass:method(void(int32))
214 * @param item
215 */
216 public void setItem(String item) {
217 this.item = item;
218 }
219
220 /**
221 * include line number information; default=false
222 * @param linenumbers
223 */
224 public void setLinenumbers(boolean linenumbers) {
225 this.linenumbers = linenumbers;
226 }
227
228 /**
229 * include metadata information
230 * @param metadata
231 */
232 public void setMetadata(boolean metadata) {
233 this.metadata = metadata;
234 }
235
236 /**
237 * show a graphical progress bar in a window during the process; off by default
238 * @param progressBar
239 */
240 public void setProgressBar(boolean progressBar) {
241 this.progressBar = progressBar;
242 }
243
244 /**
245 * quote all names.
246 * @param quoteallnames
247 */
248 public void setQuoteallnames(boolean quoteallnames) {
249 this.quoteallnames = quoteallnames;
250 }
251
252 /**
253 * enable raw exception handling (default = false)
254 * @param rawExceptionHandling
255 */
256 public void setRawExceptionHandling(boolean rawExceptionHandling) {
257 this.rawExceptionHandling = rawExceptionHandling;
258 }
259
260 /**
261 * include the source as comments (default=false)
262 */
263 public void setShowSource(boolean showSource) {
264 this.showSource = showSource;
265 }
266
267 /**
268 * the file to disassemble -required
269 * @param sourceFile
270 */
271 public void setSourceFile(File sourceFile) {
272 this.sourceFile = sourceFile;
273 }
274
275 /**
276 * alternate name for sourceFile
277 * @param sourceFile
278 */
279 public void setSrcFile(File sourceFile) {
280 setSourceFile(sourceFile);
281 }
282 /**
283 * This method sets the visibility options. It chooses one or more of the following, with + signs to
284 * concatenate them:
285 * <pre>
286 * pub : Public
287 * pri : Private
288 * fam : Family
289 * asm : Assembly
290 * faa : Family and Assembly
291 * foa : Family or Assembly
292 * psc : Private Scope
293 *</pre>
294 * e.g. visibility="pub+pri".
295 * Family means <code>protected</code> in C#;
296 * @param visibility
297 */
298 public void setVisibility(String visibility) {
299 this.visibility = visibility;
300 }
301
302 /**
303 * verify that source and dest are ok
304 */
305 private void validate() {
306 if (sourceFile == null || !sourceFile.exists() || !sourceFile.isFile()) {
307 throw new BuildException("invalid source");
308 }
309 if (destFile == null || destFile.isDirectory()) {
310 throw new BuildException("invalid dest");
311 }
312 if (resourceDir != null
313 && (!resourceDir.exists() || !resourceDir.isDirectory())) {
314 throw new BuildException("invalid resource directory");
315 }
316 }
317
318 /**
319 * Test for disassembly being needed; use existence and granularity
320 * correct date stamps
321 * @return true iff a rebuild is required.
322 */
323 private boolean isDisassemblyNeeded() {
324 if (!destFile.exists()) {
325 log("Destination file does not exist: a build is required",
326 Project.MSG_VERBOSE);
327 return true;
328 }
329 long sourceTime = sourceFile.lastModified();
330 long destTime = destFile.lastModified();
331 if(sourceTime > (destTime + FileUtils.newFileUtils().getFileTimestampGranularity())) {
332 log("Source file is newer than the dest file: a rebuild is required",
333 Project.MSG_VERBOSE);
334 return true;
335 } else {
336 log("The .il file is up to date", Project.MSG_VERBOSE);
337 return false;
338 }
339
340 }
341 /**
342 * do the work
343 * @throws BuildException
344 */
345 public void execute() throws BuildException {
346 validate();
347 if(!isDisassemblyNeeded()) {
348 return;
349 }
350 NetCommand command = new NetCommand(this, "ildasm", executable);
351 command.setFailOnError(true);
352 //fill in args
353 command.addArgument("/text");
354 command.addArgument("/out=" + destFile.toString());
355 if (!progressBar) {
356 command.addArgument("/nobar");
357 }
358 if (linenumbers) {
359 command.addArgument("/linenum");
360 }
361 if (showSource) {
362 command.addArgument("/source");
363 }
364 if (quoteallnames) {
365 command.addArgument("/quoteallnames");
366 }
367 if (header) {
368 command.addArgument("/header");
369 }
370 if (!assembler) {
371 command.addArgument("/noil");
372 }
373 if (metadata) {
374 command.addArgument("/tokens");
375 }
376 command.addArgument("/item:", item);
377 if (rawExceptionHandling) {
378 command.addArgument("/raweh");
379 }
380 command.addArgument(EncodingTypes.getEncodingOption(encoding));
381 if (bytes) {
382 command.addArgument("/bytes");
383 }
384 command.addArgument("/vis:", visibility);
385
386 //add the source file
387 command.addArgument(sourceFile.getAbsolutePath());
388
389 //determine directory: resourceDir if set,
390 //the dir of the destFile if not
391 File execDir = resourceDir;
392 if (execDir == null) {
393 execDir = destFile.getParentFile();
394 }
395 command.setDirectory(execDir);
396
397 //now run
398 try {
399 command.runCommand();
400 } catch (BuildException e) {
401 //forcibly delete the output file in case of trouble
402 if (destFile.exists()) {
403 log("Deleting destination file as it may be corrupt");
404 destFile.delete();
405 }
406 //then rethrow the exception
407 throw e;
408 }
409
410 }
411
412 /**
413 * encoding options; the default is ascii
414 */
415 public static class EncodingTypes extends EnumeratedAttribute {
416 public final static String UNICODE = "unicode";
417 public final static String UTF8 = "utf8";
418 public final static String ASCII = "ascii";
419 public String[] getValues() {
420 return new String[]{
421 ASCII,
422 UTF8,
423 UNICODE,
424 };
425 }
426
427 /**
428 * This method maps from an encoding enum to an encoding option.
429 * @param enumValue
430 * @return The encoding option indicated by the enum value.
431 */
432 public static String getEncodingOption(String enumValue) {
433 if (UNICODE.equals(enumValue)) {
434 return "/unicode";
435 }
436 if (UTF8.equals(enumValue)) {
437 return "/utf8";
438 }
439 return null;
440 }
441 }
442
443 /**
444 * visibility options for decoding
445 */
446 public static class VisibilityOptions extends EnumeratedAttribute {
447 public String[] getValues() {
448 return new String[]{
449 "pub", //Public
450 "pri", //Private
451 "fam", //Family
452 "asm", //Assembly
453 "faa", //Family and Assembly
454 "foa", //Family or Assembly
455 "psc", //Private Scope
456 };
457 }
458
459 }
460}
Note: See TracBrowser for help on using the repository browser.