Split a string in Ant - ant

I need to split and manipulate a string using Ant.
Requirement is: I have following properties in my ant file
UserName=userName
Password=password
ConnectString=jdbc.oracle:thin#testdb:1521:db11g
I need to manipulate ConnectString to:
jdbc.oracle:thin:userName/password#testdb:1521:db11g
Any pointers will be very helpful.

Why not built your ConnectString property like that ? :
<property name="UserName" value="userName"/>
<property name="Password" value="password"/>
<property name="ConnectString" value="jdbc.oracle:thin:${UserName}/${Password}#testdb:1521:db11g"/>
Otherwise use script task with builtin javascript engine (JDK >= 1.6.0_06) and ant api for property manipulation, f.e. :
<project>
<property name="UserName" value="userName"/>
<property name="Password" value="password"/>
<property name="ConnectString" value="jdbc.oracle:thin#testdb:1521:db11g"/>
<script language="javascript">
a = project.getProperty('ConnectString').split('#')
// to overwrite existing ConnectString property use
// project.setProperty('ConnectString' ...);
project.setProperty('foo', a[0] + ':' + project.getProperty('UserName') +
'/' + project.getProperty('Password') + '#' + a[1]);
</script>
<echo>$${foo} => ${foo}</echo>
</project>
output :
[echo] ${foo} => jdbc.oracle:thin:userName/password#testdb:1521:db11g

Related

Ant property value as parameter variable In JENKINS

I am working on Jenkins.
I have built a job1 with secret text: username and Password variable as
APP1_Dev_password
And using this variable from my ANT script by sending this variable in the predefined parameter to my other job2. I am accessing this variable using
<property name="DBPassword" value="${APP1_Dev_password}"/>
This works well.
But my ant script is a single generalized script for all my applications.
So I have get this APP1_Dev_password string constructed automatically from my ant script using
<property name="constructPasswordVariable" value="${APPLICATIONNAME}_${ENVIRON}_password"/>
<echo message= "constructPasswordVariable: ${constructPasswordVariable}" />
This clearly prints me constructPasswordVariable as APP1_Dev_password.
Now i have to use this value of the constructPasswordVariable property as a variable to fetch from the job1.
<echo message= "PasswordValue: ${${constructPasswordVariable}}" />
This statement fails. Can you guide me of how to work on this.
SOLUTION
<property name="constructPasswordVariable" value="${env.Module}_${env.Environment}_password"/>
<echo message= "constructPasswordVariable: ${constructPasswordVariable}" />
<propertycopy name="prop" from="${constructPasswordVariable}"/>
<echo message= "ENV VALUE: ${prop}" />
Output
constructPasswordVariable: APP1_Dev_password
ENV VALUE: asdhasd
Ant says nested property is not directly supported. Referring documentation from here
However, it can be achieved using library Flaka
Sample: from above reference
<project xmlns:fl="antlib:it.haefelinger.flaka">
<fl:install-property-handler/>
<property name="foo" value="foo.value"/>
<property name="var" value="foo" />
<property name="buildtype" value="test"/>
<property name="appserv_test" value="//testserver"/>
<echo>
#{${var}} = foo.value
<!-- nested property -->
#{appserv_${buildtype}}
</echo>
</project>
There is another reference here which make it possible without additional library as well.
Sample:
<project default="test">
<property name="foo" value="ABC"/>
<property name="pfoo" value="foo"/>
<target name="test">
<echo file="deref.properties">
deref: $${${pfoo}}
</echo>
<property file="deref.properties"/>
</target>

What are the alternatives for <first> in NAnt?

In Ant you can use the following script:
<first id="first">
<fileset dir="dir.zips" includes="**/a.zip" />
</first>
<echo message="${toString:first}" />
to get the first file from the filelist.
Is there any alternative for the same in NAnt. <First> is not a valid task in NAnt.
I found an alterative, though it is not efficient
<property name="iter" value="0" overwrite="true"/>
<property name="first" value="" overwrite="true"/>
<foreach item="file" property="filename" in"src\build">
<do>
<if test="${iter == '0'}">
<property name="first" value="${filename}" overwrite="true"/>
</if>
<do>
<property name = "iter" value="${int::parse(iter) + 1}"/>
</foreach>
Since the loop won't break after first iteration, I have decided to create a custom task.

In Ant, how can I dynamically build a property that references a property file?

I am using Input tasks to collect specific property values and I want to concatenate those into one property value that references my properties file.
I can generate the format of the property but at runtime it is treated as a string and not a property reference.
Example properties file:
# build.properties
# Some Server Credentials
west.1.server = TaPwxOsa
west.2.server = DQmCIizF
east.1.server = ZCTgqq9A
Example build file:
<property file="build.properties"/>
<target name="login">
<input message="Enter Location:" addproperty="loc" />
<input message="Enter Sandbox:" addproperty="box" />
<property name="token" value="\$\{${loc}.${box}.server}" />
<echo message="${token}"/>
</target>
When I call login and provide "west" and "1" for the input values, echo will print ${west.1.server} but it will not retrieve the property value from the properties file.
If I hardcode the property value in the message:
<echo message="${west.1.server}"/>
then Ant will dutifully retrieve the string from the properties file.
How can I get Ant to accept the dynamically generated property value and treat it as a property to be retrieved from the properties file?
The props antlib provides support for this but as far as I know there's no binary release available yet so you have to build it from source.
An alternative approach would be to use a macrodef:
<macrodef name="setToken">
<attribute name="loc"/>
<attribute name="box"/>
<sequential>
<property name="token" value="${#{loc}.#{box}.server}" />
</sequential>
</macrodef>
<setToken loc="${loc}" box="${box}"/>
Additional example using the Props antlib.
Needs Ant >= 1.8.0 (works fine with latest Ant version 1.9.4)
and Props antlib binaries.
The current build.xml in official Props antlib GIT Repository (or here) doesn't work out of the box :
BUILD FAILED
Target "compile" does not exist in the project "props".
Get the sources of props antlib and unpack in filesystem.
Get the sources of antlibs-common and unpack contents to ../ant-antlibs-props-master/common
Run ant antlib for building the jar :
[jar] Building jar: c:\area51\ant-antlibs-props-master\build\lib\ant-props-1.0Alpha.jar
Otherwise get the binaries from MVNRepository or here
The examples in ../antunit are quite helpful.
For nested properties look in nested-test.xml
Put the ant-props.jar on ant classpath.
<project xmlns:props="antlib:org.apache.ant.props">
<!-- Activate Props antlib -->
<propertyhelper>
<props:nested/>
</propertyhelper>
<property file="build.properties"/>
<input message="Enter Location:" addproperty="loc" />
<input message="Enter Sandbox:" addproperty="box" />
<property name="token" value="${${loc}.${box}.server}"/>
<echo message="${token}"/>
</project>
output :
Buildfile: c:\area51\ant\tryme.xml
[input] Enter Location:
west
[input] Enter Sandbox:
1
[echo] TaPwxOsa
BUILD SUCCESSFUL
Total time: 4 seconds
Solution is :
Consider problem is this, where you want to achieve this :
<property name="prop" value="${${anotherprop}}"/> (double expanding the property)?
You can use javascript:
<script language="javascript">
propname = project.getProperty("anotherprop");
project.setNewProperty("prop", propname);
</script>
I gave it a try and this is working for me.

Use Property value as a Key to read another value from Properties file

For Ant Script I have following myBuild.properties file
p.buildpath=c:\production\build
d.buildpath=c:\development\build
I wrote following build.xml:
<?xml version="1.0"?>
<project name="Test Project" default="info">
<property file="myBuild.properties"/>
<target name="info">
<input
message="Please enter the Server Name(p: production, d: development)?"
validargs="p,d"
addproperty="do.Server"
/>
<echo>Your Server type: ${do.Server} </echo>
<property name="myserv.buildpath" value="${do.Server}.buildpath" />
<property name="newProperty" value="${myserv.buildpath}" />
<echo>New Property Value: ${newProperty}</echo>
<!-- Following is an incorrect syntax -->
<echo>Build Path: ${${newProperty}}</echo>
</target>
</project>
When I run it using:
c:\>ant
I get following Output:
Buildfile: C:\build.xml
info:
[input] Please enter the Server Name(p: production, d: development)? (p, d)
p
[echo] Your Server type : p
[echo] New Property Value: p.buildpath
[echo] Build Path: ${${newProperty}}
BUILD SUCCESSFUL
Total time: 2 seconds
I want to echo the "Build Path" value same as p.buildpath value.
How is it possible to do in above case?
Taking the macrodef advice of Ant Faq you need no Ant addons like antcontrib, it's foolproof :
<project>
<macrodef name="cp_property">
<attribute name="name"/>
<attribute name="from"/>
<sequential>
<property name="#{name}" value="${#{from}}"/>
</sequential>
</macrodef>
<property file="myBuild.properties"/>
<input
message="Please enter the Server Name(p: production, d: development)?"
validargs="p,d"
addproperty="do.Server"
/>
<echo>Your Server type: ${do.Server}</echo>
<cp_property name="myserv.buildpath" from="${do.Server}.buildpath"/>
<echo>$${myserv.buildpath} : ${myserv.buildpath}</echo>
</project>
output :
[input] Please enter the Server Name(p: production, d: development)? (p, d)
p
[echo] Your Server type: p
[echo] ${myserv.buildpath} : c:/production/build
btw. Within your propertyfile you need to change your path separator to either unix style '/' (when on windows ant will handle it correctly) or double '\\' , otherwise with :
p.buildpath=c:\production\build
d.buildpath=c:\development\build
you'll get something like :
[input] Please enter the Server Name(p: production, d: development)? (p, d)
p
[echo] Your Server type: p
[echo] ${myserv.buildpath} : c:productionbuild
Also see https://stackoverflow.com/a/25681686/130683 for a very similar problem solved with Props antlib
You can do it without additional tools this way (edited/revised version):
<project name="Test Project" default="info">
<property file="myBuild.properties"/>
<target name="info">
<input
message="Please enter the Server Name(p: production, d: development)?"
validargs="p,d"
addproperty="do.Server"
/>
<echo>Your Server type: ${do.Server} </echo>
<property name="buildstage.production" value="p.buildpath" />
<property name="myserv.buildpath" value="${do.Server}.buildpath" />
<echo>New Property Value: ${myserv.buildpath}</echo>
<condition property="isProduction">
<equals arg1="${buildstage.production}" arg2="${myserv.buildpath}" />
</condition>
<antcall target="production" />
<antcall target="development" />
</target>
<target name="production" if="${isProduction}">
<echo>Build Path: ${p.buildpath}</echo>
</target>
<target name="development" unless="${isProduction}">
<echo>Build Path: ${d.buildpath}</echo>
</target>
</project>
Core idea is using a <conditional> task for a test on the selected property key and calling two tasks named production and development, where the first runs if the property isProduction is avaluated to true, the second if not (unlesss).
The condition is checked against a property named buildstage.production which is set to the property key p.buildpath as discriminator.
With "property key" I reference to the keys in the properties file. A hole bunch of "properties" here, could be confusing :)
By the way: you need to escape the backslashs in the property values as follows, otherwise they won't be echoed:
p.buildpath=c:\\production\\build
d.buildpath=c:\\development\\build
How it says in this post (http://ant.apache.org/faq#propertyvalue-as-name-for-property), without any external help, it's tricky.
With AntContrib (external task library) you can do <propertycopy name="prop" from="${anotherprop}"/>.
Anyway, there are other alternatives in the same post.
Hope it helps you.
There is a much simpler way that does not require macrodef or antcontrib:
<property name="a" value="Hello"/>
<property name="newProperty" value="a"/>
<loadresource property="b">
<propertyresource name="${newProperty}"/>
</loadresource>
<echo message="a='${a}'"/>
<echo message="b='${b}'"/>

Using Ant, how do I open a file in a browser?

I have an Ant task that creates an HTML report. Is it possible to load that report automatically in a browser from the Ant task? If so, is it possible to do so in a user-independent way or would it require the use of custom user properties?
Thanks,
Paul
I used <script> with javascript:
<property name="mydirectory" location="target/report"/>
<script language="javascript"><![CDATA[
location = "file:///"+project.getProperty("mydirectory").toString().replaceAll("\\\\","/")+"/index.html";
java.awt.Desktop.getDesktop().browse(java.net.URI.create(location));
]]></script>
There is an independent way, like we do in java:
Desktop.getDesktop.open(new File("file.html")) ?
I see no exit without ant optional tasks. From all the scripts beanshell looks most lightweight and does not require any new knowledge. So I did it this way:
<property name="bshJar" value="
C:\lang\java\bsh-1.3.0.jar:
C:\lang\java\bsf.jar:
C:\lang\java\commons-logging-1.1.1.jar" />
<script manager="bsf" language="beanshell" classpath="${bshJar}">
java.awt.Desktop.getDesktop().open(
new java.io.File("c:\\temp\\1\\stackoverflow\\DVD FAQ.htm"));
</script>
And this is an answer about getting script task running. However javascript language is indeed a better option, as it needs no classpath (and no manager) in JDK 6. And the code inside remains the same.
Try using Ant's exec task to execute a system command.
http://ant.apache.org/manual/Tasks/exec.html
An example from that document:
<property name="browser" location="C:/Program Files/Internet Explorer/iexplore.exe"/>
<property name="file" location="ant/docs/manual/index.html"/>
<exec executable="${browser}" spawn="true">
<arg value="${file}"/>
</exec>
I need a solution that is platform independent, so based upon "1.21 gigawatts" answer:
<scriptdef name="open" language="javascript">
<attribute name="file" />
<![CDATA[
var location = "file://"+attributes.get("file").toString().replaceAll("\\\\","/");
location = java.net.URLEncoder.encode(location, "UTF-8");
location = location.toString().replace("%3A",":");
location = location.toString().replace("%2F","/");
println("Opening file " + location);
var uriLocation = java.net.URI.create(location);
var desktop = java.awt.Desktop.getDesktop();
desktop.browse(uriLocation);
]]>
</scriptdef>
This can be called in ant with:
<open file="C:\index.html" />
How I did it:
In my build.properties
#Browser
browser = open
browser.args = -a Firefox
In my build.xml
<target name="openCoverage">
<exec executable="${browser}" spawn="yes">
<arg line="${browser.args}" />
<arg line="${unit.html}" />
</exec>
</target>
Basing this on Gabor's answer I had to do a few more things to get it to work. Here's my code:
<!-- Build and output the Avenue.swf-->
<target name="Open in browser" >
<property name="myDirectory" location="BuildTest/bin-debug"/>
<script language="javascript">
<![CDATA[
var location = "file:///"+project.getProperty("myDirectory").toString().replaceAll("\\\\","/")+"/BuildTest.html";
location = location.toString().replace(/ /g, "%20");
// show URL - copy and paste into browser address bar to test location
println(location);
var uriLocation = java.net.URI.create(location);
var desktop = java.awt.Desktop.getDesktop();
desktop.browse(uriLocation);
]]>
</script>
</target>
I had to append the project name to the directory and replace the spaces with "%20". After that it worked fine.
One way to do this is to invoke your favorite browser with the filename. If you have Ant execute
firefox "file:///G:/Report.html"
it will launch Firefox with that file.
This opens the given HTML file in the system-default browser using only pure Ant.
<property name="report.file" value="${temp.dir}/report/index.html" />
<exec executable="cmd" spawn="yes">
<arg value="/c" />
<arg value="${report.file}" />
</exec>

Resources