Conditional token replacement in Ant - ant

I'm trying to do a token replace in an Ant build file, but only if the token is in a line that has specific content.
Sample mockup snippet from the file:
<script type="text/javascript" src="scripts/someFolder/someFile1.js"></script>
<script type="text/javascript" src="scripts/otherFolder/fileName.js"></script>
<script type="text/javascript" src="scripts/aFolder/file3.js"></script>
<script type="text/javascript" src="scripts/someFolder/aFile.js"></script>
<script type="text/javascript" src="scripts/someFolder/subfolder/anotherFile.js"></script>
<body>
<p>Stuff</p>
In this example, I want to append a ?timestamp to any of the js files that are coming from "somefolder".
I've tried something along these lines (actual regex is different):
<copy file="xyz.jsp" tofile="${staging}/jsp/Links-test.jsp">
<filterchain>
<linecontainsregexp>
<regexp pattern="someFolder" />
</linecontainsregexp>
<replacestring from=".js" to=".js?blahblah" />
</filterchain>
</copy>
but that just results in a file with only the lines that were modified. What flag do I need to set to keep all of the file contents? I need the entire file, just with some conditional replaces.

You can put multiple filterchains together. Your filter chain filters out lines that contain the regular expression. What you need is a second filter chain to add it back in.
Completely untested:
<copy file="xyz.jsp" tofile="${staging}/jsp/Links-test.jsp">
<filterchain>
<linecontainsregexp>
<regexp pattern="someFolder" />
</linecontainsregexp>
<replacestring from=".js" to=".js?blahblah" />
</filterchain>
<filterchain>
<linecontainsregexp negate="true">
<regexp pattern="someFolder" />
</linecontainsregexp>
</filterchain>
</copy>

Related

Ant substring by position

I need to extract a substring from property value by length, f.e. :
<property name="prop1" value="nameBLABLABLA" />
I want get the value
name
Is it possible without using javascript code ?
Not with vanilla ant, you would need to add some Ant addon like Antcontrib (latest release 2006 !) or Ant Flaka - means you'll need additional jars/libraries.
With using the jdk builtin Javascript engine it's as easy as :
<project>
<!-- create a macrodef for reuse -->
<macrodef name="getsubstring">
<attribute name="src"/>
<attribute name="from"/>
<attribute name="to"/>
<attribute name="result"/>
<sequential>
<script language="javascript">
project.setProperty(
"#{result}", "#{src}".substring(#{from},#{to})
);
</script>
</sequential>
</macrodef>
<property name="foo" value="nameBLABLABLA"/>
<getsubstring src="${foo}" from="0" to="4" result="foobar"/>
<echo> $${foobar} => ${foobar}</echo>
</project>
No additional libraries needed.
Created a macrodef that works for properties respectively for strings in general.
The JavaScript engine understands Javascript and Java and you'll get full access to Ant api.
I'd use JavaScript as in Rebse's answer, but there is a way to do this without it using <loadresource> and a <tokenfilter>. This uses start/length rather than from/to for the substring:
<macrodef name="getsubstring">
<attribute name="src"/>
<attribute name="start"/>
<attribute name="length"/>
<attribute name="result"/>
<sequential>
<loadresource property="#{result}">
<string value="#{src}}" />
<filterchain>
<tokenfilter>
<replaceregex pattern="^.{#{start}}(.{#{length}}).*" replace="\1" />
</tokenfilter>
</filterchain>
</loadresource>
</sequential>
</macrodef>
<property name="prop1" value="nameBLABLABLA" />
<getsubstring src="${prop1}" start="0" length="4" result="p"/>
<echo message="${p}" />

How to concatenate paths returned from `fileset` into the XML file?

I'm trying to concatenate an unknown number of HTML files into one XML file.
That's no problem with:
<concat destfile="${temp.dir}/file.xml" encoding="UTF-8" outputencoding="UTF-8">
<fileset dir="${html.dir}" includes="**/*.html" />
</concat>
Now what I would like to do is, for each file of the fileset, insert its path into the concatenated file.
Example
I have the following HTML files in C:\whatever\sources:
A.html
B.html
In the result XML file, I'd like to get:
<allfiles>
<html url="C:\whatever\sources\A.html>...content of A.html...</html>
<html url="C:\whatever\sources\B.html>...content of B.html...</html>
</allfiles>
Is there a way to do that simply without reinventing the wheel and if possible without using ant-contrib?
As mentioned, you can use a scriptfilter inside filterchain task to run Javascript inside your Ant build.
For example:
<concat destfile="${temp.dir}/file.xml" encoding="UTF-8" outputencoding="UTF-8">
<fileset dir="${html.dir}" includes="**/*.html" id="my-files"/>
<filterchain>
<tokenfilter>
<filetokenizer />
<scriptfilter language="javascript" byline="false"><![CDATA[
content = self.getToken();
// Modify content of token.
//content=content.replaceAll("(?s)/\\*.*?\\*/","");
self.setToken(content);
]]></scriptfilter>
</tokenfilter>
<striplinecomments>
<comment value="//"/>
</striplinecomments>
<striplinebreaks/>
</filterchain>
</concat>
Find more examples at:
JavaExplorer/blob/master/static/build.xml
Getting file name inside Ant copy task filter
Using Ant scriptfilter to count lines

ant.concat task translation to Gradle / Groovy

<concat destfile="${database_dir}/xxxx-create-constraints.sql">
<filelist dir="${database_dir}" files="XXXX-hsqldb-nodrop.sql" />
<filterchain>
<striplinebreaks />
<replacestring from=";" to=";
" />
<linecontains>
<contains value="add constraint" />
</linecontains>
</filterchain>
</concat>
<concat destfile="${database_dir}/XXXXX-drop-constraints.sql">
<filelist dir="${database_dir}" files="xxxx-hsqldb.sql" />
<filterchain>
<striplinebreaks />
<replacestring from=";" to=";
" />
<linecontains>
<contains value="drop constraint" />
</linecontains>
</filterchain>
</concat>
I am trying to translate this into Gradle, it is part of a larger task the majority of which I have already translated, I am having trouble with the following section.
<filterchain>
<striplinebreaks />
<replacestring from=";" to=";
" />
<linecontains>
<contains value="drop constraint" />
</linecontains>
</filterchain>
I can't find any examples or documentation on how this might look in Groovy.
Thus far I have just:
ant.concat(destFile:"${database_dir}/XXXX-create-constraints.sql"){
files("XXXX-hsqldb-nodrop.sql")
filelist(dir:"${database_dir}")
}
Any help or insight would be appreciated.
EDIT
I've nutted out a version though I'm not sure about correctness, just because its not throwing errors or breaking doesn't mean its right.
ant.concat(destFile:"${database_dir}/XXXX-create-constraints.sql"){
files("XXXX-hsqldb-nodrop.sql")
filelist(dir:"${database_dir}")
filterchain{
striplinebreaks()
replacestring(from:';', to:';
')
linecontains{
'add constraint'
}
}
}

Ant: Convert class name to file path

How do I convert Java class names into file paths using Ant tasks?
For example, given a property containing foo.bar.Duck I'd like to get out foo/bar/Duck.class.
I tried (and failed) to implement this in terms of <pathconvert> and <regexpmapper>.
Here's a possible way to do this:
<property name="class.name" value="foo.bar.Duck"/>
<loadresource property="file.name">
<string value="${class.name}" />
<filterchain>
<replaceregex pattern="\." replace="/" flags="g" />
<replaceregex pattern="$" replace=".class" />
</filterchain>
</loadresource>
This puts the desired foo/bar/Duck.class into the file.name property.
Here's another way, using Ant resources and an unpackagemapper, which is designed for this purpose. The opposite package mapper is also available.
<property name="class.name" value="foo.bar.Duck"/>
<resources id="file.name">
<mappedresources>
<string value="${class.name}" />
<unpackagemapper from="*" to="*.class" />
</mappedresources>
</resources>
You use the resource value by means of the property helper syntax ${toString:...}, e.g.:
<echo message="File: ${toString:file.name}" />
Yields
[echo] File: foo/bar/Duck.class
I feel using ant script-javascript for this is much simpler
<property name="class.name" value="foo.bar.duck" />
<script language="javascript">
var className = project.getProperty("class.name");
println("before: " + className);
var filePath= className.replace("\\", "/");
println("File Path: "+filePath);
project.setProperty("filePath", filePath);
</script>
<echo message="${filePath}" />
note: that naming your variable same as argument e.g var wsPath may give error, it gave to me!
courtesy: https://stackoverflow.com/a/16099717/4979331

Get multiple strings at ant

I have for example the js file containing these lines:
<script defer src="/js/libs/ui.achtung.js"></script>
<script defer src="/js/libs/jquery.tipsy.js"></script>
<script defer src="/js/libs/jquery.mousewheel.js"></script>
I need to concatenate these files at one and place a link to newly created file here replacing existing scripts.
So the algorithm is a) read lines with scripts b) concatenate all scripts to one c) replace script links to only one
I cant find a decision to read multiple lines to place each of them to separate property or so.
Can anyone help me?
To read multiple lines, have a look at:
Ant: get multiple matches with propertyregex
The example there extract
ABC
ABCD
ABCE
out of
test.ABC.test
test.ABCD.test
test.ABCE.test
with
<target name="test">
<loadfile property="record" srcFile="./index.html">
<filterchain>
<tokenfilter>
<containsregex pattern=".*test\.([^\.]*)\.test.*" replace="\1"/>
</tokenfilter>
</filterchain>
</loadfile>
<echo message="${record}" />
</target>

Resources