My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
FlakaExamples  
Snippets, Flaka in the wild, Ant problems and solutions
Featured
Updated Jun 27, 2011

This is work in progress ...

Flaka provides some very innovative features and syntactic sugar. This page will show how to tackle common ant problems with Flaka. Examples are taken from 'real-life' => production code, questions from stackoverflow.com, the Ant user list .. etc.

Categories

Properties

One of the most common question is how to overwrite or edit existing properties in ant.

Question : How do i overwrite an existing property ?
Solution : use the let task

Properties once set are immutable in ant by design.

<!-- set a new property -->
<fl:let>foo := 'bar'</fl:let>
<!-- overwrite an existing property or userproperty
     (those properties defined on the commandline via -Dfoo=bar ..) -->
<fl:let>foo ::= 'baz'</fl:let>

notice the double '::' in foo ::= 'baz'

Question : How do i extract a specific part from a csv separated property ?
Solution : use the split function with index

<project xmlns:fl="antlib:it.haefelinger.flaka">

  <property name="module.list" value="mod1,mod2,mod3,mod4,mod5"/>

  <target name="main">
    <!-- simple echo -->
    <fl:echo>xtractedvalue => #{split('${module.list}',',')[0]}</fl:echo>
    <!-- create property for further processing.. -->
    <fl:let>
      xtractedvalue := split('${module.list}',',')[0]
    </fl:let>
    <echo>$${xtractedvalue} => ${xtractedvalue}</echo>
  </target>

</project>

output :

 [fl:echo] xtractedvalue => mod1
 [echo] ${xtractedvalue} => mod1

a similar one :

Question : Given is an ant property which has value of the type 1.0.0.123
How to extract the value after the last dot, in this case that would be '123' ?
Solution : use the split function with index

<project xmlns:fl="antlib:it.haefelinger.flaka">

 <property name="foobar" value="1.0.0.123"/>

  <target name="main">
   <!-- simple echo -->
   <fl:echo>xtractedvalue => #{split('${foobar}','\.')[3]}</fl:echo>
   <!-- create property for further processing.. -->
   <fl:let>
    xtractedvalue := split('${foobar}','\.')[3]
   </fl:let>
   <echo>$${xtractedvalue} => ${xtractedvalue}</echo>
  </target>
</project>

output :

 [fl:echo] xtractedvalue => 123
 [echo] ${xtractedvalue} => 123

Question : For some reason i need to strip of the drive name of some property
${basedir} = "D:\some\directory\blah\blah"
${cwd} = some\directory\blah\blah"
Solution : use the replace function

<project xmlns:fl="antlib:it.haefelinger.flaka" name="World">
  <!-- simple echo -->
  <fl:echo>#{replace('${basedir}', '$1' , '.:\\\\(.+)' )}</fl:echo>
  <!-- set property -->
  <fl:let>cwd := replace('${basedir}', '$1' , '.:\\\\(.+)' )</fl:let>
</project>

Files / Directories

Question : After compiling my java sources how to run the corresponding classes ?
Solution : Iterate over the fileset which contains the java sources and use the replace function to call the corresponding class files.

This example shows also how to iterate over a fileset with the ant builtin ${toString:filesetid} property.

<project xmlns:fl="antlib:it.haefelinger.flaka">

  <property name="srcroot" value="path/to/srcrootdir"/>
  <property name="classroot" value="path/to/classrootdir"/>

  <!-- seek all classes with main method -->
  <fileset dir="${srcroot}" includes="**/*.java" id="mainclasses">
    <contains text="public static void main"/>
  </fileset>

  <!-- iterate over classes with main method and call
       corresponding classfile -->
  <fl:for var="file" in="split('${toString:mainclasses}', ';')">
    <fl:let>
      ; strip the '.java' extension
      file = replace(file, '', '.java')
      ; replace fileseparator with '.'
      ; when running on windows you have to use :
      ; replace(file, '\.', '${file.separator}${file.separator}')
      file = replace(file, '\.', '${file.separator}')
      </fl:let>
    <fl:echo>
      starting => #{file} in ${classroot}..
    </fl:echo>
    <java classname="#{file}">
      <classpath>
       <!--
         when using a fileset you'll get a
         java.util.zip.ZipException because you're
         referencing not jarfiles but classfiles
         therefore you've to use pathelement location
       -->
       <pathelement location="${classroot}"/>
      </classpath>
    </java>
  </fl:for>

</project>

Question : In ant, how can i check if a set of files (comma-separated list of paths) exists or not?
Solution : use

a) when with combined file function calls
or
b) use list function to iterate over the commaseparated pathentries

<project xmlns:fl="antlib:it.haefelinger.flaka">

  <!-- when you have a cvs property use split function
       to get your list to iterate over -->
  <property name="checkpath" value="/foo/bar,/foo/baz,/foo/bazz"/>
  <fl:for var="file" in="split('${checkpath}', ',')">
    <fl:fail message="#{file} does not exist !!" test="!file.tofile.exists"/>
  </fl:for>

  <!-- creating the list inline -->
  <fl:for var="file" in="list('/foo/bar','/foo/baz', '/foo/bazz')">
    <fl:fail message="#{file} does not exist !!" test="!file.tofile.exists"/
  </fl:for>

  <!-- using some if then else construct with choose -->
  <fl:choose>
    <fl:when test="file('/foo/bar').exists and file('/foo/baz' and file('/foo/bazz').exists">
      <!-- create property based on existence -->
      <fl:let>pathExist := true</fl:let>
      <!-- .. other nested tasks .. -->
    </fl:when>
    <fl:otherwise>
      <fl:let>pathExist := false</fl:let>
      <!-- .. other nested tasks .. -->
    </fl:otherwise>
  </fl:choose>

  <echo>${pathExist}</echo>

</project>

Conditions

Question : I would like to do something like this

<target name="clean" description="clean">
    <if>
        <available file="${build}" type="dir" />
        <then>
            <delete dir="${build}" />
        </then>
    </if>
</target>

Solution :

The standard way in vanilla ant would be something like

<target name="check">
  <condition property="delbuild">
    <available file="${build}" type="dir"/>
  </condition>
 </target>

 <target name="clean" depends="check" if="delbuild">
 <delete dir="${build}"/>
    <!-- .. -->
 </target>

with Flaka its straightforward

<fl:when test=" '${build}'.isdir ">
  <delete dir="${build}"/>
</fl:when>

Question : Is there any if then else construct in ant ?
Solution : Use choose/when/otherwise

<project xmlns:fl="antlib:it.haefelinger.flaka">
  <!-- some if/then/else construct -->
  <fl:choose>
    <!-- if -->
    <when test=" '${buildtype}' eq 'prod' ">
      <!-- then -->
      <echo>..starting ProductionBuild</echo>
    </when>
    <when test=" '${buildtype}' eq 'test' ">
      <!-- then -->
      <echo>..starting TestBuild</echo>
    </when>
    <!-- else -->
    <otherwise>
      <fl:unless test="has.property.dummybuild">
        <fail message="No valid buildtype !, found => '${buildtype}'"/>
      </fl:unless>
      <echo>.. is DummyBuild</echo>
    </otherwise>
  </fl:choose>
</project>

output with ant -f build.xml -Dbuildtype=prod or
ant -f build.xml -Dbuildtype=prod -Ddummybuild=whatever

[echo] ..starting ProductionBuild

output with typo => ant - build.xml -Dbuildtype=testt

BUILD FAILED
/home/rosebud/workspace/AntTest/build.xml:21: No valid buildtype !, found => 'testt'

output with ant -f build.xml -Ddummybuild=whatever

[echo] .. is DummyBuild

Sign in to add a comment
Powered by Google Project Hosting