Browse Source

Zip task

duplicate (attribute): behavior when a duplicate file is found.  Valid values are add, preserve, and fail. The default value is add.

zipgroupfileset (nested fileset): 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.


Jar task

duplicate/zipgroupfileset: same as in Zip task

filesetmanifest (attribute): behavior when a Manifest is found in a zipfileset or zipgroupfileset file is found.  Valid values are skip, merge, and mergewithoutmain.  mergewill merge all of manifests together, and merge this into any other specified manifests  mergewithoutmain merges everything but the Main section of the manifests.  Default value is skip

manifest (existing attribute): this attribute now also accepts the name of a jar added through a fileset.  If its the name of an added jar, the task expects the manifest to be in the jar at META-INF/Manifest.mf

Submitted by: Brian Deitte <bdeitte@macromedia.com>

PR: 5667, 5036


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271698 13f79535-47bb-0310-9956-ffa450edef68
master
Magesh Umasankar 23 years ago
parent
commit
4ab1950bd8
12 changed files with 437 additions and 159 deletions
  1. +7
    -0
      WHATSNEW
  2. +26
    -4
      docs/manual/CoreTasks/jar.html
  3. +25
    -2
      docs/manual/CoreTasks/zip.html
  4. +3
    -0
      docs/manual/OptionalTasks/jlink.html
  5. +20
    -2
      src/etc/testcases/taskdefs/zip.xml
  6. BIN
      src/etc/testcases/taskdefs/zip/zipgroupfileset1.zip
  7. BIN
      src/etc/testcases/taskdefs/zip/zipgroupfileset2.zip
  8. BIN
      src/etc/testcases/taskdefs/zip/zipgroupfileset3.zip
  9. +176
    -90
      src/main/org/apache/tools/ant/taskdefs/Jar.java
  10. +48
    -25
      src/main/org/apache/tools/ant/taskdefs/Manifest.java
  11. +92
    -16
      src/main/org/apache/tools/ant/taskdefs/Zip.java
  12. +40
    -20
      src/testcases/org/apache/tools/ant/taskdefs/ZipTest.java

+ 7
- 0
WHATSNEW View File

@@ -77,6 +77,13 @@ Fixed bugs:

Other changes:
--------------
* Users can control what <zip> and <jar> must do when duplicate files
are found. A new element <zipgroupfileset> allows for multiple zip
files to be merged into the archive. In addition, <jar> also has
another new attribute: filesetmanifest. The existing manifest
attribute of <jar> now also accepts the name of a jar added through
a fileset.

* gzip now checks that the zipfile is older than the source file
before rebuilding the zipfile.



+ 26
- 4
docs/manual/CoreTasks/jar.html View File

@@ -28,11 +28,12 @@ supports all attributes of <code>&lt;fileset&gt;</code>
<code>&lt;patternset&gt;</code> elements.</p>
<p>You can also use nested file sets for more flexibility, and specify
multiple ones to merge together different trees of files into one JAR.
The extended fileset attributes from the zip task are also available
in the jar task.
The extended fileset and groupfileset attributes from the zip task are
also available in the jar task.
See the <a href="zip.html">Zip</a> task for more details and examples.</p>
<p>If the manifest is omitted, a simple one will be supplied by Ant.
You should not include <samp>META-INF/MANIFEST.MF</samp> in your set of files.</p>
If there is a manifest or manifests in your set of files, these manifests can
be used if <i>filesetmanifests</i> is set to <i>merge</i> or <i>mergewithoutmain</i>.</p>
<p>The <code>update</code> parameter controls what happens if the
JAR file already exists. When set to <code>yes</code>, the JAR file is
updated with the files specified. When set to <code>no</code> (the
@@ -117,7 +118,13 @@ being wrapped and continued on the next line.
</tr>
<tr>
<td valign="top">manifest</td>
<td valign="top">the manifest file to use.</td>
<td valign="top">the manifest file to use. This can be either the location of a manifest, or the name of a jar added through a fileset. If its the name of an added jar, the task expects the manifest to be in the jar at META-INF/MANIFEST.MF</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">filesetmanifest</td>
<td valign="top">behavior when a Manifest is found in a zipfileset or zipgroupfileset file is found. Valid values are &quot;skip&quot;, &quot;merge&quot;, and &quot;mergewithoutmain&quot;. &quot;merge&quot; will merge all of manifests together, and merge this into any other specified manifests. &quot;mergewithoutmain&quot; merges everything but the Main section of the manifests. Default value is &quot;skip&quot;.
</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
@@ -126,6 +133,21 @@ being wrapped and continued on the next line.
the destination file if it already exists.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">whenempty</td>
<td valign="top">behavior when no files match. Valid values are &quot;fail&quot;, &quot;skip&quot;, and &quot;create&quot;. Default is &quot;skip&quot;.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">duplicate</td>
<td valign="top">behavior when a duplicate file is found. Valid values are &quot;add&quot;, &quot;preserve&quot;, and &quot;fail&quot;. The default value is &quot;add&quot;. </td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">index</td>
<td valign="top">whether to create an <A HREF="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#JAR%20Index">index list</A> to speed up classloading. This is a JDK 1.3+ specific feature. Defaults to false. </td>
<td valign="top" align="center">No</td>
</tr>
</table>

<h3>Nested elements</h3>


+ 25
- 2
docs/manual/CoreTasks/zip.html View File

@@ -2,7 +2,7 @@

<head>
<meta http-equiv="Content-Language" content="en-us">
<title>AZip Task</title>
<title>Zip Task</title>
</head>

<body>
@@ -33,6 +33,9 @@ if <code>basedir</code> is set. You may use any mixture of the implicit file set
and optional subelements like <code>&lt;include&gt;</code>); explicit nested
<code>&lt;fileset&gt;</code> elements so long as at least one fileset total is specified. The ZIP file will
only reflect the relative paths of files <i>within</i> each fileset. The Zip task and its derivatives know a special form of a fileset named zipfileset that has additional attributes (described below). </p>
<p>The Zip task also supports the merging of multiple zip files into the zip file.
This is possible through either the <i>src</i> attribute of any nested filesets
or by using the special nested fileset <i>zipgroupfileset</i>.</p>
<p>The <code>update</code> parameter controls what happens if the
ZIP file already exists. When set to <code>yes</code>, the ZIP file is
updated with the files specified. (New files are added; old files are
@@ -122,7 +125,12 @@ Java.</p>
</tr>
<tr>
<td valign="top">whenempty</td>
<td valign="top">Behavior when no files match.</td>
<td valign="top">behavior when no files match. Valid values are &quot;fail&quot;, &quot;skip&quot;, and &quot;create&quot;. Default is &quot;skip&quot;.</td>
<td valign="top" align="center">No</td>
</tr>
<tr>
<td valign="top">duplicate</td>
<td valign="top">behavior when a duplicate file is found. Valid values are &quot;add&quot;, &quot;preserve&quot;, and &quot;fail&quot;. The default value is &quot;add&quot;. </td>
<td valign="top" align="center">No</td>
</tr>
</table>
@@ -140,6 +148,11 @@ exact location in the archive. (The <i>fullpath</i> attribute can only be set fo
may be used in place of the <i>dir</i> attribute to specify a zip file whose
contents will be extracted and included in the archive. As with directories, include and exclude patterns may be used to specify a subset of the zip file
for inclusion in the archive.</p>
<h4>zipgroupfileset</h4>
<p>A <code>&lt;zipgroupfileset&gt;</code> 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 <i>zipfileset src</i> files are added.</p>


<h3>Examples</h3>
<pre> &lt;zip destfile=&quot;${dist}/manual.zip&quot;
@@ -188,6 +201,16 @@ under <code>docs/examples</code>. The archive might end up containing the files
docs/ChangeLog.txt
docs/examples/index.html
</code></pre>
<p>
The code
<pre>
&lt;zip destfile=&quot;${dist}/manual.zip&quot;&gt;
&lt;zipfileset dir=&quot;htdocs/manual&quot; prefix=&quot;docs/user-guide&quot;/&gt;
&lt;zipgroupfileset dir=&quot;.&quot; includes=&quot;examples*.zip&quot;/&gt;
&lt;/zip&gt;</pre>
</pre>
<p>
<p>zips all files in the <code>htdocs/manual</code> directory into the <code>docs/user-guide</code> directory in the archive and includes all the files in any file that maches <code>examples*.zip</code>, such as all files within <code>examples1.zip</code> or <code>examples_for_brian.zip</code>.
<hr>
<p align="center">Copyright &copy; 2001-2002 Apache Software Foundation. All rights
Reserved.</p>


+ 3
- 0
docs/manual/OptionalTasks/jlink.html View File

@@ -5,6 +5,9 @@
<body>

<h2><a name="jlink">Jlink</a></h2>
<h3><i>Deprecated</i></h3>
<p><i>This task has been deprecated. Use the zipfileset and zipgroupfileset attributes of the <a href="../CoreTasks/jar.html">Jar task</a> or <a href="../CoreTasks/zip.html">Zip task</a> instead.</i></p>

<h3><b>Description:</b></h3>
<p>Links entries from sub-builds and libraries.</p>



+ 20
- 2
src/etc/testcases/taskdefs/zip.xml View File

@@ -49,7 +49,7 @@
</target>

<target name="feather">
<zip destFile="asf-logo.gif.zip"
<zip destFile="asf-logo.gif.zip"
basedir=".."
includes="asf-logo.gif" />
</target>
@@ -60,7 +60,24 @@
<exclude name="test8.zip" />
</zip>
</target>

<target name="testZipgroupfileset">

<zip zipfile="zipgroupfileset.zip" basedir=".">
<zipgroupfileset dir="zip"
includes="zipgroupfileset*.zip"
excludes="zipgroupfileset3.zip" />
<include name="zip/zipgroupfileset3.zip" />
</zip>
</target>

<target name="testDuplicateFail">

<zip zipfile="duplicateFail.zip" basedir="." duplicate="fail">
<zipgroupfileset dir="duplicate" includes="duplicate*.zip" />
</zip>
</target>

<target name="cleanup">
<delete file="test3.zip"/>
<delete file="test4.zip"/>
@@ -70,5 +87,6 @@
<delete file="test7.zip"/>
<delete file="test8.zip"/>
<delete file="asf-logo.gif.zip"/>
<delete file="zipgroupfileset.zip"/>
</target>
</project>

BIN
src/etc/testcases/taskdefs/zip/zipgroupfileset1.zip View File


BIN
src/etc/testcases/taskdefs/zip/zipgroupfileset2.zip View File


BIN
src/etc/testcases/taskdefs/zip/zipgroupfileset3.zip View File


+ 176
- 90
src/main/org/apache/tools/ant/taskdefs/Jar.java View File

@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2002 The Apache Software Foundation. All rights
* Copyright (c) 2000-2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -9,7 +9,7 @@
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
@@ -17,15 +17,15 @@
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
@@ -58,6 +58,7 @@ import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.FileScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.ZipFileSet;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.zip.ZipOutputStream;

import java.io.IOException;
@@ -75,8 +76,9 @@ import java.util.Enumeration;

/**
* Creates a JAR archive.
*
*
* @author James Davidson <a href="mailto:duncan@x180.com">duncan@x180.com</a>
* @author Brian Deitte <a href="mailto:bdeitte@macromedia.com">bdeitte@macromedia.com</a>
*
* @ant.task category="packaging"
*/
@@ -84,12 +86,33 @@ public class Jar extends Zip {
/** The index file name. */
private final static String INDEX_NAME = "META-INF/INDEX.LIST";

private File manifestFile;
/** merged manifests added through addConfiguredManifest */
private Manifest configuredManifest;

/** merged manifests added through filesets */
private Manifest filesetManifest;

/**
* whether to merge fileset manifests;
* value is true if filesetmanifest is 'merge' or 'mergewithoutmain'
*/
private boolean mergeManifests = false;

/**
* whether to merge the main section of fileset manifests;
* value is true if filesetmanifest is 'merge'
*/
private boolean mergeManifestsMain = false;

/** the manifest specified by the 'manifest' attribute **/
private Manifest manifest;
private Manifest execManifest;
/** true if a manifest has been specified in the task */
private boolean buildFileManifest = false;

/**
* The file found from the 'manifest' attribute. This can be either the location of a manifest,
* or the name of a jar added through a fileset. If its the name of an added jar, the manifest is
* looked for in META-INF/MANIFEST.MF
*/
private File manifestFile;

/** jar index is JDK 1.3+ only */
private boolean index = false;
@@ -124,33 +147,30 @@ public class Jar extends Zip {
}

public void addConfiguredManifest(Manifest newManifest) throws ManifestException {
if (manifest == null) {
manifest = Manifest.getDefaultManifest();
if (configuredManifest == null) {
configuredManifest = newManifest;
}
else {
configuredManifest.merge(newManifest);
}
manifest.merge(newManifest);
buildFileManifest = true;
}

public void setManifest(File manifestFile) {
if (!manifestFile.exists()) {
throw new BuildException("Manifest file: " + manifestFile + " does not exist.",
throw new BuildException("Manifest file: " + manifestFile + " does not exist.",
getLocation());
}

this.manifestFile = manifestFile;
}

private Manifest getManifest(File manifestFile) {

Manifest newManifest = null;
Reader r = null;
try {
r = new FileReader(manifestFile);
Manifest newManifest = new Manifest(r);
if (manifest == null) {
manifest = Manifest.getDefaultManifest();
}
manifest.merge(newManifest);
}
catch (ManifestException e) {
log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR);
throw new BuildException("Invalid Manifest: " + manifestFile, e, getLocation());
newManifest = getManifest(r);
}
catch (IOException e) {
throw new BuildException("Unable to read manifest file: " + manifestFile, e);
@@ -165,6 +185,29 @@ public class Jar extends Zip {
}
}
}
return newManifest;
}

private Manifest getManifest(Reader r) {

Manifest newManifest = null;
try {
newManifest = new Manifest(r);
}
catch (ManifestException e) {
log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR);
throw new BuildException("Invalid Manifest: " + manifestFile, e, getLocation());
}
catch (IOException e) {
throw new BuildException("Unable to read manifest file", e);
}
return newManifest;
}

public void setFilesetmanifest(FilesetManifestConfig config) {
String filesetManifestConfig = config.getValue();
mergeManifests = ! "skip".equals(filesetManifestConfig);
mergeManifestsMain = "merge".equals(filesetManifestConfig);
}

public void addMetainf(ZipFileSet fs) {
@@ -176,31 +219,60 @@ public class Jar extends Zip {
protected void initZipOutputStream(ZipOutputStream zOut)
throws IOException, BuildException
{
String ls = System.getProperty("line.separator");
try {
execManifest = Manifest.getDefaultManifest();
Manifest finalManifest = Manifest.getDefaultManifest();

if (manifest != null) {
execManifest.merge(manifest);
if (manifest == null) {
if (manifestFile != null) {
// if we haven't got the manifest yet, attempt to get it now and
// have manifest be the final merge
manifest = getManifest(manifestFile);
finalManifest.merge(filesetManifest);
finalManifest.merge(configuredManifest);
finalManifest.merge(manifest, ! mergeManifestsMain);
}
else if (configuredManifest != null) {
// configuredManifest is the final merge
finalManifest.merge(filesetManifest);
finalManifest.merge(configuredManifest, ! mergeManifestsMain);
}
else if (filesetManifest != null) {
// filesetManifest is the final (and only) merge
finalManifest.merge(filesetManifest, ! mergeManifestsMain);
}
} else {
// manifest is the final merge
finalManifest.merge(filesetManifest);
finalManifest.merge(configuredManifest);
finalManifest.merge(manifest, ! mergeManifestsMain);
}
for (Enumeration e = execManifest.getWarnings(); e.hasMoreElements(); ) {

for (Enumeration e = finalManifest.getWarnings(); e.hasMoreElements(); ) {
log("Manifest warning: " + (String)e.nextElement(), Project.MSG_WARN);
}

// need to set the line.separator as \r\n due to a bug with the jar verifier
System.setProperty("line.separator", "\r\n");

zipDir(null, zOut, "META-INF/");
// time to write the manifest
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(baos);
execManifest.write(writer);
finalManifest.write(writer);
writer.flush();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
super.zipFile(bais, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis());
super.zipFile(bais, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis(), null);
super.initZipOutputStream(zOut);
}
catch (ManifestException e) {
log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR);
throw new BuildException("Invalid Manifest", e, getLocation());
}
finally {
System.setProperty("line.separator", ls);
}
}

protected void finalizeZipOutputStream(ZipOutputStream zOut)
@@ -212,14 +284,11 @@ public class Jar extends Zip {

/**
* Create the index list to speed up classloading.
* This is a JDK 1.3+ specific feature and is enabled by default. See
* <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#JAR+Index">the
* JAR index specification</a> for more details.
*
* This is a JDK 1.3+ specific feature and is disabled by default.
* {@link http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#JAR%20Index}
* @param zOut the zip stream representing the jar being built.
* @throws IOException thrown if there is an error while creating the
* index and adding it to the zip stream.
*
*/
private void createIndexList(ZipOutputStream zOut) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -260,70 +329,73 @@ public class Jar extends Zip {

writer.flush();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
super.zipFile(bais, zOut, INDEX_NAME, System.currentTimeMillis());
super.zipFile(bais, zOut, INDEX_NAME, System.currentTimeMillis(), null);
}




/**
* Handle situation when we encounter a manifest file
*
* If we haven't been given one, we use this one.
*
* If we have, we merge the manifest in, provided it is a new file
* and not the old one from the JAR we are updating
* Overriden from Zip class to deal with manifests
*/
private void zipManifestEntry(InputStream is) throws IOException {
try {
if (execManifest == null) {
execManifest = new Manifest(new InputStreamReader(is));
}
else if (isAddingNewFiles()) {
execManifest.merge(new Manifest(new InputStreamReader(is)));
}
}
catch (ManifestException e) {
log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR);
throw new BuildException("Invalid Manifest", e, getLocation());
}
}
protected void zipFile(File file, ZipOutputStream zOut, String vPath)
throws IOException
{
// If the file being added is META-INF/MANIFEST.MF, we warn if it's not the
// one specified in the "manifest" attribute - or if it's being added twice,
// meaning the same file is specified by the "manifeset" attribute and in
// a <fileset> element.
if (vPath.equalsIgnoreCase("META-INF/MANIFEST.MF")) {
log("Warning: selected "+archiveType+" files include a META-INF/MANIFEST.MF which will be ignored " +
"(please use manifest attribute to "+archiveType+" task)", Project.MSG_WARN);
filesetManifest(file, null);
} else {
super.zipFile(file, zOut, vPath);
}

}

protected void zipFile(InputStream is, ZipOutputStream zOut, String vPath, long lastModified)
/**
* Overriden from Zip class to deal with manifests
*/
protected void zipFile(InputStream is, ZipOutputStream zOut, String vPath, long lastModified, File file)
throws IOException
{
// If the file being added is META-INF/MANIFEST.MF, we merge it with the
// current manifest
if (vPath.equalsIgnoreCase("META-INF/MANIFEST.MF")) {
try {
zipManifestEntry(is);
filesetManifest(file, is);
} else {
super.zipFile(is, zOut, vPath, lastModified, null);
}
}

private void filesetManifest(File file, InputStream is) {
if (manifestFile.equals(file)) {
// If this is the same name specified in 'manifest', this is the manifest to use
log("Found manifest " + file, Project.MSG_VERBOSE);
if (is != null) {
manifest = getManifest(new InputStreamReader(is));
}
catch (IOException e) {
throw new BuildException("Unable to read manifest file: ", e);
else {
manifest = getManifest(file);
}
}
else if (mergeManifests) {
// we add this to our group of fileset manifests
log("Found manifest to merge in file " + file, Project.MSG_VERBOSE);

try
{
Manifest newManifest = getManifest(new InputStreamReader(is));
if (filesetManifest == null) {
filesetManifest = newManifest;
} else {
filesetManifest.merge(newManifest);
}
}
catch (ManifestException e) {
log("Manifest in file " + file + " is invalid: " + e.getMessage(), Project.MSG_ERR);
throw new BuildException("Invalid Manifest", e, getLocation());
}
} else {
super.zipFile(is, zOut, vPath, lastModified);
}
else {
// assuming 'skip' otherwise
log("File " + file + " includes a META-INF/MANIFEST.MF which will be ignored. " +
"To include this file, set filesetManifest to a value other than 'skip'.", Project.MSG_WARN);
}
}

/**
* Check whether the archive is up-to-date;
* Check whether the archive is up-to-date;
* @param scanners list of prepared scanners containing files to archive
* @param zipFile intended archive file (may or may not exist)
* @return true if nothing need be done (may have done something already); false if
@@ -332,7 +404,7 @@ public class Jar extends Zip {
*/
protected boolean isUpToDate(FileScanner[] scanners, File zipFile) throws BuildException {
// need to handle manifest as a special check
if (buildFileManifest || manifestFile == null) {
if (configuredManifest != null || manifestFile == null) {
java.util.zip.ZipFile theZipFile = null;
try {
theZipFile = new java.util.zip.ZipFile(zipFile);
@@ -342,17 +414,17 @@ public class Jar extends Zip {
return false;
}
Manifest currentManifest = new Manifest(new InputStreamReader(theZipFile.getInputStream(entry)));
if (manifest == null) {
manifest = Manifest.getDefaultManifest();
if (configuredManifest == null) {
configuredManifest = Manifest.getDefaultManifest();
}
if (!currentManifest.equals(manifest)) {
if (!currentManifest.equals(configuredManifest)) {
log("Updating jar since jar manifest has changed", Project.MSG_VERBOSE);
return false;
}
}
catch (Exception e) {
// any problems and we will rebuild
log("Updating jar since cannot read current jar manifest: " + e.getClass().getName() + e.getMessage(),
log("Updating jar since cannot read current jar manifest: " + e.getClass().getName() + e.getMessage(),
Project.MSG_VERBOSE);
return false;
}
@@ -372,17 +444,31 @@ public class Jar extends Zip {
}
return super.isUpToDate(scanners, zipFile);
}
protected boolean createEmptyZip(File zipFile) {
// Jar files always contain a manifest and can never be empty
// Jar files always contain a manifest and can never be empty
return true;
}
/**
* Make sure we don't think we already have a MANIFEST next time this task
* gets executed.
*/
protected void cleanUp() {
super.cleanUp();

configuredManifest = null;
filesetManifest = null;
mergeManifests = false;
mergeManifestsMain = false;
manifest = null;
manifestFile = null;
index = false;
}

public static class FilesetManifestConfig extends EnumeratedAttribute {
public String[] getValues() {
return new String[] {"skip", "merge", "mergewithoutmain"};
}
}
}

+ 48
- 25
src/main/org/apache/tools/ant/taskdefs/Manifest.java View File

@@ -397,14 +397,14 @@ public class Manifest extends Task {
* Get a attribute of the section
*
* @param attributeName the name of the attribute
* @return a Manifest.Attribute instance if the attribute is
* single-valued, otherwise a Vector of Manifest.Attribute
* @return a Manifest.Attribute instance if the attribute is
* single-valued, otherwise a Vector of Manifest.Attribute
* instances.
*/
public Object getAttribute(String attributeName) {
return attributes.get(attributeName.toLowerCase());
}
/**
* Get the value of the attribute with the name given.
*
@@ -511,8 +511,8 @@ public class Manifest extends Task {
for (Enumeration e = attributes.keys(); e.hasMoreElements();) {
String attributeName = (String)e.nextElement();
Object attributeValue = attributes.get(attributeName);
Object rhsAttributeValue = rhsSection.attributes.get(attributeName);
if (!attributeValue.equals(rhsAttributeValue)) {
Object rshAttributeValue = rhsSection.attributes.get(attributeName);
if (!attributeValue.equals(rshAttributeValue)) {
return false;
}
}
@@ -629,22 +629,45 @@ public class Manifest extends Task {
* to the Manifest spec.
*/
public void merge(Manifest other) throws ManifestException {
if (other.manifestVersion != null) {
manifestVersion = other.manifestVersion;
}
mainSection.merge(other.mainSection);
for (Enumeration e = other.sections.keys(); e.hasMoreElements();) {
String sectionName = (String)e.nextElement();
Section ourSection = (Section)sections.get(sectionName);
Section otherSection = (Section)other.sections.get(sectionName);
if (ourSection == null) {
sections.put(sectionName, otherSection);
}
else {
ourSection.merge(otherSection);
}
}
merge(other, false);
}

/**
* Merge the contents of the given manifest into this manifest
*
* @param other the Manifest to be merged with this one.
* @param overwriteMain whether to overwrite the main section of the current manifest
*
* @throws ManifestException if there is a problem merging the manfest according
* to the Manifest spec.
*/
public void merge(Manifest other, boolean overwriteMain) throws ManifestException {
if (other != null) {
if (overwriteMain) {
mainSection = other.mainSection;
}
else {
mainSection.merge(other.mainSection);
}

if (other.manifestVersion != null) {
manifestVersion = other.manifestVersion;
}

for (Enumeration e = other.sections.keys(); e.hasMoreElements();) {
String sectionName = (String)e.nextElement();
Section ourSection = (Section)sections.get(sectionName);
Section otherSection = (Section)other.sections.get(sectionName);
if (ourSection == null) {
if (otherSection != null) {
sections.put(sectionName.toLowerCase(), otherSection);
}
}
else {
ourSection.merge(otherSection);
}
}
}
}

/**
@@ -774,7 +797,7 @@ public class Manifest extends Task {
public String getManifestVersion() {
return manifestVersion;
}
/**
* Get the main section of the manifest
*
@@ -788,13 +811,13 @@ public class Manifest extends Task {
* Get a particular section from the manifest
*
* @param name the name of the section desired.
* @return the specified section or null if that section
* @return the specified section or null if that section
* does not exist in the manifest
*/
public Section getSection(String name) {
return (Section)sections.get(name);
}
/**
* Get the section names in this manifest.
*
@@ -803,7 +826,7 @@ public class Manifest extends Task {
public Enumeration getSectionNames() {
return sections.keys();
}
/**
* Create or update the Manifest when used as a task.
*/
@@ -833,7 +856,7 @@ public class Manifest extends Task {
}
}
}
try {
toWrite.merge(this);
} catch (ManifestException m) {


+ 92
- 16
src/main/org/apache/tools/ant/taskdefs/Zip.java View File

@@ -61,8 +61,6 @@ import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;

import java.util.Calendar;
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
@@ -96,6 +94,9 @@ public class Zip extends MatchingTask {

protected File zipFile;
private File baseDir;
protected Hashtable entries = new Hashtable();
private Vector groupfilesets = new Vector();
protected String duplicate = "add";
private boolean doCompress = true;
private boolean doUpdate = false;
private boolean doFilesonly = false;
@@ -112,7 +113,6 @@ public class Zip extends MatchingTask {
adding back the unchanged files */
private boolean addingNewFiles;


/**
* Encoding to use for filenames, defaults to the platform's
* default encoding.
@@ -152,7 +152,7 @@ public class Zip extends MatchingTask {
this.zipFile = destFile;
}

/**
* This is the base directory to look in for
* things to zip.
@@ -205,6 +205,24 @@ public class Zip extends MatchingTask {
filesets.addElement(set);
}

/**
* Adds a group of zip files (a group of nested filesets).
*/
public void addZipGroupFileset(FileSet set) {
groupfilesets.addElement(set);
}

/**
* Sets behavior for when a duplicate file is about to be added
* Possible values are: <code>keep</code> (keep both
* of the files); <code>skip</code> (keep the first version
* of the file found); <code>overwrite</code> overwrite the file
* with the new file
* Default for zip tasks is <code>keep</code>
*/
public void setDuplicate(Duplicate df) {
duplicate = df.getValue();
}

/** Possible behaviors when there are no matching files for the task. */
public static class WhenEmpty extends EnumeratedAttribute {
@@ -238,7 +256,8 @@ public class Zip extends MatchingTask {
}

public void execute() throws BuildException {
if (baseDir == null && filesets.size() == 0 && "zip".equals(archiveType)) {
if (baseDir == null && filesets.size() == 0
&& groupfilesets.size() == 0 && "zip".equals(archiveType)) {
throw new BuildException( "basedir attribute must be set, or at least " +
"one fileset must be given!" );
}
@@ -272,6 +291,23 @@ public class Zip extends MatchingTask {
}
}

// Add the files found in groupfileset to fileset
for (int i=0; i<groupfilesets.size(); i++) {

log("Processing groupfileset ", Project.MSG_VERBOSE);
FileSet fs = (FileSet) groupfilesets.elementAt(i);
FileScanner scanner = fs.getDirectoryScanner(project);
String[] files = scanner.getIncludedFiles();
File basedir = scanner.getBasedir();
for (int j=0; j<files.length; j++) {

log("Adding file " + files[j] + " to fileset", Project.MSG_VERBOSE);
ZipFileSet zf = new ZipFileSet();
zf.setSrc(new File(basedir, files[j]));
filesets.add(zf);
}
}

// Create the scanners to pass to isUpToDate().
Vector dss = new Vector ();
if (baseDir != null) {
@@ -333,7 +369,7 @@ public class Zip extends MatchingTask {
addFiles(tmp, zOut);
}
finalizeZipOutputStream(zOut);
// If we've been successful on an update, delete the temporary file
if (doUpdate) {
if (!renamedFile.delete()) {
@@ -360,8 +396,8 @@ public class Zip extends MatchingTask {
}
}
}
} catch (Throwable t) {
String msg = "Problem creating " + archiveType + ": " + t.getMessage();
} catch (IOException ioe) {
String msg = "Problem creating " + archiveType + ": " + ioe.getMessage();

// delete a bogus ZIP file
if (!zipFile.delete()) {
@@ -375,7 +411,7 @@ public class Zip extends MatchingTask {
}
}

throw new BuildException(msg, t, location);
throw new BuildException(msg, ioe, location);
} finally {
cleanUp();
}
@@ -446,6 +482,8 @@ public class Zip extends MatchingTask {
ZipOutputStream zOut, String prefix, String fullpath)
throws IOException
{
log("adding zip entries: " + fullpath, Project.MSG_VERBOSE);

if (prefix.length() > 0 && fullpath.length() > 0) {
throw new BuildException("Both prefix and fullpath attributes may not be set on the same fileset.");
}
@@ -465,11 +503,11 @@ public class Zip extends MatchingTask {
if (zipScanner.match(vPath)) {
if (fullpath.length() > 0) {
addParentDirs(null, fullpath, zOut, "");
zipFile(in, zOut, fullpath, entry.getTime());
zipFile(in, zOut, fullpath, entry.getTime(), zipSrc);
} else {
addParentDirs(null, vPath, zOut, prefix);
if (! entry.isDirectory()) {
zipFile(in, zOut, prefix+vPath, entry.getTime());
zipFile(in, zOut, prefix+vPath, entry.getTime(), zipSrc);
}
}
}
@@ -608,6 +646,8 @@ public class Zip extends MatchingTask {
// no warning if we try, it is harmless in and of itself
return;
}

log("adding directory " + vPath, Project.MSG_VERBOSE);
addedDirs.put(vPath, vPath);

ZipEntry ze = new ZipEntry (vPath);
@@ -628,9 +668,33 @@ public class Zip extends MatchingTask {
}

protected void zipFile(InputStream in, ZipOutputStream zOut, String vPath,
long lastModified)
long lastModified, File file)
throws IOException
{
if (entries.contains(vPath)) {

if (duplicate.equals("preserve"))
{
log(vPath + " already added, skipping", Project.MSG_INFO);
return;
}
else if (duplicate.equals("fail"))
{
throw new BuildException("Duplicate file " + vPath + " was found and the duplicate attribute is 'fail'.");
}
else
{
// duplicate equal to add, so we continue
log("duplicate file " + vPath + " found, adding.", Project.MSG_VERBOSE);
}
}
else
{
log("adding entry " + vPath, Project.MSG_VERBOSE);
}

entries.put(vPath, vPath);

ZipEntry ze = new ZipEntry(vPath);
ze.setTime(lastModified);

@@ -698,7 +762,7 @@ public class Zip extends MatchingTask {

FileInputStream fIn = new FileInputStream(file);
try {
zipFile(fIn, zOut, vPath, file.lastModified());
zipFile(fIn, zOut, vPath, file.lastModified(), null);
} finally {
fIn.close();
}
@@ -787,15 +851,27 @@ public class Zip extends MatchingTask {
* need to do is to reset some globals.</p>
*/
protected void cleanUp() {
addedDirs = new Hashtable();
addedFiles = new Vector();
filesets = new Vector();
addedDirs.clear();
addedFiles.clear();
filesets.clear();
zipFile = null;
baseDir = null;
entries.clear();
groupfilesets.clear();
duplicate = "add";
archiveType = "zip";
doCompress = true;
emptyBehavior = "skip";
doUpdate = false;
doFilesonly = false;
addingNewFiles = false;
encoding = null;
}

/** Possible behaviors when a duplicate file is added. */
public static class Duplicate extends EnumeratedAttribute {
public String[] getValues() {
return new String[] {"add", "preserve", "fail"};
}
}
}

+ 40
- 20
src/testcases/org/apache/tools/ant/taskdefs/ZipTest.java View File

@@ -55,54 +55,74 @@
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.BuildFileTest;

import java.io.File;
import java.io.IOException;
import java.util.zip.ZipFile;
import java.util.Enumeration;

/**
* @author Nico Seessle <nico@seessle.de>
* @author Nico Seessle <nico@seessle.de>
*/
public class ZipTest extends BuildFileTest {
public ZipTest(String name) {
public class ZipTest extends BuildFileTest {
public ZipTest(String name) {
super(name);
}
public void setUp() {
}
public void setUp() {
configureProject("src/etc/testcases/taskdefs/zip.xml");
}
public void test1() {
public void test1() {
expectBuildException("test1", "required argument not specified");
}

public void test2() {
public void test2() {
expectBuildException("test2", "required argument not specified");
}
public void test3() {
public void test3() {
expectBuildException("test3", "zip cannot include itself");
}

public void test4() {
public void test4() {
expectBuildException("test4", "zip cannot include itself");
}
public void tearDown() {
executeTarget("cleanup");
}
public void test5() {
public void test5() {
executeTarget("test5");
}


public void test6() {
public void test6() {
executeTarget("test6");
}


public void test7() {
public void test7() {
executeTarget("test7");
}

public void test8() {
public void test8() {
executeTarget("test8");
}
}

public void testZipgroupfileset() throws IOException {
executeTarget("testZipgroupfileset");

ZipFile zipFile = new ZipFile(new File(getProjectDir(), "zipgroupfileset.zip"));

assert(zipFile.getEntry("ant.xml") != null);
assert(zipFile.getEntry("optional/jspc.xml") != null);
assert(zipFile.getEntry("zip/zipgroupfileset3.zip") != null);

assert(zipFile.getEntry("test6.mf") == null);
assert(zipFile.getEntry("test7.mf") == null);

zipFile.close();
}
}

Loading…
Cancel
Save