How do I convert an Ant Path into a FileSet? - ant

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.

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>

How do I convert textile to Eclipse help using ant?

I've been using the Mylyn WikiText User Guide to learn how to convert textile files to Eclipse help but I also want to be able to do this using ant because, ultimately, I want to have many textile files contribute to a single textile file then convert to Eclipse help to enable multiple developers to create help pages with minimal conflicts.
The following ant script should take all *.textile files in the 'doc' folder and convert them to Eclipse help:
<?xml version="1.0"?>
<project name="helpwikitext" default="generate-help">
<property name="wikitext.standalone" value="doc" />
<path id="wikitext.classpath">
<fileset dir="${wikitext.standalone}">
<include name="org.eclipse.mylyn.wikitext.*core*.jar" />
</fileset>
</path>
<taskdef classpathref="wikitext.classpath" resource="org/eclipse/mylyn/wikitext/core/util/anttask/tasks.properties" />
<target name="generate-help" description="Generate Eclipse help from textile source">
<wikitext-to-eclipse-help markupLanguage="Textile" multipleOutputFiles="true" navigationImages="true" helpPrefix="help">
<fileset dir="${basedir}">
<include name="doc/*.textile" />
</fileset>
<stylesheet url="styles/help.css" />
<stylesheet url="styles/main.css" />
</wikitext-to-eclipse-help>
</target>
</project>
I get the following error:
[taskdef] Could not load definitions from resource org/eclipse/mylyn/wikitext/core/util/anttask/tasks.properties. It could not be found.
build.xml:11: Problem: failed to create task or type wikitext-to-eclipse-help
I'm fairly sure that I have all the Mylyn features installed so it looks like the ant script doesn't know where to find them. Does anyone know how to fix this?
Do you have the wikitext standalone package installed in your doc directory?
That is what is expected as you define the path used by the taskdef like this:
<property name="wikitext.standalone" value="doc" />
I'll take a guess that your wikitext package is in a different dir.
You then use the same dir as the root for your textfiles. I would suggest to keep the wikitext standalone package separate from your textfiles.

BND Ant task - wrap non-OSGi jars

I'm trying to use Ant bndwrap task to wrap non-OSGi jars in a directory. My current Ant configuration for this is:
<target name="wrap-jars" description="Wrap non-OSGi jars">
<taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${biz.aQute:bnd:jar}"/>
<bndwrap output="${dist.dir}/app-modules">
<fileset dir="${dist.dir}/app-modules" includes="*.jar" />
</bndwrap>
<move overwrite="true" todir="${dist.dir}/app-modules" >
<fileset dir="${dist.dir}/app-modules" includes="*.bar" />
<mapper type="glob" from="*.bar" to="*.jar" />
</move>
</target>
This works fine, but the problem is that it also wraps existing OSGi jar, which causes problems. For instance, I noticed it changes Bundle-SymbolicName header to some default value. It might be changing something else, which I don't want. I only want it to operate on jars that have no OSGi info at all.
Is there some way to tell BND to ignore existing OSGi headers in manifest, or complete jars that are already OSGi-fied?
I would store non-OSGi jars in a separate folder and modify the fileset to process only that folder.
I've noticed that recent bnd versions (for example, 2.1.0) now honour the Bundle-SymbolicName when rewrapping OSGi jars.
just change your fileset to exclude that jar

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.

Ant Copying Empty Directories

I am still very new to ant and, although I know coldfusion, I don't know very much about java conventions, but I know that ant is built using java conventions. That being said I am working on an ant process to copy a project to a temp folder, change some code in the project, and then push the temp directory up to an FTP. I am trying to exclude all of my git, eclipse, and ant files from the copy so that my testing platform doesn't get cluttered. I setup a target to do the copy, but it seems that Ant not only is ignoring my excludes (which I am sure I wrote wrong), but it is only copying top level directories and files. No recursive copy. My current target is:
<target name="moveToTemp" depends="init">
<delete dir="./.ant/temp" />
<mkdir dir="./.ant/temp" />
<copy todir="./.ant/temp">
<fileset dir=".">
<include name="*" />
<exclude name=".*/**" />
<exclude name=".*" />
<exclude name="build.xml" />
<exclude name="settings.xml" />
<exclude name="WEB-INF/**" />
</fileset>
<filterset>
<filter token="set(environment='design')" value="set(environment='testing')" />
</filterset>
</copy>
</target>
I know that I am not doing my excludes right, but I don't know what I am doing wrong with them. I see double asterisks (**) used all the time in Ant but I can't figure out
By default an Ant fileset will (recursively) include all files under the specified directory, equivalent to:
<include name="**/*" />
That's the implicit include. If you supply an include, it overrides the implicit one.
Your include
<include name="*" />
Says 'match any file in the fileset directory', but that excludes traversal of subdirectories, hence your issue. Only files and the top-level directories are being copied.
See Patterns in the Ant docs for directory-based tasks: ** matches any directory tree (zero or more directories).
For your case you should be able to simply remove the 'include', so that the implicit 'include all' applies.
Suggest you also investigate the defaultexcludes task, which lets you set up this sort of thing once for the whole project.
Responding to the title of the question. You can include copy of empty directories as follows. (includeemptydirs attribute)
Example:
<copy includeemptydirs="true" todir="${directory}${file.separator}sentinel_files">
<fileset dir="${basedir}${file.separator}sentinel_files"/>
</copy>
Use the documentation provided in:
https://ant.apache.org/manual/Tasks/copy.html

Resources