antcall based on a condition - ant

This is what I am trying to achieve:
if a property is set then call antcall target. is this doable? can someone tell me how?
<condition>
<isset property="some.property">
<antcall target="do.something">
</isset>
</condition>

Something like this should work:
<if>
<isset property="some.property"/>
<then>
<antcall target="do.something"/>
</then>
</if>
If then conditions require ant-contrib, but so does just about anything useful in ant.

I know I'm really late to this but here is another way to do this if you are using an of ant-contrib where if doesn't support a nested antcall element (I am using antcontrib 1.02b which doesn't).
<target name="TaskUnderRightCondition" if="some.property">
...
</target>
You can further expand this to check to see if some.property should be set just before this target is called by using depends becuase depends is executed before the if attribute is evaluated. Thus you could have this:
<target name="TestSomeValue">
<condition property="some.property">
<equals arg1="${someval}" arg2="${someOtherVal}" />
</condition>
</target>
<target name="TaskUnderRightCondition" if="some.property" depends="TestSomeValue">
...
</target>
In this case TestSomeValue is called and, if someval == someOtherVal then some.property is set and finally, TaskUnderRightCondition will be executed. If someval != someOtherVal then TaskUnderRightCondition will be skipped over.
You can learn more about conditions via the documentation.

Consider also you can invoke groovy for these purposes:
<use-groovy/>
<groovy>
if (Boolean.valueOf(properties["some.property"])) {
ant.project.executeTarget("do.something")
}
</groovy>

Related

Ant conditionally set attribute

Is it possible to have a dynamically set attribute in Ant?
At the moment all of our wars have the same name: "mywar.war". I'd like to have wars built with JDK6 to be "mywar-1.6.war" and those built with JDK7 to still just be "mywar.war".
Currently:
<war warfile="${dist.dir}/mywar.war">
..
<war />
I can include the Java version like this:
<war warfile="${dist.dir}/mywar-${ant.java.version}.war">
But what I'd like to have is the logic to do something like this:
if (${ant.java.version} == "1.6") {
war.name="mywar-${ant.java.version}";
} else {
war.name="mywar";
}
<war warfile="${dist.dir}/${war.name}.war">
Is there a correct way to go about that?
The way to set properties conditionally is to use the condition task:
<condition property="war.suffix" value="-1.6" else="">
<equals arg1="${ant.java.version}" arg2="1.6"/>
</condition>
<war warfile="${dist.dir}/mywar${war.suffix}.war">
The trick here is that the else="" means that war.suffix will be an empty string on any version other than 1.6.
Yes you can use some thing like that but it's not available in ant as such. You will have to download ant-contrib.jar
And then you have some thing like this
<if>
<equals arg1="${ant.java.version}" arg2="1.6" />
<then>
war.name="mywar-${ant.java.version}";
</then>
<else>
war.name="mywar";
</else>
</if>
See this link for ant contrib

Ant target calling

I would like to call target backup.yes only if the condition is true.
<condition property="directory.found.yes">
<equals arg1="${directory.found}" arg2="true"/>
</condition>
<antcall target="update.backup"/>
Is there any way to do this.
Instead of <antcall/>, do the following:
Imagine you're calling target foo, and you want to do a backup before, but only if that condition exists:
<target name="foo"
depends="update.backup">
<..../>
</target>
<target name="update.backup.test">
<condition property="directory.found.yes">
<equals arg1="${directory.found}" arg2="true"/>
</condition>
</target>
<target name="update.backup"
depends="update.backup.test"
if="directory.found.yes">
<.../>
</target>
The problem with <antcall/> is that it is used when the dependency matrix Ant uses is broken, and it's used to force a task to be done before another task is complete. When really abused, you'll end up calling the same task multiple times. I had a project here that literally called each target between 10 to 14 times, and there were over two dozen targets. I rewrote the entire build sans <antcall/> and by using true dependency setup, cut the build time by 75%.
From my experience 90% of <antcall/> is due to poor target dependency management.
Let's say you want to execute target foo. (The target the user wants to really execute), and before foo is called, you want to do your backup, but only if the directory actually exists.
In the above, foo is called. It depends upon update.backaup. The target update.backup is called, but it depends upon update.backup.test which will test whether or not the directory actually exists.
If the directory exists, the if clause on the update.backup task is true, and the task will actually execute. Otherwise, if the directory isn't there, it won't execute.
Note that update.backup first calls any dependencies before it checks whether the property on the if or unless parameter for the target entity is checked. This allows the target to call a test before it attempts to execute.
This is not a mere side effect, but built into the design of Ant. In fact, the Ant Manual on Targets](http://ant.apache.org/manual/targets.html) specifically gives a very similar example:
<target name="myTarget" depends="myTarget.check" if="myTarget.run">
<echo>Files foo.txt and bar.txt are present.</echo>
</target>
<target name="myTarget.check">
<condition property="myTarget.run">
<and>
<available file="foo.txt"/>
<available file="bar.txt"/>
</and>
</condition>
</target>
And states:
Important: the if and unless attributes only enable or disable the target to which they are attached. They do not control whether or not targets that a conditional target depends upon get executed. In fact, they do not even get evaluated until the target is about to be executed, and all its predecessors have already run.
You can do the following
In the other target:
<antcall target="update.back">
<param name="ok" value="${directory.found.yes}"/>
</antcall>
And in the update.backup target:
<target name="update.backup" if="ok">
But I think you can also do the following using the if statement from ant-contrib:
<if>
<equals arg1="${directory.found.yes}" arg2="true" />
<then>
<antcall target="update.back" />
</then>
</if>

exception when using if statment in ant script

I am trying to compare the value of a properties variable with a string as following
<if>
<equals "${mat.projectName}"="seal">
<then>
When done so, I'm getting following message.
Element type "equals" must be followed by either attribute specifications,">" or
"/>"
I'm using eclipse framework to do this.
Read the manual first:
http://ant.apache.org/manual/Tasks/conditions.html
clearly, from the manual we know for equals:
arg1 First value to test
arg2 Second value to test
So it should be
<if>
<equals arg1="${mat.projectName}" arg2="seal" />
<then>
...
I recommend you to read guides about XML first, and then, Ant's manual.
Update:
<if> task is not provided by Ant; it is provided by Ant-Contrib. So you need <taskdef>.
For example, I have ant-contrib.jar put in my project's lib directory (${basedir}/lib), so I can write the following:
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="lib/ant-contrib.jar"/>
</classpath>
</taskdef>
For more, you can check taskdef's manual page, as well as Ant-contrib's webpage:
http://ant.apache.org/manual/Tasks/taskdef.html
http://ant-contrib.sourceforge.net/
Exactly what you're error message says...
Element type "equals" must be followed by either attribute specifications,">" or "/>"
You want this:
<if>
<equals arg1="${mat.projectName}" arg2="seal"/>
<then>
<yadda, yadda, yadda/>
</then>
</if>
This is XML, so you need parameters with values. Take a look at the equals condition on this page. It takes two parameters.
Notice the format of the <if>. The condition ends with a />. The <then> is a sub-entity of the <if>, and the if clause is a sub-entity of the <then> clause. Notice that you basically indent twice.
If you're doing a not equals condition, it would look like this:
<if>
<not>
<equals arg1="${mat.projectName}" arg2="seal"/>
</not>
<then>
<yadda, yadda, yadda/>
</then>
</if>

How to make a property in Ant as mutable

I'm using ant condition task to check a file existence and directory existence and below is my code
<project name="makeitmutable" basedir="." default="main">
<target name="main">
<condition property="folderexists?" value="Yeah" else="Nope">
<and>
<available file="folderexistance" type="dir"/>
<available file="a.zip" type="file"/>
</and>
</condition>
<echo>before deleting "folderexistance" folder property folderexists?=${folderexists?}</echo>
<delete dir="folderexistance"/>
<!--after delete-->
<condition property="folderexists?" value="Yeah" else="Nope">
<and>
<available file="folderexistance" type="dir"/>
<available file="a.zip" type="file"/>
</and>
</condition>
<!--how to make below line to print Nope ?-->
<echo>After deleting "folderexistance" folder property folderexists?=${folderexists?}</echo>
</target>
</project>
My output value of the property folderexists? remains same even after deleting the directory,i.e.., Nope two times
I knew that ant properties are immutable once set cannot be changed,and also an alternative to this solution is we can use
<antcall>
task and call the main target.
Is there a way to make the property mutable within that target as in the above scenario,I'm looking for other possibilities to resolve this, what's the better programming practice for this type of problem.
As you said, properties are immutable. The only other option is to use the var task from ant-contrib.
Quote from the docs: In general, use of this task is DISCOURAGED, and the standard Ant Property should be used if possible. Having said that, in real life I use this a lot.
which says a lot, too ;-)

conditional property setting

How can i set a single property to different values based on conditions. My scenario is as follows:
1) Loop through different values of messageid
2) Give different 'comment' for each messageid
<for list="12,23,34,45" param="messageid">
<sequential>
<condition property="comment" value="wireMsg-Inbound">
<equals arg1="messageid" arg2="12"/>
</condition>
<condition property="comment" value="wireMsg-Outbound">
<equals arg1="messageid" arg2="12"/>
</condition>
<condition property="comment" value="appMsg-Inbound">
<equals arg1="messageid" arg2="12"/>
</condition>
<condition property="comment" value="appMsg-Outbound">
<equals arg1="messageid" arg2="12"/>
</condition>
</sequential>
</for>
Is this valid? Is there any other way?
Also if i want to go through the loop each time the property comment should get updated with the new value, but since properties are immutable, how do i solve this?
Thanks
The variable task is mutable. It's in the ant contrib library which I see you are already using for the for task.

Resources