Ant - how to get all files' name in a specific folder - ant

Here is my Ant script for generating jar package. I have bunch of jar packages for manifest Class-Path attribute, they are all in an specific folder.
I don't want to hard code it, how can I get them automatically?
<jar jarfile="${client_deploy_dir}/HelloWorld.jar"
basedir="${client_work_dir}/compiled">
<manifest>
<attribute name="Main-Class" value="HelloWorld.Main"/>
<attribute name="Class-Path" value="???"/>
</manifest>
</jar>
Thanks

You're on the right track, use manifestclasspath task. The jarfile attribute is used to create relative links to the jars contained in the fileset.
<manifestclasspath property="jar.classpath" jarfile="${client_work_dir}/HelloWorld.jar">
<classpath>
<fileset name="" dir="${client_work_dir}/lib" includes="*.jar"/>
</classpath>
</manifestclasspath>
<jar jarfile="${client_deploy_dir}/HelloWorld.jar" basedir="${client_work_dir}/compiled">
<manifest>
<attribute name="Main-Class" value="HelloWorld.Main"/>
<attribute name="Class-Path" value=""${jar.classpath}"/>
</manifest>
</jar>

Check out the ant pathconvert task. You can use this to expand an existing fileset into a list of files.

Related

How to get hold on the flattenmapper result in ant?

Please, find below a few targets from my ant file:
<fileset id="test-dep-jars" dir="o:/java">
<include name="junit-4.10.jar"/>
<include name="easymock-3.1\easymock-3.1.jar"/>
<include name="easymockclassextension-3.1\easymockclassextension-3.1.jar"/>
</fileset>
<target name="copy-test-deps">
<mkdir dir="${deploy.dir}"/>
<copy todir="${deploy.dir}">
<fileset refid="test-dep-jars"/>
<flattenmapper/>
</copy>
</target>
<target name="jar" depends="copy-test-deps">
<jar destfile="${deploy.dir}/test-${ant.project.name}.jar" basedir="${test.classes.dir}"
includes="**/*.class" filesetmanifest="skip">
<manifest>
<attribute name="Class-Path"
value="${ant.project.name}.jar junit-4.10.jar easymock-3.1.jar easymockclassextension-3.1.jar"/>
</manifest>
</jar>
</target>
My problem is that I have to state the test dependency jars twice - once when defining the test-dep-jars fileset and the second time when specifying the Class-Path manifest attribute of the produced jar.
If I only could get hold on the flattenmapper result, then I would be able to use it in the Class-Path as is.
How can I get hold on the flattenmapper result?
Thanks.
If you want to use flattenmapper you can use following...
<pathconvert property="mf.classpath" pathsep=" ">
<path refid="build.class.path" />
<flattenmapper />
</pathconvert>
<manifest>
<attribute name="Class-Path"
value="${ant.project.name}.jar ${mf.classpath}"/>
</manifest>
I would recommend using the manifestclasspath task instead:
<manifestclasspath property="jar.classpath" jarfile="${jar.file}">
<classpath>
<fileset dir="${deploy.dir}" includes="*.jar"/>
</classpath>
</manifestclasspath>
<jar destfile="${jar.file}" basedir="${classes.dir}">
<manifest>
<attribute name="Main-Class" value="${jar.main.class}" />
<attribute name="Class-Path" value="${jar.classpath}" />
</manifest>
</jar>
It will generate the correct classpath property definition and even works with relative paths (for example if you were to place the dependent jars in sub-directory).

How can I use a zipfileset src attribute without having to specify it manually for all my jars?

I currently have this:
<jarjar destfile="a.jar" manifest="Manifest.mf">
<zipfileset src="first.jar"/>
<zipfileset src="second.jar"/>
</jarjar>
The problem is I have to manually specify each jar, because I need the src parameter to be taken in consideration. I would want something like this:
<zipfileset>
<include name="*.jar"/>
<zipfileset>
And have their contents extracted and included in my resulting archive. Is this possible?
Maybe you could merge the jars first with:
<zip destfile="out.jar">
<zipgroupfileset dir="lib" includes="*.jar"/>
</zip>
and specify the merged jar in the zipfileset.
zipgroupfileset
A <zipgroupfileset> allows for multiple zip files to be merged into
the archive. Each file found in this
fileset is added to the archive the
same way that zipfileset src files are
added.
<zipgroupfileset> is a fileset and supports all of its attributes and
nested elements.
According to comments on the jarjar wiki, you can use this in your jarjar:
<zipgroupfileset dir="lib" includes="*.jar" />
I haven't tried it.
<jar destfile="./dist/Ohmyfish.jar" basedir="./bin">
<manifest>
<attribute name="Created-By" value="Bruce Yang" />
<attribute name="Main-Class" value="org.bruce.ohmyfish.entry.Main" />
</manifest>
<zipgroupfileset dir="./libs" includes="**/*.jar" />
</jar>

Building a "fat jar" in ant using ivy without copying the jars to a lib directory

I'm interesting in building a "fat jar" in my Java project where Ivy resolves the dependencies. It seems wasteful to me to have to copy the referenced jar files from the ivy cache to the local project, so I'd like to avoid doing that. I found a solution that works, but wonder if there is a slightly simpler way. In the code below what I thought would be easiest is for the zipfileset line to work, but it does not - the jars are included in the built jar file, but they are not expanded. If instead I use the section it works properly, but seems like a bit of extra fuss. Is there a cleaner way of doing this?
<target depends="clean, build" name="jar">
<ivy:cachefileset setid="Ping.runclasspath" conf="default" />
<jar destfile="dist/Ping.jar" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
<attribute name="Class-Path" value="."/>
</manifest>
<fileset dir="build"/>
<zipfileset refid="Ping.runclasspath"/> <--- this does NOT work
<restrict> <--- this DOES work
<name name="**/*.class"/>
<archives>
<zips>
<fileset refid="Ping.runclasspath"/>
</zips>
</archives>
</restrict>
</jar>
</target>
Have you experimented with zipgroupfileset? I don't know if it would actually work in your example, but it seems to have a similar purpose for existence.
I just had to do the same thing in one of my ant projects. Chris' suggestion of using zipgroupfileset works:
<target depends="clean, build" name="jar">
<ivy:cachefileset setid="Ping.runclasspath" conf="default" />
<jar destfile="dist/Ping.jar" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="${main-class}"/>
<attribute name="Class-Path" value="."/>
</manifest>
<fileset dir="build"/>
<zipgroupfileset refid="Ping.runclasspath"/>
</jar>
</target>

Ant + Class-path Issue

I have written an ANT script and finally am building the jar
here is the building of jar section
<jar jarfile="${destination}/#{name}.jar">
<fileset dir="${output}">
<include name="abc/xyz/#{name}/**"/>
</fileset>
<zipfileset dir="lib" prefix="lib/"/>
<manifest>
<attribute name="Main-Class" value="com.abc.xyz.HelloWorld"/>
<attribute name="Class-Path" value=".:lib/activation.jar:lib/antlr-2.7.6.jar:lib/asm-attrs.jar:lib/asm.jar:lib/cglib-2.1.3.jar:lib/commons-collections-2.1.1.jar:lib/commons-logging-1.1.jar:lib/dom4j-1.6.1.jar:lib/ehcache-1.2.3.jar:lib/ejb3-persistence.jar:lib/hibernate-annotations.jar:lib/hibernate-commons-annotations.jar:lib/hibernate-entitymanager.jar:lib/hibernate-tools.jar:lib/hibernate3.jar:lib/javassist.jar:lib/jdbc2_0-stdext.jar:lib/jta.jar:lib/mysql-connector-java-5.1.5-bin.jar"/>
</manifest>
</jar>
Now when I try to execute the package it executes, but whenever data is sent I get an error.
java.lang.NoClassDefFoundError: javax/persistence/NoResultException
But the persistence jar is there in the class-path, I've tried all the combinations for the class-path, but in vain.
But in another system I tried without create a jar like
set classpath=.;lib/activation.jar;lib/antlr-2.7.6.jar;lib/asm-attrs.jar;lib/asm.jar;lib/cglib-2.1.3.jar;lib/commons-collections-2.1.1.jar;lib/commons-logging-1.1.jar;lib/dom4j-1.6.1.jar;lib/ehcache-1.2.3.jar;lib/ejb3-persistence.jar;lib/hibernate-annotations.jar;lib/hibernate-commons-annotations.jar;lib/hibernate-entitymanager.jar;lib/hibernate-tools.jar;lib/hibernate3.jar;lib/javassist.jar;lib/jdbc2_0-stdext.jar;lib/jta.jar;lib/mysql-connector-java-5.1.5-bin.jar
java com.abc.xyz.HelloWorld
This works fine.
In Mac when I try like this:
java -cp .:lib/activation.jar:lib/antlr-2.7.6.jar:lib/asm-attrs.jar:lib/asm.jar:lib/cglib-2.1.3.jar:lib/commons-collections-2.1.1.jar:lib/commons-logging-1.1.jar:lib/dom4j-1.6.1.jar:lib/ehcache-1.2.3.jar:lib/ejb3-persistence.jar:lib/hibernate-annotations.jar:lib/hibernate-commons-annotations.jar:lib/hibernate-entitymanager.jar:lib/hibernate-tools.jar:lib/hibernate3.jar:lib/javassist.jar:lib/jdbc2_0-stdext.jar:lib/jta.jar:lib/mysql-connector-java-5.1.5-bin.jar com.abc.xyz.HelloWorld
Also it works fine :(, but the minute I create the jar it stops.
How can I resolve this issue?
First of all the "Main-Class" and "Class-Path" manifiest entries is only used for executeable jars. In other words when you invoke java as follows:
java -jar foo.jar
Invoking java using the -cp option means you're supplying your own classpath and note that you also have to provide the main class on the command line as well.
Secondly you need to replace the ":" characters with spaces:
<attribute name="Class-Path" value=". lib/activation.jar lib/antlr-2.7.6.jar lib/asm-attrs.jar lib/asm.jar lib/cglib-2.1.3.jar lib/commons-collections-2.1.1.jar lib/commons-logging-1.1.jar lib/dom4j-1.6.1.jar lib/ehcache-1.2.3.jar lib/ejb3-persistence.jar lib/hibernate-annotations.jar lib/hibernate-commons-annotations.jar lib/hibernate-entitymanager.jar lib/hibernate-tools.jar lib/hibernate3.jar lib/javassist.jar lib/jdbc2_0-stdext.jar lib/jta.jar lib/mysql-connector-java-5.1.5-bin.jar"/>
Finally I'd recommend using the manifestclasspath task to build your classpath string for you. It will correcly resolve any relative links between your jar and it's run-time dependencies.
<manifestclasspath property="mf.classpath" jarfile="${destination}/#{name}.jar">
<classpath>
<fileset dir="lib" includes="*.jar"/>
<classpath>
</manifestclasspath>
<jar jarfile="${destination}/#{name}.jar">
<fileset dir="${output}">
<include name="abc/xyz/#{name}/**"/>
</fileset>
<zipfileset dir="lib" prefix="lib/"/>
<manifest>
<attribute name="Main-Class" value="com.abc.xyz.HelloWorld"/>
<attribute name="Class-Path" value=". ${mf.classpath}"/>
</manifest>
</jar>
One final observation.... Why are you including the contents of the lib directory inside the jar? (The zipfileset tag in the jar command?)
This appears unnecessary, all you need to do is ensure that the run-time dependencies are present in a lib directory as specified in your Class-Path manifest entry.
The reason for it not works was there not in the class path, the explanation is given here:
Java-Jar-Ignores-Classpath-Workaround

how to add a complete folder to a jar file by ant

I'd like to create like a "fat" jar with ant where I have, not only the usual classes, manifest files, etc, but also my 'libs' folder too.
I tried with:
<jar destfile="myjar.jar" update="yes" basedir="${libs.dir}"/>
but this adds the files in 'libs' the root of the jar file where I'd like to have the libs folder itself in the jar (with everything it contains of course)
Can I maybe create the lib folder myself in the jar and add the files to that specific location in the jar then ?
If you specify to use the directory as the root for your file set then you can just match for the directory and it will preserve the structure.
<jar destfile="myjar.jar" >
<fileset dir=".">
<include name="**/${libs.dir}/**"/>
</fileset>
</jar>
You have to do something like the following. Specifically, the zipfileset command. You basically are saying you want to build the ${build.name}.jar (you could hard code a path to be "myjar.jar" or something along those lines) and then add the various files to the JAR.
Hope this helps!
<jar destfile="${dist}/${build.name}.jar">
<!-- Generate the MANIFEST.MF file. -->
<manifest>
<attribute name="Built-By" value="${user.name}" />
<attribute name="Release-Version" value="${version}" />
<attribute name="Main-Class" value="my.lib.Main" />
<attribute name="SplashScreen-Image" value="TitleScreen.png" />
<attribute name="Class-Path" value="${classpath}" />
</manifest>
<zipfileset dir="${build.dir}" />
<zipfileset dir="${resources}" />
<fileset file="${resources}/icons/misc_icons/TitleScreen.png" />
</jar>
Use this ant extension: http://one-jar.sourceforge.net/
There is also Eclipse plugin: FatJar
http://www.vertigrated.com/blog/2009/11/how-to-bundle-command-line-programs-into-a-single-executable-jar-file/

Resources