The Ant buildfile snippet below is an attempt to simply output the time before and after each sql script is run. I cannot change the structure of the Ant targets (create-tables must call run-sql-script just as it does). The problem is that the properties (time and time2) are immutable (http://ant.apache.org/manual/Tasks/property.html) and thus only time the first operation and not the second. Is there no way to do what I'm trying to do in Ant?
<target name="create-tables">
<antcall target="run-sql-script">
<param name="db.script" value="teams.sql"/>
</antcall>
<!-- Create the base UDM schema. -->
<antcall target="run-sql-script">
<param name="db.script" value="players.sql"/>
</antcall>
</target>
<target name="run-sql-script">
<tstamp>
<format property="time" pattern="MM/dd/yyyy hh:mm:ss aa"
offset="-5" unit="hour"/>
</tstamp>
<echo>before: ${time}</echo>
<sql
classpath="${classpath}"
driver="${db.driver}"
url="${db.url}"
userid="${db.userid}"
password="${db.password}"
src="${script.dir}/${db.script}"
delimiter="${script.delimiter}"
onerror="abort">
</sql>
<tstamp>
<format property="time2" pattern="MM/dd/yyyy hh:mm:ss aa"
offset="-5" unit="hour"/>
</tstamp>
<echo>after: ${time2}</echo>
</target>
Update: You can use an antcall to invoke a task, and create/echo a new timestamp within the scope of that call.
This example shows how to pass a message to the call and echo the current timestamp with a message:
<target name="timestamp2">
<tstamp>
<format property="current.time" pattern="MM/dd/yyyy hh:mm:ss aa" />
</tstamp>
<echo message="${message} ${current.time}" />
</target>
<target name="test">
<antcall target="timestamp2">
<param name="message" value="hello" />
</antcall>
<sleep seconds="5"/>
<antcall target="timestamp2">
<param name="message" value="world" />
</antcall>
</target>
The output when this is run is:
test:
timestamp2:
[echo] hello 09/24/2009 05:33:22 PM
timestamp2:
[echo] world 09/24/2009 05:33:24 PM
Use a <macrodef> task together with the <local> task (introduced in Ant 1.8):
<macrodef name="echotimestamp">
<sequential>
<local name="timestamp" />
<tstamp>
<format property="timestamp" pattern="yyyy-MM-dd HH:mm:ss" />
</tstamp>
<echo message="${timestamp}" />
</sequential>
</macrodef>
<echotimestamp />
Following on from #Niek's answer, we can build a macro that behaves like echo but with a time stamp
<macrodef name="echoTS">
<attribute name="message"/>
<sequential>
<var name="current.time" unset="true"/>
<tstamp><format property="current.time" pattern="yyyy-MM-dd HH:mm:ss" /></tstamp>
<echo message="${current.time}> #{message}" />
</sequential>
</macrodef>
<target name="test-timestamp">
<echoTS message="hi" />
</target>
which will give output
test-timestamp:
[echo] 2013-05-03 12:02:38> hi
I like the macrodef solution if indeed it is more efficient than the target one, but I use a var unset=true to force a resetting of the variable, like:
<macrodef name="echoTimestamp">
<sequential>
<var name="current.time" unset="true"/>
<tstamp>
<format property="current.time" pattern="yyyy-MM-dd HH:mm:ss" />
</tstamp>
<echo message="${current.time}" />
</sequential>
</macrodef>
Usage
<echoTimestamp />
<sleep seconds="3"/>
<echoTimestamp />
I found that if you use it as a macro rather than an ant target, it works better since it doesn't loop thru the ant file from the beginning everytime you do a antcall target= (less check if you have dependencies and property sets).
<target name="testMe">
<MyTimestamp></MyTimestamp>
<sleep seconds="5"></sleep>
<MyTimestamp></MyTimestamp>
</target>
<macrodef name="MyTimestamp">
<sequential >
<tstamp>
<format property="current.time" pattern="MM/dd/yyyy hh:mm:ss aa"/>
</tstamp>
<echo message="RUN_TIME: ${current.time}"/>
</sequential>
</macrodef>
Related
I'm reading a file that contains a list of files path.
For each file, I would like to know if it contains a substring.
the answer is always false, although part of it should be true.
Here is my target:
<target name="chek-file">
<loadfile property="file" srcfile="c:\tmp\testing.txt"/>
<for param="line" list="${file}" delimiter="${line.separator}">
<sequential>
<echo>#{line}</echo>
<loadfile property="inner_file" srcfile="#{line}"/>
<if>
<resourcecontains resource="${inner_file}" substring="parent" />
<then>
<echo message="this is a jpa jar"/>
</then>
<else>
<echo message="this is NOT a jpa jar"/>
</else>
</if>
</sequential>
</for>
</target>
the echo is typing "this is NOT a jpa jar" for all jars.
Is 'if' not working with 'resourcecontains'?
OK, found two problems:
1) The second load file is actually not needed here because resourcecontains needs to get the file name and not its value.
2) resourcecontains is inherited from <condition>
so the solution should be:
<target name="chek-file">
<loadfile property="file" srcfile="c:\tmp\testing.txt"/>
<for param="line" list="${file}" delimiter="${line.separator}">
<sequential>
<echo>#{line}</echo>
<condition property="substring_found">
<resourcecontains resource="#{line}" substring="JPA>true" />
</condition>
<echo message="substring_found value: ${substring_found}"/>
<if>
<equals arg1="${substring_found}" arg2="true" />
<then>
<echo message="this is a jpa jar"/>
<get_jar_name_no_version property.to.process="#{line}" output.property="linetobeadd" />
</then>
<else>
<echo message="this is NOT a jpa jar"/>
</else>
</if>
<var name="substring_found" unset="true"/>
</sequential>
</for>
</target>
I can run my build file from two targets as below
<target name="makeMinificationTarget" depends="inheritedTarget" />
<target name="skipMinificationTarget" depends="inheritedTarget" />
However, these both targets internally calls "inheritedTarget" and this "inheritedTarget" internally calls "makeMinification" target.
Following is "inheritedTarget" and "makeMinification"
<target name="makeMinification">
<echo message="makingMinification...">
</target>
<target name="inheritedTarget" depends="makeMinification"/>
<echo message="compileFiles">
<echo message="ExecuteFiles">
</target>
My question is i want to skip execution of "makeMinification" target from
this call <target name="skipMinificationTarget" depends="inheritedTarget" />
And
let it happen if we call <target name="makeMinificationTarget" depends="inheritedTarget" />
How can I achieve this ???
Does this work? Using "antcall" and passing the parameter. Instead of using "depends"
<target name="makeMinificationTarget" >
<antcall target="inheritedTarget">
<param name="Minification" value="true"/>
</antcall>
</target>
<target name="skipMinificationTarget" >
<antcall target="inheritedTarget">
<param name="Minification" value="false"/>
</antcall>
</target>
<target name="inheritedTarget" >
<if>
<equals arg1="${Minification}" arg2="true" />
<then>
<antcall target="makeMinification"/>
</then>
<else>
<!-- Do something else-->
</else>
</if>
<!-- Do other stuff -->
</target>
<target name="makeMinification" >
<!-- Do something -->
</target>
I need to change the values of an ANT-script list in real time.
This is the situation;
I have these properties:
x.y.6.1=something1
x.y.6.2=something2
x.y.6.3=something3
list=6.1,6.2
I want the list to become list=something1;something2
This is the gist of the code;
<target name="target1">
<foreach list="${list}" target="target2" param="var" delimiter="," />
</target>
<target name="target2">
<propertycopy name="var" from="x.y.${var}" silent="true"/>
</target>
Now, the propertycopy part works, however, it will not keep the new value.
I tried many variations, none which worked.
I am using ant-contrib.
Help would be much appreciated!
Adam
The target attribute of your foreach should be the name of the target called.
I guess here it should be <foreach list="${list}" target="agent_version_to_path" param="var" delimiter="," />
If I'm wrong, post your target2 and explain what you're trying to do.
Edit:
Ok for your edit, did you already try override="yes"?
And cannot you change your name of property (var) it is quite confusing!
I'm not a fan of the ant-contrib tasks. Have you considered embedding a scripting language instead?
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
properties["list"].split(",").each {
println properties["x.y.${it}"]
}
</groovy>
Update
Here's a more complete example that loops and calls another target:
$ ant
Buildfile: build.xml
process:
doSomething:
[echo] something1
doSomething:
[echo] something2
BUILD SUCCESSFUL
Total time: 0 seconds
build.xml
<project name="demo" default="process">
<property file="build.properties"/>
<path id="build.path">
<pathelement location="lib/groovy-all-2.1.5.jar"/>
</path>
<target name="process" description="Process values in a list">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
properties["list"].split(",").each {
properties.var = properties["x.y.${it}"]
ant.ant(target:"doSomething")
}
</groovy>
</target>
<target name="doSomething">
<echo>${var}</echo>
</target>
</project>
I have solved the problem, in an icky way, but it works great!
<project name="Test" default="main">
<property file="agent.properties" />
<property file="temp_updates.txt" />
<taskdef name="propertycopy" classname="net.sf.antcontrib.property.PropertyCopy" />
<taskdef name="foreach" classname="net.sf.antcontrib.logic.ForEach" />
<target name="main">
<property name="Agent Updates" value="6.1,6.2" />
<antcall target="create_temp_files" />
<antcall target="agent_updates_target" />
<propertycopy name="custom.agent.release.group" from="updates" silent="true" override="true" />
</target>
<target name="agent_updates_target">
<foreach list="${Agent Updates}" target="agent_version_to_path" param="var" delimiter="," />
</target>
<target name="agent_version_to_path">
<propertycopy name="var" from="agent.installer.${var}" silent="true" override="true"/>
<echo message="${var};" file="temp_updates.txt" append="true" />
</target>
<target name="create_temp_files">
<echo message="updates=" file="temp_updates.txt" />
</target>
</project>
on another file, "agent.properties" I had that;
agent.installer.6.3=something3
agent.installer.6.2=something2
agent.installer.6.1=something1
agent.installer.6.0=...
agent.installer.5.6=...
agent.installer.5.0.12=...
agent.installer.5.0.11=...
agent.installer.5.0.9.5=...
agent.installer.3.8=...
agent.installer.3.7=...
As a result, a new file "temp_updates.txt" was created, having
updates=something1;something2;
Which I then loaded into the actual program.
May not be pretty, but it works quite well.
Thank you Skoll and Mark O'Connor for all your help, I used those ideas to come up with this one. I would rate you, but I can't :( Sorry!
I have the following code:
<dirset id="aa" dir="FOLDER" includes="example*" excludes=".*">
</dirset>
<pathconvert pathsep="," property="bb" refid="aa">
<mapper type="flatten"/>
</pathconvert>
<echo message="LIST:${bb}"/>
and the output is for example 'examle.aa,example.bb'
And I would like to call another target for each example.*.. Can you help me please?
A macrodef would work for this, you could invoke it with custom attributes or elements based on you current property:
macrodef
Try antcontrib for the loop functionality. Here's an example
<project>
<target name="test">
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="./lib/ant-contrib-1.0.jar" />
<for param="file">
<dirset dir="." />
<sequential>
<task dir="#{file}" />
</sequential>
</for>
</target>
<macrodef name="task">
<attribute name="dir" />
<sequential>
<echo>#{dir}</echo>
</sequential>
</macrodef>
</project>
I am using ant, and I have a problem with if/then/else task, (ant-contrib-1.0b3.jar).
I am running something that can be simplified with build.xml below.
I am expecting to obtain from 'ant -Dgiv=Luke' the message
input name: Luke
should be overwritten with John except for Mark: John
but it seems property "giv" is not overwritten inside if/then/else..
input name: Luke
should be overwritten with John except for Mark: Luke
Is it depending from the fact I am using equals task with ${giv} ?
Otherwise what is wrong in my code?
build.xml CODE:
<project name="Friend" default="ifthen" basedir=".">
<property name="runningLocation" location="" />
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="${runningLocation}/antlib/ant-contrib-1.0b3.jar" />
</classpath>
</taskdef>
<target name="ifthen">
<echo message="input name: ${giv}" />
<if>
<equals arg1="${giv}" arg2="Mark" />
<then>
</then>
<else>
<property name="giv" value="John" />
</else>
</if>
<echo message="should be overwritten with John except for Mark: ${giv}" />
</target>
</project>
In Ant a property is always set once, after that variable is not alterable anymore.
Here follows a solution using standard Ant (without ant-contrib) which could be useful for the people who does not want an extra dependency.
<target name="test" >
<echo message="input name: ${param}" />
<condition property="cond" >
<equals arg1="${param}" arg2="Mark" />
</condition>
</target>
<target name="init" depends="test" if="cond">
<property name="param2" value="Mark" />
</target>
<target name="finalize" depends="init">
<property name="param2" value="John" />
<echo message="should be overwritten with John except for Mark: ${param2}" />
</target>
Ant Properties are very hard to overwrite (if not impossible). What you need is a Variable. These are also defined in the Ant Contrib JAR.
Editing your example:
<target name="ifthen">
<var name="Evangelist" value="${giv}" />
<echo message="input name: ${Evangelist}" />
<if>
<equals arg1="${Evangelist}" arg2="Mark" />
<then>
</then>
<else>
<var name="Evangelist" value="John" />
</else>
</if>
<echo message="should be overwritten with John except for Mark: ${Evangelist}" />
</target>
<project name="Friend" default="ifthen" basedir=".">
<property name="runningLocation" location="" />
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="${runningLocation}/antlib/ant-contrib-1.0b3.jar" />
</classpath>
</taskdef>
<target name="ifthen">
<echo message="input name: ${giv}" />
<if>
<equals arg1="${giv}" arg2="Mark" />
<then>
</then>
<else>
<var name="giv" unset="true"/>
<property name="giv" value="John" />
</else>
</if>
<echo message="should be overwritten with John except for Mark: ${giv}" />
</target>
</project>
We can use var task to unset the property also.
I know this is old, but should prove handy to others searching for a solution.
to re-assign a property without using ant-contrib, use macrodef with a script.
<macrodef name="property-change">
<attribute name="name"/>
<attribute name="value"/>
<sequential>
<script language="javascript"><![CDATA[
project.setProperty("#{name}", "#{value}");
]]></script>
</sequential>
</macrodef>
then in anywhere in ant, just call this like the property tag
<property-change name="giv" value="John"/>
to Implement this in your original version of xml, it would look like this:
<project name="Friend" default="ifthen" basedir=".">
<property name="runningLocation" location="" />
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="${runningLocation}/antlib/ant-contrib-1.0b3.jar" />
</classpath>
</taskdef>
<target name="ifthen">
<echo message="input name: ${giv}" />
<if>
<equals arg1="${giv}" arg2="Mark" />
<then>
</then>
<else>
<property-change name="giv" value="John" />
</else>
</if>
<echo message="should be overwritten with John except for Mark: ${giv}" />
</target>
</project>
This sample is given purely as an example on writing a macro to replace the <var> command in ant-contrib. In a situation like this one, where the <if> command is being used, it makes more sense to use <var> sinnce ant-contrib is already loaded, and <var> might be faster in processing.
Hope this helps.
It is possible to re-assign the value of a property using the ant-contrib 'propertycopy'. This is an alternative to using ant-contrib Variables.
This way the property "giv" can be overwritten.
<target name="ifthen">
<echo message="input name: ${giv}" />
<if>
<equals arg1="${giv}" arg2="Mark" />
<then>
</then>
<else>
<property name="tempName" value="John" />
<propertycopy name="giv" from="tempName" override="true" />
</else>
</if>
<echo message="should be overwritten with John except for Mark: ${giv}" />
</target>
Be aware this assumes the property tempName is not already set to a value other than 'John'.