using if with resourcecontains in and is not returning true value - ant

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>

Related

ant: condition command does not find pattern when pattern is a file path

I am using the following code with the idea of finding a file in a directory that is also part of a list in a file:
<loadfile property="ReportFileContent" srcFile="${ReportFile}"/>
<for param="file">
<path>
<fileset dir="${MainDir}" includes="**/**"/>
</path>
<sequential>
<basename file="#{file}" property="#{file}" />
<condition property="found-file${index2}">
<matches pattern="#{file}" string="${ReportFileContent}"/>
</condition>
<if>
<isset property="found-file${index2}"/>
<then>
<echo message=" Found file #{file}" level="warning" />
</then>
<else>
<echo message="Not Found file #{file}" level="warning" />
</else>
</if>
<math result="index2" operand1="${index2}" operation="+" operand2="1" datatype="int" />
</sequential>
</for>
The command is not working though as it is not finding the file that is available in ${ReportFileContent}.
The content of the ReportFileContent property is the following:
c:\___tools\test\file1.txt;2
c:\___tools\test\file2.txt;2
c:\___tools\test\file3.txt;2
Any idea why the condition is not working correctly?
Thanks
Tony

Ant- How can i compare the list of strings?

<target name="build">
<for list="${platform}" param="platform" trim="true">
<sequential>
<if>
<equals arg1="${platform}" arg2="${project.SuppoortedPlatforms}" />
<then>
<antcall target="package.${platform}" />
</then>
</if>
</sequential>
</for>
</target>
where i'm getting platfrom values at runtime (eg:windows,ios) and project.SuppoortedPlatforms is declared under build.properties (eg:android,ios). how can i compare the list of strings?
could anyone help me to solve this problem?
Thanks,
sandhiya
You are looping over a comma-separated list of platforms, and for each one you're checking if it is contained in the list of supported platforms in project.SuppoortedPlatforms. This should go like this:
<for list="${platform}" param="platformParam" trim="true">
<sequential>
<if>
<contains string="${project.SuppoortedPlatforms}" substring="#{platformParam}" />
<then>
<antcall target="package.#{platformParam}" />
</then>
</if>
</sequential>
</for>
The parameter in the loop should be accessed with # instead of $. Also it would be better to rename the parameter for readability (platformParam instead of platform).
Instead of using contains task, i myself tried with the nested for loop, its cool working fine.
<for list="${platforms}" param="platformparam" trim="true">
<sequential>
<for list="${project.SupportedPlatforms}" param="supplatformparam" trim="true">
<sequential>
<if>
<equals arg1="#{platformparam}" arg2="#{supplatformparam}" />
<then>
<antcall target="package.#{platformParam}" />
</then>
</if>
</sequential>
</for>
</sequential>
</for>

copy doesn't support the nested "if" element in Ant-contrib Nested Loop

I need to copy all dml.sql files to inside DB2_List.txt file if DML.sql file is present. But after executing this file i'm getting error like this:
copy doesn't support the nested "if" element.
Please let me know if you have any better idea about the nested loop in Ant.
<available file="DB/DML.sql" property="db.check.present"/>
<copy file="DB/DDL.sql" tofile="DB2/DB2_List.txt" >
<if>
<equals arg1="${db.check.present}" arg2="true"/>
<then>
<filterchain>
<concatfilter append="DB/DML.sql" />
<tokenfilter delimoutput="${line.separator}" />
</filterchain>
</then>
</if>
</copy>
It is possible to accomplish what you are after, you just have to approach it quite differently in Ant. Just note that you will need to utilize separate targets.
<target name="db.check">
<available file="DB/DML.sql" property="db.check.present"/>
</target>
<target name="db.copy" depends="db.check" if="db.check.present">
<copy file="DB/DDL.sql" tofile="DB2/DB2_List.txt" >
<filterchain>
<concatfilter append="DB/DML.sql" />
<tokenfilter delimoutput="${line.separator}" />
</filterchain>
</copy>
</target>
Take a look at Ant 1.9.1 which supports special if/unless attributes on tags. This might be possible:
<project name="mysterious.moe" basedir="." default="package"
xmlns:if="ant:if"
xmlns:unless="ant:unless"/>
<target name="db.copy">
<available file="DB/DML.sql" property="db.check.present"/>
<copy file="DB/DDL.sql"
tofile="DB2/DB2_List.txt">
<filterchain if:true="db.ceck.present">
<concatfilter append="DB/DML.sql" />
<tokenfilter delimoutput="${line.separator}" />
</filterchain>
</copy>
<target>
...
</project>
Otherwise, you'll have to use two separate copies. You can't put <if> antcontrib inside tasks. Only around tasks:
<available file="DB/DML.sql" property="db.check.present"/>
<if>
<equals arg1="${db.check.present}" arg2="true"/>
<then>
<copy file="DB/DDL.sql" tofile="DB2/DB2_List.txt" >
<filterchain>
<concatfilter append="DB/DML.sql" />
<tokenfilter delimoutput="${line.separator}" />
</filterchain>
</copy>
</then>
<else>
<copy file="DB/DDL.sql" tofile="DB2/DB2_List.txt" >
</else>
</if>
</copy>

Delete files specified via a zipfileset?

I have the following Ant target which extracts contents from a specific .ZIP archive:
<!-- UNPACK-MATH -->
<target name="unpack-math" depends="init-contrib">
<!-- NOTE: the 'unzip' task doesn't fail when it cannot extract over read-only files; however, 'copy' with a 'zipfileset' does. -->
<first id="math.archive">
<fileset dir="${builddir}" includes="MATH_MF*.zip" />
</first>
<if>
<length string="${toString:math.archive}" when="greater" length="0" />
<then>
<copy todir="${basedir}">
<zipfileset src="${toString:math.archive}" />
</copy>
</then>
<else>
<echo message="No math to unpack." />
</else>
</if>
</target>
What I'd like to do now is "clean up" the files that were extracted. However, the following does not work:
<!-- CLEAN-MATH -->
<target name="clean-math" depends="init-contrib">
<first id="math.archive">
<fileset dir="${builddir}" includes="MATH_MF*.zip" />
</first>
<if>
<length string="${toString:math.archive}" when="greater" length="0" />
<then>
<delete>
<zipfileset src="${toString:math.archive}" />
</delete>
</then>
<else>
<echo message="No math to clean." />
</else>
</if>
</target>
I get the following stack trace:
BUILD FAILED
D:\Development\MForce\Games\gamebuild.xml:214: java.lang.ClassCastException: class org.apache.tools.ant.types.resources.ZipResource doesn't provide files
at org.apache.tools.ant.types.resources.comparators.FileSystem.resourceCompare(FileSystem.java:43)
...
Any ideas?
This solution appears to work, but requires unpacking the .ZIP archive (which lists the files you'd like to delete as some other root) first, which I'd prefer to avoid:
<!-- CLEAN-MATH -->
<target name="clean-math" depends="init-contrib">
<first id="math.archive">
<fileset dir="${builddir}" includes="MATH_MF*.zip" />
</first>
<if>
<length string="${toString:math.archive}" when="greater" length="0" />
<then>
<unzip dest="${builddir}/tmp" src="${toString:math.archive}"/>
<delete>
<fileset dir="${basedir}" includes="**/*">
<present present="both" targetdir="${builddir}/tmp"/>
</fileset>
</delete>
<delete dir="${builddir}/tmp"/>
</then>
<else>
<echo message="No math to clean." />
</else>
</if>
</target>

ant-contrib - if/then/else task

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'.

Resources