Valid <property> names in Ant - ant

I'd like to set some properties in my ant build file, the names of which, are based on ant's build in properties. In particular, I'd like to set a property like:
<property name="${ant.project.name}.compiled" value="true" />
However, when I tried this the ${ant.project.home} portion was not expanded.
Is it possible to use the value of properties as the names of other properties, and if so, how?

<property name="name.holder" value="iamholder" />
<property name="${name.holder}.flag" value="true" />
<echoproperties></echoproperties>
result:
[echoproperties] iamholder.flag=true
this is definitely valid ant code and the property iamholder.flag gets the value of true.
If ${name.holder} does not get expanded, it means it has not been set yet (like if the first line in my sample was missing).
Anyways, this still does not quite solve your problem, as you have pretty much no means of getting the value of this property as you don't know it's name and you can't do a nested resolve in pure ant. Depending on what you are trying to do it could still be useful to you though. This one would work (keep in mind, that until 1.8 the value is irrelevant as long as the property is set):
<target name="compile_stuff" unless="${name.holder}.flag">
<echo>compiling...</echo>
</target>
To really get the value of such a property you have to use ant-contrib's propertycopy as suggested in one of the answers. That way you can get the value in a property whose name you know. Just make sure to do the trick just before use and set the override parameter to true (your post implies that you would be setting more properties like these, but without override your final property could not be changed). Another option for working with such properties is to use ant macros.

I think the only way is to echo your values to a .properties file and then load them back.
However, you should ask yourself if you really need it; when I last used ant I tried to do the same thing but concluded I didn't really need to.
Is
$ant.project.home.compiled
not just as useful?

It can be done, a bit ugly, though. You need the < propertycopy > task from ant-contrib for this. The following shows an example
<property name="projectNameCompiled" value="${ant.project.name}.compiled" />
<property name="${projectNameCompiled}" value="true" />
<propertycopy property="final" from="${ant.project.name}.compiled" />
The property final contains the value true.

There are several ways to achieve that, see Ant FAQ
One possible solution via macrodef simulates the antcontrib / propertycopy task but doesn't need any external library.

Related

Create a fileset from a comma-separated list in a property without losing order

I use a specified property to create fileset:
<property name="cases" value="B.java,A.java,C.java" />
<fileset id="casesToBeRunning" dir="${src}" includes="${cases}" />
When casesToBeRunning created, I list the content of it:
<echo>Cases to be running: ${toString:casesToBeRunning}</echo>
it shows A.java,B.java,C.java which I'm not expected to.
I don't want Ant autosort for me, I need the original sort order of the property I defined to execute the cases orderly.
Anyone know how to handle this?
Ant filesets don't retain order - as you've seen. The related filelist type does respect ordering, so you might use:
<filelist id="casesToBeRunning" dir="${src}" files="${cases}" />
Whether the order is respected will depend on what task you plan to use to process the files. Most core Ant tasks that accept a fileset will accept a filelist instead, so you should be ok with them. For non-core tasks it may not work.
(Note that before Ant 1.8.0 some tasks didn't respect the order when traversing a filelist - among them copy for example).

How to reset a property in ANT?

I'm writing a velocity macro within which I have some ant tasks. Within a #foreach loop in the velocity macro, I have a pathconvert task:
#foreach(<iterate through something>)
<pathconvert property='filename' refid='swf.file'>
<mapper>
<chainedmapper>
<flattenmapper/>
<globmapper from='*-d.swf' to='*'/>
</chainedmapper>
</mapper>
</pathconvert>
#end
The problem I have is that the 'filename' property gets set only once, during the first iteration, since properties in ANT are immutable.
But I need the filename to be set during each iteration. Is there a way to get this done?
If there was a way to reset the property, I could do that at the end of each iteration. Or is there a better way to do this?
Any help would be highly appreciated!
Thanks in advance,
Anand
You could use ant-contrib's variables. They act like mutable properties.
http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html
Use the new lexically scoped properties in Ant 1.8:
"Lexically scoped local properties, i.e. properties that are only defined inside a target, sequential block or similar environment."
Annoucement.
Properties in Ant were designed to be immuatable, but they gave in to popular demand and gave us variables. Your alternative is to write a custom task ( in Java or a Dynamic Language) but this seems like a good compromise.
The following snippet illustrates an ant property which I guess is not documented. Properties are immutable, but references are mutable. So any data type which has no name, but a reference, is mutable. For example a fileset. But today I found a way to have a kind of mutable property. Connected with local task or some other tricks it may be a way of having variables in ant.
<property name="a" value="aaa" id="refa" />
<property name="b" refid="refa" />
<echo>${b}</echo>
<property name="c" value="ccc" id="refa" />
<property name="d" refid="refa" />
<echo>${d}</echo>
The output is:
aaa
ccc
Although in both cases a reference refa is printed.
Here is a post about it. And another one.
Use a combination of for + let task from Ant Plugin Flaka to overwrite existing properties.
See some snippets here.

How can I iterate over properties from a file?

All my projects and their versions are defined in a properties file like this:
ProjectNameA=0.0.1
ProjectNameB=1.4.2
I'd like to iterate over all the projects, and use their names and versions in an Ant script.
At present I read the entire file using the property task, then iterate over a given list in a for loop like this:
<for list="ProjectNameA,ProjectNameB" param="project">
<sequential>
<echo message="#{project} has version ${#{project}}" />
</sequential>
</for>
How can I avoid the hard-coding of the project names in the for loop?
Basically iterate over each line and extract the name and the version of a project as I go.
Seeing as you're already using antcontrib for, how about making use of the propertyselector task:
<property file="properties.txt" prefix="projects."/>
<propertyselector property="projects" match="projects\.(.*)" select="\1"/>
<property file="properties.txt" />
<for list="${projects}" param="project">
...
</for>
The idea here is to read the properties once with the projects prefix, and use the resulting set of properties to build a comma-separated list of projects with the propertyselector task. Then the properties are re-read without the prefix, so that your for loop can proceed as before.
Something you want to keep in mind, if you are reading additional .property files (besides build.properties) is scoping. If you read an additional file (via the property file="foo.property") tag, ant will show that the file was read, and the properties loaded. However, when you goto reference them, they come up un-defined.

Ant var and property scope

I have a main build script that calls various targets. One of these targets needs to store a value and another target needs to display it. Obviously this is not working so I think it may be related to scope. I've tried var, property, and declaring the property outside of target1. Since var seems to be mutable, it looks like I need to use it instead, but each time my output is empty.
Main script
<antcall target="target1"/>
<antcall target="display"/>
In target1:
<var name="myVar" value="${anotherVar}"/>
In display:
<echo>${myVar}</echo>
Do you really need to use <antcall>? Can you use target dependencies instead?
As you suspect, using <antcall> essentially creates a new scope.
antcall will start the ant target in a new project and will not affect the main project in any way. Try runtarget from antcontrib to run the targets in the same project.
You can call multiple targets with one antcall element. These targets will then share a single project instance including the properties defined. To do this specify the targets as nested elements like this:
<antcall>
<target name="target1"/>
<target name="display"/>
</antcall>
Another option I found was the antcallback, and it appears to work. This limits what is returned to just a particular list of values, which seems inherently safer than opening up the scope of the whole target (as it sets, creates, modifies many var and properties).
<antcallback target="target1" return="myVar"/>
<antcall target="display"/>
I think all of these are valid solutions, it just depends on what level you want to change the variable scope at.
<antcall target="display">
<param name="param1" value="anything" />
</antcall>
put the above code in your target1. I am sure you will be able to access your param1 in display now.

Reasons for using Ant Properties files over "Properties Tasks"

I'm currently working with some developers who like to set up Ant tasks that define environment specific variables rather than using properties files. It seems they prefer to do this because it's easier to type:
ant <environment task> dist
Than it is to type:
ant -propertyfile <environment property file> dist
So for example:
<project name="whatever" default="dist">
<target name="local">
<property name="webXml" value="WebContent/WEB-INF/web-local.xml"/>
</target>
<target name="remote">
<property name="webXml" value="WebContent/WEB-INF/web-remote.xml"/>
</target>
<target name="build">
<!-- build tasks here --->
</target>
<target name="dist" depends="build">
<war destfile="/dist/foo.war" webxml="${webXml}">
<!-- rest of war tasks here -->
</war>
</target>
I am finding it hard to convince them that properties files are they right way to go. I believe properties files are better because:
They provides more flexibility - if you need a new environment just add a new properties file
It's clearer what's going on - You have to know about this little "trick" to realize what they're accomplishing
Doesn't provide default values and the ability to use overrides - if they used property files they could provide defaults at the top of the project but have the ability to override them with a file
Script won't break if an environment task isn't supplied on command line
Of course all they hear is that they need to change their Ant script and have to type more on the command line.
Can you provide any additional arguments in favor of properties files over "property tasks"?
Properties tasks tightly couple the build file to environments. If your fellow developers are arguing that they "have to change their ant script" with your suggestions, why aren't they arguing about changing it every time they have to deploy to a new environment? :)
Perhaps you can convince them to allow both properties file and command-line configuration. I set up my Ant builds so that if a build.properties exists in the same directory as the build.xml, it reads it in. Otherwise it uses a set of default properties hard-coded into the build. This is very flexible.
<project name="example">
<property file="build.properties"/>
<property name="foo.property" value="foo"/>
<property name="bar.property" value="bar"/>
...
</project>
I don't provide a build.properties with the project (i.e. build.properties is not versioned in SCM). This way developers aren't forced to use the property file. I do provide a build.properties.example file that developers can reference.
Since Ant properties, once set, are immutable, the build file will use properties defined in this order:
Properties provided with -D or -propertyfile via the command line
Properties loaded from build.properties
Default properties within build.xml
Advantages of this approach:
The build file is smaller and therefore more maintainable, less bug-prone
Developers that just can't get away from setting properties at the command line can still use them.
Properties files can be used, but aren't required
The arguments you have are already pretty compelling. If those arguments haven't worked, then arguing isn't going to solve the problem. In fact, nothing is going to solve the problem. Don't assume that people are rational and will do the most practical thing. Their egos are involved.
Stop arguing. Even if you win, the resentment and irritation you create will not be worth it. Winning an argument can be worse than losing.
Make your case, then let it go. It's possible that after a while they will decide to switch to your way (because it actually is better). If that happens, they will act like it was their own idea. There will be no mention of your having proposed it.
On the other hand, they may never switch.
The only solution is to work towards a position of authority, where you can say how things are to be done.
The problem with the first solution (using ant property) is basically hardcoding.
It can be convenient when you start a project for yourself but quickly you have to remove that bad habit.
I'm using a property file close to what said robhruska except that I have committed the build.properties file directly. This way you have a default one.
In other hand, I understand I could add those default values in the build.xml. (I will probably try that in the next hours/days ;-) ).
Anyway, I really don't like the first approach and I would force those guys to follow the second one ...

Resources