Peter and Jon,
Thanks for the quick feedback. I've updated index.html to reflect the
changes, and have updated the Zip task to accept a prefixedfileset, with a
warning to the user that it has been deprecated.
-Don
Don Ferguson wrote:
With these patches, Zip (and derivative tasks such as Jar and War) can
merge the entries of multiple zip files into a single output zip file.
The contents of an input zip file may be selectively extracted based on
include/exclude patterns.
An included zip file is specified using a <fileset> with a "src" attribute,
as in:
<target name="jartest">
<jar jarfile="utils.jar">
<fileset
src="weblogic.jar"
includes="weblogic/utils/"
excludes="weblogic/utils/jars/,**/reflect/"
/>
</jar>
</target>
In this example, a subset of the "weblogic/utils" directory is extracted
from weblogic.jar, into utils.jar.
The fileset may also contain "prefix" and "fullpath" attributes (the
functionality of PrefixedFileSet has been retained in the new class
ZipFileSet). Prefixes apply to directory-based and zip-based filesets.
The fullpath attributes applies only to a single file in a directory-based
fileset.
The War task may extract entries from a zip file for all of its filesets
(including the files in "classes" and "lib").
The motivation for this change is:
1) There is significant overlap between "jlink" and "zip", and it seemed
better to combine them.
2) "jlink" does not support include/exclude patterns which are extremely
useful for writing packaging-type tasks such as Zip/Jar/War. This
was my main motivation.
3) By adding this functionality to the base task, it can also be used in
derivative tasks such as Jar and War.
This is my first submission jakarta-ant; I hope it is deemed worthy.
-Don
------------------------------------------------------------------------
Index: src/main/org/apache/tools/ant/taskdefs/Zip.java
===================================================================
RCS file: /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Zip.java,v
retrieving revision 1.26
diff -u -r1.26 Zip.java
--- src/main/org/apache/tools/ant/taskdefs/Zip.java 2001/01/08 16:45:32 1.26
+++ src/main/org/apache/tools/ant/taskdefs/Zip.java 2001/01/15 22:21:26
@@ -109,40 +109,10 @@
/**
* Adds a set of files (nested fileset attribute).
*/
- public void addFileset(FileSet set) {
+ public void addFileset(ZipFileSet set) {
filesets.addElement(set);
}
- /**
- * Adds a set of files (nested fileset attribute).
- */
- public void addPrefixedfileset(PrefixedFileSet set) {
- addFileset(set);
- }
-
- /**
- * FileSet with an additional prefix attribute to specify the
- * location we want to move the files to (inside the archive).
- * Or, if this FileSet represents only a single file, then the
- * fullpath attribute can be set, which specifies the full path
- * that the file should have when it is placed in the archive.
- */
- public static class PrefixedFileSet extends FileSet {
- private String prefix = "";
- private String fullpath = "";
-
- public void setPrefix(String loc) {
- prefix = loc;
- }
-
- public String getPrefix() {return prefix;}
-
- public void setFullpath(String loc) {
- fullpath = loc;
- }
-
- public String getFullpath() {return fullpath;}
- }
/**
* Sets behavior of the task when no files match.
@@ -164,7 +134,7 @@
public void execute() throws BuildException {
if (baseDir == null && filesets.size() == 0 && "zip".equals(archiveType)) {
throw new BuildException( "basedir attribute must be set, or at least " +
- "one fileset or prefixedfileset must be given!" );
+ "one fileset must be given!" );
}
if (zipFile == null) {
@@ -191,7 +161,8 @@
try {
boolean success = false;
- ZipOutputStream zOut = new ZipOutputStream(new FileOutputStream(zipFile));
+ ZipOutputStream zOut =
+ new ZipOutputStream(new FileOutputStream(zipFile));
try {
if (doCompress) {
zOut.setMethod(ZipOutputStream.DEFLATED);
@@ -283,6 +254,26 @@
}
}
+ protected void addZipEntries(ZipFileSet fs, DirectoryScanner ds,
+ ZipOutputStream zOut, String prefix)
+ throws IOException
+ {
+ ZipScanner zipScanner = (ZipScanner) ds;
+ String zipSrc = fs.getSrc();
+
+ ZipEntry entry;
+ ZipInputStream in = new ZipInputStream(new FileInputStream(new File(zipSrc)));
+ while ((entry = in.getNextEntry()) != null) {
+ String vPath = entry.getName();
+ if (zipScanner.match(vPath)) {
+ addParentDirs(null, vPath, zOut, prefix);
+ if (! entry.isDirectory()) {
+ zipFile(in, zOut, prefix+vPath, entry.getTime());
+ }
+ }
+ }
+ }
+
protected void initZipOutputStream(ZipOutputStream zOut)
throws IOException, BuildException
{
@@ -499,28 +490,22 @@
}
/**
- * Iterate over the given Vector of (prefixed)filesets and add
+ * Iterate over the given Vector of zipfilesets and add
* all files to the ZipOutputStream using the given prefix.
*/
protected void addFiles(Vector filesets, ZipOutputStream zOut)
throws IOException {
// Add each fileset in the Vector.
for (int i = 0; i<filesets.size(); i++) {
- FileSet fs = (FileSet) filesets.elementAt(i);
+ ZipFileSet fs = (ZipFileSet) filesets.elementAt(i);
DirectoryScanner ds = fs.getDirectoryScanner(project);
- String prefix = "";
- String fullpath = "";
- if (fs instanceof PrefixedFileSet) {
- PrefixedFileSet pfs = (PrefixedFileSet) fs;
- prefix = pfs.getPrefix();
- fullpath = pfs.getFullpath();
- }
-
+ String prefix = fs.getPrefix();
if (prefix.length() > 0
&& !prefix.endsWith("/")
&& !prefix.endsWith("\\")) {
prefix += "/";
}
+ String fullpath = fs.getFullpath();
// Need to manually add either fullpath's parent directory, or
// the prefix directory, to the archive.
if (prefix.length() > 0) {
@@ -529,8 +514,13 @@
} else if (fullpath.length() > 0) {
addParentDirs(null, fullpath, zOut, "");
}
- // Add the fileset.
- addFiles(ds, zOut, prefix, fullpath);
+
+ if (fs.getSrc() != null) {
+ addZipEntries(fs, ds, zOut, prefix);
+ } else {
+ // Add the fileset.
+ addFiles(ds, zOut, prefix, fullpath);
+ }
}
}
------------------------------------------------------------------------
Index: src/main/org/apache/tools/ant/taskdefs/Jar.java
===================================================================
RCS file: /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Jar.java,v
retrieving revision 1.14
diff -u -r1.14 Jar.java
--- src/main/org/apache/tools/ant/taskdefs/Jar.java 2001/01/08 16:45:32 1.14
+++ src/main/org/apache/tools/ant/taskdefs/Jar.java 2001/01/15 22:22:12
@@ -55,6 +55,7 @@
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.ZipFileSet;
import java.io.*;
import java.util.zip.*;
@@ -85,12 +86,12 @@
if (!manifest.exists())
throw new BuildException("Manifest file: " + manifest + " does not exist.");
- // Create a PrefixedFileSet for this file, and pass it up.
- PrefixedFileSet fs = new PrefixedFileSet();
+ // Create a ZipFileSet for this file, and pass it up.
+ ZipFileSet fs = new ZipFileSet();
fs.setDir(new File(manifest.getParent()));
fs.setIncludes(manifest.getName());
fs.setFullpath("META-INF/MANIFEST.MF");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
------------------------------------------------------------------------
Index: src/main/org/apache/tools/ant/taskdefs/War.java
===================================================================
RCS file: /home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/War.java,v
retrieving revision 1.9
diff -u -r1.9 War.java
--- src/main/org/apache/tools/ant/taskdefs/War.java 2001/01/08 16:45:32 1.9
+++ src/main/org/apache/tools/ant/taskdefs/War.java 2001/01/15 22:22:33
@@ -55,7 +55,7 @@
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.*;
-import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.ZipFileSet;
import java.io.*;
import java.util.Vector;
@@ -86,30 +86,30 @@
if (!deploymentDescriptor.exists())
throw new BuildException("Deployment descriptor: " + deploymentDescriptor + " does not exist.");
- // Create a PrefixedFileSet for this file, and pass it up.
- PrefixedFileSet fs = new PrefixedFileSet();
+ // Create a ZipFileSet for this file, and pass it up.
+ ZipFileSet fs = new ZipFileSet();
fs.setDir(new File(deploymentDescriptor.getParent()));
fs.setIncludes(deploymentDescriptor.getName());
fs.setFullpath("WEB-INF/web.xml");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
- public void addLib(PrefixedFileSet fs) {
+ public void addLib(ZipFileSet fs) {
// We just set the prefix for this fileset, and pass it up.
fs.setPrefix("WEB-INF/lib/");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
- public void addClasses(PrefixedFileSet fs) {
+ public void addClasses(ZipFileSet fs) {
// We just set the prefix for this fileset, and pass it up.
fs.setPrefix("WEB-INF/classes/");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
- public void addWebinf(PrefixedFileSet fs) {
+ public void addWebinf(ZipFileSet fs) {
// We just set the prefix for this fileset, and pass it up.
fs.setPrefix("WEB-INF/");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
protected void initZipOutputStream(ZipOutputStream zOut)
------------------------------------------------------------------------
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* 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
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* 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
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.types;
import java.io.File;
import java.util.Stack;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
/**
* A ZipFileSet is a FileSet with extra attributes useful in the context of
* Zip/Jar tasks.
*
* A ZipFileSet extends FileSets with the ability to extract a subset of the
* entries of a Zip file for inclusion in another Zip file. It also includes
* a prefix attribute which is prepended to each entry in the output Zip file.
*
* At present, ZipFileSets are not surfaced in the public API. FileSets
* nested in a Zip task are instantiated as ZipFileSets, and their attributes
* are only recognized in the context of the the Zip task.
* It is not possible to define a ZipFileSet outside of the Zip task and
* refer to it via a refid. However a standard FileSet may be included by
* reference in the Zip task, and attributes in the refering ZipFileSet
* can augment FileSet definition.
*
* @author Don Ferguson <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a>
*/
public class ZipFileSet extends FileSet {
private String srcFileName = null;
private String prefix = "";
private String fullpath = "";
private boolean hasDir = false;
/**
* Set the directory for the fileset. Prevents both "dir" and "src"
* from being specified.
*/
public void setDir(File dir) throws BuildException {
if (srcFileName != null) {
throw new BuildException("Cannot set both dir and src attributes");
} else {
super.setDir(dir);
hasDir = true;
}
}
/**
* Set the source Zip file for the zipfileset. Prevents both "dir" and
"src"
* from being specified.
*
* @param srcFileName The zip file from which to extract entries.
*/
public void setSrc(String srcFileName) {
if (hasDir) {
throw new BuildException("Cannot set both dir and src attributes");
}
this.srcFileName = srcFileName;
}
/**
* Get the zip file from which entries will be extracted.
* References are not followed, since it is not possible
* to have a reference to a ZipFileSet, only to a FileSet.
*/
public String getSrc() {
return srcFileName;
}
/**
* Prepend this prefix to the path for each zip entry.
* Does not perform reference test; the referenced file set
* can be augmented with a prefix.
*
* @param prefix The prefix to prepend to entries in the zip file.
*/
public void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* Return the prefix prepended to entries in the zip file.
*/
public String getPrefix() {
return prefix;
}
/**
* Set the full pathname of the single entry in this fileset.
*
* @param prefix The prefix to prepend to entries in the zip file.
*/
public void setFullpath(String fullpath) {
this.fullpath = fullpath;
}
/**
* Return the full pathname of the single entry in this fileset.
*/
public String getFullpath() {
return fullpath;
}
/**
* Return the DirectoryScanner associated with this FileSet.
* If the ZipFileSet defines a source Zip file, then a ZipScanner
* is returned instead.
*/
public DirectoryScanner getDirectoryScanner(Project p) {
if (isReference()) {
return getRef(p).getDirectoryScanner(p);
}
if (srcFileName != null) {
ZipScanner zs = new ZipScanner();
zs.setSrc(srcFileName);
if (getDir(p) == null) {
super.setDir(new File("."));
}
setupDirectoryScanner(zs, p);
zs.init();
return zs;
} else {
return super.getDirectoryScanner(p);
}
}
/**
* Performs the check for circular references and returns the
* referenced FileSet.
*/
private FileSet getRef(Project p) {
if (!checked) {
Stack stk = new Stack();
stk.push(this);
dieOnCircularReference(stk, p);
}
Object o = ref.getReferencedObject(p);
if (!(o instanceof FileSet)) {
String msg = ref.getRefId()+" doesn\'t denote a fileset";
throw new BuildException(msg);
} else {
return (FileSet) o;
}
}
}
------------------------------------------------------------------------
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* 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
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* 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", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.types;
import org.apache.tools.ant.DirectoryScanner;
import java.io.File;
/**
* ZipScanner accesses the pattern matching algorithm in DirectoryScanner,
* which are protected methods that can only be accessed by subclassing.
*
* This implementation of FileScanner defines getIncludedFiles to return
* only the Zip File which is being scanned, not the matching Zip entries.
* Arguably, it should return the matching entries, however this would
* complicate existing code which assumes that FileScanners return a
* set of file system files that can be accessed directly.
*
* @author Don Ferguson <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a>
*/
public class ZipScanner extends DirectoryScanner {
/**
* The zip file which should be scanned.
*/
protected String srcFile;
/**
* Sets the srcFile for scanning. This is the jar or zip file that is
scanned
* for matching entries.
*
* @param srcFile the (non-null) zip file name for scanning
*/
public void setSrc(String srcFile) {
this.srcFile = srcFile;
}
/**
* Returns the zip file itself, not the matching entries within the zip
file.
* This keeps the uptodate test in the Zip task simple; otherwise we'd need
* to treat zip filesets specially.
*
* @return the source file from which entries will be extracted.
*/
public String[] getIncludedFiles() {
String[] result = new String[1];
result[0] = srcFile;
return result;
}
/**
* Returns an empty list of directories to create.
*/
public String[] getIncludedDirectories() {
return new String[0];
}
/**
* Initialize DirectoryScanner data structures.
*/
public void init() {
if (includes == null) {
// No includes supplied, so set it to 'matches all'
includes = new String[1];
includes[0] = "**";
}
if (excludes == null) {
excludes = new String[0];
}
}
/**
* Matches a jar entry against the includes/excludes list,
* normalizing the path separator.
*
* @param path the (non-null) path name to test for inclusion
*
* @return <code>true</code> if the path should be included
* <code>false</code> otherwise.
*/
public boolean match(String path) {
String vpath = path.replace('/', File.separatorChar).
replace('\\', File.separatorChar);
return isIncluded(vpath) && !isExcluded(vpath);
}
}
------------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
Zip.diff
Content-Type:
text/plain
Content-Encoding:
7bit
------------------------------------------------------------------------
Jar.diff
Content-Type:
text/plain
Content-Encoding:
7bit
------------------------------------------------------------------------
War.diff
Content-Type:
text/plain
Content-Encoding:
7bit
------------------------------------------------------------------------
ZipFileSet.java
Content-Type:
text/plain
Content-Encoding:
7bit
------------------------------------------------------------------------
ZipScanner.java
Content-Type:
text/plain
Content-Encoding:
7bit
------------------------------------------------------------------------
attachment.txt
Content-Type:
text/plain
Index: docs/index.html
===================================================================
RCS file: /home/cvspublic/jakarta-ant/docs/index.html,v
retrieving revision 1.188
diff -u -r1.188 index.html
--- docs/index.html 2001/01/15 01:22:55 1.188
+++ docs/index.html 2001/01/16 02:54:41
@@ -2943,6 +2943,8 @@
<code><patternset></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.
See the <a href="#zip">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.
@@ -2952,7 +2954,7 @@
If <code>fail</code>, the JAR is not created and the build is halted with an
error.
<p>(The Jar task is a shortcut for specifying the manifest file of a JAR file.
The same thing can be accomplished by using the <i>fullpath</i>
-attribute of a prefixedfileset in a Zip task. The one difference is that if the
+attribute of a fileset in a Zip task. The one difference is that if the
<i>manifest</i> attribute is not specified, the Jar task will
include an empty one for you.)</p>
</p>
@@ -5138,7 +5140,9 @@
<code>WEB-INF</code> directories of the Web Application Archive.
<p>(The War task is a shortcut for specifying the particular layout of a WAR
file.
The same thing can be accomplished by using the <i>prefix</i> and
<i>fullpath</i>
-attributes of the prefixedfilesets in a Zip or Jar task.)</p>
+attributes of filesets in a Zip or Jar task.)</p>
+<p>The extended fileset attributes from the zip task (<i>prefix</i>,
<i>fullpath</i>, and <i>src</i>) are available for all filesets used in the War
task.</p>
+
<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -5243,8 +5247,8 @@
<exclude name="jdbc1.jar"/>
</lib>
<classes dir="build/main"/>
- <prefixedfileset dir="src/graphics/images/gifs"
- prefix="images"/>
+ <fileset dir="src/graphics/images/gifs"
+ prefix="images"/>
</war>
</pre>
will consist of
@@ -5287,16 +5291,7 @@
(with <code>basedir</code> set, and optional attributes like
<code>includes</code>
and optional subelements like <code><include></code>); explicit nested
<code><fileset></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.</p>
-<p><code><zip></code> elements may contain both regular
<code><fileset></code> elements
-and also <code><prefixedfileset></code> elements. A
<code><prefixedfileset></code> is an extended form of a fileset,
-which may include one of two special attributes:
-<i>prefix</i> or <i>fullpath</i>. These attributes modify the location of the
files when they are placed
-inside the archive. If the <i>prefix</i> attribute is set, all the files in
the prefixedfileset are prefixed
-with that path in the archive. If the <i>fullpath</i> attribute is set, the
file described by the prefixedfileset is placed at that
-exact location in the archive. (The <i>fullpath</i> attribute can only be set
for prefixedfilesets that
-represent a single file. The <i>prefix</i> and <i>fullpath</i> attributes
cannot both be set on the
-same prefixedfileset.)</p>
+only reflect the relative paths of files <i>within</i> each fileset. A
fileset has additional attributes that are available in the context of the Zip
task and its derivatives (described below). </p>
<p>The <code>whenempty</code> parameter controls what happens when no files
match.
If <code>skip</code> (the default), the ZIP is not created and a warning is
issued.
If <code>fail</code>, the ZIP is not created and the build is halted with an
error.
@@ -5360,6 +5355,18 @@
<td valign="top" align="center">No</td>
</tr>
</table>
+<h3>Parameters specified as nested elements</h3>
+<h4>fileset</h4>
+The zip task supports any number of nested <a
href="#fileset"><code><fileset></code></a> elements to specify the files
to be included in the archive. A <code><fileset></code> has three
additional attributes when
+used in the context of the <code><zip></code> task: <i>prefix</i>,
<i>fullpath</i>, and <i>src</i>. The
+<i>prefix</i> and <i>fullpath</i> attributes modify the location of the files
when they are placed
+inside the archive. If the <i>prefix</i> attribute is set, all files in the
fileset are prefixed
+with that path in the archive. If the <i>fullpath</i> attribute is set, the
file described by the fileset is placed at that
+exact location in the archive. (The <i>fullpath</i> attribute can only be set
for filesets that represent a single file. The <i>prefix</i> and
<i>fullpath</i> attributes cannot both be set on the same fileset.) The
<i>src</i> attribute
+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.
+
<h3>Examples</h3>
<pre> <zip zipfile="${dist}/manual.zip"
basedir="htdocs/manual"
@@ -5387,13 +5394,18 @@
current directory. <code>ChangeLog.txt</code> will be added to the top of the
ZIP file, just as if
it had been located at <code>htdocs/manual/ChangeLog.txt</code>.</p>
<pre> <zip zipfile="${dist}/manual.zip">
- <prefixedfileset dir="htdocs/manual"
prefix="docs/user-guide"/>
- <prefixedfileset dir="." includes="ChangeLog27.txt"
fullpath="docs/ChangeLog.txt"/>
+ <fileset dir="htdocs/manual"
prefix="docs/user-guide"/>
+ <fileset dir="." includes="ChangeLog27.txt"
fullpath="docs/ChangeLog.txt"/>
+ <fileset src="examples.zip" includes="**/*.html"
prefix="docs/examples"/>
</zip></pre>
<p>zips all files in the <code>htdocs/manual</code> directory into the
<code>docs/user-guide</code> directory
-in the archive, and also adds the file <code>ChangeLog27.txt</code> in the
-current directory as <code>docs/ChangeLog.txt</code>. For example, the archive
might end up containing two files:
-<code>docs/user-guide/html/index.html</code> and
<code>docs/ChangeLog.txt</code></p>
+in the archive, adds the file <code>ChangeLog27.txt</code> in the
+current directory as <code>docs/ChangeLog.txt</code>, and includes all the
html files in <code>examples.zip</code> under <code>docs/examples</code>. The
archive might end up containing the files:
+<pre><code> docs/user-guide/html/index.html
+ docs/ChangeLog.txt
+ docs/examples/index.html
+</code></pre>
+</p>
<hr>
<h2><a name="optionaltasks">Optional tasks</a></h2>
Index: src/main/org/apache/tools/ant/taskdefs/Zip.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Zip.java,v
retrieving revision 1.26
diff -u -r1.26 Zip.java
--- src/main/org/apache/tools/ant/taskdefs/Zip.java 2001/01/08 16:45:32
1.26
+++ src/main/org/apache/tools/ant/taskdefs/Zip.java 2001/01/16 02:48:37
@@ -109,41 +109,19 @@
/**
* Adds a set of files (nested fileset attribute).
*/
- public void addFileset(FileSet set) {
+ public void addFileset(ZipFileSet set) {
filesets.addElement(set);
}
/**
- * Adds a set of files (nested fileset attribute).
+ * @deprecated addPrefixedfileset is deprecated; replaced by ZipFileSet
*/
- public void addPrefixedfileset(PrefixedFileSet set) {
- addFileset(set);
+ public void addPrefixedfileset(ZipFileSet set) {
+ log("WARNING: PrefixedFileSets are deprecated; use the fileset tag
instead.");
+ filesets.addElement(set);
}
- /**
- * FileSet with an additional prefix attribute to specify the
- * location we want to move the files to (inside the archive).
- * Or, if this FileSet represents only a single file, then the
- * fullpath attribute can be set, which specifies the full path
- * that the file should have when it is placed in the archive.
- */
- public static class PrefixedFileSet extends FileSet {
- private String prefix = "";
- private String fullpath = "";
-
- public void setPrefix(String loc) {
- prefix = loc;
- }
-
- public String getPrefix() {return prefix;}
- public void setFullpath(String loc) {
- fullpath = loc;
- }
-
- public String getFullpath() {return fullpath;}
- }
-
/**
* Sets behavior of the task when no files match.
* Possible values are: <code>fail</code> (throw an exception
@@ -164,7 +142,7 @@
public void execute() throws BuildException {
if (baseDir == null && filesets.size() == 0 &&
"zip".equals(archiveType)) {
throw new BuildException( "basedir attribute must be set, or at
least " +
- "one fileset or prefixedfileset must be
given!" );
+ "one fileset must be given!" );
}
if (zipFile == null) {
@@ -191,7 +169,8 @@
try {
boolean success = false;
- ZipOutputStream zOut = new ZipOutputStream(new
FileOutputStream(zipFile));
+ ZipOutputStream zOut =
+ new ZipOutputStream(new FileOutputStream(zipFile));
try {
if (doCompress) {
zOut.setMethod(ZipOutputStream.DEFLATED);
@@ -283,6 +262,26 @@
}
}
+ protected void addZipEntries(ZipFileSet fs, DirectoryScanner ds,
+ ZipOutputStream zOut, String prefix)
+ throws IOException
+ {
+ ZipScanner zipScanner = (ZipScanner) ds;
+ String zipSrc = fs.getSrc();
+
+ ZipEntry entry;
+ ZipInputStream in = new ZipInputStream(new FileInputStream(new
File(zipSrc)));
+ while ((entry = in.getNextEntry()) != null) {
+ String vPath = entry.getName();
+ if (zipScanner.match(vPath)) {
+ addParentDirs(null, vPath, zOut, prefix);
+ if (! entry.isDirectory()) {
+ zipFile(in, zOut, prefix+vPath, entry.getTime());
+ }
+ }
+ }
+ }
+
protected void initZipOutputStream(ZipOutputStream zOut)
throws IOException, BuildException
{
@@ -499,28 +498,22 @@
}
/**
- * Iterate over the given Vector of (prefixed)filesets and add
+ * Iterate over the given Vector of zipfilesets and add
* all files to the ZipOutputStream using the given prefix.
*/
protected void addFiles(Vector filesets, ZipOutputStream zOut)
throws IOException {
// Add each fileset in the Vector.
for (int i = 0; i<filesets.size(); i++) {
- FileSet fs = (FileSet) filesets.elementAt(i);
+ ZipFileSet fs = (ZipFileSet) filesets.elementAt(i);
DirectoryScanner ds = fs.getDirectoryScanner(project);
- String prefix = "";
- String fullpath = "";
- if (fs instanceof PrefixedFileSet) {
- PrefixedFileSet pfs = (PrefixedFileSet) fs;
- prefix = pfs.getPrefix();
- fullpath = pfs.getFullpath();
- }
-
+ String prefix = fs.getPrefix();
if (prefix.length() > 0
&& !prefix.endsWith("/")
&& !prefix.endsWith("\\")) {
prefix += "/";
}
+ String fullpath = fs.getFullpath();
// Need to manually add either fullpath's parent directory, or
// the prefix directory, to the archive.
if (prefix.length() > 0) {
@@ -529,8 +522,13 @@
} else if (fullpath.length() > 0) {
addParentDirs(null, fullpath, zOut, "");
}
- // Add the fileset.
- addFiles(ds, zOut, prefix, fullpath);
+
+ if (fs.getSrc() != null) {
+ addZipEntries(fs, ds, zOut, prefix);
+ } else {
+ // Add the fileset.
+ addFiles(ds, zOut, prefix, fullpath);
+ }
}
}
Index: src/main/org/apache/tools/ant/taskdefs/Jar.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/Jar.java,v
retrieving revision 1.14
diff -u -r1.14 Jar.java
--- src/main/org/apache/tools/ant/taskdefs/Jar.java 2001/01/08 16:45:32
1.14
+++ src/main/org/apache/tools/ant/taskdefs/Jar.java 2001/01/15 22:22:12
@@ -55,6 +55,7 @@
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.*;
+import org.apache.tools.ant.types.ZipFileSet;
import java.io.*;
import java.util.zip.*;
@@ -85,12 +86,12 @@
if (!manifest.exists())
throw new BuildException("Manifest file: " + manifest + " does not
exist.");
- // Create a PrefixedFileSet for this file, and pass it up.
- PrefixedFileSet fs = new PrefixedFileSet();
+ // Create a ZipFileSet for this file, and pass it up.
+ ZipFileSet fs = new ZipFileSet();
fs.setDir(new File(manifest.getParent()));
fs.setIncludes(manifest.getName());
fs.setFullpath("META-INF/MANIFEST.MF");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
Index: src/main/org/apache/tools/ant/taskdefs/War.java
===================================================================
RCS file:
/home/cvspublic/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/War.java,v
retrieving revision 1.9
diff -u -r1.9 War.java
--- src/main/org/apache/tools/ant/taskdefs/War.java 2001/01/08 16:45:32
1.9
+++ src/main/org/apache/tools/ant/taskdefs/War.java 2001/01/15 22:22:33
@@ -55,7 +55,7 @@
package org.apache.tools.ant.taskdefs;
import org.apache.tools.ant.*;
-import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.ZipFileSet;
import java.io.*;
import java.util.Vector;
@@ -86,30 +86,30 @@
if (!deploymentDescriptor.exists())
throw new BuildException("Deployment descriptor: " +
deploymentDescriptor + " does not exist.");
- // Create a PrefixedFileSet for this file, and pass it up.
- PrefixedFileSet fs = new PrefixedFileSet();
+ // Create a ZipFileSet for this file, and pass it up.
+ ZipFileSet fs = new ZipFileSet();
fs.setDir(new File(deploymentDescriptor.getParent()));
fs.setIncludes(deploymentDescriptor.getName());
fs.setFullpath("WEB-INF/web.xml");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
- public void addLib(PrefixedFileSet fs) {
+ public void addLib(ZipFileSet fs) {
// We just set the prefix for this fileset, and pass it up.
fs.setPrefix("WEB-INF/lib/");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
- public void addClasses(PrefixedFileSet fs) {
+ public void addClasses(ZipFileSet fs) {
// We just set the prefix for this fileset, and pass it up.
fs.setPrefix("WEB-INF/classes/");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
- public void addWebinf(PrefixedFileSet fs) {
+ public void addWebinf(ZipFileSet fs) {
// We just set the prefix for this fileset, and pass it up.
fs.setPrefix("WEB-INF/");
- super.addPrefixedfileset(fs);
+ super.addFileset(fs);
}
protected void initZipOutputStream(ZipOutputStream zOut)
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* 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
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* 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
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.types;
import java.io.File;
import java.util.Stack;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
/**
* A ZipFileSet is a FileSet with extra attributes useful in the context of
* Zip/Jar tasks.
*
* A ZipFileSet extends FileSets with the ability to extract a subset of the
* entries of a Zip file for inclusion in another Zip file. It also includes
* a prefix attribute which is prepended to each entry in the output Zip file.
*
* At present, ZipFileSets are not surfaced in the public API. FileSets
* nested in a Zip task are instantiated as ZipFileSets, and their attributes
* are only recognized in the context of the the Zip task.
* It is not possible to define a ZipFileSet outside of the Zip task and
* refer to it via a refid. However a standard FileSet may be included by
* reference in the Zip task, and attributes in the refering ZipFileSet
* can augment FileSet definition.
*
* @author Don Ferguson <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a>
*/
public class ZipFileSet extends FileSet {
private String srcFileName = null;
private String prefix = "";
private String fullpath = "";
private boolean hasDir = false;
/**
* Set the directory for the fileset. Prevents both "dir" and "src"
* from being specified.
*/
public void setDir(File dir) throws BuildException {
if (srcFileName != null) {
throw new BuildException("Cannot set both dir and src attributes");
} else {
super.setDir(dir);
hasDir = true;
}
}
/**
* Set the source Zip file for the zipfileset. Prevents both "dir" and
"src"
* from being specified.
*
* @param srcFileName The zip file from which to extract entries.
*/
public void setSrc(String srcFileName) {
if (hasDir) {
throw new BuildException("Cannot set both dir and src attributes");
}
this.srcFileName = srcFileName;
}
/**
* Get the zip file from which entries will be extracted.
* References are not followed, since it is not possible
* to have a reference to a ZipFileSet, only to a FileSet.
*/
public String getSrc() {
return srcFileName;
}
/**
* Prepend this prefix to the path for each zip entry.
* Does not perform reference test; the referenced file set
* can be augmented with a prefix.
*
* @param prefix The prefix to prepend to entries in the zip file.
*/
public void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* Return the prefix prepended to entries in the zip file.
*/
public String getPrefix() {
return prefix;
}
/**
* Set the full pathname of the single entry in this fileset.
*
* @param prefix The prefix to prepend to entries in the zip file.
*/
public void setFullpath(String fullpath) {
this.fullpath = fullpath;
}
/**
* Return the full pathname of the single entry in this fileset.
*/
public String getFullpath() {
return fullpath;
}
/**
* Return the DirectoryScanner associated with this FileSet.
* If the ZipFileSet defines a source Zip file, then a ZipScanner
* is returned instead.
*/
public DirectoryScanner getDirectoryScanner(Project p) {
if (isReference()) {
return getRef(p).getDirectoryScanner(p);
}
if (srcFileName != null) {
ZipScanner zs = new ZipScanner();
zs.setSrc(srcFileName);
if (getDir(p) == null) {
super.setDir(new File("."));
}
setupDirectoryScanner(zs, p);
zs.init();
return zs;
} else {
return super.getDirectoryScanner(p);
}
}
/**
* Performs the check for circular references and returns the
* referenced FileSet.
*/
private FileSet getRef(Project p) {
if (!checked) {
Stack stk = new Stack();
stk.push(this);
dieOnCircularReference(stk, p);
}
Object o = ref.getReferencedObject(p);
if (!(o instanceof FileSet)) {
String msg = ref.getRefId()+" doesn\'t denote a fileset";
throw new BuildException(msg);
} else {
return (FileSet) o;
}
}
}
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* 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
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* 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", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.types;
import org.apache.tools.ant.DirectoryScanner;
import java.io.File;
/**
* ZipScanner accesses the pattern matching algorithm in DirectoryScanner,
* which are protected methods that can only be accessed by subclassing.
*
* This implementation of FileScanner defines getIncludedFiles to return
* only the Zip File which is being scanned, not the matching Zip entries.
* Arguably, it should return the matching entries, however this would
* complicate existing code which assumes that FileScanners return a
* set of file system files that can be accessed directly.
*
* @author Don Ferguson <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a>
*/
public class ZipScanner extends DirectoryScanner {
/**
* The zip file which should be scanned.
*/
protected String srcFile;
/**
* Sets the srcFile for scanning. This is the jar or zip file that is
scanned
* for matching entries.
*
* @param srcFile the (non-null) zip file name for scanning
*/
public void setSrc(String srcFile) {
this.srcFile = srcFile;
}
/**
* Returns the zip file itself, not the matching entries within the zip
file.
* This keeps the uptodate test in the Zip task simple; otherwise we'd need
* to treat zip filesets specially.
*
* @return the source file from which entries will be extracted.
*/
public String[] getIncludedFiles() {
String[] result = new String[1];
result[0] = srcFile;
return result;
}
/**
* Returns an empty list of directories to create.
*/
public String[] getIncludedDirectories() {
return new String[0];
}
/**
* Initialize DirectoryScanner data structures.
*/
public void init() {
if (includes == null) {
// No includes supplied, so set it to 'matches all'
includes = new String[1];
includes[0] = "**";
}
if (excludes == null) {
excludes = new String[0];
}
}
/**
* Matches a jar entry against the includes/excludes list,
* normalizing the path separator.
*
* @param path the (non-null) path name to test for inclusion
*
* @return <code>true</code> if the path should be included
* <code>false</code> otherwise.
*/
public boolean match(String path) {
String vpath = path.replace('/', File.separatorChar).
replace('\\', File.separatorChar);
return isIncluded(vpath) && !isExcluded(vpath);
}
}