Tuesday, May 10, 2011

ANT (Another Neat Tool)

Introduction
Ant is a Java-base builds tool. According to James Duncan Davidson (ANT http://www.assoc-amazon.com/e/ir?t=intelligentam-20&l=btl&camp=213689&creative=392969&o=1&a=0596006098author) ANT is an Another Neat Tool. Later the term ANThttp://www.assoc-amazon.com/e/ir?t=intelligentam-20&l=btl&camp=213689&creative=392969&o=1&a=0596006098 synchronized with real ant (nature creature ant) to see ant’s capability and strength. An ant can carry a weight dozens of times of its own. Thus we can understand that ant is a java base building tool that works multiple times more to its real power. ANT works just the “make” tool that works for C and C++. Using ANT we can make a numerous tasks without any customization. This document contains explanation on each task in more details step-by-step when it requires. To understand this document, I shall go step-by-step, starting from installation of ANT binary.

ANT Installation
This document is prepared under this assumption that the reader of this document has knowledge about system variables, environment variables and installation and configuration of software. Steps for ANT installation is –
To get up and running with the binary edition of Ant quickly, follow these steps:
1.      Make sure you have a Java environment installed. To get latest JAVA click hit this link - http://www.oracle.com/technetwork/java/javase/downloads/index.html. If JDK is not present, only the JRE runtime, then many tasks will not work. Ant 1.8.* works with JDK 1.4 but strongly recommended JDK 1.5. So first be sure that machine must have JDK 1.5 or later environment.
2.      Download Ant – visit this link - http://ant.apache.org/bindownload.cgi
3.      Uncompress the downloaded file into a directory.
4.      Set environmental variables JAVA_HOME to your Java environment, ANT_HOME to the directory you uncompressed Ant to, and add ${ANT_HOME}/bin (in UNIX environment) or %ANT_HOME%/bin (Windows) to your PATH.
5.      Optionally, from the ANT_HOME directory run ant -f fetch.xml -Ddest=system to get the library dependencies of most of the Ant tasks that require them. If you don't do this, many of the dependent Ant tasks will not be available.
Once you completed above steps, then open command prompthttp://www.assoc-amazon.com/e/ir?t=intelligentam-20&l=btl&camp=213689&creative=392969&o=1&a=1553951905 and run the following commands –
C:\>set path=”c:apache-ant-1.8.1\bin”; %path%
C :\> ant -version
 If both command run properly that means you have configured Another Neat Tool (ANT). And to seeing this screen means your installation phase has over.
Note: Ant 1.8.* works with jdk1.4 and higher, Ant 1.7.* works with JDK.3 and higher, Ant 1.6.* works with JDK 1.2 and higher, Ant 1.2 to Ant 1.5.* work with JDK 1.1 and higher.


ANT Basics
After successful installation of ANT version 1.8.1, now I move on to some core or basics of ant.  An ant build file comes in the form of an XML documents, all that is required is a simple text editor to edit the build file(s). An editor that provides XML syntax supportive utility is more suitable and preferable. The ant installation comes with a JAXP-compliant XML parser, this means that the installation of an external XML parser is not necessary. Details about “build.xml” file … Following build.xml are well formatted xml file that comprised of several target entities. There a lot to explain about the following build.xml file.


First Line of the build.xml is –
 xml version="1.0"?>
Since Ant build files are XML files the document begins with an XML declaration which specifies which version of XML is in use, this is to allow for the possibility of automatic version recognition should it become necessary. Next lien of this document is project element.

Project Element
Every build file must have least project and target (default) elements. Above build file has also a project element. Project element has an optionally a description for the project can be provided as a top-level element. Each project defines one or more targets. A target is a set of tasks you want to be executed. When starting Ant, you can select which target(s) you want to have executed. When no target is given, the project's default is used. In following table describe the attribute of project element –
       Attribute
                  Description
                 Required
        name
the name of the project.
                        No
      default


the default target to use when no target is supplied.
No; however, since Ant 1.6.0, every project includes an implicit target that contains any and all top-level tasks and/or types. This target will always be executed as part of the project's initialization, even when Ant is run with the -projecthelp option.
      


        basedir
the base directory from which all path calculations are done. This attribute might be overridden by setting the "basedir" property beforehand. When this is done, it must be omitted in the project tag. If neither the attribute nor the property has been set, the parent directory of the buildfile will be used.
                     


                          No

Target Element
Next element of this file is target –

The target element is used as a wrapper for sequences of actions. A target has a name, so that it can be referenced from elsewhere, either externally from the command line, or internally via the depends keyword, or through a direct call. The target in the example is called "init" (initiate), it makes a directory using the mkdir element with the name specified by the build property defined in three. The target element has a number of possible attributes, unless otherwise specified, these are optional:

       Attribute
                  Description
         Required
name
The name of the target is used to reference it from elsewhere, it is subject to the constraints of XML well formed-ness.
                    
           Yes
depends
This is a comma separated list of all the targets on which this target depends, for example, immediate next block illustrates how compile depends on init, in other words, depends contains the list of the targets that must be executed prior to executing this target.

            No
if
This is a useful attribute which allows one to add a conditional attribute to a target based on the value of a property for example, if="gui-ready" could be used to only execute the encapsulating target's instructions if the property gui-ready was is (to any value).

             No
unless
This is the converse of if, for example, unless="gui-ready" could be used to conditionally execute the contents of the encapsulating target. The targets' contents will be executed unless the the property gui-ready is set (to any value).

             No
description
This is a short description of the target.
              No
extensionOf
Adds the current target to the depend list of the named extension-point. Since Ant 1.8.0.

             No

onMissingExtensionPoint
What to do if this target tries to extend a missing extension-point. ("fail", "warn", "ignore"). Since Ant 1.8.2.
No. Not allowed unless extensionOf is present. Defaults to fail.

Target element has a attribute name depends, following example are concerning this attribute –
As explained in above block, depends allows one to specify other targets that must be executed prior to the execution of this target. In the listing above depends="init" is used to indicate that the compile target requires that the target named init be executed prior to executing the body of compile. For more details about target just visit this link http://ant.apache.org/manual/targets.html.


Property Element
In given example build file there is an element name property. For example you may see the following snippet of build.xml file –
                   
                        <property name="sourceDir" value="src" />
                                name=”builddir value=”build” />
                                <property name="outputDir" value="classes" />
                                <property name="deployJSP" value="/web/deploy/jsp" />
                                <property name="deployProperties" value="/web/deploy/conf" />
 
Properties are an important way to customize a build process or to just provide shortcuts for strings that are used repeatedly inside a build file.
In its most simple form properties are defined in the build file (for example by the property task) or might be set outside Ant. A property has a name and a value; the name is case-sensitive. Properties may be used in the value of task attributes or in the nested text of tasks that support them. This is done by placing the property name between "${" and "}" in the attribute value. For example, if there is a "builddir" property with the value "build", then this could be used in an attribute like this: ${builddir}/classes. This is resolved at run-time as build/classes.
Normally property values cannot be changed, once a property is set, most tasks will not allow its value to be modified. In general properties are of global scope, i.e. once they have been defined they are available for any task or target invoked subsequently - it is not possible to set a property in a child build process created via the ant, antcall or subant tasks and make it available to the calling build process, though, with Ant 1.8.0 property expansion has become much more powerful than simple key value pairs, more details can be found from here http://ant.apache.org/manual/properties.html. Ant provides access to all system properties as if they had been defined using a task. For example, ${os.name} expands to the name of the operating system. Some built-in properties are –

Built-in properties
                     Description 
basedir
The absolute path of the project's basedir (as set 
with the basedir attribute of ).
ant.file
The absolute path of the buildfile.
ant.version
The version of Ant.
ant.project.name
The name of the project that is currently executing; 
it is set in the name attribute of .
ant.project.default-target
The name of the currently executing project's default target;
 it is set via the default attribute of .
ant.project.invoked-targets
 
A comma separated list of the targets that have been specified 
on the command line (the IDE, an  task ...) when 
invoking the current project.
 
ant.java.version
The JVM version Ant detected; currently it can hold the values 
"1.2", "1.3", "1.4", “1.5" and "1.6".
 
ant.core.lib
The absolute path of the ant.jar file.
 
Task Element
 A task is a piece of code that can be executed. A task can have multiple attributes (or arguments, if we prefer). The value of an attribute might contain references to a property. These references will be resolved before the task is executed. Tasks have a common structure:
<name attribute1="value1" attribute2="value2" ... />
 
Where name is the name of the task, attributeN is the attribute name, and valueN is the value for this attribute. All tasks share a task name attribute. The value of this attribute will be used in the logging messages generated by Ant. Tasks can be assigned an id attribute:
 <taskname id="taskID" ... />
Where taskname is the name of the task, and taskID is a unique identifier for this task. For understanding I am giving the snippet code from given example –

The javac element, as used above, is a task, tasks are performed in the body of a target, in this case, the source directory is specified by referencing the src property and the destination directory is specified by referencing the build property. The example above causes javac to be executed, compiling all the .java files in the directory specified by the src property and placing the resultant .class files in the directory specified by the build property.
These are a set of built-in tasks, but it is also very easy to write your own. To write your own task visits this link - http://ant.apache.org/manual/develop.html

         Tasks
                                            Description
ant
Used to execute another ant process from within the current one.
copydir
Used to copy an entire directory.
copyfile
Used to copy a single file.
cvs
Handles packages/modules retrieved from a CVS repository.
delete
Deletes either a single file or all files in a specified directory and its sub-directories.
deltree
Deletes a directory with all its files and subdirectories.
exec
Executes a system command. When the os attribute is specified, then the command is only executed when Ant is run on one of the specified operating systems.
get
Gets a file from an URL.
jar
Jars a set of files.
java
Executes a Java class within the running (Ant) VM or forks another VM if specified.
javac
Compiles a source tree within the running (Ant) VM.
javadoc/javadoc2
Generates code documentation using the javadoc tool.
mkdir
Makes a directory.
property
Sets a property (by name and value), or set of properties (from file or resource) in the project.
rmic
Runs the rmic compiler for a certain class.
tstamp
Sets the DSTAMP, TSTAMP, and TODAY properties in the current project.
style
Processes a set of documents via XSLT.

These are the some basic elements about ant build.xml file. You can learn in depth by visiting this link - http://ant.apache.org/manual/index.html. Now I am going to make a sample project using build.xml…

 A Typical project as an Example
The purpose of this section is to make a project using ant and its build.xml file. Steps that I shall follow are –
1.     1. Preparing directory structure.
2.      2.Creating source file in standard directory location (recommended by ant)
3.     3.  Building build.xml file.
4.     4. Execute ant command.
1. Preparing directory structure -
It is good idea to adhere the ant recommendation because we will use the ant as a building tool. According to ant recommendation we shall create a root directory inside this we will create following directory structure:

1.1  src: For project source files.
1.2  build: For compiled/output files produced (by Ant).
1.3  lib : For class libraries and dependency files.

Create an “Application” directory and from within this, create the three directories described above. A simple Java program will be used to illustrate the use of Ant.

2. Source File inside directory src -
 Copy following code and paste in java compatible editor, this is not mandatory you may even a simple editor also. Save this file inside src folder using same package hierarchy which is mention as package statements with name “HelloWorld.java”.
package com.greensoft.ant.example;

/**
 * @author Pravind Kumar
 *
 */
public class HelloWorld {

            /**
             * Default Constructor
             */
            public HelloWorld() {
                       
            }

            /**
             * @param args
             */
            public static void main(String[] args) {
                        System.out.println("Hello World By Pravind Kumar");
                       

            }

}
3. Building build.xml -
This is a standard build.xml file, just copy and pastes it in an editor and saves as “build.xml” in parallel to src folder.
          
 Inside this build.xml file I used some tasks like javac, jar and java. I hope every elements there is not a problem to understand this file because I have already discussed all elements whatever I used inside this file. Even then there is any issue then you are suggested that review this document once again or visit this link for a more and complete idea about build.xml file - http://ant.apache.org/manual/index.html. Now it’s time to cheers.
4. Execute ant Command -
1.      Open run command with combination of window key + r.
2.      Type cmd and press Enter key.
3.      On command prompt type cd\ and press enter
4.      Now go to your “Application” folder
5.      Type ant and press enter…. WOW! Your result on you console. And look like this…


Ant File Sets
A FileSet is a filter which uses one or more patterns to specify which files are desired. A FileList is a list of desired files. FileSets use PatternSets and Patterns to define their actions.
          ? is used to match any character.
          * is used to match zero or more characters.
          ** is used to match zero or more directories.
A FileSet must specify a base directory from which all other path calculations are made; this is supplied via the dir attribute.  Fileset has a various attribute; following tables dictate about fileset attribute
       Attribute
                  Description
         Required
     dir
The root of the directory tree of this FileSet.
Yes, Either dir or file must be specified
     file
shortcut for specifying a single-file fileset

  defaultexcludes
Indicates whether default excludes should be used or not (yes | no); default excludes are used when omitted.

           NO
      includes
Comma- or space-separated list of patterns of files that must be included; all files are included when omitted.
NO
    includesfile
The name of a file; each line of this file is taken to be an include pattern.
NO
  excludes
Comma- or space-separated list of patterns of files that must be excluded; no files (except default excludes) are excluded when omitted.
NO
excludesfile
The name of a file; each line of this file is taken to be an exclude pattern.
               NO
casesensitive
Must the include and exclude patterns be treated in a case sensitive way? Defaults to true.
NO
followsymlinks
Shall symbolic links be followed? Defaults to true. See the note below.
NO
erroronmissingdir
Specify what happens if the base directory does not exist. If true a build error will happen, if false, the fileset will be ignored/empty. Defaults to true. Since Ant 1.7.1 (default is true for backward compatibility reasons.)
NO

Before going to depth about fileset I want to discuss about structure of fileset elements –

Or:

Since both of these FileSets contain no patterns, they match the default; every file in the base directory and all its subdirectories, recursively.

Some Basic Use of fileset –

If one desires to delete any of these default excluded files, for example, to delete all scratch files that editplus (a text editor) made, recursively, one has to set defaultexcludes="no" so that the defaults are not excluded and then one could use something like:
Removing temporary files...

Includes all files ending in the extensions "java" and "j2ee" in the base directory and all subdirectories, the pattern is applied recursively in the subdirectories.

Includes all files those contain the string "java" in the base directory and all sub directories, recursively. Excludes any files in any directory called "j2ee", whether it occurs in the current directory or any of the sub directories, recursively. Notice that the syntax is slightly different, in that, include and name are used instead of includes and exclude and name are used instead of excludes. In the context of the sentences above, the word "recursively" means that the pattern is applied to each of the subdirectories as well as the base directory hence it is then applied to the sub-directories of the sub-directories and so on. The pattern is applied to all directories under the base directory.

A Bit about PatternSet

Patterns can be grouped to sets and later be referenced by their id attribute. They are defined via a patternset element, which can appear nested into a FileSet or a directory-based task that constitutes an implicit FileSet. In addition, patternsets can be defined as a standalone element at the same level as target — i.e., as children of project as well as children of target. Patternsets may be nested within one another, adding the nested patterns to the parent patternset. A nested patternset can be inverted using the element (Since Ant 1.7.1). Patterns can be specified by nested , or elements for example –
  
  


Patterns can be specified by nested ,
or  elements
or the following attributes.
Attribute                                                      Discription
include Each such element defines a single pattern for files to include or exclude.
includes Comma- or space-separated list of patterns of files that must be included. All files are included when omitted.
exclude Each such element defines a single pattern for files to include or exclude.
excludes Comma- or space-separated list of patterns of files that must be excluded; no files (except default excludes) are excluded when omitted.
includesfile The name of a file; each line of this file is taken to be an include pattern. You can specify more than one include file by using a nested includesfile elements.
excludesfile The name of a file; each line of this file is taken to be an exclude pattern. You can specify more than one exclude file by using a nested excludesfile elements.
A little bit about attributes –

Include and exclude
Include and exclude have three attributes among them name is required attribute. Two more attribute for conditional purpose these are if and unless. Following table say about this –
       Attribute
                  Description
         Required
name The pattern to in/exclude.           YES
if Only use this pattern if the named property is set.           NO         
unless Only use this pattern if the named property is not set           NO

Includesfile and excludesfile
if you want to list the files to include or exclude external to your build file, you should use the includesfile/excludesfile attributes or elements. Using the attribute, you can only specify a single file of each type, while the nested elements can be specified more than once - the nested elements also support if/unless attributes you can use to test the existance of a property.

       Attribute
                  Description
         Required
name The name of the file holding the patterns to in/exclude.           YES
if Only read this file if the named property is set           NO         
unless Only read this file if the named property is not set           NO

Ant Flow of Control
Since Ant does not contain any real control structures like if..then..else, one has to manipulate Ant's ability to call internal targets that support conditional execution to emulate the desired control structures. In ant we can do such flow using customize task. For example just look following build.xml –


Case – 1 Assuming the case where the first file, fileone, and the second file, filetwo are not available. The initial condition checks if the file fileone available, if it is, the property condition is set. Calls to the targets then and else follow. The execution of then is conditional, dictated by (if="condition"). Since the assumption is fileone is not available, condition will not be set and the body of then will not be executed. The next target, else, will be called. The execution of else is conditional, dictated by condi- (unless="tion") which means that the body will be executed unlesscondition is set. Since condition has not been set, the body of else will be executed.

Case – 2 Assuming the case where the first file, fileone, is present, and the second file, filetwo is not. The initial condition will be set because fileone is available so the call to then will be successful. The body of then contains another condition which checks for the existence of the file filetwo, if it is available, the property, inner-condition is set. Since the assumption is that filetwo is not available, the property inner-condition will not be set. Calls to the targets inner.then and inner.else follow. The execution of inner.then is conditional, dictated by (if="inner-condition") so the body of inner.then will not be executed. The execution of inner else is conditional, dictated by (unless="inner-condition") so the body of inner.else will be executed since the only thing that would stop the execution of it would be if inner-condition was set.

Case – 3 Assuming the case where the first file, fileone, and the second file, filetwo are both available. The outer condition will cause the property condition to be set because fileone is available, so when the target then is called, the body will be executed. The condition within then will cause the property inner-condition to be set because filetwo is available. This means that the call to inner.then will be successful. Upon exiting inner.then, inner.else will be called but the body will not be executed because innercondition is set. Upon exiting then, else will be called but the body will not be executed because condition is set.

ANT USING EXTERNAL LIBRARIES (log4j)
In my previous example I ran a build file and output was coming on console. But assume in case where output is required on log file or other file. I mean I want to execute a build file using external file instead of java IO API. So in this example I am going to use log4j API to write information in log file instead of standard console.  
 We store the external jar or library inside lib folder what we have created earlier. Here we are putting the log4j jar inside lib folder. 2nd step would be to change the HelloWorld.java code, and now HelloWorld.java looks like –
package com.greensoft.ant.example;
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;


/**
 * @author Pravind Kumar
 *
 */
public class HelloWorld {

                private static Logger logger = Logger.getLogger(HelloWorld.class);
                /**
                 * Default Constructor
                 */
                public HelloWorld() {
                               
                }

                /**
                 * @param args
                 */
                public static void main(String[] args) {
                                //System.out.println("Hello World By Pravind Kumar");
                                BasicConfigurator.configure();
                                logger.info("Hello World By Pravind using Log4j api");
                               
                               

                }
}
Now, it’s time to  update the build.xml file accordingly so that it can find the all imported class files in class path otherwise it will show a couple of exception during compilation.  In build.xml file add one more line for property inside init target like this –
      value="lib"/>
After that, to compile new java file need log4j jar file. There are two ways to get log4j jar; one is to set that jar file into class path of system environment variable and another is to set path element inside build.xml file. So I think second option is better. To set the jar file in build.xml, add following line of code into init target. Path element line looks like this –
                                               
Path element is using to make a group of jar file recursively using fileset element. About fileset element see the  
above block.
We had coded BasicConfigurator.configure(); which implies a simple, but hard coded configuration. More confortable would be using a property file. In the java source delete the BasicConfiguration-line from the main() method (and the related import-statement). Log4J will search then for a configuration as described in it's manual. Then create a new file src/log4j.properties. That's the default name for Log4J's configuration and using that name would make life easier - not only the framework knows what is inside, we too! So put this properties file inside src (source ) directory. Properties file is – log4j.properties
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%m%n
Now according to this configuration file we need to change the compile target inside build.xml file. Thus new compile target look like this –
  
   
Also update run target after updating run target looks like –
       

And this is the final build.xml file and ready for execution –
               




Just go on command prompt and switch to your application folder and type “ant” and press enter. What’s up! Congratulation your application is configured properly and in running state.



No comments:

Post a Comment