ANT Conditions task with regex match in a file - regex

I'm reading the ANT Conditions task and trying to figure out how to use it based on a string found in one file.
I have an ANT build with series of replaceregexp targets that it runs on any .htm files in a directory. So I specify the fileset dir, then the regex pattern and the substitution, and makes the replacements in all .htm files in that directory. For example:
<target name="title" description="convert title">
<replaceregexp byline="false" flags="gs">
<regexp pattern="(<p.*?)(TopicTitle>.*?)(>)(.*?)(</span.*?/p>)"/>
<substitution expression="<title>\4</title>"/>
<fileset dir=".">
<include name="*.htm"/>
</fileset>
</replaceregexp>
</target>
Now what I want to do is use a regex to see if there's a certain word in the .htm file, and set a condition if it's a match. For example:
<condition property="isConcept">
<matches pattern="<body.*(?=ConceptStyle).*</body>" string=" "/>
</condition>
So if the string ConceptStyle is matched by that regex, then the property isConcept is set.
My question is: what do I put in the string=" " part of that task? Or how do I give it the directory/file to search for the match?
UPDATE:
Okay so this is the new code from Manouti's answer below:
<target name="setProperties">
<loadfile property="contents" srcFile="C:\Developer\SVN\trunk\WordTemplates\conversions\Conversion_Demo.htm"/>
<condition property="isConcept">
<matches pattern="<body.*(?=ConceptStyle).*</body>" string="${contents}"/>
</condition>
</target>
To test if the property is set, my understanding is that I can add unless to another target, like this:
<!-- sticking in a replace task to test if condition is set -->
<target name="conditionTest" unless="isConcept">
<replaceregexp byline="false" flags="gs">
<regexp pattern="conbody"/>
<substitution expression="BOOOO"/>
<fileset dir=".">
<include name="*.htm"/>
</fileset>
</replaceregexp>
</target>
So far this isn't working, that is, the target that contains unless="isConcept" is functioning (the "BOOOO" is appearing in the result), whereas if the property is set, it shouldn't fire.
I've used unless for other purposes but only in cases where it was based on a flag in the command that starts the ANT build. From what I've read however, this looks like it should work. What do I have wrong?
UPDATE II
Okay this is working beautifully, based on Stefan's answer:
<target name="Concept3" description="Insert closing body tag" depends="Concept2,Concept1,Concept0">
<replaceregexp byline="false" flags="gs">
<regexp pattern="(<)(/body)(>)"/>
<substitution expression="\1\/conbody>"/>
<fileset dir=".">
<include name="*.htm"/>
<not>
<contains text="TaskChar"/>
</not>
<not>
<contains text="RefChar"/>
</not>
</fileset>
</replaceregexp>
</target>
<target name="Task3" description="" depends="Task2,Task1,Task0">
<!-- Insert closing body tag-->
<replaceregexp byline="false" flags="gs">
<regexp pattern="(<)(/body)(>)"/>
<substitution expression="\1\/taskbody>"/>
<fileset dir=".">
<include name="*.htm"/>
<not>
<contains text="ConceptStyle"/>
</not>
<not>
<contains text="RefChar"/>
</not>
</fileset>
</replaceregexp>
</target>
<target name="Ref3" description="" depends="Ref2,Ref1,Ref0">
<!-- Insert closing body tag-->
<replaceregexp byline="false" flags="gs">
<regexp pattern="(<)(/body)(>)"/>
<substitution expression="\1\/refbody>"/>
<fileset dir=".">
<include name="*.htm"/>
<not>
<contains text="ConceptStyle"/>
</not>
<not>
<contains text="TaskChar"/>
</not>
</fileset>
</replaceregexp>
</target>
Each target operates on a fileset filtered for a string that mustn't appear in the file in order for the target to act on it. There are three style type names, and my source files include only one of the three (by design), and this now triggers the ANT build to handle each file differently depending on which type it is. Great.

First of all it doesn't really look as if you needed a regex at all, a simple <contains> would probably do it - unless there are files where "ConceptStyle" appears outside of the the body.
AFAIU you want to perform the substitution on all files unless they contain ConceptStyle. Rather than using condition and attributes on the target I'd recommend filtering the fileset instead.
<replaceregexp byline="false" flags="gs">
<regexp pattern="conbody"/>
<substitution expression="BOOOO"/>
<fileset dir=".">
<include name="*.htm"/>
<not>
<contains text="ConceptStyle">
</not>
</fileset>
</replaceregexp>
If you really need the regex, then use <containsregex> instead.

Related

How can I execute an ant target depending on the value of an environment variable?

I want to execute an ant script on two different computers. Depending on the name of the computer either one of the two targets should be executed. Following doesn't work:
<project name="import" default="all">
<property environment="env"/>
<target name="staging" if="${env.COMPUTERNAME}='STG'">
<echo>executed on staging</echo>
</target>
<target name="production" if="${env.COMPUTERNAME}='PRD'">
<echo>executed on production</echo>
</target>
<target name="all" depends="staging,production" description="STG or PRD"/>
</project>
As I understood, "if" can only be used with property and it checks whether a property is set or not. But is there a way to to make a condition depending on the value of a property?
I would suggest writing an "init" target that sets any conditions you need for later build steps, and also fails the build if certain required properties don't evaluate to what's expected.
For example:
<target name="all" depends="staging,production,init" />
<target name="staging" if="staging.environment" depends="init">
<echo message="executed on staging" />
</target>
<target name="production" if="production.environment" depends="init">
<echo message="executed on production" />
</target>
<target name="init">
<condition property="staging.environment">
<equals arg1="${env.COMPUTERNAME}" arg2="STG" />
</condition>
<condition property="production.environment">
<equals arg1="${env.COMPUTERNAME}" arg2="PRD" />
</condition>
<fail message="Neither staging nor production environment detected">
<condition>
<not>
<or>
<isset property="staging.environment" />
<isset property="production.environment" />
</or>
</not>
</condition>
</fail>
</target>

Creating folders inside zip file in NAnt

At the end of a NAnt script, the last step is to create a ZIP file.
Currently, I'm doing this:
<zip zipfile="${target.dropfile}">
<fileset basedir="${somefolder}">
<include name="file1.dll" />
</fileset>
<fileset basedir="${someotherfolder}">
<include name="file2.dll" />
</fileset>
<!-- ...etc ... -->
</zip>
This works fine, but I want the zip file to be a little more organized. I want the zip file to contain two folders, folder1 and folder2, and I want file1.dll to be in folder1 and file2.dll to be in folder2. Is there any way of doing this within the <zip /> task?
Just use the prefix variable.
<zip zipfile="${target.dropfile}">
<fileset basedir="${somefolder}" prefix="folder1">
<include name="file1.dll" />
</fileset>
<fileset basedir="${someotherfolder}" prefix="folder2">
<include name="file2.dll" />
</fileset>
<!-- ...etc ... -->
</zip>

Apache Ant: Can I search all files for a specific regex and then print the matches to a file?

In an Ant build.xml, I would like to be able to find any matches in all .html files using the following regex:
("|')((?!http://|#|mailto:|&|/)([^#\n\s\."])+?\.([^#\n\s"])+?)\1
Then, I want to list those matches of \2 in a file. Is this possible?
Final result, thanks to #bakoyaro:
<echo message="Collecting appcache files" />
<concat destFile="your_output_file">
<fileset dir="./${dir.publish}">
<include name="**/*.html"/>
</fileset>
<filterchain>
<linecontainsregexp>
<regexp pattern="(.)*?("|')((?!http://|\?|#|mailto:|\1)([^#\n\s\."'?])+?\.([^#\n\s"'?])+?)\2" />
</linecontainsregexp>
<tokenfilter>
<replaceregex pattern="(.)*?("|')((?!http://|\?|#|mailto:|\1)([^#\n\s\."'?])+?\.([^#\n\s"'?])+?)\2" flags="g" replace="\1\2\3\2${line.separator}" />
</tokenfilter>
<linecontainsregexp>
<regexp pattern="(.)*?("|')((?!http://|\?|#|mailto:|\1)([^#\n\s\."'?])+?\.([^#\n\s"'?])+?)\2" />
</linecontainsregexp>
<tokenfilter>
<replaceregex pattern="(.)*?("|')((?!http://|\?|#|mailto:|\1)([^#\n\s\."'?])+?\.([^#\n\s"'?])+?)\2" flags="g" replace="\3" />
</tokenfilter>
<linecontainsregexp>
<regexp pattern="((?!http://|\?|#|mailto:|\1)([^#\n\s\."'?])+?\.([^#\n\s"'?])+?)" />
</linecontainsregexp>
</filterchain>
</concat>
Here is a snippet that may help, it will create a .zip file containing any of the files that match your regex. I use it to examine my builds to ensure that all of the ant tokens were replaced.
<zip destfile="${your_file_name}" update="true" whenempty="skip">
<fileset dir="${your_search_directory}">
<!-- your file pattern -->
<include name="**/*.html" />
<!-- this will destroy an executable file. best to exclude them -->
<exclude name="**/*.jar" />
<containsregexp expression="your_regex_to_match" />
</fileset>
</zip>
You should be able to do this using the Concat task with a nested FilterChain.
Something like this:
<concat destFile="your_output_file">
<fileset dir="WebContent">
<include name="**/*.html"/>
</fileset>
<filterchain>
<linecontainsregexp>
<regexp pattern="your_pattern_to_match" />
</linecontainsregexp>
<tokenfilter>
<replaceregex pattern="your_pattern_to_extract" replace="output_required" />
</tokenfilter>
</filterchain>
</concat>

axis-java2wsdl task classpath setting problem

here is my build.xml
<?xml version="1.0" standalone="yes"?>
<path id='axis2.classpath'>
<fileset dir='D:\Tools\axis2-1.5.1-bin\axis2-1.5.1\lib'>
<include name='**/*.jar' />
</fileset>
</path>
<path id='compiled.class.path'>
<fileset dir='./bin/pkg'>
<include name='*.class' />
</fileset>
</path>
<taskdef resource="axis-tasks.properties" classpathref="axis2.classpath" />
<target name="run" >
<axis-java2wsdl
output="out/TestService.wsdl"
location="http://localhost:8080/axis2/service/TestService"
namespace="service"
classname="TestService">
<classpath refid="compiled.class.path"/>
<mapping namespace="TestService" package="pkg"/>
</axis-java2wsdl>
</target>
here is my file structure:
prj->bin->pkg->TestService.class///////////
prj->src->pkg->TestService.java///////////
prj->build.xml
I get java.lang.ClassNotFoundException: TestService.
Can anybody tell me how to fix it? Thanks so much. !!!!!!!!!!!!!
Is TestService in a package called "pkg", or is it in the default package (i.e., no package)? If it's in a package called "pkg", you want to define your "compiled.class.path" like:
<path id='compiled.class.path'>
<fileset dir='./bin'>
<include name='**/*.class' />
</fileset>
</path>

I want to use NAnt's foreach to iterate files in a folder, how to force alphabetic iteration?

I have an NAnt task "ship" to package my current .sql scripts into a build, then name the build with an incrementing int {######} and copy it to a build folder.
I have another NAnt task which executes those build scripts.
They must execute in order, but in my last attempt, they were not. Can I "force" NAnt to work alphabetically?
FAIL:
<fileset basedir="source\tsql\builds\" id="buildfiles">
<include name="*.sql.template.sql" />
<exclude name="*.sql" />
<exclude name="*asSentTo*" />
</fileset>
<foreach item="File" property"filename">
<in refid="buildfiles">
<echo message="${filename}" />
</in>
</foreach>
PASS:
<foreach item="File" property="filename" in="source\tsql\builds">
<do>
<if test="${string::ends-with(filename,'.sql.template.sql')}">
<echo message="${filename}" />
</if>
</do>
</foreach>
To satisfy my curiosity I tried to reproduce the problem with this script:
<?xml version="1.0"?>
<project name="foreach.test" default="foreach.alpha">
<target name="foreach.alpha">
<foreach item="File" in="C:\foo" property="filename">
<do>
<echo message="${filename}" />
</do>
</foreach>
</target>
</project>
The filenames are printed out in alphabetical order. So conventional use of foreach already seems to be the solution to the problem.
Here is how you do it with a fileset
<fileset id="mySet">
<include name="*.sql" />
</fileset>
<copy>
<fileset refid="mySet" />
</copy>
<foreach item="File" property="filename">
<in>
<items refid="mySet" />
</in>
<do>
<echo message="Copied files: ${filename} to directory: ${Folder}." />
</do>
</foreach>