Remove fileset directories from Ant war lib - ant

Is there a simple way to use Ant <mappedresources> to flatten directories in a <fileset> into a <war> <lib>. For example:
<fileset id="xx.lib" dir="${base.lib.path}">
<include name="library1/library1.jar"/>
<include name="library2/library2.jar"/>
</fileset>
So that the jars are in WEB-INF/lib without their "library1"/"library2" paths.
I have read the above link and several related questions here on SO, but I can't envision the mechanism to do exactly what I'm describing, for just one of several <lib> elements.

Related

How do you create a classpath in ANT that includes all jars in a directory and it's subdirectories

I'm using ANT to build a Java project that has dependency jars during compile time. The dependency jars are nested inside a directory. What this means is, the directory contains sub-directories (which might contain sub-directories) and jars as well.
I want to create an ANT element to include all the jars inside the directory. Below is my code but doesn't work. I'm wondering if this can't be done in ANT or I'm doing something wrong:
<path id="javaee.classpath">
<fileset dir="${javaee.modules.dir}">
<patternset>
<include name="**/*.jar" />
</patternset>
</fileset>
</path>

adding the specified folders in the jar created using ant

I have a folder structures
build/classes/com/vaannila/domain/.class files
build/classes/com/vaannila/service/.class files
build/classes/com/vaannila/web/.class files
My requirement is to create a jar file using ant, how can I include the specified folders in the jar,say I want include only domain and service (or) domain and web in the jar, like the way I create the jar using Eclipse(Export-->archive file).
Can anyone help me with this please?
You can use include and exclude tags in the fileset element, and choose specific files...
<jar destfile="${jar.dir}/${jar.file.name}" index="true"
manifest="${manif.dir}/${manif.file.name}">
<fileset dir="${build.classes.dir}" >
<include/>
<exclude/>
</fileset>
</jar>
<fileset dir="${build.classes.dir}">
<exclude name="**/property/*"/>
<include name="**/abcd/*"/>
</fileset>
This way you can remove/include respective directories.

Exclude empty directories with Jar Jar Links

I am using an Ant task from Jar Jar Links to embed classes from a 3rd-party jar file (objenesis) in my distributable jar file (example.jar). Jar Jar will translate classes from the original package (org.objenesis) to one of my choosing.
It works but it leaves empty directories in the distributable jar.
Here is a simplified build.xml:
<target name="jar" depends="compile">
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask"
classpath="lib/jarjar-1.1.jar"/>
<jarjar jarfile="dist/example.jar" excludes="org.objenesis.**">
<fileset dir="build/classes/main"/>
<zipfileset src="lib/objenesis-1.2.jar"/>
<rule pattern="org.objenesis.**" result="org.thirdparty.#1"/>
</jarjar>
</target>
A sample of contents of the example.jar includes (as expected):
org/thirdparty/Objenesis.class
org/thirdparty/ObjenesisBase.class
but also these empty directories (undesirable):
org/objenesis/
org/objenesis/instantiator/
org/objenesis/instantiator/basic/
My question: how to I exclude these empty directories?
I tried the "zap" option (listed in the doc), but that didn't work.
This appears to be a known issue in Jar Jar, listed in their issue tracker: http://code.google.com/p/jarjar/issues/detail?q=empty&id=32
Given that this was raised almost three years ago and doesn't appear to have got any traction, I suppose your options are to contribute a fix, or to work around it.
An example Ant target to work around it, taking advantage of Ant's support for removing empty directories on copy, would be:
<target name="unpolluted-jarjar" description="JarJars without empty directories">
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="${location.lib}/build/jarjar-1.2.jar"/>
<jarjar basedir="${location.classes}" destfile="${location.dist.binaries}/my-app.jar">
<zipfileset src="${location.lib}/shipped/dependency.jar"/>
<rule pattern="com.example.dependency.**" result="com.example.my-app.jarjar.com.example.dependency.#1"/>
</jarjar>
<mkdir dir="${location.dist.binaries}/exploded"/>
<unzip src="${location.dist.binaries}/my-app.jar" dest="${location.dist.binaries}/exploded/my-app.jar"/>
<copy includeemptydirs="false" todir="${location.dist.binaries}/unpolluted/my-app.jar">
<fileset dir="${location.dist.binaries}/exploded/my-app.jar"/>
</copy>
<jar destfile="${location.dist.binaries}/my-app-unpolluted.jar">
<fileset dir="${location.dist.binaries}/unpolluted/my-app.jar"/>
</jar>
</target>
It's a bit grungy, but it achieves what you want.

How do I convert an Ant Path into a FileSet?

I'm writing an Ant script to package a project into a WAR file. The software consists of several projects with their own source directories, libraries, etc.
The WAR task has a nested element lib which I'm currently working on. I currently have a reference of the required libs as a Path (containing several FileSets, which I use in a classpath reference. The lib, however, wants the input to be a FileSet, and it refuses a Path.
I tried converting my Path into a FileSet, but then I didn't get it to work as a classpath elsewhere.
Is there a way to convert a Path into a FileSet? I would hate to copy-paste the directories.
<path id="compile.libs">
<fileset dir="${common.path}/lib" includes="*.jar"/>
<fileset dir="${data.path}/lib" includes="*.jar"/>
<fileset dir="${gui.path}/lib" includes="*.jar"/>
<fileset dir="${gui.path}/WebContent/WEB-INF/lib" includes="*.jar"/>
</path>
...when used with <war ..><../> <lib refid="compile.libs"/> </war> leads to:
BUILD FAILED
build.xml:173: compile.libs doesn't denote a zipfileset or a fileset
Assuming the paths are absolute, you can first convert the Path to a comma-delimited list using <pathconvert>, and then convert the list back into a Fileset:
<!-- create path -->
<path id="foo.path">
<pathelement location="/foo/bar/baz.txt"/>
<pathelement location="/qux/quux/quuux.txt"/>
</path>
<!-- convert foo.path to foo.list -->
<pathconvert
refid="foo.path"
property="foo.list"
pathsep=","
dirsep="/"
>
<!--
<fileset> will want relative paths, so we need to strip
the leading /. result: "foo/bar/baz.txt,qux/quux/quuux.txt"
-->
<map from="/" to=""/>
</pathconvert>
<!-- convert foo.list to fileset -->
<fileset id="foo.fileset" dir="/" includes="${foo.list}"/>
(Note the above assumes Unix; you may need to fiddle a bit with separators and whatnot if you're on Windows or you want to make it platform-independent.)
You may have several choices.
You may provide more than one
<lib> nested element to <war>
task. Maybe this would be enough.
You may preassemble all of your
lib files in one temporary
directory and then just reference that
directory as a fileset.
There is an ant-contrib
PathToFileSet task, but it
requires a central root directory,
and this may not be a case with your
compile.libs layout.
Since Ant 1.8.0 you can use a mappedresources. Source: Ant script: Prevent duplication of JAR in javac-classpath war-lib
I think I would try option 1.
I solved this by staging the libs like this :
<copy todir="stage/libs" flatten="true">
<path refid="classpath" />
</copy>
and then using a in the WAR task.simple.
The jars in the classpath used to compile are not the same that needs to be packaged inside the war. For example: I'm sure you need servlet-api.jar to compile your project but you don't need it inside the war because the container provides it. And some jars aren't needed at compile time but at runtime.
I know I'm not answering your question, just want you to think what you are doing.

How to create directories specified by a mapper in Ant

Given a fileset
<fileset id="myFiles" dir=".">
<include name="**/*.file"/>
</fileset>
How do I create a sub-directory at each file in the set, named after the filename without the extension?
For example, given the files folderA/X.file and folderA/folderB/Y.file, I want to create the directories folderA/X and folderA/folderB/Y
The ant touch task supports creating files, parent dirs and filename mapping, so can be used to achieve this:
<target name="mkdirs">
<touch mkdirs="true">
<fileset dir="the_dir"/>
<mapper type="glob" from="*.file" to="the_dir/*/.tmp" />
</touch>
<delete>
<fileset dir="the_dir" includes="**/.tmp"/>
</delete>
</target>
This creates temporary files in target dirs (creating the dirs if the don't exist) then deletes the temporary files leaving the dirs you wanted.
You would be using for task to iterate on your file list. But I have not come across any substring type of utility in Ant which you can use to strip the extension and create the directory. Do search for this utility, if its not there then you need to implement an Ant task to do that.
Sorry to answer my own question. Unless someone knows otherwise, there appears to be no way for out-of-the-box ANT to create directories (e.g. using mkdir) relative to entries in a fileset.
Ant-Contrib contains useful for loop tasks, as Bhushan suggests, which could possibly perform this sort of task.
Had some better things to be getting on with, so in the end, I just wrote a batch file called by an ANT task (apply tasks can iterate over filesets).
<apply executable="cmd" failonerror="1">
<arg value="/c"/>
<arg line="build\tools\makeRelDir.bat"/>
<fileset dir=".">
<include name="**/*.file"/>
</fileset>
</apply>
where the batch file does this:
mkdir %~dp1%~n1
(Why is it so hard to do something some simple in ANT? Am I missing something?)

Resources