Replace property in a xml file using ANT - ant

I'm trying to replace a version number in a build.xml file using an ANT script.
I've tried various approaches, searched and re-searched StackOverflow for answers but could not get the exact query.
so here is my xml file:
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<project name="feature" default="main" basedir=".">
<target name="init">
<property name="Version" value="1.0.0.20120327"/>
</target>
<target name="main" depends="init">
<description>Main target</description>
</target>
</project>
Now as u can see the Version has yesterday's date. I need to replace it with the current date.
Here is what I've tried:
<target name="replace">
<tstamp >
<format property="touch.time" pattern="yyyyMMdd"/>
</tstamp>
<property name="Feature.dir" location="../feature" />
<!--Didnt Work-->
<copy file="${Feature.dir}\build.xml" tofile="${Feature.dir}\build1.xml"
filtering="yes" overwrite="yes">
<filterset>
<filter token="Version" value="1.0.0.${touch.time}"/>
</filterset>
</copy>
<!--Didnt work
<replacetoken><![CDATA[<property name="Version" value=""/>]]>
</replacetoken>
<replacevalue><![CDATA[<property name="Version"value="1.0.0.${touchtime}" />]]>
</replacevalue>
-->
<!-- Didnt work
<copy file="${Feature.dir}/build.xml" tofile="${Feature.dir}/build1.xml" >
<filterchain>
<tokenfilter>
<replaceregex pattern="^[ \t]*Version[ \t]*=.*$"
replace="Version=1.0.0.${touch.time}"/>
</tokenfilter>
</filterchain>
</copy>
-->
</target>

I would use replaceregex inside a filterchain.
For example:
<copy file="${Feature.dir}\build.xml" tofile="${Feature.dir}\build1.xml"
filtering="yes" overwrite="yes">
<filterchain>
<tokenfilter>
<replaceregex pattern="1.0.0.[0-9.]*" replace="1.0.0.${touch.time}"/>
</tokenfilter>
</filterchain>
</copy>
If you want to replace the file, feel free to copy to a temp file and move it back.
<tempfile property="build.temp.file.name"/>
<copy file="${Feature.dir}\build.xml" tofile="${build.temp.file.name}" ... />
<move file="${build.temp.file.name}" tofile="${Feature.dir}\build.xml" />

Related

Find the number of occurrences of a particular character like comma in a string using ant script?

<project>
<target name="test">
<property name="src.dir" value="src" />
<property name="search4" value=","/>
<fileset id="existing" dir="${src.dir}/src">
<patternset id="files">
<include name="*.txt"/>
</patternset>
</fileset>
<resourcecount property="count">
<fileset id="matches" dir="../src">
<patternset refid="files" />
<contains text="${search4}" />
</fileset>
</resourcecount>
<echo message="Found '${search4}' in files : '${count}'"/>
</target>
</project>
I used this, but this only prints the first occurrence. I would like to print the total count.
For eg - abc,xyz,pg--> The number of occurrences of commas(,) is 2.
Here's one way. Copies the file to another file, with a filter to remove all non-commas, then gets the size of the output, which is the number of commas in the input file.
<delete file="out.txt" />
<copy file="in.txt" tofile="out.txt">
<filterchain>
<striplinebreaks />
<replaceregex pattern="[^,]" replace="" flags="gm" />
</filterchain>
</copy>
<length file="out.txt" property="out.size" />
<echo message="Commas found: ${out.size}" />
On your follow up question: how to restrict this to just the first line of the file: add this before the "striplinebreaks" line:
<headfilter lines="1" />
That will count commas in just the first line of the file.

Illegal value at 'filematch': patternSet{ includes: [Index_*.xml] excludes: [] }

I have to search a given string "OK" from a file Index_*.xml. This * is a random generated Id. This file is generated after every 15seconds
This is what I have done so far, but I am getting the exception " Illegal value at 'filematch': patternSet{ includes: [Index_*.xml] excludes: [] }"
<?xml version="1.0" encoding="UTF-8"?>
<project name="StringSearch" default="wait-for-some-time" basedir=".">
<patternset id="filematch">
<include name="Index_*.xml"/>
</patternset>
<target name="wait-for-some-time">
<waitfor maxwait="15" maxwaitunit="second" timeoutproperty="notfound">
<resourcecontains refid="filematch" substring="OK" />
</waitfor>
<antcall target="success" />
</target>
<target name="success" depends="fail" unless="notfound">
<echo message="String OK found" />
</target>
<target name="fail" if="notfound">
<echo message="String not found" />
</target>
</project>
Any suggestion of what is wrong here or may be another approach if this is not feasible.
Thanks
New code:
Using this
<path id="pathtoIndexfile">
<fileset dir="${destination.dir}">
<include name="Index_*.xml"/>
</fileset>
</path>
<target name="wait-for-some-time">
<echo>${destination.dir}</echo>
<waitfor maxwait="1" maxwaitunit="minute" timeoutproperty="notfound">
<resourcecontains refid="pathtoIndexfile" substring="OK" />
</waitfor>
<antcall target="success" />
</target>
1) The exception is "java.lang.ClassCastException: org.apache.tools.ant.types.Path cannot be cast to org.apache.tools.ant.types.Resource".
2) With fileSet the exception is "java.lang.ClassCastException: org.apache.tools.ant.types.FileSet cannot be cast to org.apache.tools.ant.types.Resource"
Am I missing some Jars?
I have achieved the solution by two steps which are as follows:
Step 1: Copying the index_*.xml file to output.xml file
Step 2: Search OK in the output.xml file
My improvised code which does the search of a string "OK" is
<target name="StringSearch">
<sleep seconds="10"/>
<copy tofile="${destination.dir}/output.xml">
<fileset dir="${destination.dir}">
<include name="Index_*.xml"/>
</fileset>
</copy>
<sleep seconds="10"/>
<echo>destination.dir is: ${destination.dir}</echo>
<loadfile property="OK.exists" srcfile="${destination.dir}/output.xml">
<filterchain>
<linecontainsregexp>
<regexp pattern="OK"/>
</linecontainsregexp>
</filterchain>
</loadfile>
<echo>OK exists: ${OK.exists}</echo>
</target>

Generating MD5 for files in an ant-contrib for loop in ANT

I am selecting set of files using file set and then using them to generate the checksum of all the files in the selected fileset
here is my script
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="MyTask1" basedir="." default="jar">
<property name="cms.dir" value="D:\Test" />
<property name="comma" value="," />
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<target name="A">
<fileset id="src.files" dir="${cms.dir}" casesensitive="yes">
<include name="**/*.uim"/>
<include name="**/*.properties"/>
<include name="**/*.txt"/>
</fileset>
<pathconvert pathsep="${line.separator}" property="sounds" refid="src.files">
<!-- To get the names of the files only then use mapper-->
<!-- <mapper type="flatten" />-->
</pathconvert>
<delete file="sounds.txt"/>
<for list="${sounds}" delimiter="${line.separator}" param="mod">
<sequential>
<checksum file="#{mod}" property="MD5_Value"/>
<echo file="sounds.txt" append="true">#{mod}${comma}${MD5_Value}${line.separator}</echo>
</sequential>
</for>
<!--<checksum file="Test.txt" property="foobarMD5"/>-->
<!--<echo file="sounds.txt">${foobarMD5}</echo>-->
</target>
</project>
However its failing and its generating duplicate MD5 value here is my output
D:\Test\Test1.txt,6d326741a99efbcda928e5096b43cb9a
D:\Test\Test2.txt,6d326741a99efbcda928e5096b43cb9a
Any help ...
The checksum task can process filesets...
<checksum>
<fileset dir=".">
<include name="foo*"/>
</fileset>
</checksum>
Lot simpler than using the for task, which is not part of standard ANT.

how to replace all matches with ant script

How can i replace all matching lines? I wanna replace all matching lines in *xml file.
Script snippet which is below just only replace one line
Thanks in advance.
brgds
<?xml version="1.0" encoding="windows-1252" ?>
<project default="init" basedir=".">
<property file="build.properties"/>
<target name="init">
<tstamp/>
<loadfile property="jndiurl"
srcfile="${src.model}/META-INF/persistence.xml">
<filterchain>
<linecontains>
<contains value="hibernate.jndi.url"></contains>
</linecontains>
</filterchain>
</loadfile>
<replace file="${src.model}/META-INF/persistence.xml" token="${jndiurl}"
value="${hibernate.jndi.url.live}${line.separator}"/>
<echo>${hibernate.jndi.url.live}</echo>
<loadfile property="providerurl"
srcfile="${src.structure}/com/arsivist/structure/connection.properties">
<filterchain>
<linecontains>
<contains value="providerurl"></contains>
</linecontains>
</filterchain>
</loadfile>
<replace file="${src.structure}/com/arsivist/structure/connection.properties"
token="${providerurl}"
value="${providerurl.live}${line.separator}"/>
<echo>${providerurl.live}</echo>
<loadfile property="ucmusername"
srcfile="${src.roketsanutil}/com/arsivist/util/ucmConnection.properties">
<filterchain>
<linecontains>
<contains value="username"></contains>
</linecontains>
</filterchain>
</target>
</project>
Instead of trying to edit files in place, wouldn't it be simpler to use the copy task as a templating system, it supports a filterset which can be used to substitute production values.
Example
.
├── build.xml
└── src
└── resources
└── persistence.xml
build.xml
<project name="demo" default="template">
<target name="template">
<copy todir="build/META-INF">
<fileset dir="src/resources" includes="*.xml"/>
<filterset>
<filter token="HIBERNATE.HBM2DDL.AUTO" value="create-drop"/>
</filterset>
</copy>
</target>
<target name="clean">
<delete dir="build"/>
</target>
</project>
persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="sample">
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="#HIBERNATE.HBM2DDL.AUTO#"/>
</properties>
</persistence-unit>
</persistence>
That snippet works for me:
<?xml version="1.0" encoding="windows-1252" ?>
<project default="init" basedir=".">
<property file="build.properties"/>
<target name="init">
<tstamp/>
<loadfile property="jndiurl"
srcfile="${src.model}/META-INF/persistence.xml">
<filterchain>
<linecontains>
<contains value="hibernate.jndi.url"></contains>
</linecontains>
<headfilter lines="1"/>
</filterchain>
</loadfile>
<echo>${jndiurl}</echo>
<replace file="${src.model}/META-INF/persistence.xml" token="${jndiurl}"
value="${hibernate.jndi.url.live}${line.separator}"/>
<echo>${hibernate.jndi.url.live}</echo>
</project>

Multiple renaming using ant script

Let me explain the scenario:
D:\project\src\one.txt
D:\project\src\two.txt
D:\project\src\three.txt
D:\project\src\four.txt
The above files should be copied as :
D:\project\dst\one.xls
D:\project\dst\two.xls
D:\project\dst\three.xls
D:\project\dst\four.xls
I need to change the extension without using the mapper and move task. I need to rename as above using a for loop with fte:filecopy function inside. Is this possible ???
For anyone arriving here without the negative requirement afflicting the OP, the much simpler answer is to use a mapper.
<project default="move_files">
<target name="move_files">
<copy todir="dst">
<fileset dir="src">
<include name="*.txt"/>
</fileset>
<globmapper from="*.txt" to="*.xls"/>
</copy>
</target>
</project>
This works for me :
<?xml version="1.0"?>
<project name="so-copy-rename" default="build2">
<property name="ant-contrib-jar" value="${user.home}/.ant/lib/ant-contrib-1.0b3.jar"/>
<target name="setup" unless="ant-contrib.present">
<echo>Getting ant-contrib</echo>
<mkdir dir="${user.home}/.ant/lib"/>
<!--
Note: change this to a locally hosted maven repository manager such as nexus http://nexus.sonatype.org/
-->
<get dest="${ant-contrib-jar}"
src="http://repo1.maven.org/maven2/ant-contrib/ant-contrib/1.0b3/ant-contrib-1.0b3.jar"/>
</target>
<target name="taskdefs">
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<pathelement location="${ant-contrib-jar}"/>
</classpath>
</taskdef>
</target>
<target name="build" depends="taskdefs">
<property name="srcdir" value="src"/>
<property name="targetdir" value="target"/>
<property name="files" value="file1,file2,file3,file4"/>
<mkdir dir="${targetdir}"/>
<foreach list="${files}" target="copy-rename" param="srcfile" trim="true">
<param name="srcdir" value="${srcdir}" />
<param name="targetdir" value="${targetdir}" />
</foreach>
</target>
<target name="copy-rename">
<var name="src-suffix" value="txt"/>
<var name="tgt-suffix" value="xls"/>
<copy file="${srcdir}/${srcfile}.${src-suffix}" tofile="${targetdir}/${srcfile}.${tgt-suffix}" />
</target>
<target name="build2" depends="taskdefs">
<property name="srcdir" value="src"/>
<property name="targetdir" value="target"/>
<mkdir dir="${targetdir}"/>
<foreach target="copy-rename2" param="srcfile">
<path id="srcfilepath">
<fileset dir="${srcdir}" casesensitive="yes">
<include name="*.txt"/>
</fileset>
</path>
<param name="targetdir" value="${targetdir}" />
</foreach>
</target>
<target name="copy-rename2">
<var name="basefile" value="" unset="true"/>
<basename property="basefile" file="${srcfile}" suffix=".txt"/>
<var name="tgt-suffix" value="xls"/>
<copy file="${srcfile}" tofile="${targetdir}/${basefile}.${tgt-suffix}" />
</target>
</project>
Can you slice it the other way and perform the renaming inside the fte:filecopy command? Looking at the IBM documentation, you can specify tasks to be carried out at the source or destination agents either before or after the copy, using presrc, postdst etc. This task could be an Ant task that does the renaming?

Resources