alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Ant example source code file (Ildasm.java)

This example Ant source code file (Ildasm.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Ant tags/keywords

ascii, assembly, assembly, buildexception, buildexception, enumeratedattribute, family, file, file, io, netcommand, private, string, string, utf8

The Ildasm.java source code

/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package org.apache.tools.ant.taskdefs.optional.dotnet;

import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.FileUtils;

import java.io.File;

/**
 * Task to take a .NET or Mono -generated managed executable and turn it
 * into ILASM assembly code. Useful when converting imported typelibs into
 * assembler before patching and recompiling, as one has to do when doing
 * advanced typelib work.
 * <p>
 * As well as generating the named output file, the ildasm program
 * will also generate resource files <code>Icons.resources
 * <code>Message.resources and a .res file whose filename stub is derived
 * from the source in ways to obscure to determine.
 * There is no way to control whether or not these files are created, or where they are created
 * (they are created in the current directory; their names come from inside the
 * executable and may be those used by the original developer). This task
 * creates the resources in the directory specified by <code>resourceDir if
 * set, else in the same directory as the <code>destFile.
 *
 * <p>
 * This task requires the .NET SDK installed and ildasm on the path.
 * To disassemble using alternate CLR systems, set the executable attribute
 * to the name/path of the alternate implementation -one that must
 * support all the classic ildasm commands.
 *
 * <p>
 * Dependency logic: the task executes the command if the output file is missing
 * or older than the source file. It does not take into account changes
 * in the options of the task, or timestamp differences in resource files.
 * When the underlying ildasm executable fails for some reason, it leaves the
 * .il file in place with some error message. To prevent this from confusing
 * the dependency logic, the file specified by the <code>dest
 * attribute is <i>always deleted after an unsuccessful build.
 * @ant.task category="dotnet"
 */
public class Ildasm extends Task {

    private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

    /**
     * source file (mandatory)
     */
    private File sourceFile;

    /**
     * dest file (mandatory)
     */
    private File destFile;
    /**
     * progress bar switch
     */
    private boolean progressBar = false;

    /**
     * what is our encoding
     */
    private String encoding;

    /**
     * /bytes flag for byte markup
     */

    private boolean bytes = false;

    /**
     * line numbers? /linenum
     */
    private boolean linenumbers = false;

    /**
     * /raweh flag for raw exception handling
     */
    private boolean rawExceptionHandling = false;

    /**
     * show the source; /source
     */
    private boolean showSource = false;

    /**
     * /quoteallnames to quote all names
     */
    private boolean quoteallnames = false;

    /**
     * /header for header information
     */
    private boolean header = false;

    /**
     * when false, sets the /noil attribute
     * to suppress assembly info
     */
    private boolean assembler = true;

    /**
     * include metadata
     * /tokens
     */

    private boolean metadata = false;

    /**
     * what visibility do we want.
     *
     */
    private String visibility;

    /**
     * specific item to disassemble
     */

    private String item;

    /**
     * override for the executable
     */
    private String executable = "ildasm";

    /**
     *  name of the directory for resources to be created. We cannot control
     * their names, but we can say where they get created. If not set, the
     * directory of the dest file is used
     */
    private File resourceDir;


    /**
     * Set the name of the directory for resources to be created. We cannot control
     * their names, but we can say where they get created. If not set, the
     * directory of the dest file is used
     * @param resourceDir the directory in which to create resources.
     */
    public void setResourceDir(File resourceDir) {
        this.resourceDir = resourceDir;
    }

    /**
     * override the name of the executable (normally ildasm) or set
     * its full path. Do not set a relative path, as the ugly hacks
     * needed to create resource files in the dest directory
     * force us to change to this directory before running the application.
     * i.e use <property location> to create an absolute path from a
     * relative one before setting this value.
     * @param executable the name of the executable to use.
     */
    public void setExecutable(String executable) {
        this.executable = executable;
    }

    /**
     * Select the output encoding: ascii, utf8 or unicode
     * @param encoding the enumerated value.
     */
    public void setEncoding(EncodingTypes encoding) {
        this.encoding = encoding.getValue();
    }

    /**
     * enable (default) or disable assembly language in the output
     * @param assembler a <code>boolean value.
     */
    public void setAssembler(boolean assembler) {
        this.assembler = assembler;
    }

    /**
     * enable or disable (default) the original bytes as comments
     * @param bytes a <code>boolean value.
     */
    public void setBytes(boolean bytes) {
        this.bytes = bytes;
    }

    /**
     * the output file (required)
     * @param destFile the destination file.
     */
    public void setDestFile(File destFile) {
        this.destFile = destFile;
    }

    /**
     * include header information; default false.
     * @param header a <code>boolean value.
     */
    public void setHeader(boolean header) {
        this.header = header;
    }

    /**
     * name a single item to decode; a class or a method
     * e.g item="Myclass::method" or item="namespace1::namespace2::Myclass:method(void(int32))
     * @param item the item to decode.
     */
    public void setItem(String item) {
        this.item = item;
    }

    /**
     * include line number information; default=false
     * @param linenumbers a <code>boolean value.
     */
    public void setLinenumbers(boolean linenumbers) {
        this.linenumbers = linenumbers;
    }

    /**
     * include metadata information
     * @param metadata a <code>boolean value.
     */
    public void setMetadata(boolean metadata) {
        this.metadata = metadata;
    }

    /**
     * show a graphical progress bar in a window during the process; off by default
     * @param progressBar a <code>boolean value.
     */
    public void setProgressBar(boolean progressBar) {
        this.progressBar = progressBar;
    }

    /**
     * quote all names.
     * @param quoteallnames a <code>boolean value.
     */
    public void setQuoteallnames(boolean quoteallnames) {
        this.quoteallnames = quoteallnames;
    }

    /**
     * enable raw exception handling (default = false)
     * @param rawExceptionHandling a <code>boolean value.
     */
    public void setRawExceptionHandling(boolean rawExceptionHandling) {
        this.rawExceptionHandling = rawExceptionHandling;
    }

    /**
     * include the source as comments (default=false)
     * @param showSource a <code>boolean value.
     */
    public void setShowSource(boolean showSource) {
        this.showSource = showSource;
    }

    /**
     * the file to disassemble -required
     * @param sourceFile the file to disassemble.
     */
    public void setSourceFile(File sourceFile) {
        this.sourceFile = sourceFile;
    }

    /**
     * alternate name for sourceFile
     * @param sourceFile the source file.
     */
    public void setSrcFile(File sourceFile) {
        setSourceFile(sourceFile);
    }
    /**
     * This method sets the visibility options. It chooses one
     * or more of the following, with + signs to concatenate them:
     * <pre>
     * pub : Public
     * pri : Private
     * fam : Family
     * asm : Assembly
     * faa : Family and Assembly
     * foa : Family or Assembly
     * psc : Private Scope
     *</pre>
     * e.g. visibility="pub+pri".
     * Family means <code>protected in C#;
     * @param visibility the options to use.
     */
    public void setVisibility(String visibility) {
        this.visibility = visibility;
    }

    /**
     *  verify that source and dest are ok
     */
    private void validate() {
        if (sourceFile == null || !sourceFile.exists() || !sourceFile.isFile()) {
            throw new BuildException("invalid source");
        }
        if (destFile == null || destFile.isDirectory()) {
            throw new BuildException("invalid dest");
        }
        if (resourceDir != null
                && (!resourceDir.exists() || !resourceDir.isDirectory())) {
            throw new BuildException("invalid resource directory");
        }
    }

    /**
     * Test for disassembly being needed; use existence and granularity
     * correct date stamps
     * @return true iff a rebuild is required.
     */
    private boolean isDisassemblyNeeded() {
        if (!destFile.exists()) {
            log("Destination file does not exist: a build is required",
                    Project.MSG_VERBOSE);
            return true;
        }
        long sourceTime = sourceFile.lastModified();
        long destTime = destFile.lastModified();
        if (sourceTime > (destTime + FILE_UTILS.getFileTimestampGranularity())) {
            log("Source file is newer than the dest file: a rebuild is required",
                    Project.MSG_VERBOSE);
            return true;
        } else {
            log("The .il file is up to date", Project.MSG_VERBOSE);
            return false;
        }

    }
    /**
     * do the work
     * @throws BuildException if there is an error.
     */
    public void execute() throws BuildException {
        log("This task is deprecated and will be removed in a future version\n"
            + "of Ant.  It is now part of the .NET Antlib:\n"
            + "http://ant.apache.org/antlibs/dotnet/index.html",
            Project.MSG_WARN);
        validate();
        if (!isDisassemblyNeeded()) {
            return;
        }
        NetCommand command = new NetCommand(this, "ildasm", executable);
        command.setFailOnError(true);
        //fill in args
        command.addArgument("/text");
        command.addArgument("/out=" + destFile.toString());
        if (!progressBar) {
            command.addArgument("/nobar");
        }
        if (linenumbers) {
            command.addArgument("/linenum");
        }
        if (showSource) {
            command.addArgument("/source");
        }
        if (quoteallnames) {
            command.addArgument("/quoteallnames");
        }
        if (header) {
            command.addArgument("/header");
        }
        if (!assembler) {
            command.addArgument("/noil");
        }
        if (metadata) {
            command.addArgument("/tokens");
        }
        command.addArgument("/item:", item);
        if (rawExceptionHandling) {
            command.addArgument("/raweh");
        }
        command.addArgument(EncodingTypes.getEncodingOption(encoding));
        if (bytes) {
            command.addArgument("/bytes");
        }
        command.addArgument("/vis:", visibility);

        //add the source file
        command.addArgument(sourceFile.getAbsolutePath());

        //determine directory: resourceDir if set,
        //the dir of the destFile if not
        File execDir = resourceDir;
        if (execDir == null) {
            execDir = destFile.getParentFile();
        }
        command.setDirectory(execDir);

        //now run
        try {
            command.runCommand();
        } catch (BuildException e) {
            //forcibly delete the output file in case of trouble
            if (destFile.exists()) {
                log("Deleting destination file as it may be corrupt");
                destFile.delete();
            }
            //then rethrow the exception
            throw e;
        }

    }

    /**
     * encoding options; the default is ascii
     */
    public static class EncodingTypes extends EnumeratedAttribute {
        /** Unicode */
        public static final String UNICODE = "unicode";
        /** UTF8 */
        public static final String UTF8 = "utf8";
        /** ASCII */
        public static final String ASCII = "ascii";
        /** {@inheritDoc}. */
        public String[] getValues() {
            return new String[]{
                ASCII,
                UTF8,
                UNICODE,
            };
        }

        /**
         * This method maps from an encoding enum to an encoding option.
         * @param enumValue the value to use.
         * @return The encoding option indicated by the enum value.
         */
        public static String getEncodingOption(String enumValue) {
            if (UNICODE.equals(enumValue)) {
                return "/unicode";
            }
            if (UTF8.equals(enumValue)) {
                return "/utf8";
            }
            return null;
        }
    }

    /**
     * visibility options for decoding
     */
    public static class VisibilityOptions extends EnumeratedAttribute {
        /** {@inheritDoc}. */
        public String[] getValues() {
            return new String[]{
                "pub", //Public
                "pri", //Private
                "fam", //Family
                "asm", //Assembly
                "faa", //Family and Assembly
                "foa", //Family or Assembly
                "psc", //Private Scope
            };
        }

    }
}

Other Ant examples (source code examples)

Here is a short list of links related to this Ant Ildasm.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.