I have defined a macro in ant script which takes host as parameter:
<macrodef name="upload">
<attribute name="host"/>
<sequential>
<echo>Uploading source code to #{host}...</echo>
<scp trust="true"
file="package/code.zip"
todir="${webserver.username}##{host}:${webserver.upload_dir}"
keyfile="${webserver.keyfile}"
passphrase="" />
</sequential>
</macrodef>
Problem is I can't figure out how to use #{host} in todir string as it already has a '#' character between username and host.
Per : https://ant.apache.org/manual/Tasks/macrodef.html ,
The escape sequence ## is used to escape #.
This allows #{x} to be placed in the text without substitution of x by using ##{x}.
So try with adding additional '#' prior to getting value of host attribute.
Also you could try setting <property name="token" value="#"/> and use it withing todir with ${token} to see if that helps
Related
Ant tasks implemented in Java, as opposed to XML Ant macros, have this peculiarity of offering a slightly different behavior for missing attributes.
In my case, I'm trying to wrap the <testng> Ant task, implemented in Java, with a macro. Specifically, I would like to expose most of the functionality offered by the TestNG ant task with some minor tweaks.
Among other similar attributes, timeOut seems a bit difficult to reproduce, since its omission behaves differently than specifying and empty string.
This is simplified version of my macro definition:
<macrodef name="my-wrapper">
<attribute name="timeOut" default=""/>
<element name="nested-elements" optional="true" implicit="true"/>
<sequential>
<testng timeOut="#{timeOut}">
<nested-elements/>
</testng>
</sequential>
</macrodef>
Which fails because Ant tries to convert the value to an integer:
Can't assign value '' to attribute timeout, reason: class java.lang.NumberFormatException with message 'For input string: ""'
I've been suggested to use <augment>, which seems to be the solution to this problem. However, I fail to understand how it should be used:
<macrodef name="my-wrapper">
<attribute name="timeOut" default=""/>
<element name="nested-elements" optional="true" implicit="true"/>
<sequential>
<augment unless:blank="timeOut" id="invocation" timeOut="#{timeOut}"/>
<testng id="invocation">
<nested-elements/>
</testng>
</sequential>
</macrodef>
The above fails because of a forward reference:
java.lang.IllegalStateException: Unknown reference "invocation"
Invering the order of <testng> and <augment> doesn't really work because the <testng> task starts executing before being augmented.
What I would need is a way to conditionally add an XML attribute to a task call. Is this possible only using Ant XML syntax?
In this situation, the simplest solution would just be to set the default for timeOut to a valid value. It expects a string that can be resolved as an integer, so try using -1 if you don't want there to be a max timeout.
<macrodef name="my-wrapper">
<attribute name="timeOut" default="-1"/>
<element name="nested-elements" optional="true" implicit="true"/>
<sequential>
<testng timeOut="#{timeOut}">
<nested-elements/>
</testng>
</sequential>
</macrodef>
Can the token itself be parsed from other values from within the property file?
Is it possible to evaluate the token key, without hardcoding the token? Can the token itself be parsed from other values from within the property file?
For example, if the properties file has the following tokens (test.properties):
module_no = 01
module_code = bb
title_01_aa = ABC
title_02_aa = DEF
title_03_aa = GHI
title_01_bb = JKL
title_02_bb = MNO
title_03_bb = PQR
Contents of build.xml
<?xml version="1.0" encoding="utf-8"?>
<project default="repl">
<property file="test.properties" />
<target name="repl">
<replace file="test.txt" token="module_title" value="title_${module_no}_${module_code}" />
</target>
</project>
Sample content with text:
Welcome to module_title.
The replace task will result in:
Welcome to title_01_bb.
How to achieve this instead?
Welcome to JKL.
This might be very basic, but please do guide me in the right direction. Thank you.
Nested property expansion does not work by default in Ant as described in the documentation:
Nesting of Braces
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.
If you check the workarounds link, one solution is to use a macrodef to copy the property:
<property file="test.properties" />
<target name="repl">
<gettitleprop name="titleprop" moduleno="${module_no}" modulecode="${module_code}" />
<replace file="test.txt" token="module_title" value="${titleprop}" />
</target>
<macrodef name="gettitleprop">
<attribute name="name"/>
<attribute name="moduleno"/>
<attribute name="modulecode"/>
<sequential>
<property name="#{name}" value="${title_#{moduleno}_#{modulecode}}"/>
</sequential>
</macrodef>
I tried to use ants loadproperties with expandproperties:
This works for simple text properties but i get weird results when a property contains a windows path.
<property name="myAntFile" value="${ant.file}" />
<loadproperties srcFile="my.properties">
<filterchain>
<expandproperties />
</filterchain>
</loadproperties>
<echo message="$${external} = ${external}" />
the properties file looks like this:
external=${myAntFile}
the result is:
Buildfile: C:\projects\trunk\build.xml
...
[echo] ${external} = C:projects\trunkbuild.xml
I know that for properties files there are escape rules for backslashes and special whitespace characters. However i dont see how i can translate the buildscripts properties to that special meaning.
Anyone has a idea how to solve that or is this a ant bug (maybe the expandproperties chain should get a additional property for escaping when used in property file contexts?)?
With ant you can use a forward slash / as the path separator when defining paths, even on Windows: C:/projects/trunk/build.xml
If ${ant.file} returns the path using backslashes, convert this path first before you load the properties file.
Unfortunately I haven't yet found the definitive way to convert paths from C:\a\path to C:/a/path and back. Supposedly pathconvert can do the trick...
<pathconvert targetos="unix" property="myAntFile.withForwardSlashes">
<path location="${myAntFile}"/>
</pathconvert>
... but it confuses relative and absolute paths and I couldn't make it work while testing this on my OS X machine.
I can create a local property in Ant within a "block" scope.
But how can I now reference the global property within the same block?
<property name="myprop" value="global"/>
...
<sequential>
<local name="myprop"/>
<property name="myprop" value="local"/>
<echo message="my local prop is ${myprop}"/> //<-- this works fine
<echo message="my global prop is ????"/> //<-- HOW?
</sequential/>
No ant-contrib please.
I'd also like to keep this in Ant, not resorting to JS.
The only thing I could think of was "copying" the global property under a different name to be used in this block
<local name="myglobprop"/>
<property name"myglobprop" value="${myprop}"/>
<local name="myprop"/>
<property name="myprop" value="local"/>
<echo message="my global prop is ${myglobprop}"/>
But that is rather unsightly and seems redundant. I am really just looking for an out-of-scope property reference method.
Edit - use case
My attempt to coerce Ant to do delayed expansion:
Let's say I have a property whose value is a combination of several other properties.
<property name="mycmdline" value="${cmd}=${type}"/>
If ${cmd} and ${type} are known before the above property, all is great. However in my case, these values are not defined (no property set). These values only become known at later stage inside a build macrodef.
I have another simple macrodef that will perform delayed expansion:
<property name="mycmdline" value="${cmd}=${type}"/>
...
<macrodef name="property-expand">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<fail if="#{name}" message="Property #{name} is already set"/>
<property name="#{name}" value="#{value}"/>
</sequential>
</macrodef>
Finally my build macrodef would contain the following snippet:
<local name="cmd"/>
<local name="type"/>
<local name="mycmdline"/>
<property name="cmd" value="#{cmd}"/>
<property name="type" value="#{type}"/>
<property-expand name="mycmdline" value="${mycmdline}"/>
The last line is obviously wrong. I am creating a (now local) property called mycmdline with expanded value of global (now out of scope) ${mycmdline}. The macrodef for delayed expansion works great on it's own, but the problem is that the global ${mycmdline} is out of scope and cannot be referenced.
What I really wanted is:
<property name="mycmdline" value="${cmd}=${type}"/>
...
<!-- In macrodef now -->
<local name="mycmdline"/>
<property-expand name="mycmdline" value="GLOBAL:${mycmdline}"/>
Instead, what I have to do is:
<property name="unexpanded_mycmdline" value="${cmd}=${type}"/>
...
<!-- In macrodef now -->
<local name="mycmdline"/>
<property-expand name="mycmdline" value="${unexpanded_mycmdline}"/>
Why?
It may not look like a lot of difference, but it's about readability. unexpanded_mycmdline and mycmdline are now two different names, when trying to follow the way the value of property gets used through a script, it now makes a disconnected jump from one property name to another (not matter how similar the names may look). The whole unexpanded_ prefix looks out of place and doesn't fit with the rest of the naming conventions, unless I name all my global variables with some prefix, which doesn't make sense either.
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