How do I rename files when included in a jar by ant's jar task?
Asked Answered
C

3

13

I want to put a set of files that look like this into a jar:

yay/my.jar
boo/my.jar
foo/my.jar
bar/my.jar

In the process, I want all of them renamed as follows:

yay_my.jar
boo_my.jar
foo_my.jar
bar_my.jar

I was hoping to use a mapper to accomplish this, but the fileset elements I am using and the jar task don't seem to support it anywhere.

How do I apply a mapper when building a jar, or else how can I perform a transformation like this? I want to avoid copying all the files to the directory structure I want and making duplicates all over the place, which is how our build system works now.

Cephalochordate answered 22/9, 2009 at 14:25 Comment(0)
T
17

You can use a zipfileset with a fullpath attribute to rename the filename in the jar:

<jar destfile="newjar.jar">
    <zipfileset dir="yay" includes="my.jar" fullpath="yay_my.jar"/>
    <zipfileset dir="boo" includes="my.jar" fullpath="boo_my.jar"/>
    <!-- etc. -->
</jar>

You can't use a mapper with this technique though, you'll have to list each jar file explicitly. If you can assume that every file is named my.jar, and they are all in an immediate child directory, you can use the subant target to glob them all up:

<target name="glom">
    <subant genericantfile="${ant.file}" target="update-jar">
        <dirset dir="." includes="*"/>
    </subant>
</target>

<target name="update-jar">
    <basename file="${basedir}" property="dirname"/>
    <property name="path" value="${dirname}_my.jar"/>
    <jar destfile="../newjar.jar" update="yes">
        <zipfileset dir="." includes="my.jar" fullpath="${path}"/>
    </jar>
</target> 
Thrombophlebitis answered 26/9, 2009 at 23:43 Comment(1)
+1 Nice easy way to rename a file during the jar task. Thanks.Bohn
H
2

Update: you probably actually want the copy task rather than move, but the regexp mapper works the same for both copy and move.

The following regexp will copy all jars in the jars directory to jars_out, mapping [folder]/[file].jar to [folder]_[file].jar.

<copy todir="./jars_out">
  <fileset dir="jars"/>
  <mapper type="regexp" from="([^/\\]*)[/\\](.*)\.jar$$" to="\1_\2.jar"/>
</copy>

The regexp mapper needs an appropriate regexp implementation jar on the classpath to work. Various implementations are available:

Horsemint answered 22/9, 2009 at 14:32 Comment(4)
That's great but doesn't accomplish my goal of building the jar without making extra copies of the files. Move would avoid copies, but then the jars would be rebuilt each time I build instead of only if their source files have changed.Cephalochordate
However, the mapper tag you built is awesome, and I'll be borrowing that instead of coming up with one of my own. :) I hadn't gotten far enough to actually build the mapper I needed yet since I couldn't get any mapper at all to work with fileset and jar.Cephalochordate
sorry I misread the question. I'll have a think about how to accomplish this, but I am being called to the pub right nowHorsemint
Your help was still great, Rich. It was a long question, and I think you can be forgiven for missing part of it. :) Thank you.Cephalochordate
T
2

If you don't want to (or can't readily) list each file individually, one solution is to use the Zip task, which allows a nested <mappedresources> (Ant 1.8.0+). Once the Zip task completes, you can use the Jar task to add/update the manifest and/or add an index.

Suppose, for example, that in addition to wanting

yay_my.jar
boo_my.jar
foo_my.jar
bar_my.jar

in the output JAR, you also have a directory stuff/, containing some files and subdirectories. If you want the contents of stuff/ included in the JAR, but you want stuff/subdir/* to be added as other_subdir/*, consider the following:

<zip destfile="newjar.jar">
    <zipfileset dir="yay" includes="my.jar" fullpath="yay_my.jar"/>
    <zipfileset dir="boo" includes="my.jar" fullpath="boo_my.jar"/>
    <!-- etc. -->

    <mappedresources>
        <fileset dir="stuff"/>
        <compositemapper>
            <globmapper from="subdir/*" to="other_subdir/*"/>
            <identitymapper/>
        </compositemapper>
    </mappedresources>
</zip>
<!-- Update the newly-created ZIP in-place to add a basic manifest -->
<jar destfile="newjar.jar" update="true"/>

I tested this build file and it works with Ant 1.8.2. However, if after changing it Ant begins throwing a NullPointerException, see Bug 54026.

Twinkling answered 18/10, 2012 at 23:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.