How to make a property in Ant as mutable - ant

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 ;-)

Related

How to check a property or variable is empty and set a value then test for that value

We are using Ant 1.8. I am not an Ant developer but I have to pretend sometimes.
A new property, ${noReportDSUpgrade}, is intended to be "true" or "false".
By default it is empty (not exist?) which is "false" for our purposes.
If this property is empty it should be set to "false".
A command line using this parameter should set it to true.
1) How do I set ${noReportDSUpgrade} to false if empty and true if supplied?
2) For the target, how to execute only if false?
I have tried several suggestions I've found but can't get it to work.
At the beginning of the script:
<target name="init">
<antcall target="setnoReportDSUpgradeProperty"/>
Further down:
<target name="setnoReportDSUpgradeProperty">
<condition>
<or>
<equals arg1="${noReportDSUpgrade}" arg2=""/>
<not>
<isset property="false"/>
</not>
</or>
</condition>
<echo message="noReportDSUpgrade set to ${noReportDSUpgrade}"/>
</target>
Here's how to set a default property value in Ant:
<property name="noReportDSUpgrade" value="false" />
That's it! Properties are immutable in Ant, so if you set a value via command line or earlier in the script, subsequent <property> tasks won't change it. This won't account for the property being set to a blank value (i.e. ""), but as a general good practice, try to avoid setting properties to blank.
Even though I don't think you need a <condition> task for your goals here, I feel I should clear some things up in your example. The <condition> task doesn't affect the <target> that it's nested in; it simply sets a property, specified by the property attribute. Additionally, the isset condition's property attribute is used to point to the name of the property you're checking, not the value.
<condition property="noReportDSUpgrade">
<or>
<equals arg1="${noReportDSUpgrade}" arg2=""/>
<not>
<isset property="noReportDSUpgrade" />
</not>
</or>
</condition>
But like I said above, don't use that unless you really need to check for a blank value for some reason. Just use <property>.
As for running targets conditionally, the <target> block supports if and unless attributes that control whether or not the entire thing runs. This can be a bit confusing because there are two modes in which this operates.
<target name="myTarget" if="myCondition">
<echo message="Running myTarget" />
</target>
The above target will run if myCondition is set (not if its value is true). So if it evaluates to "true", "false", "asdf", or just blank, the target will still run. Conversely, if we used the unless attribute, it wouldn't run if myCondition is set to anything. This is usually convenient for when you're using the <condition> task to set your properties (since <condition> does not set a value if the boolean evaluates to false).
<target name="myTarget" if="${myCondition}">
<echo message="Running myTarget" />
</target>
Notice the ${} around myCondition. When you expand the property like this, Ant will only run the target if the property's value is "true", "on", or "yes".
Lastly, you typically don't need to make a separate target just for setting conditions. In relatively simple scripts, you can just use the implicite root target (i.e. put the tasks at root level outside of all other targets).
In short, here's the simplest way to write your script.
<project name="myProject">
<property name="noReportDSUpgrade" value="false" />
<target name="myTarget" if="${noReportDSUpgrade}">
<echo message="Running myTarget" />
</target>
</project>
If you really need an initialization target (note the depends attribute):
<project name="myProject">
<target name="init">
<property name="noReportDSUpgrade" value="false" />
</target>
<target name="myTarget" if="${noReportDSUpgrade}" depends="init">
<echo message="Running myTarget" />
</target>
</project>

Removing absent entries from an ant path

I've got a situation where we're generating an Ant <path> which may contain some directories which don't actually exist. Unfortunately this is being fed into bnd, which blows up if anything in the path is missing.
So what I want is a way to filter a <path> to keep only those path elements which actually exist.
Is there a simple way to say this in Ant, or do I have to write a task?
I believe I have found an answer:
<path id="bnd.cp.existing">
<restrict>
<path refid="bnd.cp"/>
<exists/>
</restrict>
</path>
<!-- To see when it happens, add the following: -->
<echo message="bnd classpath is: ${toString:bnd.cp.existing}"/>
<iff>
<not>
<equals arg1="${toString:bnd.cp.existing}"
arg2="${toString:bnd.cp}"/>
</not>
<then>
<echo message=" trimmed from: ${toString:bnd.cp}"/>
</then>
</iff>
The restrict operation can take a path-like structure as input and return a version of it with the requested filtering applied -- in this case keep only the path elements which actually exist. This is then re-bound to a new ID for use by the <bnd> operation.

Ant condition block

I have an ant condition like this:
<condition property="create_stub">
<and>
<available file="${create_stub_command_file}" property="stub_script.present" />
<isset property="packaged_stub_file"/>
</and>
</condition>
My understanding is: If create_stub_command_file is present then set stub_script.present=true. But I am not sure about
<isset property="packaged_stub_file"/>
What is this doing? And how does it change the overall condition. i.e In which case would the condition block evaluate to true?
A slight mistake?
<condition property="create_stub">
<and>
<available file="${create_stub_command_file}" property="stub_script.present" />
<isset property="packaged_stub_file"/>
</and>
</condition>
I don't believe that property="stub_script.present" is doing anything. It should be:
<condition property="create_stub">
<and>
<available file="${create_stub_command_file}"/>
<isset property="packaged_stub_file"/>
</and>
</condition>
All that condition statement is doing is setting a property called create_stub. It will set the property if both a file or directory called whatever {$create_stub_command_file} exists, and if the property packaged_stuf_file is set to any value. The property packaged_stub_file can be set to false, to a null string, to true, to YES! YES! YES! or to anything, as long as it is set.
So now you can use this property as a test for a target:
<target name="package_stub"
if="create_stub">
<blah...blah...blah/>
<yadda...yadda...yadda/>
</target>
This target, package_stub will only execute if the property package_stub is set. And it will only be set if that <condition> above is true.
That <condition> statement should be outside of any targets, so it will be executed first before any targets are executed.
Equivolent pseudo code:
if (File($create_stub_command_file).exists) then
property["stub_script.present"] := true
end
if (File($create_stub_command_file).exists AND property["property["stub_script.present"] != NULL) then
property["create_stub"] := true
end
Forgive any errors... I find condition blocks tricky and they need lots of testing. You're best advised to keep them simple. ANT is not a programming language.

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>

antcall based on a condition

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>

Resources