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

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>

Related

How to develope a method to substitute repetitive code block

I am new in ant, so I wasn't able to find an approach to make my buld file a bit more elegant. I believe there is an approach to substitute repetitive block of code into my build. So here is build file:
<project basedir="../../../" name="do-report" default="zip-all">
<xmlproperty keeproot="false" file="implementation/xml/ant/properties.xml"/>
<!-- -->
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="${infrastructure-base-dir}/apache-ant-1.9.6/lib/ant-contrib-0.3.jar"/>
</classpath>
</taskdef>
<!-- -->
<target name="clean">
<delete dir="${dita-odt.path.odt-unzipped-base-dir}" includeemptydirs="true" failonerror="no"/>
<delete dir="examples/intermediate/odt-files" includeemptydirs="true" failonerror="no"/>
</target>
<!-- -->
<target name="unzip-writing-odt-file" depends="clean">
<unzip src="${dita-odt.path.writing-odt}" dest="${dita-odt.path.writing-odt-unzipped}"/>
</target>
<!-- -->
<target name="extract-common-paths" depends="unzip-writing-odt-file">
<foreach target="copy-text-path" param="file">
<path>
<fileset dir="${dita-odt.path.text-xml-base-dir}">
<include name="**/content.xml"/>
</fileset>
</path>
</foreach>
</target>
<!-- -->
<target name="copy-text-path" description="copy text-xml path relative to text-xml-base-dir">
<dirname property="text-absolute-dir-path" file="${file}"/>
<property name="absolute-path-text-base-dir" location="${dita-odt.path.text-xml-base-dir}"/>
<pathconvert property="common-path" dirsep="/">
<path location="${text-absolute-dir-path}"/>
<map from="${absolute-path-text-base-dir}/" to=""/>
</pathconvert>
<antcall target="copy-writing-unzipped">
<param name="common-path" value="${common-path}"/>
</antcall>
</target>
<!-- -->
<target name="copy-writing-unzipped">
<echo>${common-path}</echo>
<copy todir="${dita-odt.path.odt-unzipped-base-dir}/${common-path}">
<fileset dir="${dita-odt.path.writing-odt-unzipped}">
<include name="**/*"/>
</fileset>
</copy>
</target>
<!-- -->
<target name="transform-all" depends="extract-common-paths">
<foreach target="transform" param="file">
<path>
<fileset dir="${dita-odt.path.text-xml-base-dir}">
<include name="**/content.xml"/>
</fileset>
</path>
</foreach>
</target>
<!-- -->
<target name="transform">
<basename property="file-base-name" file="${file}"/>
<dirname property="file-dir-absolute-path" file="${file}"/>
<property name="text-xml-base-dir-absolute-path" location="${dita-odt.path.text-xml-base-dir}"/>
<pathconvert property="common-path" dirsep="/">
<path location="${file-dir-absolute-path}"/>
<map from="${text-xml-base-dir-absolute-path}/" to=""/>
</pathconvert>
<!--Substitutes backslashes with forword slashes. Basedir is a reserved property that returns absolute path with separator symbols of the current OS.-->
<pathconvert dirsep="/" property="base-dir-unix">
<path location="${basedir}"/>
</pathconvert>
<echo>TRANSFORM TO: ${dita-odt.path.odt-unzipped-base-dir}/${common-path}/${file-base-name}</echo>
<xslt in="${file}" out="${dita-odt.path.odt-unzipped-base-dir}/${common-path}/${file-base-name}" style="${dita-odt.path.text-odt-xsl}" extension=".xml" force="true">
<param name="dir-path-styles-xml" expression="${dita-odt.path.odt-unzipped-base-dir}/${common-path}"/>
<param name="project-base-dir-absolute-path" expression="${base-dir-unix}"/>
<classpath location="${infrastructure-base-dir}/${dita-odt.text-odt-xsl.processor}"/>
</xslt>
</target>
<!-- -->
<target name="zip-all" depends="transform-all" description="Turns all unzipped text folders into ODT files">
<foreach target="zip-odt" param="file">
<path>
<fileset dir="${dita-odt.path.odt-unzipped-base-dir}" includes="**/content.xml" excludes="writing/**"/>
</path>
</foreach>
</target>
<!-- -->
<target name="zip-odt">
<basename property="file-base-name" file="${file}"/>
<dirname property="file-dir-absolute-path" file="${file}"/>
<!--This property will be used to provided name for the produced ODT file. The document will have the same name as the folder that contains it.-->
<basename property="odt-doc-name" file="${file-dir-absolute-path}.odt"/>
<property name="odt-unzipped-base-dir-absolute-path" location="${dita-odt.path.odt-unzipped-base-dir}"/>
<pathconvert property="common-path" dirsep="/">
<path location="${file-dir-absolute-path}"/>
<map from="${odt-unzipped-base-dir-absolute-path}/" to=""/>
</pathconvert>
<echo>COMMON PATH: ${common-path}</echo>
<zip destfile="examples/intermediate/odt-files/${common-path}/${odt-doc-name}" basedir="${dita-odt.path.odt-unzipped-base-dir}/${common-path}" update="true"/>
</target>
<!-- -->
</project>
So this part of the script does pretty much the same, but shared among almost all the target in the project:
<dirname property="file-dir-absolute-path" file="${file}"/>
<property name="text-xml-base-dir-absolute-path" location="${dita-odt.path.text-xml-base-dir}"/>
<pathconvert property="common-path" dirsep="/">
<path location="${file-dir-absolute-path}"/>
<map from="${text-xml-base-dir-absolute-path}/" to=""/>
</pathconvert>
This part does nothing but to obtain part of a path. For example if ${file} stands for /folder/subfolder1/subfolder2 then take the path after /folder namely subfolder1/subfolder2 and assign it to a property. I this case that property is named common-path that holds same path for all the target. I examined MacroDef Task, but as far as I understand it doesn't return, only accepts some parameters in form of attributes. Anyway, any help would be much appreciated.
You are on the right track in considering <macrodef> to reduce repetitive code.
While it's true that <macrodef> doesn't return anything, <macrodef> can be given the name of a property to set. For example...
<macrodef name="my-hello">
<attribute name="person"/>
<attribute name="output-property"/>
<sequential>
<property name="#{output-property}" value="Hello, #{person}!"/>
</sequential>
</macrodef>
<my-hello person="Riko" output-property="say-hi-to-riko"/>
<echo>my-hello said: ${say-hi-to-riko}</echo>
...outputs...
[echo] my-hello said: Hello, Riko!
In this example, the caller of <my-hello> tells the macrodef to "return" its results in the say-hi-to-riko property.
Knowing this, several of the <target>s in your script can be converted to <macrodef>s that set properties...
<project name="ant-macrodef-pathconvert" default="extract-common-paths">
<taskdef resource="net/sf/antcontrib/antlib.xml" />
<property name="dita-odt.path.text-xml-base-dir" value="C:\temp\dita-odt"/>
<macrodef name="my-pathconvert">
<attribute name="file"/>
<attribute name="common-path-property"/>
<sequential>
<!-- <local> allows multiple calls to a macrodef. -->
<local name="file-dir-absolute-path"/>
<echo>In my-pathconvert for #{file}</echo>
<dirname property="file-dir-absolute-path" file="#{file}"/>
<property name="text-xml-base-dir-absolute-path"
location="${dita-odt.path.text-xml-base-dir}"/>
<pathconvert property="#{common-path-property}" dirsep="/">
<path location="${file-dir-absolute-path}"/>
<map from="${file-dir-absolute-path}/" to=""/>
</pathconvert>
</sequential>
</macrodef>
<macrodef name="copy-text-path"
description="copy text-xml path relative to text-xml-base-dir">
<attribute name="file"/>
<sequential>
<local name="common-path"/>
<echo>In copy-text-path for #{file}</echo>
<my-pathconvert file="#{file}" common-path-property="common-path"/>
<copy-writing-unzipped common-path="${common-path}"/>
</sequential>
</macrodef>
<macrodef name="copy-writing-unzipped">
<attribute name="common-path"/>
<sequential>
<echo>In copy-writing-unzipped for #{common-path}</echo>
<echo>copy task goes here.</echo>
</sequential>
</macrodef>
<target name="extract-common-paths">
<for param="file">
<path>
<fileset dir="${dita-odt.path.text-xml-base-dir}">
<include name="**/content.xml"/>
</fileset>
</path>
<sequential>
<copy-text-path file="#{file}"/>
</sequential>
</for>
</target>
</project>
In general, it's better to prefer calling <macrodef>s over calling <target>s directly. In the above example, <foreach> is replaced with <for> because <for> lets us call <macrodef>s.
Output
[echo] In copy-text-path for C:\temp\dita-odt\dir1\content.xml
[echo] In my-pathconvert for C:\temp\dita-odt\dir1\content.xml
[echo] In copy-writing-unzipped for C:/temp/dita-odt/dir1
[echo] copy task goes here.
[echo] In copy-text-path for C:\temp\dita-odt\dir2\content.xml
[echo] In my-pathconvert for C:\temp\dita-odt\dir2\content.xml
[echo] In copy-writing-unzipped for C:/temp/dita-odt/dir2
[echo] copy task goes here.

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.

Read the each file name and check for the string using ant

I have particular requirement. I have multiple reports file in particlar directly. Currently I build up ant script reading all files and checking for the particular string using the below code.
<target name="GenerateReports" >
<property name="search.string" value="Internal Error" />
<fileset id="existing" dir="${report.dir}">
<patternset id="files">
<include name="*.txt" />
</patternset>
</fileset>
<fileset id="matches" dir="${report.dir}">
<patternset refid="files" />
<contains text="${search.string}" />
</fileset>
<fail message="Found '${search.string}' in one or more test cases results in '${report.dir}' One or more test cases are failed">
<condition>
<resourcecount when="greater" count="0" refid="matches" />
</condition>
</fail>
</target>
But i want to read each file and give the name of the file where the error exists in my report file.
How to read the each file name and read the content also.
<foreach target="-List-File-Names" param="foreach.file" inheritall="true">
<path>
<fileset dir="${report.dir}" includes="*.txt">
<contains text="${search.string}" />
</fileset>
</path>
</foreach>
<target name="-List-File-Names">
<dirname property="file.dir" file="${foreach.file}"/>
<!-- dirname now holds the file -->
</target>

ant build.xml target to check for debug code

When debugging it's quite common for me to use things such as Zend_Debug and die() in the PHP to locate an issue. Occasionally I forget to take these out before committing my code. So I was wondering...
How do I write an ant build.xml target which checks all the files in my application for specific strings and fails if they have been found?
Basically, I'm after a reverse grep command which fails when it finds a string.
Any ideas?
Also, given my build.xml file looks like this (I've removed most of my targets to make it short), how do I make it work?
I don't know how ant works, so I'm after a 'drop-in' solution or good instructions.
<?xml version="1.0" encoding="UTF-8"?>
<project name="API" default="build" basedir=".">
<property name="source" value="application"/>
<target name="build" depends="prepare,lint,phpcpd,phpdox,phpunit,phpcb"/>
<target name="clean" description="Cleanup build artifacts">
<delete dir="${basedir}/build/api"/>
</target>
<target name="lint">
<apply executable="php" failonerror="true">
<arg value="-l" />
<fileset dir="${basedir}/${source}">
<include name="**/*.php" />
</fileset>
<fileset dir="${basedir}/tests">
<include name="**/*.php" />
</fileset>
</apply>
</target>
</project>
Within the lint target (after the apply element) add
<fileset id="die-files" dir="${basedir}/${source}">
<include name="**/*.php" />
<contains text="die()"/>
</fileset>
<fail message="The following files contain "die()": ${ant.refid:die-files}">
<condition>
<resourcecount when="greater" count="0" refid="die-files"/>
</condition>
</fail>
If you can use ant-contrib than:
<for param="file">
<path>
<fileset dir="/path/to/application/"/>
</path>
<sequential>
<if>
<contains string="#{file}" substring="bad elements"/>
<then>
<fail>warning! substring is present in directory</fail>
</then>
</if>
</sequential>
</for>

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