ant : jar and zipfileset - copy files from one JAR into another - java

I am currently doing this:
<jar update="yes"
jarfile="${pwd}/dist/${release}_installer.jar">
<zipfileset src="${pwd}/dist/app.jar" includes="com/izforge/izpack/panels/**"/>
<zipfileset src="${pwd}/dist/app.jar" includes="com/xyz/img/logo.png"/>
</jar>
My existing installer JAR gets updated to include the files as needed, extracted from the app JAR.
So far, so good.
However, I want to modify the behaviour such that the path of the image file is different than what is being copied from:
Currently:
com/izforge/izpack/panels/MyIzPanel.class
com/xyz/img/logo.png
What I want:
com/izforge/izpack/panels/MyIzPanel.class
blah/img/logo.png
So I need to copy the files, but use <zipfileset> and <jar> in such a way that I can modify the directory structure.
Is there a way to do this, apart from unzipping the entire contents copying file and then zipping it back up again?
EDIT:
Link to earlier related question: ant task to remove files from a jar

You can use the fullpath attribute:
<zipfileset src="${pwd}/dist/app.jar"
includes="com/xyz/img/logo.png" fullpath="blah/img/logo.img"/>
If you need to copy several files you may want to have a look at the prefix attribute, e.g.:
<zipfileset src="${pwd}/dist/app.jar"
includes="**/*.png" prefix="blah/img"/>

In order to modify the directory structure within the archive on the fly you can use the task in combination with <mappedresources>, eg:
<jar file="target.jar" update="true">
<mappedresources>
<zipfileset src="source.jar">
<include name="com/xyz/img/*.png"/>
</zipfileset>
<mapper type="glob" from="com/xyz/img/*.png" to="bla/img/*.png" />
</mappedresources>
</jar>

You should probably look into zipgroupfileset as explained here.

Related

Exclude Jar from Ant Build using zipgroupfileset

I have created a Jar Project which contains Filter.
I need to use servlet-api.jar when I compile the Filter code.
But when I want to use the Jar in another application, I want to build the jar in such a way that it will exclude servlet-api.jar.
I am using Apache Ant with NetBeans 8:
I have added below code in build.xml.
<target name="-post-jar">
<jar destfile="dist/MyJar.jar">
<zipfileset src="dist/MyJarAsLibrary.jar"/>
<zipgroupfileset dir="dist/lib/." excludes="javax/*"/>
</jar>
</target>
I have used Apache Ant zipgroupfileset.
But I searched on google I found the excludes for files.
I tried with excluding the servlet packages as javax/*, but it did not work.
No Idea how to exclude specific packages.
I found few excludes with zipfileset, but I need to use zipgroupfileset and exclude the javax.servelt.* packages.
The excludes attribute of zipgroupfileset is used to select the archives to pick entries from, not to filter the contents of the archives. zipgroupfileset always contains everything included inside the matched archives.
The simple solution if you know which archive contains the servlet classes is to exclude it from the zipgroupfileset and add an explicit zipfileset.
If you don't know the archive, you can mimic zipgroupfileset using the archives resource collection and wrap that into a restrict container. Something like
<restrict>
<archives>
<zips>
<fileset dir="dist/lib/"/>
</zips>
</archives>
<not>
<name name="javax/servlet/*"/>
</not>
</restrict>

Ant zip change base dir to zip at different level

I have an Ant zip task that looks like this:
<zip basedir="${workspace.dir}"
destfile="${build.output.dir}/test.zip"
includes="${eLibrary}/bin/com/**,
${Common}
excludes="${eLibrary}/lib,
${eLibrary}/src"
>
</zip>
The eLibrary folder has a structure similar to:
`--bin
`--com
`--lib
`--src
I'd like to have the zip file look like this:
`--eLibrary
`--com
`--Common
When the zip is created though it has the following structure:
`--eLibrary
`--bin
`--com
`--Common
I've tried various types of include statements, but they all include the bin folder:
includes="${eLibrary}/bin/**
includes="${eLibrary}/bin/com/**
includes="${eLibrary}/bin
includes="${eLibrary}/bin/com
Changing the basedir won't work because I also need the Common folder included. Any help would be appreciated. Thanks.
You can check the zip task documentation for examples on how to achieve this. The below snippet uses a zipfileset nested element which maps the included entries to the directories inside the archive.
<zip destfile="${build.output.dir}/test.zip">
<zipfileset dir="${eLibrary}/bin/com" prefix="${eLibrary}/com"/>
<zipfileset dir="${Common}" prefix="${Common}"/>
</zip>

wrong JAR packaging in ant file with zipfileset

I'm encountering a strange issue in an ANT file I use for building a Java app. When generating the jar file, eventually I include resource files (images, fonts and config files) in the JAR using zipfileset, like this:
<zipfileset dir="src/res" prefix="res"/>
<zipfileset dir="src/res/images" prefix="res/images" />
<zipfileset dir="src/res/images/Bubbles" prefix="res/images/Bubbles"/>
<zipfileset dir="src/res/images/Clocks" prefix="res/images/Clocks"/>
<zipfileset dir="src/config" prefix="res/config"/>
<zipfileset dir="src/ontology" prefix="res/ontology"/>
To mantain original structure, that looks like this:
res
|-images
| |-Bubbles
| |-Clocks
|-fonts
|-config
|-ontology
Within the JAR, I'm using the prefix parameter in zipfileset. I'm getting duplicated images in res/images and triple images (3 copies of the same image) in any of the res/images/Bubbles and res/images/Clocks folders, which, in the other hand, are 2 and 3 depth levels respectively. res/config and res/ontology are correct, no duplicated files there...a screenshot to see what I mean:
I forgot to mention, but obviously, I only have one instance of each image in every folder. Any ideas what is causing this behaviour?
Regards,
Alex
ant actually does exactly what you told it do. You told him to:
pack all the files under src/res and to map them to res.
pack all the files under src/res/images and to map them to res/images
pack all the files under src/res/images/Bubbles and to them under res/images/Bubbles
Now let's assume that you have a src/res/images/Bubbles/activity_bubble_orange.png files. That file is contained in the first zipfileset, the second zipfileset and the third zipfileset. Ergo it will be packed three times.
To do what you want you need to do a single <zipfileset dir="src/res" prefix="res" /> but filter the contents using includes/excludes filters.
See here: http://ant.apache.org/manual/Types/zipfileset.html where it say that is a type of fileset. and here: http://ant.apache.org/manual/Types/fileset.html to see how you specify includes/excludes filter for a fileset.
You can use the following attribute to include the whole path without hardcoding each sub-directory.
includes="*/.*"
<zipfileset src="examples.zip" includes="**/*.html" prefix="docs/examples"/>
In above example, I'm including *.html recursively.
Sukhbir Dhillon
Addteq

How to combine two Jar files

Is it possible to combine two jar files such that in an applet tag I can simply do something like
archive="jarjar.jar/jar1.jar"... ...archive="jarjar.jar/jar2.jar"... instead of
archive="jar1.jar"... ...archive="jar2.jar"...
I need to only have one jar file so putting two jar files in a folder will not help me.
Sure, just extract the two jar files and recreate a new one
$ mkdir tmp
$ (cd tmp; unzip -uo ../jar1.jar)
$ (cd tmp; unzip -uo ../jar2.jar)
$ jar -cvf combined.jar -C tmp .
The stuff with tmp ensures that the two existing jars are extracted into a clean directory and then the new one made from that.
Be aware that you may also need to merge any manifest.mf files contained therein, and if there are any also include the '-m' option in that file command.
Use zipgroupfileset with the Ant Zip task
<zip destfile="out.jar">
<zipgroupfileset dir="lib" includes="*.jar"/>
</zip>
Might help you.
If you are using gradle, just add the following to build.gradle. No plugins required. If you need special options, then go with Fatjar plugin, as initialZero suggests.
task superSimpleJar(type: Jar) {
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
For Android project, add this to app/build.gradle and run "gradlew superSimpleJar". Find jar in build/libs/app-all.jar
task superSimpleJar(type: Jar) {
baseName = project.name + '-all'
from {
configurations.compile.findAll {
it.getName() != 'android.jar'
}.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project name="zip-test" default="zip" basedir=".">
<target name="zip">
<zip destfile="out.jar">
<zipgroupfileset dir="." includes="*.jar"/>
</zip>
</target>
</project>
save this code in build.xml file and keep it in same folder where all the jar files to be combined are kept. Open cmd, give path of folder and run command : ant zip.
It will generate out.jar which is combination of all jars.
Just unzip both jar files, then zip the results into one zip file, and rename this to jar again.
But as adarshr said: Better use the jar command for that.
Extract both jars and create a new one works. (Use jar commands shown above).
One caveat about manifest file is that you want to extract the jar whose manifest file you want to retain in the last.
I know it's an old question and I just wanted to add my two cents (no permission to comment yet, so creating a new answer).
I do see the value in sumanth.donthula's answer as the problem for all of us merging jars will be how to deal with the manifest files. In my case I wanted to merge some library files (mainly generated web service client code) into the jar of an application written by me. It was OK to replace the manifests with the one of my own jar.
The simplest way of doing this is taking care of the order in which you unzip the original files (as Alnitak and sumanth.donthula noted).
I wanted to use the zip ant task (thank you, ykombinator, for the idea). It turned out that the only way of controlling the order of compressing/packaging is renaming the files. See my ant target below.
The output directory in my example is called codemodule.dir (I created a FileNet code module). The rest of the names are self-explaining. The important step is renaming the application jar to 0_... to be the 1st in order. This way its manifest will be retained as the duplicate attribute of the zip ant task is set to preserve.
<target name="merge_jars">
<delete dir="${codemodule.dir}" quiet="true" />
<mkdir dir="${codemodule.dir}" />
<copy todir="${codemodule.dir}">
<fileset dir="${lib.dir}" includes="*.jar"/>
<fileset dir="${basedir}" includes="${app-name}.jar"/>
</copy>
<move file="${codemodule.dir}/${app-name}.jar" tofile="${codemodule.dir}/0_${app-name}.jar"/>
<zip destfile="${codemodule.dir}/${app-name}-fat.jar" duplicate="preserve">
<zipgroupfileset dir="${codemodule.dir}">
<include name="*.jar"/>
</zipgroupfileset>
</zip>

Ant task for easier deployment

We have quite a big tree of source code, parts of it are deployed as two separate jar files. We need an easy control of what goes to which jar.
So far we do this by <exclude name="" /> and <include name="" /> tags, but this is quite inconvenient. The best option would be a separate config file with all the packages listed which we could comment out when needed, say with a '#' character.
Does something similar exist or do we have to write a new ant task that reads such a file and runs a <jar> task?
The best option would bee to seperate the code into different modules which can be build on their own (of course with dependencies to each other). Doing this also makes cyclic dependencies obvious and gives you the chance to optimize your code base.
ANT includes and excludes can be managed with external files and referenced in a fileset using includesfile and excludesfile attributes.
includesfile the name of a file; each
line of this file is taken to be an
include pattern.
excludesfile the
name of a file; each line of this file
is taken to be an exclude pattern.
For example:
<jar destfile="${dist}/lib/app1.jar">
<fileset dir=".">
<includesfile name="app1.properties"/>
</fileset>
</jar>
<jar destfile="${dist}/lib/app2.jar">
<fileset dir=".">
<includesfile name="app2.properties"/>
</fileset>
</jar>

Categories

Resources