Ant get the value of a parameter obtained at runtime - ant

I have an Ant build task where in based I need to lookup the property file based on a value which I get at runtime. For example, I have the following information in property file
COMPLETE_LIST=TEST1,TEST2,TEST3
TEST1=val1
TEST2=val2
TEST3=val3
In my Ant target, I have the following task.
<target name="target_main">
<foreach param="profile_name" list="${COMPLETE_LIST}" target="target_child">
</foreach>
</target>
<target name="target_child">
<echo>Printing the value of the param passed ${${profile_name}}</echo>
</target>
But this is not working. Is there any way to get the value of TEST1 which is passed as a parameter?

Since you already are using ant-contrib, the propertycopy task will help you do what you want. Here's the body of target_child modified to suit your purpose:
<target name="target_child">
<propertycopy name="value" from="${profile_name}"/>
<echo>Printing the value of the param passed ${${profile_name}}</echo>
</target>
The output:
target_main:
target_child:
[echo] Printing the value of the param passed val1
target_child:
[echo] Printing the value of the param passed val2
target_child:
[echo] Printing the value of the param passed val3

Related

how to pass parameters to ant task's depends field

I have a build.xml that should receive dynamically parameters to the depends field.
I define this parameter in some other app.xml such as:
ops=op1, op2, op3,op4,op5,.... opn
then I import this app.xml into build.xml and want to use the parameter ops there.
<project name="Project" basedir="." default="help">
<target name="test" depends="{$ops}" description="executea series of commands in ant">
<echo message="batch operation job done. tasks = {$ops}"/>
</target>
</project>
How can I pass a parameter from one ant file to another?
The depends parameter does not take properties.
Ant uses a dependency matrix to determine what should be built and in what order. This matrix is calculated before any part of the build file itself is executed, so properties aren't even set when this is done.
What are you trying to accomplish? Maybe if we have a better idea what you want, we can help you with it. Ant isn't a scripting language like BASH or Python.
As already mentioned, you can't put properties into the Depends field. However, if you are setting a property, you can use it in the If field. Example
<project name="appProject">
<target name="test" depends="target1,target2,target3" description="execute series of commands"/>
<target name="target1" if="do.target1">
<echo message="Target1 executed." />
</target>
<target name="target2" if="do.target2">
<echo message="Target2 executed." />
</target>
<target name="target3" if="do.target3">
<echo message="Target3 executed." />
</target>
</project>
Then you set in your build.xml the given target flag do.target1, do.target2 or do.target3 and it gets executed. Basically what you wanted to have. In the If field properties are only checked for value. Also, you don't have to use the ${ } construction for the properties.

Does ANT apply prefixValues if there is no property of the desired name ? Or is this a bug ? (SSCCE provided)

I have this weird behavior with ant and properties and I'd like to know what do you think. I don't get the logic.
This behavior could be usefull but I would like to know if I can rely on it or if this is a bug.
It looks like ant is applying the prefix when expanding the right hand side of properties if there is no property of the desired name. Here is the SSCCE:
build.properties:
a=A
formula=${a}
build.xml:
<project default="test">
<target name="test">
<property name="test.a" value="[test.a has been used instead of a, why? prefixValues is false]" />
<property file="build.properties" prefix="test" prefixValues="false" />
<echo>${test.formula}</echo>
</target>
</project>
output:
test:
[echo] [test.a has been used instead of a, why? prefixValues is false]
BUILD SUCCESSFUL
Total time: 364 milliseconds
As you can see, test.formula should use "a" and not "test.a" but "a" is never defined. Is it the reason?
Indeed, it seems weird.
In my opinion, the output should be ${a}
I did a few test and I notice that:
If you define a in the build.xml instead of build.properties : it works as expected. i.e. with the following build.xml:
<project default="test">
<target name="test">
<property name="a" value="A" />
<property file="build.properties" prefix="test" prefixValues="false" />
<echo>${test.formula}</echo>
</target>
</project>
and the build.properties
formula=${a}
output is
A
But, if you change to prefixValues="true" the ouput is :
${a}
while I was expecting : ${test.a}
Finally, if you define <property name="test.a" value="some value" /> in the build.xml (always with prefixValues="true") : the output is now (as expected)
some value
So, my conclusion:
prefixValues works fine as soon as the property used on the right side is not defined in the same property file.
prefixValues is ignored for properties used on the right side and defined in the same property file.
Taking a look in Ant code, in properties related classes, on org.apache.tools.ant.property.ResolvePropertyMap class:
public void resolveAllProperties(Map<String, Object> map, String prefix,
boolean prefixValues) {
// The map, prefix and prefixValues flag get used in the
// getProperty callback
this.map = map;
this.prefix = prefix;
this.prefixValues = prefixValues;
for (String key : map.keySet()) {
expandingLHS = true;
Object result = getProperty(key);
String value = result == null ? "" : result.toString();
map.put(key, value);
}
Then, in getProperty(String) method (snippet):
// If the property we are looking up is a key in the map
// (first call into this method from resolveAllProperties)
// or we've been asked to prefix the value side (later
// recursive calls via the GetProperty interface) the
// prefix must be prepended when looking up the property
// outside of the map.
String fullKey = name;
if (prefix != null && (expandingLHS || prefixValues)) {
fullKey = prefix + name;
}
So, as you can see, if the property is present in the property file, it will receive the prefix even if prefixValues is false.
I ran some more test and could get a lot of different results.
After checking the sources, I think that there is a bug when looking for properties while adding them through a file. By modifying some ant source code, I could get it to work.
In the end, I decided to fill a bug report (https://issues.apache.org/bugzilla/show_bug.cgi?id=54769) with a proposed patch.
Thank you all.
It's because properties are immutable. Once set, they're stuck that way for the rest of the build. Check out the docs for 'property' on the Ant manual. It's actually kind of a problem for some people, so the ant-contrib guys included a new task to mimic a variable.
If you change your build around like this:
<project default="test">
<target name="test">
<property file="build.properties" prefix="test" prefixValues="false" />
<property name="test.a" value="[test.a has been used instead of a, why? prefixValues is false]" />
<echo>${test.formula}</echo>
</target>
</project>
You get 'A' on the console. This is because test.a and test.formula got defined in the first call to before your new (ignored) assignment to 'test.a'

Override one value in properties file

I have a properties file:
custom.properties
the content of this properties file is:
id=sf2j2345kkklljhlaasfsdfafsf543
name=SOME_NAME
The value of id is a long random string.
I want to make an Ant script to replace/over-write the value of id to another one, I tried with Ant <replace> syntax:
<target name="change-id">
<replace file="custom.properties" token="id" value="aaa" />
</target>
I run ant change-id , the content of the properties file becomes:
aaa=sf2j2345kkklljhlaasfsdfafsf543
name=SOME_NAME
That's the key "id" get replaced instead of its value. But I need to replace the value to "aaa" , how to achieve this in Ant?
Please do not recommend me to set token to id's random value, because that value is random generated and put there. I only want to over-write the random value of "id" by Ant script, how to achieve this?.
You can do it using replaceregexp task. Try to do it like in this example
conf.ini (utf-8)
aaa=sf2j2345kkklljhlaasfsdfafsf543
name=SOME_NAME
build.xml
<project name="regexp.replace.test" default="test">
<target name="test">
<replaceregexp file="conf.ini" match="^aaa=.*" replace="aaa=newId" encoding="UTF-8" />
</target>
</project>
I don't know exactly if this regular expression is correct but this is the way you can do it.

How to acess property within a property in ant

Hi all please give a look to this code
in my properties file i have
win-x86.pc-shared-location=E:\Ant_Scripts
Now below i am trying to call PrintInstallerName_build from my build.xml,while as PrintInstallerName_build is in test.xml. In build.xml file,${platform.id} has value=win-x86 in the calling target and in called target param1 also has value=win-x86
<target name="PrintInstallerName" >
<echo>PlatForm.Id====>${platform.id}</echo>
<ant antfile="test.xml" target="PrintInstallerName_build">
<property name="param1" value="${platform.id}"/>
</ant>
<target name="PrintInstallerName_build" >
<echo>${param1.pc-shared-location}</echo><!--${param1.pc-shared-location}-->
<echo>${param1}.pc-shared-location}</echo><!--win-x86.pc-shared-location-->
<echo>${win-x86.pc-shared-location}</echo><!--E:\\Ant_Scripts-->
</target>
as you can see only the last statement gives correct output but it is hardcoded,i want to use param1 and the output should be E:\\Ant_Scripts i tried to use $ and # but none works,may be i am doing wrong somewhere can someone help please,i am struck and tomorrow is its DOD.
See Nesting of Braces in the Properties page of the Ant Manual.
In its default configuration Ant will not try to balance braces in
property expansions, it will only consume the text up to the first
closing brace when creating a property name. I.e. when expanding
something like ${a${b}} it will be translated into two parts:
the expansion of property a${b - likely nothing useful.
the literal text } resulting from the second closing brace
This means you can't use easily expand properties whose names are
given by properties, but there are some workarounds for older versions
of Ant. With Ant 1.8.0 and the the props Antlib you can configure Ant
to use the NestedPropertyExpander defined there if you need such a
feature.
You can use <propertycopy> to make it happen.
Consider that you need to have the property value of ${propA${propB}}
Use ant tag of propertycopy as follows:
<propertycopy property="myproperty" from="PropA.${PropB}"/>
<echo >${myproperty}</echo>
This will echo the value of ${propA${propB}}
<target name="PrintInstallerName_process" >
<echo>${param1}</echo><!--win-x86-->
<macrodef name="testing">
<attribute name="v" default="NOT SET"/>
<element name="some-tasks" optional="yes"/>
<sequential>
<echo>Source Dir of ${param1}: ${#{v}}</echo><!-- Dir of Win-x86:E:\Ant_Scripts-->
<some-tasks/>
</sequential>
</macrodef>
<testing v="${param1}.pc-shared-location">
<some-tasks>
</some-tasks>
</testing>
</target>
this is the way it works and for me it works fine anyways #sudocode your tip took me there so thank you very much

How to call some Ant target only if some environment variable was not set?

I would like to not call a target in build.xml in the case that there is a certain environment variable.
Using Ant 1.7.0, the following code does not work:
<property environment="env"/>
<property name="app.mode" value="${env.APP_MODE}"/>
<target name="someTarget" unless="${app.mode}">
...
</target>
<target name="all" description="Creates app">
<antcall target="someTarget" />
</target>
Target "someTarget" executes whether there is the environment variable APP_MODE or not.
The docs for the unlessattribute say:
the name of the property that must not be set in order for this target to execute, or something evaluating to false
So in your case, you need to put the name of the property, rather than an evaluation of the property:
<target name="someTarget" unless="app.mode">
...
</target>
Notes
In Ant 1.7.1 and earlier, these attributes could only be property names.
As of Ant 1.8.0, you may instead use property expansion; a value of true (or on or yes) will enable the item, while false (or off or no) will disable it.
Other values are still assumed to be property names and so the item is enabled only if the named property is defined.
Reference
if/unless on the ant manual
Unless attribute suggest in simple language that if property is set then the task would not be get executed. for ex.
<target name="clean" unless="clean.not">
<delete dir="${src}" />
<property name="clean.not" value="true" />
<delete dir="${dest}" />
</target>
Here , if you call clean target , it gets executed first then its value is set. And if you want to call it again in script then it would not as property must not be set in order to get the task executed.

Resources