Get multiple strings at ant - 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>

Related

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

Create a fileset from a semicolon-separated list in a property

I have an ant property ${src.dirs} that contains a list of dirs separated by a semi colon.
Now i need to specify fileset (for replaceregexp) and that fileset has to contain all java files from all dirs listed in ${src.dirs}.
How can i do it (I don't use any ant-contrib funcky stuff, I use plain vanilla ant).
The src.dirs have this form: /usr/work/dir1/src;/usr/work/java/dir2/src;/usr/libabc/src
There's is an example on how to use propertyregex, but when I try to use it I get this error:
build.xml:98: Problem: failed to create task or type propertyregex
Edit:
Here's what was my final solution:
<loadresource property="source.dir.javafiles">
<propertyresource name="source.dir"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="\s*([;,]\s*)*$" replace="/**/*.java"/>
<replaceregex pattern="\s*([;,]\s*)+" replace="/**/*.java," flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<fileset dir="" includes="${source.dir.javafiles}"/>
These regexes ensure that trailing commas or semicolons don't produce wrong fileselectors.
You might be able to do this without using ant-contrib. Here's a possibility:
<property
name="dirlist"
value="/usr/work/dir1/src;/usr/work/java/dir2/src;/usr/libabc/src" />
<property name="file.wildcard" value="*.java" />
<loadresource property="dirs.include">
<propertyresource name="dirlist"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="^/" replace="" />
<replaceregex pattern=";/" replace="/**/${file.wildcard}," flags="g"/>
<replaceregex pattern="$" replace="/**/${file.wildcard}" />
</tokenfilter>
</filterchain>
</loadresource>
<fileset id="files" dir="/" includes="${dirs.include}" />
The work is split into two: first string processing to convert the semicolon-separated list into patterns suitable for use in a fileset includes attribute; second make a fileset from the pattern.
The loadresource task here is simply being used as a wrapper around a sequence of simple regular expression replacements. The three replacements deal with the leading root directory \, expanding the intra-string semicolons into Ant patterns and commas (which are used in includes attributes to separate entries), and adding a pattern at the end of the string.
In your case you might consider tuning this to not use the root directory in the dir attribute of the fileset.
propertyregex is from ant-contrib, which is why the example is not working for you.
Here is one way to achieve what you want.
<pathconvert property="src.dirs.includes" pathsep="/**/*.java,">
<path path="${src.dirs}" />
</pathconvert>
<replaceregexp match="\s+" replace=" " flags="g" byline="true">
<files id="files" includes="${src.dirs.includes}/**/*.java" />
</replaceregexp>
However spaces in any of the filenames (including their path) will stuff you up.
Do you simply have to go through these directories and do your compile, or must these directories be compiled together because of dependencies?
If there are no dependencies, you could try the <for/> task in Ant-Contrib. This lets you loop through a list like the one you have:
<for list="${src.dirs}"
param="my.src.dir"
delimiter=";">
<sequential>
<javac destdir="${javac.destdir}"
srcdir="#{my.src.dir}"
classpathref="main.classpath"/>
</sequential>
</for>
Of course, you might have to munge things for your correct destdir. You may find the <var/> task convenient when you use the <for/> task. The <var/> task allows you to reset variable names. When you repeat the <sequential/> set of tasks, you may find you want to reset certain properties.
By the way, if you have Ant 1.8 or higher, you can use the <local/> task instead of <var/>.

Using ant to modify a file containing values in another file

I'm currently using ant to remove lines from a file if the line matches any of a list of email addresses, and output a new file without these email addresses as follows:
<copy file="src/emaillist.tmp2" tofile="src/emaillist.txt">
<filterchain>
<linecontains negate="true"><contains value="paultaylor#hotmail.com"/>
</linecontains>
<linecontains negate="true"><contains value="paultaylor2#hotmail.com"/>
</linecontains>
........
........
</filterchain>
</copy>
But I already have a file containing a list of the invalid email addresses (invalidemail.txt) I want to remove, so I want my ant file to read the list of invalid email addresses from this file rather than having to add a element for each email I don't want. Cannot work out how to do this.
Ant has some useful resource list processing tasks. Here's a 'prototype' solution.
Load the input and exclusion lists to two resource collections, tokenized by default on line breaks.
<tokens id="input.list">
<file file="src/emaillist.tmp2"/>
</tokens>
<tokens id="invalid.list">
<file file="invalidemail.txt"/>
</tokens>
Do some set arithmetic to produce a resource list of clean emails:
<intersect id="to_be_removed.list">
<resources refid="input.list"/>
<resources refid="invalid.list"/>
</intersect>
<difference id="clean.list">
<resources refid="input.list"/>
<resources refid="to_be_removed.list"/>
</difference>
Here's some diagnostics that may be useful:
<echo message="The input list is: ${ant.refid:input.list}" />
<echo message="Emails to be removed: ${ant.refid:to_be_removed.list}" />
<echo message="The clean list is: ${ant.refid:clean.list}" />
Use the pathconvert task to reformat the clean list into one entry per line:
<pathconvert property="clean.prop" refid="clean.list"
pathsep="${line.separator}" />
Finally, output to a file:
<echo file="src/emaillist.txt">${clean.prop}
</echo>

Apache Ant add header & footer to EVERY file in concat job

I'm sure that this is trivial - but have been bashing my head against a wall
I'm trying to take a directory full of mustache templates (html files essentially) and combine them into one file - wrapping each one with a tag
Example:
File1 = <a>This is a Link</a>
File2 = <b>This is in bold</b>
I want the output to look like:
<script type="text/mustache" id="File1">
<a>This is a Link</a>
</script>
<script type="text/mustache" id="File2">
<b>This is in bold</b>
</script>
I'm using a concat task
<concat destfile="mustache.js" fixlastline="yes">
<fileset dir="." includes="**/*.mustache"/>
</concat>
but can't figure out how to get the script blocks to display
At first i thought about using concat somehow with header and footer but didn't find a working solution.
If you not shy away from using some Ant addon, here's a solution based on Flaka =
<project name="demo" xmlns:fl="antlib:it.haefelinger.flaka">
<!-- make standard ant tasks understand EL expressions -->
<fl:install-property-handler />
<!-- we use path instead of pure fileset because we need
absolute filenames for loadfile later in for loop -->
<path id="foo">
<fileset dir="/some/path" includes="**/*.mustache"/>
</path>
<!-- iterate over the path/fileset -->
<fl:for var="file" in="split('${toString:foo}', ':')">
<!-- unset property for next loop -->
<fl:unset>content</fl:unset>
<!-- load file contents to property -->
<loadfile property="content" srcFile="#{file}"/>
<echo file="/some/path/foobar/mustache.js" append="true">
<!-- the id attribute gets filled with the basename of the current fileitem -->
<![CDATA[<script type="text/mustache" id="#{replace(file, '$1' , '.+?(\w+)\..+' )}">
#{trim('${content}')}
</script>]]></echo>
</fl:for>
</project>
Note : 1. my leftmost notation within the echo task to avoid unnecessary blanks in the resulting file ! just write as in my example above and your file will look like your wanted output
2. the <![CDATA[...]]> is needed, otherwise you'll get some error like "echo doesn't support the nested "script" element."

Multiple ANT properties (from file) into the one property

I use task to run a target for all values from the list, taken from one property.
<foreach list="val1,val2" delimiter="," target="my.target" param="param_name"/>
Now, I want to put those values to the separate properties file as there is a lot of them.
So the question is: how can I read multiple (don't know how many) properties (lines in file in fact) from the file into one property?
The property file should look like this:
val1
val2
anothervalue
foobar
And the output should be:
"val1,val2,anothervalue,foobar"
be put in one property.
You can achieve this using LineTokenizer filter with loadfile. For example:
<target name="t">
<loadfile property="data_range" srcFile="ls.txt">
<filterchain> <!-- this filter outputs lines delimited by "," -->
<tokenfilter delimoutput=","/>
</filterchain>
</loadfile>
<foreach list="${data_range}" param="line" delimiter="," target="print" />
</target>
<target name="print">
<echo>line [${line}]</echo> <!-- you can do anything here -->
</target>

Resources