I'd like to do something like a property set globbing from a set of properties, to a new one, but not save the result in a propertyset, but rather in the global property space.
For example:
<syspropertyset>
<propertyref prefix="foo."/>
<mapper type="glob" from="foo.*" to="bar.*"/>
</syspropertyset>
Will map all the properties like foo.something to bar.something, but they won't be generally available to other tasks, they are instead limited in scope to the propertyset.
You could use the echoproperties task and go via a property file. Something like:
<property name="foo.bar" value="bahh" />
<property name="foo.baz" value="bazz" />
<propertyset id="fooz">
<propertyref prefix="foo."/>
<mapper type="glob" from="foo.*" to="bar.*"/>
</propertyset>
<echoproperties destfile="bar.properties">
<propertyset refid="fooz" />
</echoproperties>
<property file="bar.properties"/>
<echoproperties prefix="foo"/>
<echoproperties prefix="bar"/>
Result (some verbiage removed to simplify):
[echoproperties] foo.bar=bahh
[echoproperties] foo.baz=bazz
[echoproperties] bar.bar=bahh
[echoproperties] bar.baz=bazz
Related
I am trying to check a folder's name, and if it contains a certain string, I want that folder path to be changed.
So far I came up with this:
<property name="component.release.dir" value="${install.dir}/${component.name}" />
<!-- Check if the component is a part of projectL -->
<condition property="projectLFolderSpotted">
<matches pattern="projectL" string="${component.release.dir}"/>
<!-- if so, put the component in an appropriate folder -->
<property name="component.release.dir" value="${install.dir}/projectL/${component.name}" />
<echo message="projectL component has been detected, and moved accordingly!"/>
</condition>
But I get the following error:
condition doesn't support the nested "property" element.
Is there a way to achieve this?
Thanks in advance.
Properties in ANT are immutable, once they're assigned a value it doesn't change.
Here's how I'd suggest you do it:
<project name="demo" default="build">
<property name="release.dir.seed" location="build/helloworld"/>
<condition property="release.dir" value="build/found/helloworld" else="build/notfound/helloworld">
<contains string="${release.dir.seed}" substring="helloworld"/>
</condition>
<target name="build">
<echo message="Result: ${release.dir}"/>
</target>
</project>
Hi all this is my code for target calling.
<target name="abc">
<var name="x" value="10"/>
<antcall target="def"/>
<!--Again Access The value of x here and also change it here-->
</target>
<target name="def">
<!--Access The value of x here and also change it here-->
</target>
and also i want to access this X in other build file,is there any way
This is not possible with ant. In an properties are immutable and cannot be reset. The var task from ant contrib can be used to override values, but should be used sparingly.
You could use a temporary file to achieve what you want. But probably you are trying something weird, which can be solved in a different way.
This would also work across buildfiles if they have access to the property file.
<target name="abc">
<var name="x" value="10"/>
<antcall target="def"/>
<!--Again Access The value of x here and also change it here-->
<var unset="true" file="myproperty.properties" /> <!-- read variable from property file-->
</target>
<target name="def">
<echo file="myproperty.properties" append="false">x=12</echo> <!-- create a new propertyfile-->
</target>
For the sake of justice, there is a hack that allows to alter ant's immutable properties without any additional libs (since java 6):
<scriptdef name="propertyreset" language="javascript"
description="Allows to assing #{property} new value">
<attribute name="name"/>
<attribute name="value"/>
project.setProperty(attributes.get("name"), attributes.get("value"));
</scriptdef>
Usage:
<target name="abc">
<property name="x" value="10"/>
<antcall target="def"/>
</target>
<target name="def">
<propertyreset name="x" value="11"/>
</target>
As #oers mentioned, this should be used with care after all canonical approaches proved not to fit.
It is difficult to suggest further without knowing the goal behind the question.
I'm trying to refactor an Ant buildfile with many similar targets into a buildfile that uses macros. This roughly is what it looks like:
<macrodef name="build-text">
<argument name="lang" />
<element name="file-list"/>
<sequential>
<property name="lang" value="#{lang}" />
<xslt style="my_stylesheet.xsl" destdir="build" basedir="src">
<!-- lots of params here -->
<file-list />
</xslt>
</sequential>
</macrodef>
<target name="buildTextDE">
<build-text lang="DE">
<file-list>
<mapper>
<mapper type="glob" from="Text1_${lang}.html" to="Text1_${lang}.fo"/>
<mapper type="glob" from="Text2_${lang}.html" to="Text2_${lang}.fo"/>
</mapper>
</file-list>
</build-text>
</target>
There is another task called buildTextEN that is nearly identical except for the lang attribute. In some cases, the file list differs however. Now how would I like to simplify the buildfile further by defining a "global" mapping list that contains the file lists for German and English, each file with the placeholder for the language. I would like to reference this global mapping where no special case is needed. How would I do that?
I have a set of nested Ant build files, and I need to control which properties are inherited by each "sub" task. I'm trying to define these as propertysets (to keep the code manageable) but these are not inherited by subtasks, unlike properties.
The example below demonstrates the problem, foo.* get copied into the middle project but not to the bottom project. If I define each property to be inherited explicitly, like bar.*, they get inherited by the bottom project too.
Is there any way to get a group of properties to inherit all the way down, in the same way individual properties do? Without rewriting the sub-processes, is there something else I could try?
[top.xml]
<?xml version="1.0"?>
<project name="test-top">
<property name="foo.1" value="1"/>
<property name="foo.2" value="2"/>
<property name="bar.1" value="1"/>
<property name="bar.2" value="2"/>
<ant antfile="middle.xml" inheritall="false">
<propertyset>
<propertyref prefix="foo."/>
</propertyset>
<property name="bar.1" value="${bar.1}"/>
<property name="bar.2" value="${bar.2}"/>
</ant>
</project>
[middle.xml]
<?xml version="1.0"?>
<project name="test-middle">
<echo>foo ${foo.1} ${foo.2}</echo>
<echo>bar ${bar.1} ${bar.2}</echo>
<ant antfile="bottom.xml" inheritall="false"/>
</project>
[bottom.xml]
<?xml version="1.0"?>
<project name="test-bottom">
<echo>foo ${foo.1} ${foo.2}</echo>
<echo>bar ${bar.1} ${bar.2}</echo>
</project>
[OUTPUT OF ant -f top.xml]
[echo] foo 1 2
[echo] bar 1 2
[echo] foo ${foo.1} ${foo.2}
[echo] bar 1 2
I think Alexander's solution is close. How about this though, doesn't need any change in middle.xml or bottom.xml.
The idea is to use the echoproperties task to 'unroll' the propertyset to individual properties, then to use that in the ant task call.
Before calling middle.xml, write the property set out using something like this:
<echoproperties destfile="myproperties.txt">
<propertyset>
<propertyref prefix="foo."/>
<propertyref prefix="bar."/>
</propertyset>
</echoproperties>
Then make the call to middle.xml:
<ant antfile="middle.xml" inheritall="false">
<property file="myproperties.txt" />
</ant>
Properties supplied to the ant task inherit all the way down as you say, so you only need to change top.xml:
These properties become equivalent to
properties you define on the command
line. These are special properties and
they will always get passed down, even
through additional <ant> tasks with
inheritall set to false (see above).
In top.xml you can create a file with inheritable properties using <propertyfile> task.
Then you can load this file with <property file="..."/>in each of your submodules.
I am trying to assign two different strings to two different variables dependent on two booleans in Ant.
Pseudocode (ish):
if(condition)
if(property1 == null)
property2 = string1;
property3 = string2;
else
property2 = string2;
property3 = string1;
What I've tried is;
<if>
<and>
<not><isset property="property1"/></not>
<istrue value="${condition}" />
</and>
<then>
<property name="property2" value="string1" />
<property name="property3" value="string2" />
</then>
<else>
<property name="property2" value="string2" />
<property name="property3" value="string1" />
</else>
</if>
But i get a null pointer exception for the line containing "<if>". I can get it to work using <condition property=...> tags but can only set one property at a time. I tried using <propertyset> but that wasn't allowed either.
I'm new to ant as you will probably have guessed :).
Gav
There are several ways to do this. The most straightforward is to just use two condition statements, and take advantage of property immutability:
<condition property="property2" value="string1">
<isset property="property1"/>
</condition>
<condition property="property3" value="string2">
<isset property="property1"/>
</condition>
<!-- Properties in ant are immutable, so the following assignments will only
take place if property1 is *not* set. -->
<property name="property2" value="string2"/>
<property name="property3" value="string1"/>
This is a bit cumbersome and doesn't scale well, but for just two properties I would probably use this approach.
A somewhat better way is to use a conditional target:
<target name="setProps" if="property1">
<property name="property2" value="string1"/>
<property name="property3" value="string2"/>
</target>
<target name="init" depends="setProps">
<!-- Properties in ant are immutable, so the following assignments will only
take place if property1 is *not* set. -->
<property name="property2" value="string2"/>
<property name="property3" value="string1"/>
<!-- Other init code -->
</target>
We are again taking advantage of property immutability here. If you don't want to do that, you can use the unless attribute, and an extra level of indirection:
<target name="-set-props-if-set" if="property1">
<property name="property2" value="string1"/>
<property name="property3" value="string2"/>
</target>
<target name="-set-props-if-not-set" unless="property1">
<property name="property2" value="string2"/>
<property name="property3" value="string1"/>
</target>
<target name="setProps" depends="-set-props-if-set, -set-props-if-not-set"/>
<target name="init" depends="setProps">
<!-- Other init code -->
</target>
It is important to note that the if and unless attributes of target only check if the property is set, not the value of the property.
You can use Ant-Contrib library to have access to a neat <if><then><else> syntax, however it will require a few download/install steps.
See this other SO question: ant-contrib - if/then/else task