The question is likely VERY trivial for anyone familiar with ant, of which I only use the basics thus far.
I know how to rename files, e.g. I already use:
<copy todir="build/css/">
<fileset dir="css/">
<include name="*.css"/>
</fileset>
<globmapper from="*.css" to="*-min.css"/>
</copy>
I know how to calculate an MD5:
<checksum file="foo.bar" property="foobarMD5"/>
I don't know how to include the second into the first, to rename all those files to include their MD5 - the purpose is to serve as webbrowser cache buster. The other cache-busting option, to append "?[something]" is not as good, as is explained on some Google webmaster pages, having the MD5 as part of the name is better.
You could do this without having to include ant contrib
. I had to implement this for work and was not allowed to introduce that extension for security reasons. The solution I came to was this:
<target name="appendMD5">
<copy todir="teststack">
<fileset dir="css/" includes="**/*.css"/>
<scriptmapper language="javascript"><![CDATA[
var File = Java.type('java.io.File');
var Files = Java.type('java.nio.file.Files');
var MessageDigest = Java.type('java.security.MessageDigest');
var DatatypeConverter = Java.type('javax.xml.bind.DatatypeConverter');
var buildDir = MyProject.getProperty('builddir');
var md5Digest = MessageDigest.getInstance('MD5');
var file = new File(buildDir, source);
var fileContents = FIles.readAllBytes(file.toPath());
var hash = DatatypeConverter.printHexBinary(md5Digest.digest(fileContents));
var baseName = source.substring(0, source.lastIndexOf('.'));
var extension = source.substring(source.lastIndexOf('.'));
self.addMappedName(baseName + '-' + hash + extension);
]]></scriptmapper>
</copy>
</target>
It is worth noting that I wrote this for Java 8 but with some minor tweaks it could work on Java 7. Sadly this won't work for earlier versions of Java without more effort.
I managed to produce a somewhat strange solution using for from ant contrib.
But you have to install ant contrib first.
The copy
in the sequential
does not seem to accept/evaluate mappers
(it wouldn't work, I tried with ant 1.7.0), so I had to create an extra move
with a filtermapper to create the results.
It does the following:
- for each file create an md5sum and save it in property foobarMD5
- the property has to be unset before each iteration
- I create a new file in the same
dir
named example.java_foobarMD5.java
(Notice that the filename contains the fileextension)
- I move all files with
.java_
in its name to a new Folder and remove the .java_
I leave this example with .java.
<for param="file">
<path>
<fileset dir="src/" includes="**/*.java"/>
</path>
<sequential>
<echo>Letter @{file}</echo>
<var name="foobarMD5" unset="true"/>
<checksum file="@{file}" property="foobarMD5"/>
<echo>${foobarMD5}</echo>
<copy file="@{file}" tofile="@{file}_${foobarMD5}.java"/>
</sequential>
</for>
<move todir="teststack" verbose="true">
<fileset dir="src/">
<include name="**/*java_*"/>
</fileset>
<filtermapper>
<replacestring from=".java_" to="-"/>
</filtermapper>
</move>