Overview

   JWare/AntXtras Foundation (AntXtras) is both a powerful Ant extension library as well as a collection of very useful add-on Ant components. As an extension library, AntXtras is the foundation of the other Ant-related packages you will find on this site; packages like Svn4Ant, Log4Ant, and PEd4Ant. As a collection of components (an antlib), AntXtras enhances Ant with a variety of new types, conditions, tasks, and behaviors that make it easier for you to use Ant to solve many kinds of problems– not only application builds.

Ant Solutions Enabler

Ant is a pretty nifty tool. But out-of-the-box it has quite a few limitations if you′re tasked with developing anything other than a simple Java application build script. Some of these limitations are self-imposed architectural bounds; others are the consequence of the Ant developers having to draw the line somewhere with respect to what is included in the baseline distribution. By providing both features that are awfully useful (even if they′re not 100% in tune with Ant′s architectural soul) and a collection of key Ant add-ons, AntXtras enables you to create sophisticated cross-platform build, deploy, test, and other systems easily from Ant. Some of the extras you get with AntXtras include:

  • Variables also known as changeable properties. (Why it’s useful.)
  • Recursive property reference expansion. (Why it’s useful.)
  • Function shortcuts to perform common tasks with less XML script. (Why it’s useful.)
  • Enhanced execution control statements for Ant scripts– to the task level! (Why it’s useful.)
  • Ways to capture execution exceptions and recover– all within Ant script. (Why it’s useful.)
  • A collection of new, thread-safe, and reusable conditions and selectors. (Why it’s useful.)
  • An assertion and rules antlib for creating self-verifying and correcting scripts. (Why it’s useful.)
  • Overlays, nets, and bubbles to add fine grain control over fixture modifications.(Why it’s useful.)
  • Support for locale-aware external files to store feedback messages. (Why it’s useful.)
  • Ways to capture task level console output to properties or log files– without loggers! (Why it’s useful.)
  • Exposure of “the thread” as a fixture context just like the target or the project. (Why it’s useful.)
  • A simple and consistent interface across all components regardless of their purpose.

100% Your Way

AntXtras adds a lot of stuff to a basic Ant installation— but it does it in a nice way. By “nice” we mean, even with AntXtras and all the goodies it adds, you still maintain 100% control over your Ant system. AntXtras does not impose any structural or style constraints on your Ant environment or scripts, nor does it remove or somehow disable any standard Ant functions. If a particular AntXtras component affects a standard Ant feature, we document the effect and try to ensure you can undo the effect by simply removing the AntXtras item. To our knowledge, except for the items cited in the Ant 1.8 Caveats section, AntXtras does not conflict with any other third-party Ant extensions (send us a note if you think otherwise). You can use AntXtras as part of a new Ant-based system or to support an existing environment’s architecture.

AntXtras Component Summary

You are not required to use all of AntXtras. Every main AntXtras feature is independent so you can use it, and it only, if you choose. Even so, it helps to think of each feature as belonging to one of six categories: Fixture Control, Function Shortcuts, Execution Rules, Flow Control, Feedback, or Helpers. The rest of this overview will introduce you to AntXtras in the context of these six categories: it will briefly describe the most important AntXtras components and provide links to additional information and usage examples. Throughout our descriptions, we use the term “taskset” to refer to a task that can contain other tasks; see the AntXtras Design Guide for a discussion on tasksets and other fundamental AntXtras design concepts and terminology.

Execution Fixture Control

The AntXtras fixture control components are a collection of utilities with which you define and control your Ant execution environment globally or at a local, taskset-specific level. The table below names some of the most used components; read the User Guide for the complete list. Often a feature is comprised of two or three individual components; for example, the external messages feature involves the <messagesbundle> type to declare your messages, and the <managemessages> task which actually (un)installs the named message bundle into the Ant fixture.

Task or Type General Description
messagesbundle, strings, properties, etc. Shareable, structured items containing fixture data (messages, properties, URLs, etc.). Because structured items are usually verified as they are created instead of when they are first used, you notice invalid declarations or modifications immediately. You would use structured data for a variety of reasons: to minimize the number of attributes a macrodef defines, or to group related properties together explicitly, or to control the various AntXtras execution control tasks.
datadef A task that lets you conditionally create and insert data objects into the project’s reference table. Basically the data object’s reference id (id) is not made public (to be referenced via a refid) until its enclosing target or script block is executed. Use the <unassign> task to remove the object from the Ant fixture at a later point.
managemessages, managefuncuts, etc. Administrator tasks that let you define primordial fixture settings; for instance, the <managefuncuts> task lets you configure and enable the AntXtras function shortcuts functionality. Like standard <typedef>s or <macrodefs>s, you can use any administrator task as part of an antlib.
isolate, overlay, etc. Tasksets that let you control locally what a set of tasks see and affect in the active project’s environment. The <isolate> taskset lets you create a “bubble” that shields the project from most modifications. The <overlay> taskset lets you create a “net” that removes, adds, or overrides selective bits of fixture (i.e. properties) for enclosed tasks.
assign, unassign Tasks to create, edit, and remove variables (also called mutable properties) that persist across task, target, and (sub)project boundaries. Variables let you reduce the number of extraneous, temporary properties you would otherwise create with the standard Ant write-once properties. You can also use the <unassign> task to remove transient data object references from the Ant fixture.
capturelogs, copylogged, interpretlogged, etc. Tasks that capture and save task outputs and byproducts for capture to a file or for further processing and examination. You can use these components to capture both Ant script log statements (like <echo>) as well as internal Ant logging to System I/O streams without setting up a top-level Ant logger.
copyproperty, copyreference, etc. Tasks to copy transformed properties, or variables, or references to standard Ant properties. You also can use <copyproperty> to edit the Java System properties of the Ant JRE.

Example Script Snippets

1) The following script snippet copies the logs generated by a javadoc task to a build process archive file ‘javadoc.log’. The saved log file can then be examined for errors or other problem markers, or saved by a build archive system.

<capturelogs splitentries="yes">
  <javadoc sourcepath="src" destpath="docs/apis" packagenames=...>
     ...
  </javadoc>
  <copylogged tofile="${logs.dir}/javadoc.log"/>
</capturelogs>

2) The following macrodef snippet declares a structured strings list ‘template.filetypes’ the first time it is called if and only if the enclosing project does not already include such a data object. The <datadef> task lets the macro create a default dataset if the project does not provide its own.

<macrodef name="mktemplatefilters">
  ...
    <datadef name="template.filetypes" overwrite="no">
      <strings>
        <string value="txt"/>
        <string value="xml"/>
        <string value="properties"/>
      </strings>
    </datadef>
   <doforeach i="filetype" items="template.filetypes">
     ...
  ...

3) The following macrodef snippet defines a common compilation task “compilejava” that can be reused for different sets of Java sources. The macrodef relies on AntXtras variables and the $var: function shortcut to record how long it takes to compile a particular set of Java sources. The captured information is then logged to the Ant console.

<macrodef name="compilejava">
  ...
    <assign var="javac.time" op="now"/>
    <javac srcdir="@{sources}" destdir="@{classes}" debug=...>
       ...
    </javac>
    <assign var="javac.time" op="-now"/>
    <echo message="Compilation took: ${$var:javac.time} msecs"/>
  ...

4) The following macrodef snippet creates a file with some custom formatted dates and times for use by the running system. It optionally applies those custom dates as properties only if asked to by the caller. Because the standard <tstamp> task always copies its results into project properties we need to use the AntXtras <isolate> task to prevent these transient properties from leaking into the project (and nullifying the ability to use this macro more than once per project).

<macrodef name="mktimestamps">
  ...
  <macrolocals>
    <property name="BASE_STAMP"/>  <!-- mine -->
    <property name="LONG_STAMP"/>  <!-- mine -->
    <property name="DSTAMP"/>      <!-- ants -->
    <property name="TSTAMP"/>      <!-- ants -->
    <property name="TODAY"/>       <!-- ants -->
  </macrolocals>
  <macroisolate>
    <tstamp>
      <format property="BASE_STAMP" .../>
      <format property="LONG_STAMP" .../>
    </tstamp>
    <newfile path="@{file}" overwrite="yes">
      <line value="BASE_STAMP=${BASE_STAMP}"/>
      <line value="LONG_STAMP=${LONG_STAMP}"/>
    </newfile>
  </macroisolate>
  <do true="@{apply}">
    <property file="@{file}"/>
  </do>
  ...

:!: Read the AntXtras User Guide for a detailed description of each fixture control component, its parameters, more usage examples, and related components.

Function Shortcuts aka “funcuts”

AntXtras uses a mechanism it calls function shortcuts to expose your executing environment’s fixture, utility tasks, and select Ant functions using the standard Ant property dereference semantics and a simple property naming convention (why this is useful). The general form of a function shortcut is ${$scheme:[fragment]} where the $scheme: portion selects one of installed set of function shortcuts and the optional fragment portion defines a query specific to a request and scheme. Although AntXtras comes with a decent set of built in funcuts (see table below for a small sample), the AntXtras function shortcut mechanism is open-ended; just as you can define additions to Ant’s standard conditions, tasks, and other types, you can rename most of our funcuts or add your own to AntXtras.

Funcut Scheme(s) General Description
$p: or $property: Fixed shortcut.1) Extracts the named property’s current setting and supports a special dereference ‘→’ to get at items inside a <properties> or <propertyset>. You can also specify a default value if the named property is not defined.
$v: or $var: or $variable: Fixed shortcut.2) Extracts the named variable’s current setting. You can also specify a default value if the named variable is not defined.
$system:, $sysenv:, etc. Extracts the named Java System property (System.getProperty(…)) or environment variable (System.sysenv(…)). Lets you gain access to the platform environment variables without having to load all of them. You can also specify a default value if the named item is not defined.
$test: or $criteria: Executes the named AntXtras <tallyset> or <criteria> and reflects its results as a simple boolean string. Lets you seamlessly link complex execution criteria with local tasksets or with existing Ant conditions like <true> and <false>.
$anytrue:, $isnumber:, $noneset:, $isOS:, $allset:, $not:, $isfile:, $iszero:, etc. Executes the named AntXtras short hand condition and reflects its results as a simple boolean string. The complete list of short hand conditions is defined in the Function Shortcuts Guide. Work like inlined versions of AntXtras’s new conditions that you use with execution control tasks or existing Ant conditions like <true> and <false>.
$ospath:, $uppercase:, $trim:, $lowercase:, $stripws:, $shorten:, etc. Converts the fragment part of the shortcut according to the named transformation; for example, $trim: will remove all whitespace at the beginning and end of the supplied string while $lowercase: will create an all lower case version of string. All transforms the <copyproperty> task supports have funcut equivalents.
$now:, $datetime:, $iso:, $duration:, $gmt:, $svnlog:, $strictdate:, etc. Converts the current system time or a passed in timestamp according to the named datetime formatter and locale settings. The complete list of datetime formats is defined in the Function Shortcuts Guide.
$osfamily:, $basename:, $oslibext:, etc. Extracts various platform-specific definitions of common attributes. Useful when you need to create cross-platform or cross-version Ant scripts.
$password: Extracts a password from a password file on the file system. Lets you create scripts that use passwords without having to load the passwords into Ant properties that can be inadvertently leaked.
$list:, $map: Extracts information from a structured list or map data object like a <strings>, <properties>, or other general Ant resource collection object like <zipfileset> or <fileset>. Because there are AntXtras tasks that let you generate item collections dynamically, these funcuts let you access the contents of such items.
$message: Extracts and formats a template message from the Ant fixture’s installed message resource bundles. You can specify up to nine(9) message template parameters. Works as an inlined version of the more general <copymessage> AntXtras task that lets you pass messages directly to existing Ant tasks like <echo> and <fail>.

:!: Read the Function Shortcuts Guide to get a full description of function shortcuts and an overview of the extensive funcuts antlib AntXtras includes as part of its core feature set.

Example Script Snippets

1) The following snippet uses the $istask: condition funcut with the AntXtras <do> taskset to define a set of instructions that will only execute if the ‘emmajava’ task does not exist.

<do false="${$istask:emmajava}">
   ...[only if emmajava not already defined as a task]...
</do>

2) The following snippet uses several funcuts. In essence the script sets a local variable ‘onerror.flag’ to either “ignore” or “fail” depending on the boolean setting of a property ‘emma.optional’ (note that in the sample the setting is defaulted to the empty string explicitly by $p: if the property is undefined). Then it uses that local variable value, via the $var: funcut, as a parameter to two Ant type definitions.

<assign var="onerror.flag"
  value="${$p:emma.optional?|$truefalse:?ignore,,fail}"/>
 
<taskdef onerror="${$var:onerror.flag}"
  resource="emma_ant.properties" .../>
 
<typedef onerror="${$var:onerror.flag}"
  name="emmafileset" .../>

3) The following snippet uses the $isOS: funcut to switch between two platform setup tasksets depending on the active Ant runtime. If the runtime environment is any Windows platform the <true> taskset is executed; otherwise the <otherwise> taskset is run.

<domatch value="${$isOS:windows}">
   <true>
     ...[windows setup]
   <otherwise>
     ...[solaris setup]
</domatch>

4) The following macrodef snippet uses the $var:, $isfile:, and $iszero: funcuts to create a set of directories defined inside a special layout file. The caller can pass a composite dash-delimited layout descriptor. If more than one layout is named the macro applies each layout′s directory descriptor file in order; for instance the layout ‘java-assembler’ would first create the directories for the ‘java’ layout and then add the directories for the ‘java-assembler’ layout. If the special ‘all’ layout descriptor file exists, it is always applied first.

<macrodef name="mkdirectorylayout">
  <attribute name="in"/>
  <attribute name="layout"/>
  ...
  <do true="${$isfile:${layouts.d}/all}">
    <mkdirs base="@{in}" file="${layouts.d}/all"/>
  </do>
 
  <assign var="namecount" value="0"/>
  <assign var="dirsfile" value=""/>
 
  <doforeach i="layoutname" list="@{layout}" delim="-">
    <do false="${$var:namecount|$iszero:}">
      <assign var="dirsfile" op="+s" value="-"/>
    </do>
    <assign var="dirsfile" op="+s" value="${layoutname}"/>
    <mkdirs base="@{in}" file="${layouts.d}/${$var:dirsfile}"/>
    <assign var="namecount" op="++"/>
    ...
  ...

Execution Rules Enforcement

The AntXtras execution rules components enhance the standard Ant <condition>, <available>, and <fail> tasks to create a powerful rules framework that makes it very easy for you to write non-trivial self-verifying and self-correcting (or “smart”) Ant scripts. You could easily package such scripts (as macrodefs, presetdefs, etc.) into reusable well-behaved antlibs that others can use. The rules framework includes several tasks, types, and new conditions. The table below names some of the most used components; read the User Guide for the complete list.

Task or Type General Description
assert, fixturecheck A combination of the <condition> and <fail> tasks; if the condition is false the Ant script is immediately stopped. These tasks are designed specifically to provide an extensive range of test conditions with minimal Ant script. You can disable the <assert> task by setting the appropriate configuration option. You cannot turn off fixture checks (why not?).
prefer, fallback A combination of the <condition> and <property> tasks; if the condition is false, a property is (re)set to some default value. These tasks allow you to specify default values for undefined or improperly defined runtime properties while issuing the appropriate warnings to the script’s monitors.
ruleset A reusable condition definition comprised of either all requirements (<require>) or all preferences (<prefer>). Only useful if referenced by an AntXtras rule task like <assert> or another <ruleset>. Lets you bundle semantically-related groups of assertions or preferences.
ruledef A rule macro definition comprised of either all requirements (<require>) or all preferences (<prefer>). Useful if you want to create parameterized rules where caller supplies value for one or more of the parameters used in the definition. Also lets you create reusable antlibs that include general (or specialized) rule definitions.
tally A collection of condition evaluators; typically, the conditions are of the “check existence” variety like: does class exist, or does file exist, or does resource exist. Extends the standard <condition> to include support for all the additional AntXtras conditions, shareable tallysets, forced evaluation, and false results– where a property is set if the tally is false.
tallyset A reusable collection of condition evaluators compatible with the <tally> task. Only useful if referenced by an AntXtras <tally> task or another <tallyset>. Lets you bundle semantically-related groups of evaluators.
matches A rule task that updates a project property if a value matches (or not) a specified regular expression. Can also be used as an embedded condition. You setup a <matches> to read properties, variables, or reference values (as strings).
criteria A reusable test definition that can contain items other than conditions. Useful if you want to define non-trivial loop termination tests that are called repeatedly and have side-effects other than setting a single property or variable. Except for the special result variable, AntXtras ensures a criteria′s execution is isolated from the project fixture.
batchchecks A wrapper taskset for <assert>s and <fixturecheck>s that lets you execute a set of checks in a single pass. If at least one check fails, the batch operation fails after all checks have been performed. Saves time when a large set of related execution pre-requisites must be checked.

Example Script Snippets

1) The following snippet defines an Ant macro that uses several AntXtras rule components to ensure the ‘dist.type’ property is always defined to a proper value if the current execution environment allows defaulted values. The idea is that a user could execute the script with defaults OFF to check that he has explicitly defined all the prerequisite properties (as should be the case for a public release build for instance).

<macrodef name="distribute-checklist">
  ...
  <do unlesstrue="defaults.disabled">
     [ checks the current value of our 'dist.type' ]
     <fixturecheck isset="defaults.dist.type"
          messageid="ERR.defaults.dist.type.undefined"/>
     <matches pattern="internal|local|public"
          property="dist.type"
          falseproperty="bad.dist.type"/>
     [ if not recognized, default and issue warning ]
     <prefer isnotset="bad.dist.type"
          messageid="WRN.dist.type.unrecognized"
          falseproperty="dist.type"
          default="${$p:defaults.dist.type?local}"/>
  ...

2) The following snippet uses an AntXtras ruleset “strict-distro” to ensure certain properties are not defined at execution start if a strict distribution is being generated. The rationale is that if these properties exist, the script cannot guarantee the integrity of any generated artifacts.

<ruleset id="strict-distro">  [a shareable "strict-distro" rule]
  <require failproperty="bad.dist.setup" messageid="ERR.dist.setup.dirty">
    <noneset>
      <property name="build.number">
      <property name="synch.disabled">
      <property name="clean.disabled">
      <property name="tests.disabled">
    </noneset>
  </require>
</ruleset>
 
<target name="distro">
   ...[make the distribution package]
</target>
 
<target name="strict-distro">
   <assert ruleid="strict-distro"/> [enforce the prerequisites]
   <callinline target="distro"/>    [reuse our "distro" target]
</target>

3) The following snippet defines two parameterized rules that a macro definition can use to make sure the passed in value for an ‘args’ parameter is both a valid properties map reference (<assert-propertiesdef>) and contains the expected elements (<assert-wlinstancedef>). The first ruledef also demonstrates how you can use <fixturecheck> within a rule definition to verify that the properties the rule itself relies on are there. The second ruledef also shows how to batch a set of related assertions so that the entire check fails but not before each requirement is checked. Such batching lets the script report all the problems in a single pass.

<ruledef name="assert-propertiesdef">
  <attribute name="arg"/>
  <fixturecheck allset="ojwa,oata,jlu"/>
  <require logic="or">
    <isreference name="@{arg}" class="${ojwa}.types.PropertiesList"/>
    <isreference name="@{arg}" class="${oata}.types.PropertySet"/>
    <isreference name="@{arg}" class="${jlu}.Properties" kindof="yes"/>
  </require>
</ruledef>
 
<ruledef name="assert-wlinstancedef">
  <attribute name="arg"/>
  <batchchecks messageid="ERR.reqd.smoke.fixture.notdefined">
    <isnumber value="${$property:@{arg}→port}" gt="0"/>
    <isnotwhitespace value="${$property:@{arg}→test.service.page}"/>
    <isnotwhitespace value="${$property:@{arg}→services}"/>
    ...
  </batchchecks>
</ruledef>

4) The following snippet defines an Ant macro that uses several AntXtras rule and fixture control components to verify the bootstrap environment for a build-system called “AKIMABU”. From a 50,000 foot view the script is just ensuring that a non-empty Ant script file “akimabu.import” exists; however, as this is a completely self-contained macro that exists as part of a public antlib, it uses AntXtras to self-verify and self-correct were possible (and when all else fails, to complain loudly then die).

<macrodef name="execute-checklist">
  ...
  <tally trueproperty="AKIMABU_HOMES.OK" logic="or">
    <isdirectory property="AKIMABU_HOMES"/>
    <isdirectory value="${$sysenv:AKIMABU_HOMES}"/>
  </tally>
 
  <stop unless="AKIMABU_HOMES.OK" fatal="yes"
    messageid="ERR.akimabu.homesdir.notfound"/>
 
  <fallback property="AKIMABU_HOMES"
    value="${$sysenv:AKIMABU_HOMES}"/>
 
  <show messageid="INF.akimabu.homes.found"
    arg0="${$p:AKIMABU_HOMES}"/>
 
  <prefer isset="AKIMABU_VERSION"
    falseproperty="AKIMABU_VERSION" default="active"
    messageid="WRN.akimabu.version.defaulted"/>
 
  <property name="AKIMABU_HOME"
    value="${AKIMABU_HOMES}/${AKIMABU_VERSION}"/>
 
  <property name="AKIMABU_START_FILE"
    value="${AKIMABU_HOME}/akimabu.import"/>
 
  <tally trueproperty="AKIMABU_HOME.OK">
    <filenotempty path="${AKIMABU_START_FILE}"/>
  </tally>
 
  <stop unless="AKIMABU_HOME.OK" fatal="yes"
    messageid="ERR.invalid.akimabu.version"
    arg0="${AKIMABU_VERSION}" arg1="akimabu.import"/>
  ...
</macrodef>

Execution Flow Control

The AntXtras flow control components help manage your Ant process’s execution flow by providing several looping and error handling constructs missing from the standard Ant tasks. The flow control elements do not intend to make Ant into a scripting language; instead, their main purpose is to make writing modular and parameterized Ant scripts easier. Similarly, the AntXtras error-handling features aim to make writing error-tolerant and auto-correcting Ant scripts easier. The table below names some of the most used flow control components; read the User Guide for the complete list of components, all of their options, and additional examples.

Type or Task General Description
protect A taskset that captures errors generated from nested tasks and allows the script-author to specify how to handle the error and tasks that should be executed always, regardless of whether an error occured or not. Similar in functionality to the Java language try-catch-finally construct.
do, doinline A sequence of conditionally executed tasks. Like the standard <sequential> task with support for an extended collection of execution condition specifiers. When used with a test attribute, the effect is like using an if-then Java-style construct. The <doinline> is a special version of <do> that you can use inside of an antlib definition file. With it you can create antlibs that are completely self-initializing.
domatch A taskset that tries to match a selection criterion to a set of named, nested tasksets. If a choice is matched, the <domatch> executes the selected taskset’s nested tasks. Similar in functionality to the Java language if-else[if] construct or the switch-case-default construct but with support for non-constant choices like regular expression or criteria matches.
dowhile The <dowhile> taskset lets you execute the nested tasks repeatedly until the named test returns false (like a Java language while loop block construct). The named test can be a simple condition test, a tally, or a more complex AntXtras <criteria> taskset.
doforeach The <doforeach> taskset lets you execute the nested tasks a fixed number of times. You can specify the actual execution count in a variety of ways including number sequences, adhoc resource collection iterators, or simple delimited lists. <doforeach> also supports a set of error-handling options like ‘tryeach’ that lets you describe how to react if a single iteration fails.
call, callinline Tasks that supplement the standard <antcall> tasks. Both will execute not just one but a a sequence of targets or macros in isolation (child project), and both provide a set of error-handling options if one or more of the called targets fail.
callforeach An extension of the <call> task that calls the named targets or macros a fixed number of times. Supports the same set of looping specifications as the <doforeach> taskset.
stop Like a <fail> but lets you use resource bundle-based messages and throw custom build error types.

Example Script Snippets

1) The following snippets defines several preparatory steps for a Java build. The driver macro “prepare-javasources” will, for each module listed in an external configuration file “${conf.d}/modules”, check out a pristine copy of a CVS tag and then merge that copy into a final source workspace. Optionally, the entire final source area is archived on completion. Many details have been left out to emphasize the flow control AntXtras elements <doforeach> and <do>.

<macrodef name="checkout-sources">
  <cvs command="checkout -A" dest="${originals.d}"
       failonerror="${.strict}"
       package="${module}" tag="@{tag}"/>
  ...
 
<macrodef name="merge-javasources">
  <copy filtering="true" todir="${workspace.d}">
    <fileset dir="${originals.d}/${module}/java">
      <include name="main/"/>
      <include name="programmertests/"/>
    </fileset>
    <filterset refid="copysources.filters"/>
  </copy>
  ...
 
<macrodef name="prepare-javasources">
  <attribute name="archive" default=""/>
  ...
    <assert filenotempty="${conf.d}/modules"
       messageid="ERR.modules.defined"/>
    <properties id="modules"
       file="${conf.d}/modules"/>
    <doforeach i="module" list="${$map:modules?keys}">
       <checkout-sources tag="${$map:modules?${module}}"/>
       <merge-javasources/>
    </doforeach>
    <do true="@{archive}">
      <archive-javasources/>
    </do>
  ...
</macrodef>

2) The following snippets are part of an enclosing Ant target that runs a series of deployment smoke tests across each member of a remote server cluster. In a nutshell, the script uses many of the AntXtras execution control tasksets to determine the appropriate test inputs and configuration (<domatch>), to execute the actual smoke tests (<doforeach>), and to handle failures from the tests and from within the harness itself, (<protect>). Not shown is the outer <protect> that handles errors (when the ‘.badrun’ variable is set).

<assert allset="cluster.service.url,cluster.iports"
  malformed="reject" whitespace="reject"
  messageid="ERR.required.smoke.fixture.defined"
  arg0="cluster.service.url,cluster.iports"/>
 
<properties id="cluster-common-properties">
  <property name="version" value="${release.version}"/>
  <property name="maxwait" value="${$millis:30s}"/>
  <property name="test.login.id" value="reladmin"/>
  <property name="services" value="${$p:release.services.ids?}"/>
</properties>
 
<doforeach i="port" list="${cluster.iports}" tryeach="yes" failvar=".badrun">
  <domatch value="${$filenotempty:${conf.d}/smoke-${port}.properties">
    <true>
      <datadef name="conf.${port}" setid="yes">
        <properties file="${conf.d}/smoke-${port}.properties"/>
      </datadef>
    </true>
    <otherwise>
      <datadef name="conf.${port}" setid="yes">
        <properties>
          <properties refid="cluster-common-properties"/>
          <property name="port" value="${port}"/>
          <property name="test.version.page"
            value="http://${cluster.service.url}:${port}/version"/>
          <property name="test.service.page"
            value="http://${cluster.service.url}:${port}/status"/>
        </properties>
      </datadef>
    </otherwise>
  </domatch>
  <protect>
    <verify-cluster-instance args="conf.${port}" feedback="verbose"/>
    <always>
      <unassign ref="conf.${port}"/>
    </always>
  </protect>
</doforeach>

Execution Feedback

The AntXtras core execution feedback components provide support for external resource bundle message files, message template fill-in, and conditional messages. The feedback framework also lays the groundwork for our own Log4Ant project which lets you send your Ant scripts feedback to a full-fledged logging system like Log4J or LOGBack.

Task or Type General Description
messagesbundle Shareable datatype that lets you define where your external messages are located.
managemessages Administrator task that let you define both global fallback as well as thread-specific fallback messages resource bundles.
show Simple task that displays resource bundle based messages. By default behaves like the standard Ant <echo> task only using property-based resource bundles to locate its messages. Also supports substitution for template message parameters; up to ten(10) of them.
overlaymessages Configuration taskset that adds another message bundle for use by nested AntXtras tasks. The effect of an <overlaymessages> is like a logical 'or'– if the nearest one does not contain the requested message, the previous overlay (another overlay task or a global fallback bundle) is asked to locate the message.
copymessage Task that lets you extract a message from a bundle and copy it to a regular Ant property. Also supports substitution for template message parameters.

Example Script Snippets

1) The following snippet defines two message bundles ‘main-messages’ and ‘test-messages’. The macro immediately installs the main messages as a global fallback bundle− a last resort for message lookups by all subsequent tasks. Then the macro loads the test messages into the fixture; subsequent tasks can un/install the bundle as they need. For additional information about message bundles read “How do I install message bundles for use?”.

<macrodef name="init-messages">
  <sequential>
    <messagesbundle id="main-messages" mustexist="yes"
       resource="META-INF.ui.main-messages"/>
    <managemessages action="install-fallback"
       bundleid="main-messages"/>
    <messagesbundle id="test-messages" mustexist="yes"
       resource="META-INF.ui.test-messages"/>
  <sequential>
</macrodef>

2) The following snippet shows a macrodef ‘run-subbuild’ that loads a set of custom messages for a named module into a message bundle and then wraps a call to the module’s build so its message lookups will check strings from that bundle. The messages are available only for the duration of the macro’s execution.

<macrodef name="run-subbuild">
  <attribute name="for"/>
  <sequential>
    <overlaymessages file="${conf.d}/@{for}/messages.properties">
      <show messageid="subbuild.started" arg0="${$iso:}"/>
      [do subbuilds for '@{for}' module here…]
    </overlaymessages>
  </sequential>
</macrodef>

Helpers

The AntXtras helper components include useful standalone types and utility tasks for Ant scripts and other task implementations. Several helpers were developed as debugging or test aids so their usefulness under normal circumstances is minimal (of course your mileage may vary). Read the User Guide for the complete list of helper components AntXtras has to offer.

Type or Task General Description
printenv Task to display specified project properties, variables, and references. Also helpful for debugging your <rules> and <tallyset> declarations.
printerror Task that displays the contents of an ErrorSnapshot or a thrown exception. An ErrorSnapshot is an AntXtras data type used to capture failure information within a running script (specifically by the AntXtras <protect> taskset).
tempdir, newtempdir Tasks that locate a suitable temporary directory into which scratch files and directories can be safely created. The new directory is based on the platform-specific temporary directory (for example, $TMP or $TEMP on Unix systems or $TEMPDIR on Windows systems).
newfile, newtempfile Tasks that creates files in a specified directory. You can tag the file as temporary and AntXtras will mark them automatically for deletion on normal termination of the Ant runtime. These tasks can also initialize the new file’s contents from a source prototype file or resource. Usually used with the two tempdir tasks.
vendorinfo Task to stamp the build information of a JWare-based Ant product to a set of local properties. Useful to transfer version information for display or evaluation.

Example Script Snippets

1) The following snippet stamps a set of local properties with the current AntXtras package version information then displays that information.

<vendorinfo name="antxtras"
   prefix="oja."
   fields="date,longversion"/>
 
<show messageid="about.antxtras"
   arg0="${oja.longversion}"
   arg1="${oja.date}"/>

2) The following snippet defines a diagnostic macro “grab-universe” that captures bits of fixture information like properties and variables and saves it to several files.

<tempdir subdirectory="${user.name}/.antdump"
    pathproperty="tmp.root"/><macrodef name="grab-universe">
  <attribute name="todir" default="${tmp.root}"/>
  <attribute name="onlyproperties" default="no"/>
  <sequential>
    <echo level="info" message="Dumping Ant world to: @{todir}"/>
    <assert isdirectory="@{todir}" message="'@{todir}' is a directory"/>
    <newfile path="@{todir}/all.properties">
      <propertyset>
        <propertyref builtin="all"/>
      </propertyset>
    </newfile>
    <newfile path="@{todir}/system.properties">
      <propertyset>
        <propertyref builtin="system"/>
      </propertyset>
    </newfile>
    <newfile path="@{todir}/args.properties">
      <propertyset>
        <propertyref builtin="commandline"/>
      </propertyset>
    </newfile>
    <do false="@{onlyproperties}">
      <printenv references="all"
          tofile="@{todir}/references.txt"/>
      <printenv variables="all"
          tofile="@{todir}/variables.txt"/>
    </do>
  </sequential>
</macrodef>
1) , 2) You cannot uninstall fixed shortcuts.

Navigation
Personal Tools