git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@314776 13f79535-47bb-0310-9956-ffa450edef68master
@@ -23,7 +23,10 @@ explicit use beginning in <b>Ant 1.7</b>. | |||||
<ul> | <ul> | ||||
<li><a href="#basic">resource</a> - a basic resource.</li> | <li><a href="#basic">resource</a> - a basic resource.</li> | ||||
<li><a href="#file">file</a> - a file.</li> | <li><a href="#file">file</a> - a file.</li> | ||||
<li><a href="#tarentry">zipentry</a> - an entry in a tar file.</li> | |||||
<li><a href="#zipentry">zipentry</a> - an entry in a zip file.</li> | <li><a href="#zipentry">zipentry</a> - an entry in a zip file.</li> | ||||
<li><a href="#gzipresource">gzipresource</a> - a GZip compressed resource.</li> | |||||
<li><a href="#bzip2resource">bzip2resource</a> - a BZip2 compressed resource.</li> | |||||
<li><a href="#url">url</a> - a URL.</li> | <li><a href="#url">url</a> - a URL.</li> | ||||
<li><a href="#string">string</a> - a text string.</li> | <li><a href="#string">string</a> - a text string.</li> | ||||
<li><a href="#property">property</a> - an Ant property.</li> | <li><a href="#property">property</a> - an Ant property.</li> | ||||
@@ -97,7 +100,10 @@ implementations are also usable as single-element | |||||
<h4><a name="zipentry">zipentry</a></h4> | <h4><a name="zipentry">zipentry</a></h4> | ||||
<p>Represents an entry in a ZIP archive.</p> | |||||
<p>Represents an entry in a ZIP archive. The archive can be specified | |||||
using the archive attribute or a nested single-element resource | |||||
collection. <code>zipentry</code> only supports file system resources | |||||
as nested elements.</p> | |||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -106,9 +112,10 @@ implementations are also usable as single-element | |||||
<td align="center" valign="top"><b>Required</b></td> | <td align="center" valign="top"><b>Required</b></td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">zipfile</td> | |||||
<td valign="top">zipfile or its alias name archive</td> | |||||
<td valign="top">The zip file containing this resource</td> | <td valign="top">The zip file containing this resource</td> | ||||
<td align="center" valign="top">Yes</td> | |||||
<td align="center" valign="top">Yes, unless a nested resource | |||||
collection has been specified.</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">name</td> | <td valign="top">name</td> | ||||
@@ -123,6 +130,45 @@ implementations are also usable as single-element | |||||
</tr> | </tr> | ||||
</table> | </table> | ||||
<h4><a name="tarentry">tarentry</a></h4> | |||||
<p>Represents an entry in a TAR archive. The archive can be specified | |||||
using the archive attribute or a nested single-element resource | |||||
collection.</p> | |||||
<table border="1" cellpadding="2" cellspacing="0"> | |||||
<tr> | |||||
<td valign="top"><b>Attribute</b></td> | |||||
<td valign="top"><b>Description</b></td> | |||||
<td align="center" valign="top"><b>Required</b></td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">archive</td> | |||||
<td valign="top">The tar archive containing this resource</td> | |||||
<td align="center" valign="top">Yes, unless a nested resource | |||||
collection has been specified.</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">name</td> | |||||
<td valign="top">The name of the archived resource</td> | |||||
<td align="center" valign="top">Yes</td> | |||||
</tr> | |||||
</table> | |||||
<h4><a name="gzipresource">gzipresource</a></h4> | |||||
<p>This is not a stand-alone reource, but a wrapper around another | |||||
resource providing compression of the resource's contents on the fly. | |||||
A single element resource collection must be specified as a nested | |||||
element.</p> | |||||
<h4><a name="bzip2resource">bzip2resource</a></h4> | |||||
<p>This is not a stand-alone reource, but a wrapper around another | |||||
resource providing compression of the resource's contents on the fly. | |||||
A single element resource collection must be specified as a nested | |||||
element.</p> | |||||
<h4><a name="url">url</a></h4> | <h4><a name="url">url</a></h4> | ||||
<p>Represents a URL.</p> | <p>Represents a URL.</p> | ||||
@@ -205,6 +251,10 @@ Ant's "legacy" datatypes have been modified to behave as Resource Collections: | |||||
<a href="../using.html#path">path</a> | <a href="../using.html#path">path</a> | ||||
(and derivative types) expose <a href="#file">file</a> resources | (and derivative types) expose <a href="#file">file</a> resources | ||||
</li> | </li> | ||||
<li><a href="zipfileset.html">tarfileset</a> | |||||
can expose <a href="#file">file</a> or <a href="#tarentry">tarentry</a> | |||||
resources depending on configuration | |||||
</li> | |||||
<li><a href="zipfileset.html">zipfileset</a> | <li><a href="zipfileset.html">zipfileset</a> | ||||
can expose <a href="#file">file</a> or <a href="#zipentry">zipentry</a> | can expose <a href="#file">file</a> or <a href="#zipentry">zipentry</a> | ||||
resources depending on configuration | resources depending on configuration | ||||
@@ -6,28 +6,35 @@ | |||||
<title>ZipFileSet Type</title> | <title>ZipFileSet Type</title> | ||||
</head> | </head> | ||||
<body> | <body> | ||||
<h2><a name="fileset">ZipFileSet</a></h2> | |||||
<p>A <code><zipfileset></code> is a special form of a <code><<a | |||||
<h2><a name="fileset">ZipFileSet/TarFileSet</a></h2> | |||||
<p><em>TarFileSet</em> has been added as a stand-alone type in Ant | |||||
1.7.</p> | |||||
<p>A <code><zipfileset></code> and <code><tarfileset></code> are special forms of a <code><<a | |||||
href="fileset.html">fileset</a>></code> which can behave in 2 | href="fileset.html">fileset</a>></code> which can behave in 2 | ||||
different ways : <br> | different ways : <br> | ||||
</p> | </p> | ||||
<ul> | <ul> | ||||
<li>When the <span style="font-style: italic;">src</span> attribute | <li>When the <span style="font-style: italic;">src</span> attribute | ||||
is used, the zipfileset is populated with zip entries found in the file <span | |||||
style="font-style: italic;">src</span>.<br> | |||||
is used - or a nested resource collection has been specified | |||||
(<em>since Ant 1.7</em>), the tar/zipfileset is populated with tar | |||||
or zip entries found in the file <span style="font-style: | |||||
italic;">src</span>.<br> | |||||
</li> | </li> | ||||
<li>When the <span style="font-style: italic;">dir</span> attribute | <li>When the <span style="font-style: italic;">dir</span> attribute | ||||
is used, the zipfileset is populated with filesystem files found under <span | |||||
is used, the tar/zipfileset is populated with filesystem files found under <span | |||||
style="font-style: italic;">dir</span>.<br> | style="font-style: italic;">dir</span>.<br> | ||||
</li> | </li> | ||||
</ul> | </ul> | ||||
<p><code><zipfileset></code> supports all attributes of <code><<a | |||||
<p><code><tar/zipfileset></code> supports all attributes of <code><<a | |||||
href="fileset.html">fileset</a>></code> | href="fileset.html">fileset</a>></code> | ||||
in addition to those listed below.<br> | in addition to those listed below.<br> | ||||
</p> | </p> | ||||
<p>Since Ant 1.6, a zipfileset can be defined with the <span | <p>Since Ant 1.6, a zipfileset can be defined with the <span | ||||
style="font-style: italic;">id </span>attribute and referred to with | style="font-style: italic;">id </span>attribute and referred to with | ||||
the <span style="font-style: italic;">refid</span> attribute.<br> | |||||
the <span style="font-style: italic;">refid</span> attribute. This is | |||||
also true for tarfileset which has been added in Ant 1.7.<br> | |||||
</p> | </p> | ||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
@@ -70,14 +77,33 @@ and other modes in the standard Unix fashion. Only applies to | |||||
directories. Default is 755. <em>since Ant 1.5.2</em>.</td> | directories. Default is 755. <em>since Ant 1.5.2</em>.</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">encoding</td> | |||||
<td valign="top">The character encoding to use for filenames | |||||
inside the zip file. For a list of possible values see <a | |||||
href="http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html">http://java.sun.com/j2se/1.5.0/docs/guide/intl/encoding.doc.html</a>. | |||||
Defaults to the platform's default character encoding. | |||||
<b>Only supported by zipfileset.</b></td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
<p>The <i>fullpath</i> attribute can only be set for filesets that | <p>The <i>fullpath</i> attribute can only be set for filesets that | ||||
represent a single file. The <i>prefix</i> and <i>fullpath</i> | represent a single file. The <i>prefix</i> and <i>fullpath</i> | ||||
attributes cannot both be set on the same fileset.</p> | attributes cannot both be set on the same fileset.</p> | ||||
<p>When using the <i>src</i> attribute, include and exclude patterns | <p>When using the <i>src</i> attribute, include and exclude patterns | ||||
may be used to specify a subset of the zip file for inclusion in the | |||||
may be used to specify a subset of the archive for inclusion in the | |||||
archive as with the <i>dir</i> attribute.</p> | archive as with the <i>dir</i> attribute.</p> | ||||
<h3>Parameters specified as nested elements</h3> | |||||
<h4>any <a href="resources.html">resource</a> or single element | |||||
resource collection</h4> | |||||
<p>The specified resource will be used as src. zipfileset can only | |||||
support filesystem based resources while tarfileset can operate on | |||||
arbitrary resources.</p> | |||||
<h4>Examples</h4> | <h4>Examples</h4> | ||||
<blockquote> | <blockquote> | ||||
<pre> <zip destfile="${dist}/manual.zip"><br> <zipfileset dir="htdocs/manual" prefix="docs/user-guide"/><br> <zipfileset dir="." includes="ChangeLog27.txt" fullpath="docs/ChangeLog.txt"/><br> <zipfileset src="examples.zip" includes="**/*.html" prefix="docs/examples"/><br> </zip><br></pre> | <pre> <zip destfile="${dist}/manual.zip"><br> <zipfileset dir="htdocs/manual" prefix="docs/user-guide"/><br> <zipfileset dir="." includes="ChangeLog27.txt" fullpath="docs/ChangeLog.txt"/><br> <zipfileset src="examples.zip" includes="**/*.html" prefix="docs/examples"/><br> </zip><br></pre> | ||||
@@ -90,6 +116,25 @@ The archive might end up containing the files:</p> | |||||
docs/ChangeLog.txt<br> | docs/ChangeLog.txt<br> | ||||
docs/examples/index.html<br> | docs/examples/index.html<br> | ||||
</code></blockquote> | </code></blockquote> | ||||
<blockquote> | |||||
<pre> | |||||
<copy todir="some-dir"> | |||||
<tarfileset includes="lib/**"> | |||||
<bzip2resource> | |||||
<url url="http://example.org/dist/some-archive.tar.bz2"/> | |||||
</bzip2resource> | |||||
</tarfileset> | |||||
</copy> | |||||
</pre></blockquote> | |||||
<p>downloads the archive some-archive.tar.bz2, uncompresses and | |||||
extracts it on the fly, copies the contents of the lib directory into | |||||
some-dir and discards the rest of the archive. File timestamps will | |||||
be compared between the archive's entries and files inside the target | |||||
directory, no files get overwritten unless they are out-of-date.</p> | |||||
<hr> | <hr> | ||||
<p align="center">Copyright © 2003-2005 The Apache Software Foundation. All | <p align="center">Copyright © 2003-2005 The Apache Software Foundation. All | ||||
rights Reserved.</p> | rights Reserved.</p> | ||||
@@ -34,6 +34,7 @@ | |||||
<a href="CoreTypes/resources.html">Resources</a><br> | <a href="CoreTypes/resources.html">Resources</a><br> | ||||
<a href="CoreTypes/resources.html#collection">Resource Collections</a><br> | <a href="CoreTypes/resources.html#collection">Resource Collections</a><br> | ||||
<a href="CoreTypes/selectors.html">Selectors</a><br> | <a href="CoreTypes/selectors.html">Selectors</a><br> | ||||
<a href="CoreTypes/zipfileset.html">TarFileSet</a><br> | |||||
<a href="CoreTypes/xmlcatalog.html">XMLCatalog</a><br> | <a href="CoreTypes/xmlcatalog.html">XMLCatalog</a><br> | ||||
<a href="CoreTypes/zipfileset.html">ZipFileSet</a><br> | <a href="CoreTypes/zipfileset.html">ZipFileSet</a><br> | ||||
@@ -0,0 +1,26 @@ | |||||
<project default="not me"> | |||||
<target name="not me"> | |||||
<fail>only use from within unit tests</fail> | |||||
</target> | |||||
<property name="testout" location="testout"/> | |||||
<target name="setUp"> | |||||
<mkdir dir="${testout}"/> | |||||
</target> | |||||
<target name="uncompressSource" depends="setUp"> | |||||
<ant antfile="../../taskdefs/tar.xml" target="feather" /> | |||||
<copy todir="${testout}"> | |||||
<tarentry name="asf-logo.gif"> | |||||
<gzipresource> | |||||
<file file="../../taskdefs/expected/asf-logo.gif.tar.gz"/> | |||||
</gzipresource> | |||||
</tarentry> | |||||
</copy> | |||||
</target> | |||||
<target name="tearDown"> | |||||
<delete dir="${testout}"/> | |||||
<ant antfile="../../taskdefs/tar.xml" target="cleanup" /> | |||||
</target> | |||||
</project> |
@@ -434,18 +434,14 @@ public class Tar extends MatchingTask { | |||||
* This is a FileSet with the option to specify permissions | * This is a FileSet with the option to specify permissions | ||||
* and other attributes. | * and other attributes. | ||||
*/ | */ | ||||
public static class TarFileSet extends FileSet { | |||||
public static class TarFileSet | |||||
extends org.apache.tools.ant.types.TarFileSet { | |||||
private String[] files = null; | private String[] files = null; | ||||
private int fileMode = UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM; | |||||
private int dirMode = UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM; | |||||
private String userName = ""; | private String userName = ""; | ||||
private String groupName = ""; | private String groupName = ""; | ||||
private int uid; | private int uid; | ||||
private int gid; | private int gid; | ||||
private String prefix = ""; | |||||
private String fullpath = ""; | |||||
private boolean preserveLeadingSlashes = false; | private boolean preserveLeadingSlashes = false; | ||||
/** | /** | ||||
@@ -493,36 +489,14 @@ public class Tar extends MatchingTask { | |||||
* @param octalString a 3 digit octal string. | * @param octalString a 3 digit octal string. | ||||
*/ | */ | ||||
public void setMode(String octalString) { | public void setMode(String octalString) { | ||||
this.fileMode = | |||||
UnixStat.FILE_FLAG | Integer.parseInt(octalString, 8); | |||||
setFileMode(octalString); | |||||
} | } | ||||
/** | /** | ||||
* @return the current mode. | * @return the current mode. | ||||
*/ | */ | ||||
public int getMode() { | public int getMode() { | ||||
return fileMode; | |||||
} | |||||
/** | |||||
* A 3 digit octal string, specify the user, group and | |||||
* other modes in the standard Unix fashion; | |||||
* optional, default=0755 | |||||
* | |||||
* @param octalString a 3 digit octal string. | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void setDirMode(String octalString) { | |||||
this.dirMode = | |||||
UnixStat.DIR_FLAG | Integer.parseInt(octalString, 8); | |||||
} | |||||
/** | |||||
* @return the current directory mode | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public int getDirMode() { | |||||
return dirMode; | |||||
return getFileMode(); | |||||
} | } | ||||
/** | /** | ||||
@@ -589,41 +563,6 @@ public class Tar extends MatchingTask { | |||||
return gid; | return gid; | ||||
} | } | ||||
/** | |||||
* If the prefix attribute is set, all files in the fileset | |||||
* are prefixed with that path in the archive. | |||||
* optional. | |||||
* @param prefix the path prefix. | |||||
*/ | |||||
public void setPrefix(String prefix) { | |||||
this.prefix = prefix; | |||||
} | |||||
/** | |||||
* @return the path prefix for the files in the fileset. | |||||
*/ | |||||
public String getPrefix() { | |||||
return prefix; | |||||
} | |||||
/** | |||||
* If the fullpath attribute is set, the file in the fileset | |||||
* is written with that path in the archive. The prefix attribute, | |||||
* if specified, is ignored. It is an error to have more than one file specified in | |||||
* such a fileset. | |||||
* @param fullpath the path to use for the file in a fileset. | |||||
*/ | |||||
public void setFullpath(String fullpath) { | |||||
this.fullpath = fullpath; | |||||
} | |||||
/** | |||||
* @return the path to use for a single file fileset. | |||||
*/ | |||||
public String getFullpath() { | |||||
return fullpath; | |||||
} | |||||
/** | /** | ||||
* Flag to indicates whether leading `/'s should | * Flag to indicates whether leading `/'s should | ||||
* be preserved in the file names. | * be preserved in the file names. | ||||
@@ -197,7 +197,7 @@ public class Untar extends Expand { | |||||
* @exception BuildException thrown if bzip stream does not | * @exception BuildException thrown if bzip stream does not | ||||
* start with expected magic values | * start with expected magic values | ||||
*/ | */ | ||||
private InputStream decompress(final String name, | |||||
public InputStream decompress(final String name, | |||||
final InputStream istream) | final InputStream istream) | ||||
throws IOException, BuildException { | throws IOException, BuildException { | ||||
final String v = getValue(); | final String v = getValue(); | ||||
@@ -0,0 +1,420 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types; | |||||
import java.io.File; | |||||
import java.util.Iterator; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.DirectoryScanner; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.types.resources.FileResource; | |||||
import org.apache.tools.zip.UnixStat; | |||||
/** | |||||
* A ArchiveFileSet is a FileSet with extra attributes useful in the | |||||
* context of archiving tasks. | |||||
* | |||||
* It includes a prefix attribute which is prepended to each entry in | |||||
* the output archive file as well as a fullpath ttribute. It also | |||||
* supports Unix file permissions for files and directories. | |||||
* | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public abstract class ArchiveFileSet extends FileSet { | |||||
/** | |||||
* Default value for the dirmode attribute. | |||||
* | |||||
* @since Ant 1.5.2 | |||||
*/ | |||||
public static final int DEFAULT_DIR_MODE = | |||||
UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM; | |||||
/** | |||||
* Default value for the filemode attribute. | |||||
* | |||||
* @since Ant 1.5.2 | |||||
*/ | |||||
public static final int DEFAULT_FILE_MODE = | |||||
UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM; | |||||
private Resource src = null; | |||||
private String prefix = ""; | |||||
private String fullpath = ""; | |||||
private boolean hasDir = false; | |||||
private int fileMode = DEFAULT_FILE_MODE; | |||||
private int dirMode = DEFAULT_DIR_MODE; | |||||
private boolean fileModeHasBeenSet = false; | |||||
private boolean dirModeHasBeenSet = false; | |||||
/** Constructor for ArchiveFileSet */ | |||||
public ArchiveFileSet() { | |||||
super(); | |||||
} | |||||
/** | |||||
* Constructor using a fileset arguement. | |||||
* @param fileset the fileset to use | |||||
*/ | |||||
protected ArchiveFileSet(FileSet fileset) { | |||||
super(fileset); | |||||
} | |||||
/** | |||||
* Constructor using a archive fileset arguement. | |||||
* @param fileset the archivefileset to use | |||||
*/ | |||||
protected ArchiveFileSet(ArchiveFileSet fileset) { | |||||
super(fileset); | |||||
src = fileset.src; | |||||
prefix = fileset.prefix; | |||||
fullpath = fileset.fullpath; | |||||
hasDir = fileset.hasDir; | |||||
fileMode = fileset.fileMode; | |||||
dirMode = fileset.dirMode; | |||||
fileModeHasBeenSet = fileset.fileModeHasBeenSet; | |||||
dirModeHasBeenSet = fileset.dirModeHasBeenSet; | |||||
} | |||||
/** | |||||
* Set the directory for the fileset. | |||||
* @param dir the directory for the fileset | |||||
* @throws BuildException on error | |||||
*/ | |||||
public void setDir(File dir) throws BuildException { | |||||
checkAttributesAllowed(); | |||||
if (src != null) { | |||||
throw new BuildException("Cannot set both dir and src attributes"); | |||||
} else { | |||||
super.setDir(dir); | |||||
hasDir = true; | |||||
} | |||||
} | |||||
/** | |||||
* Set the source Archive file for the archivefileset. Prevents both | |||||
* "dir" and "src" from being specified. | |||||
* @param a the archive as a single element Resource collection. | |||||
*/ | |||||
public void addConfigured(ResourceCollection a) { | |||||
checkChildrenAllowed(); | |||||
if (a.size() != 1) { | |||||
throw new BuildException("only single argument resource collections" | |||||
+ " are supported as archives"); | |||||
} | |||||
setSrc((Resource) a.iterator().next()); | |||||
} | |||||
/** | |||||
* Set the source Archive file for the archivefileset. Prevents both | |||||
* "dir" and "src" from being specified. | |||||
* | |||||
* @param srcFile The archive from which to extract entries. | |||||
*/ | |||||
public void setSrc(File srcFile) { | |||||
setSrc(new FileResource(srcFile)); | |||||
} | |||||
/** | |||||
* Set the source Archive file for the archivefileset. Prevents both | |||||
* "dir" and "src" from being specified. | |||||
* | |||||
* @param srcFile The archive from which to extract entries. | |||||
*/ | |||||
public void setSrc(Resource src) { | |||||
checkAttributesAllowed(); | |||||
if (hasDir) { | |||||
throw new BuildException("Cannot set both dir and src attributes"); | |||||
} | |||||
this.src = src; | |||||
} | |||||
/** | |||||
* Get the archive from which entries will be extracted. | |||||
* @param p the project to use | |||||
* @return the source file | |||||
*/ | |||||
public File getSrc(Project p) { | |||||
if (isReference()) { | |||||
return ((ArchiveFileSet) getRef(p)).getSrc(p); | |||||
} | |||||
return getSrc(); | |||||
} | |||||
/** | |||||
* Get the archive file from which entries will be extracted. | |||||
*/ | |||||
public File getSrc() { | |||||
if (src instanceof FileResource) { | |||||
return ((FileResource) src).getFile(); | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Prepend this prefix to the path for each archive entry. | |||||
* Prevents both prefix and fullpath from being specified | |||||
* | |||||
* @param prefix The prefix to prepend to entries in the archive file. | |||||
*/ | |||||
public void setPrefix(String prefix) { | |||||
if (!prefix.equals("") && !fullpath.equals("")) { | |||||
throw new BuildException("Cannot set both fullpath and prefix attributes"); | |||||
} | |||||
this.prefix = prefix; | |||||
} | |||||
/** | |||||
* Return the prefix prepended to entries in the archive file. | |||||
* @param p the project to use | |||||
* @return the prefix | |||||
*/ | |||||
public String getPrefix(Project p) { | |||||
if (isReference()) { | |||||
return ((ArchiveFileSet) getRef(p)).getPrefix(p); | |||||
} | |||||
return prefix; | |||||
} | |||||
/** | |||||
* Return the prefix prepended to entries in the archive file. | |||||
* @deprecated | |||||
*/ | |||||
public String getPrefix() { | |||||
return prefix; | |||||
} | |||||
/** | |||||
* Set the full pathname of the single entry in this fileset. | |||||
* Prevents both prefix and fullpath from being specified | |||||
* | |||||
* @param fullpath the full pathname of the single entry in this fileset. | |||||
*/ | |||||
public void setFullpath(String fullpath) { | |||||
if (!prefix.equals("") && !fullpath.equals("")) { | |||||
throw new BuildException("Cannot set both fullpath and prefix attributes"); | |||||
} | |||||
this.fullpath = fullpath; | |||||
} | |||||
/** | |||||
* Return the full pathname of the single entry in this fileset. | |||||
* @param p the project to use | |||||
* @return the full path | |||||
*/ | |||||
public String getFullpath(Project p) { | |||||
if (isReference()) { | |||||
return ((ArchiveFileSet) getRef(p)).getFullpath(p); | |||||
} | |||||
return fullpath; | |||||
} | |||||
/** | |||||
* Return the full pathname of the single entry in this fileset. | |||||
* @deprecated | |||||
*/ | |||||
public String getFullpath() { | |||||
return fullpath; | |||||
} | |||||
/** | |||||
* Creates a scanner for this type of archive. | |||||
*/ | |||||
protected abstract ArchiveScanner newArchiveScanner(); | |||||
/** | |||||
* Return the DirectoryScanner associated with this FileSet. | |||||
* If the ArchiveFileSet defines a source Archive file, then a ArchiveScanner | |||||
* is returned instead. | |||||
* @param p the project to use | |||||
* @return a directory scanner | |||||
*/ | |||||
public DirectoryScanner getDirectoryScanner(Project p) { | |||||
if (isReference()) { | |||||
return getRef(p).getDirectoryScanner(p); | |||||
} | |||||
if (src == null) { | |||||
return super.getDirectoryScanner(p); | |||||
} | |||||
ArchiveScanner as = newArchiveScanner(); | |||||
as.setSrc(src); | |||||
super.setDir(p.getBaseDir()); | |||||
setupDirectoryScanner(as, p); | |||||
as.init(); | |||||
return as; | |||||
} | |||||
/** | |||||
* Fulfill the ResourceCollection contract. | |||||
* @return Iterator of Resources. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public Iterator iterator() { | |||||
if (isReference()) { | |||||
return ((ResourceCollection) (getRef(getProject()))).iterator(); | |||||
} | |||||
if (src == null) { | |||||
return super.iterator(); | |||||
} | |||||
ArchiveScanner as = (ArchiveScanner) getDirectoryScanner(getProject()); | |||||
return as.getResourceFiles(); | |||||
} | |||||
/** | |||||
* Fulfill the ResourceCollection contract. | |||||
* @return size of the collection as int. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public int size() { | |||||
if (isReference()) { | |||||
return ((ResourceCollection) (getRef(getProject()))).size(); | |||||
} | |||||
if (src == null) { | |||||
return super.size(); | |||||
} | |||||
ArchiveScanner as = (ArchiveScanner) getDirectoryScanner(getProject()); | |||||
return as.getIncludedFilesCount(); | |||||
} | |||||
/** | |||||
* Indicate whether this ResourceCollection is composed entirely of | |||||
* Resources accessible via local filesystem conventions. If true, | |||||
* all Resources returned from this ResourceCollection should be | |||||
* instances of FileResource. | |||||
* @return whether this is a filesystem-only resource collection. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public boolean isFilesystemOnly() { | |||||
return src == null; | |||||
} | |||||
/** | |||||
* A 3 digit octal string, specify the user, group and | |||||
* other modes in the standard Unix fashion; | |||||
* optional, default=0644 | |||||
* @param octalString a <code>String</code> value | |||||
*/ | |||||
public void setFileMode(String octalString) { | |||||
fileModeHasBeenSet = true; | |||||
this.fileMode = | |||||
UnixStat.FILE_FLAG | Integer.parseInt(octalString, 8); | |||||
} | |||||
/** | |||||
* Get the mode of the archive fileset | |||||
* @param p the project to use | |||||
* @return the mode | |||||
*/ | |||||
public int getFileMode(Project p) { | |||||
if (isReference()) { | |||||
return ((ArchiveFileSet) getRef(p)).getFileMode(p); | |||||
} | |||||
return fileMode; | |||||
} | |||||
/** | |||||
* @deprecated | |||||
*/ | |||||
public int getFileMode() { | |||||
return fileMode; | |||||
} | |||||
/** | |||||
* Whether the user has specified the mode explicitly. | |||||
* @return true if it has been set | |||||
*/ | |||||
public boolean hasFileModeBeenSet() { | |||||
if (isReference()) { | |||||
return ((ArchiveFileSet) getRef(getProject())).hasFileModeBeenSet(); | |||||
} | |||||
return fileModeHasBeenSet; | |||||
} | |||||
/** | |||||
* A 3 digit octal string, specify the user, group and | |||||
* other modes in the standard Unix fashion; | |||||
* optional, default=0755 | |||||
* @param octalString a <code>String</code> value | |||||
*/ | |||||
public void setDirMode(String octalString) { | |||||
dirModeHasBeenSet = true; | |||||
this.dirMode = | |||||
UnixStat.DIR_FLAG | Integer.parseInt(octalString, 8); | |||||
} | |||||
/** | |||||
* Get the dir mode of the archive fileset | |||||
* @param p the project to use | |||||
* @return the mode | |||||
*/ | |||||
public int getDirMode(Project p) { | |||||
if (isReference()) { | |||||
return ((ArchiveFileSet) getRef(p)).getDirMode(p); | |||||
} | |||||
return dirMode; | |||||
} | |||||
/** | |||||
* @deprecated | |||||
*/ | |||||
public int getDirMode() { | |||||
return dirMode; | |||||
} | |||||
/** | |||||
* Whether the user has specified the mode explicitly. | |||||
* | |||||
* @return true if it has been set | |||||
*/ | |||||
public boolean hasDirModeBeenSet() { | |||||
if (isReference()) { | |||||
return ((ArchiveFileSet) getRef(getProject())).hasDirModeBeenSet(); | |||||
} | |||||
return dirModeHasBeenSet; | |||||
} | |||||
/** | |||||
* A ArchiveFileset accepts another ArchiveFileSet or a FileSet as reference | |||||
* FileSets are often used by the war task for the lib attribute | |||||
* @param p the project to use | |||||
* @return the abstract fileset instance | |||||
*/ | |||||
protected final void configureFileSet(ArchiveFileSet zfs) { | |||||
zfs.setPrefix(prefix); | |||||
zfs.setFullpath(fullpath); | |||||
zfs.fileModeHasBeenSet = fileModeHasBeenSet; | |||||
zfs.fileMode = fileMode; | |||||
zfs.dirModeHasBeenSet = dirModeHasBeenSet; | |||||
zfs.dirMode = dirMode; | |||||
} | |||||
/** | |||||
* Return a ArchiveFileSet that has the same properties | |||||
* as this one. | |||||
* @return the cloned archiveFileSet | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public Object clone() { | |||||
if (isReference()) { | |||||
return ((ArchiveFileSet) getRef(getProject())).clone(); | |||||
} else { | |||||
return super.clone(); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,329 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import java.util.Map; | |||||
import java.util.Set; | |||||
import java.util.TreeMap; | |||||
import java.util.Iterator; | |||||
import java.util.Enumeration; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.DirectoryScanner; | |||||
import org.apache.tools.ant.types.resources.FileResource; | |||||
import org.apache.tools.ant.types.resources.FileResourceIterator; | |||||
/** | |||||
* ArchiveScanner 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 | |||||
* the matching archive entries. | |||||
* | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public abstract class ArchiveScanner extends DirectoryScanner { | |||||
/** | |||||
* The archive file which should be scanned. | |||||
*/ | |||||
protected File srcFile; | |||||
/** | |||||
* The archive resource which should be scanned. | |||||
*/ | |||||
private Resource src; | |||||
/** | |||||
* to record the last scanned zip file with its modification date | |||||
*/ | |||||
private Resource lastScannedResource; | |||||
/** | |||||
* record list of all file zip entries | |||||
*/ | |||||
private TreeMap fileEntries = new TreeMap(); | |||||
/** | |||||
* record list of all directory zip entries | |||||
*/ | |||||
private TreeMap dirEntries = new TreeMap(); | |||||
/** | |||||
* record list of matching file zip entries | |||||
*/ | |||||
private TreeMap matchFileEntries = new TreeMap(); | |||||
/** | |||||
* record list of matching directory zip entries | |||||
*/ | |||||
private TreeMap matchDirEntries = new TreeMap(); | |||||
/** | |||||
* encoding of file names. | |||||
* | |||||
* @since Ant 1.6 | |||||
*/ | |||||
private String encoding; | |||||
/** | |||||
* Don't scan when we have no zipfile. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public void scan() { | |||||
if (src == null) { | |||||
return; | |||||
} | |||||
super.scan(); | |||||
} | |||||
/** | |||||
* Sets the srcFile for scanning. This is the jar or zip file that | |||||
* is scanned for matching entries. | |||||
* | |||||
* @param srcFile the (non-null) archive file name for scanning | |||||
*/ | |||||
public void setSrc(File srcFile) { | |||||
setSrc(new FileResource(srcFile)); | |||||
} | |||||
/** | |||||
* Sets the src for scanning. This is the jar or zip file that | |||||
* is scanned for matching entries. | |||||
* | |||||
* @param src the (non-null) archive resource | |||||
*/ | |||||
public void setSrc(Resource src) { | |||||
this.src = src; | |||||
if (src instanceof FileResource) { | |||||
srcFile = ((FileResource) src).getFile(); | |||||
} | |||||
} | |||||
/** | |||||
* Sets encoding of file names. | |||||
* @param encoding the encoding format | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void setEncoding(String encoding) { | |||||
this.encoding = encoding; | |||||
} | |||||
/** | |||||
* Returns the names of the files which matched at least one of the | |||||
* include patterns and none of the exclude patterns. | |||||
* The names are relative to the base directory. | |||||
* | |||||
* @return the names of the files which matched at least one of the | |||||
* include patterns and none of the exclude patterns. | |||||
*/ | |||||
public String[] getIncludedFiles() { | |||||
if (src == null) { | |||||
return super.getIncludedFiles(); | |||||
} | |||||
scanme(); | |||||
Set s = matchFileEntries.keySet(); | |||||
return (String[]) (s.toArray(new String[s.size()])); | |||||
} | |||||
/** | |||||
* Override parent implementation. | |||||
* @return count of included files. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public int getIncludedFilesCount() { | |||||
if (src == null) { | |||||
return super.getIncludedFilesCount(); | |||||
} | |||||
scanme(); | |||||
return matchFileEntries.size(); | |||||
} | |||||
/** | |||||
* Returns the names of the directories which matched at least one of the | |||||
* include patterns and none of the exclude patterns. | |||||
* The names are relative to the base directory. | |||||
* | |||||
* @return the names of the directories which matched at least one of the | |||||
* include patterns and none of the exclude patterns. | |||||
*/ | |||||
public String[] getIncludedDirectories() { | |||||
if (src == null) { | |||||
return super.getIncludedDirectories(); | |||||
} | |||||
scanme(); | |||||
Set s = matchDirEntries.keySet(); | |||||
return (String[]) (s.toArray(new String[s.size()])); | |||||
} | |||||
/** | |||||
* Override parent implementation. | |||||
* @return count of included directories. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public int getIncludedDirsCount() { | |||||
if (src == null) { | |||||
return super.getIncludedDirsCount(); | |||||
} | |||||
scanme(); | |||||
return matchDirEntries.size(); | |||||
} | |||||
/** | |||||
* Get the set of Resources that represent files. | |||||
* @return an Iterator of Resources. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
/* package-private for now */ Iterator getResourceFiles() { | |||||
if (src == null) { | |||||
return new FileResourceIterator(getBasedir(), getIncludedFiles()); | |||||
} | |||||
scanme(); | |||||
return matchFileEntries.values().iterator(); | |||||
} | |||||
/** | |||||
* Get the set of Resources that represent directories. | |||||
* @return an Iterator of Resources. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
/* package-private for now */ Iterator getResourceDirectories() { | |||||
if (src == null) { | |||||
return new FileResourceIterator(getBasedir(), getIncludedDirectories()); | |||||
} | |||||
scanme(); | |||||
return matchDirEntries.values().iterator(); | |||||
} | |||||
/** | |||||
* 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); | |||||
} | |||||
/** | |||||
* Get the named Resource. | |||||
* @param name path name of the file sought in the archive | |||||
* @return the resource | |||||
* @since Ant 1.5.2 | |||||
*/ | |||||
public Resource getResource(String name) { | |||||
if (src == null) { | |||||
return super.getResource(name); | |||||
} | |||||
if (name.equals("")) { | |||||
// special case in ZIPs, we do not want this thing included | |||||
return new Resource("", true, Long.MAX_VALUE, true); | |||||
} | |||||
// first check if the archive needs to be scanned again | |||||
scanme(); | |||||
if (fileEntries.containsKey(name)) { | |||||
return (Resource) fileEntries.get(name); | |||||
} | |||||
name = trimSeparator(name); | |||||
if (dirEntries.containsKey(name)) { | |||||
return (Resource) dirEntries.get(name); | |||||
} | |||||
return new Resource(name); | |||||
} | |||||
/** | |||||
* Fills the file and directory maps with resources read from the archive. | |||||
* | |||||
* @param archive the archive to scan. | |||||
* @param encoding encoding used to encode file names inside the archive. | |||||
* @param fileEntries Map (name to resource) of non-directory | |||||
* resources found inside the archive. | |||||
* @param matchFileEntries Map (name to resource) of non-directory | |||||
* resources found inside the archive that matched all include | |||||
* patterns and didn't match any exclude patterns. | |||||
* @param dirEntries Map (name to resource) of directory | |||||
* resources found inside the archive. | |||||
* @param matchDirEntries Map (name to resource) of directory | |||||
* resources found inside the archive that matched all include | |||||
* patterns and didn't match any exclude patterns. | |||||
*/ | |||||
protected abstract void fillMapsFromArchive(Resource archive, | |||||
String encoding, | |||||
Map fileEntries, | |||||
Map matchFileEntries, | |||||
Map dirEntries, | |||||
Map matchDirEntries); | |||||
/** | |||||
* if the datetime of the archive did not change since | |||||
* lastScannedResource was initialized returns immediately else if | |||||
* the archive has not been scanned yet, then all the zip entries | |||||
* are put into the appropriate tables. | |||||
*/ | |||||
private void scanme() { | |||||
//do not use a FileResource b/c it pulls File info from the filesystem: | |||||
Resource thisresource = new Resource(src.getName(), | |||||
src.isExists(), | |||||
src.getLastModified()); | |||||
// spare scanning again and again | |||||
if (lastScannedResource != null | |||||
&& lastScannedResource.getName().equals(thisresource.getName()) | |||||
&& lastScannedResource.getLastModified() | |||||
== thisresource.getLastModified()) { | |||||
return; | |||||
} | |||||
init(); | |||||
fileEntries.clear(); | |||||
dirEntries.clear(); | |||||
matchFileEntries.clear(); | |||||
matchDirEntries.clear(); | |||||
fillMapsFromArchive(src, encoding, fileEntries, matchFileEntries, | |||||
dirEntries, matchDirEntries); | |||||
// record data about the last scanned resource | |||||
lastScannedResource = thisresource; | |||||
} | |||||
protected static final String trimSeparator(String s) { | |||||
return s.endsWith("/") ? s.substring(0, s.length() - 1) : s; | |||||
} | |||||
} |
@@ -0,0 +1,98 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types; | |||||
import java.io.File; | |||||
import java.util.Iterator; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.DirectoryScanner; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.zip.UnixStat; | |||||
/** | |||||
* A TarFileSet is a FileSet with extra attributes useful in the context of | |||||
* Tar/Jar tasks. | |||||
* | |||||
* A TarFileSet extends FileSets with the ability to extract a subset of the | |||||
* entries of a Tar file for inclusion in another Tar file. It also includes | |||||
* a prefix attribute which is prepended to each entry in the output Tar file. | |||||
* | |||||
* Since ant 1.6 TarFileSet can be defined with an id and referenced in packaging tasks | |||||
* | |||||
*/ | |||||
public class TarFileSet extends ArchiveFileSet { | |||||
/** Constructor for TarFileSet */ | |||||
public TarFileSet() { | |||||
super(); | |||||
} | |||||
/** | |||||
* Constructor using a fileset arguement. | |||||
* @param fileset the fileset to use | |||||
*/ | |||||
protected TarFileSet(FileSet fileset) { | |||||
super(fileset); | |||||
} | |||||
/** | |||||
* Constructor using a tarfileset arguement. | |||||
* @param fileset the tarfileset to use | |||||
*/ | |||||
protected TarFileSet(TarFileSet fileset) { | |||||
super(fileset); | |||||
} | |||||
protected ArchiveScanner newArchiveScanner() { | |||||
TarScanner zs = new TarScanner(); | |||||
return zs; | |||||
} | |||||
/** | |||||
* A TarFileset accepts another TarFileSet or a FileSet as reference | |||||
* FileSets are often used by the war task for the lib attribute | |||||
* @param p the project to use | |||||
* @return the abstract fileset instance | |||||
*/ | |||||
protected AbstractFileSet getRef(Project p) { | |||||
dieOnCircularReference(p); | |||||
Object o = getRefid().getReferencedObject(p); | |||||
if (o instanceof TarFileSet) { | |||||
return (AbstractFileSet) o; | |||||
} else if (o instanceof FileSet) { | |||||
TarFileSet zfs = new TarFileSet((FileSet) o); | |||||
configureFileSet(zfs); | |||||
return zfs; | |||||
} else { | |||||
String msg = getRefid().getRefId() + " doesn\'t denote a tarfileset or a fileset"; | |||||
throw new BuildException(msg); | |||||
} | |||||
} | |||||
/** | |||||
* Return a TarFileSet that has the same properties | |||||
* as this one. | |||||
* @return the cloned tarFileSet | |||||
*/ | |||||
public Object clone() { | |||||
if (isReference()) { | |||||
return ((TarFileSet) getRef(getProject())).clone(); | |||||
} else { | |||||
return super.clone(); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,90 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types; | |||||
import java.io.IOException; | |||||
import java.util.Map; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.types.resources.TarResource; | |||||
import org.apache.tools.tar.TarEntry; | |||||
import org.apache.tools.tar.TarInputStream; | |||||
/** | |||||
* Scans tar archives for resources. | |||||
*/ | |||||
public class TarScanner extends ArchiveScanner { | |||||
/** | |||||
* Fills the file and directory maps with resources read from the | |||||
* archive. | |||||
* | |||||
* @param src the archive to scan. | |||||
* @param encoding encoding used to encode file names inside the archive. | |||||
* @param fileEntries Map (name to resource) of non-directory | |||||
* resources found inside the archive. | |||||
* @param matchFileEntries Map (name to resource) of non-directory | |||||
* resources found inside the archive that matched all include | |||||
* patterns and didn't match any exclude patterns. | |||||
* @param dirEntries Map (name to resource) of directory | |||||
* resources found inside the archive. | |||||
* @param matchDirEntries Map (name to resource) of directory | |||||
* resources found inside the archive that matched all include | |||||
* patterns and didn't match any exclude patterns. | |||||
*/ | |||||
protected void fillMapsFromArchive(Resource src, String encoding, | |||||
Map fileEntries, Map matchFileEntries, | |||||
Map dirEntries, Map matchDirEntries) { | |||||
TarEntry entry = null; | |||||
TarInputStream ti = null; | |||||
try { | |||||
try { | |||||
ti = new TarInputStream(src.getInputStream()); | |||||
} catch (IOException ex) { | |||||
throw new BuildException("problem opening " + srcFile, ex); | |||||
} | |||||
while ((entry = ti.getNextEntry()) != null) { | |||||
Resource r = new TarResource(src, entry); | |||||
String name = entry.getName(); | |||||
if (entry.isDirectory()) { | |||||
name = trimSeparator(name); | |||||
dirEntries.put(name, r); | |||||
if (match(name)) { | |||||
matchDirEntries.put(name, r); | |||||
} | |||||
} else { | |||||
fileEntries.put(name, r); | |||||
if (match(name)) { | |||||
matchFileEntries.put(name, r); | |||||
} | |||||
} | |||||
} | |||||
} catch (IOException ex) { | |||||
throw new BuildException("problem reading " + srcFile, ex); | |||||
} finally { | |||||
if (ti != null) { | |||||
try { | |||||
ti.close(); | |||||
} catch (IOException ex) { | |||||
// swallow | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -34,33 +34,7 @@ import org.apache.tools.zip.UnixStat; | |||||
* Since ant 1.6 ZipFileSet can be defined with an id and referenced in packaging tasks | * Since ant 1.6 ZipFileSet can be defined with an id and referenced in packaging tasks | ||||
* | * | ||||
*/ | */ | ||||
public class ZipFileSet extends FileSet { | |||||
/** | |||||
* Default value for the dirmode attribute. | |||||
* | |||||
* @since Ant 1.5.2 | |||||
*/ | |||||
public static final int DEFAULT_DIR_MODE = | |||||
UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM; | |||||
/** | |||||
* Default value for the filemode attribute. | |||||
* | |||||
* @since Ant 1.5.2 | |||||
*/ | |||||
public static final int DEFAULT_FILE_MODE = | |||||
UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM; | |||||
private File srcFile = null; | |||||
private String prefix = ""; | |||||
private String fullpath = ""; | |||||
private boolean hasDir = false; | |||||
private int fileMode = DEFAULT_FILE_MODE; | |||||
private int dirMode = DEFAULT_DIR_MODE; | |||||
private boolean fileModeHasBeenSet = false; | |||||
private boolean dirModeHasBeenSet = false; | |||||
public class ZipFileSet extends ArchiveFileSet { | |||||
private String encoding = null; | private String encoding = null; | ||||
@@ -83,140 +57,9 @@ public class ZipFileSet extends FileSet { | |||||
*/ | */ | ||||
protected ZipFileSet(ZipFileSet fileset) { | protected ZipFileSet(ZipFileSet fileset) { | ||||
super(fileset); | super(fileset); | ||||
srcFile = fileset.srcFile; | |||||
prefix = fileset.prefix; | |||||
fullpath = fileset.fullpath; | |||||
hasDir = fileset.hasDir; | |||||
fileMode = fileset.fileMode; | |||||
dirMode = fileset.dirMode; | |||||
fileModeHasBeenSet = fileset.fileModeHasBeenSet; | |||||
dirModeHasBeenSet = fileset.dirModeHasBeenSet; | |||||
encoding = fileset.encoding; | encoding = fileset.encoding; | ||||
} | } | ||||
/** | |||||
* Set the directory for the fileset. Prevents both "dir" and "src" | |||||
* from being specified. | |||||
* @param dir the directory for the fileset | |||||
* @throws BuildException on error | |||||
*/ | |||||
public void setDir(File dir) throws BuildException { | |||||
checkAttributesAllowed(); | |||||
if (srcFile != 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 srcFile The zip file from which to extract entries. | |||||
*/ | |||||
public void setSrc(File srcFile) { | |||||
checkAttributesAllowed(); | |||||
if (hasDir) { | |||||
throw new BuildException("Cannot set both dir and src attributes"); | |||||
} | |||||
this.srcFile = srcFile; | |||||
} | |||||
/** | |||||
* 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. | |||||
* @param p the project to use | |||||
* @return the source file | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public File getSrc(Project p) { | |||||
if (isReference()) { | |||||
return ((ZipFileSet) getRef(p)).getSrc(p); | |||||
} | |||||
return srcFile; | |||||
} | |||||
/** | |||||
* 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. | |||||
* @deprecated | |||||
*/ | |||||
public File getSrc() { | |||||
return srcFile; | |||||
} | |||||
/** | |||||
* Prepend this prefix to the path for each zip entry. | |||||
* Prevents both prefix and fullpath from being specified | |||||
* | |||||
* @param prefix The prefix to prepend to entries in the zip file. | |||||
*/ | |||||
public void setPrefix(String prefix) { | |||||
if (!prefix.equals("") && !fullpath.equals("")) { | |||||
throw new BuildException("Cannot set both fullpath and prefix attributes"); | |||||
} | |||||
this.prefix = prefix; | |||||
} | |||||
/** | |||||
* Return the prefix prepended to entries in the zip file. | |||||
* @param p the project to use | |||||
* @return the prefix | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public String getPrefix(Project p) { | |||||
if (isReference()) { | |||||
return ((ZipFileSet) getRef(p)).getPrefix(p); | |||||
} | |||||
return prefix; | |||||
} | |||||
/** | |||||
* Return the prefix prepended to entries in the zip file. | |||||
* @deprecated | |||||
*/ | |||||
public String getPrefix() { | |||||
return prefix; | |||||
} | |||||
/** | |||||
* Set the full pathname of the single entry in this fileset. | |||||
* Prevents both prefix and fullpath from being specified | |||||
* | |||||
* @param fullpath the full pathname of the single entry in this fileset. | |||||
*/ | |||||
public void setFullpath(String fullpath) { | |||||
if (!prefix.equals("") && !fullpath.equals("")) { | |||||
throw new BuildException("Cannot set both fullpath and prefix attributes"); | |||||
} | |||||
this.fullpath = fullpath; | |||||
} | |||||
/** | |||||
* Return the full pathname of the single entry in this fileset. | |||||
* @param p the project to use | |||||
* @return the full path | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public String getFullpath(Project p) { | |||||
if (isReference()) { | |||||
return ((ZipFileSet) getRef(p)).getFullpath(p); | |||||
} | |||||
return fullpath; | |||||
} | |||||
/** | |||||
* Return the full pathname of the single entry in this fileset. | |||||
* @deprecated | |||||
*/ | |||||
public String getFullpath() { | |||||
return fullpath; | |||||
} | |||||
/** | /** | ||||
* Set the encoding used for this ZipFileSet. | * Set the encoding used for this ZipFileSet. | ||||
* @param enc encoding as String. | * @param enc encoding as String. | ||||
@@ -235,168 +78,12 @@ public class ZipFileSet extends FileSet { | |||||
return encoding; | return encoding; | ||||
} | } | ||||
/** | |||||
* Return the DirectoryScanner associated with this FileSet. | |||||
* If the ZipFileSet defines a source Zip file, then a ZipScanner | |||||
* is returned instead. | |||||
* @param p the project to use | |||||
* @return a directory scanner | |||||
*/ | |||||
public DirectoryScanner getDirectoryScanner(Project p) { | |||||
if (isReference()) { | |||||
return getRef(p).getDirectoryScanner(p); | |||||
} | |||||
if (srcFile == null) { | |||||
return super.getDirectoryScanner(p); | |||||
} | |||||
protected ArchiveScanner newArchiveScanner() { | |||||
ZipScanner zs = new ZipScanner(); | ZipScanner zs = new ZipScanner(); | ||||
zs.setSrc(srcFile); | |||||
super.setDir(p.getBaseDir()); | |||||
setupDirectoryScanner(zs, p); | |||||
zs.init(); | |||||
zs.setEncoding(encoding); | zs.setEncoding(encoding); | ||||
return zs; | return zs; | ||||
} | } | ||||
/** | |||||
* Fulfill the ResourceCollection contract. | |||||
* @return Iterator of Resources. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public Iterator iterator() { | |||||
if (isReference()) { | |||||
return ((ResourceCollection) (getRef(getProject()))).iterator(); | |||||
} | |||||
if (srcFile == null) { | |||||
return super.iterator(); | |||||
} | |||||
ZipScanner zs = (ZipScanner) getDirectoryScanner(getProject()); | |||||
return zs.getResourceFiles(); | |||||
} | |||||
/** | |||||
* Fulfill the ResourceCollection contract. | |||||
* @return size of the collection as int. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public int size() { | |||||
if (isReference()) { | |||||
return ((ResourceCollection) (getRef(getProject()))).size(); | |||||
} | |||||
if (srcFile == null) { | |||||
return super.size(); | |||||
} | |||||
ZipScanner zs = (ZipScanner) getDirectoryScanner(getProject()); | |||||
return zs.getIncludedFilesCount(); | |||||
} | |||||
/** | |||||
* Indicate whether this ResourceCollection is composed entirely of | |||||
* Resources accessible via local filesystem conventions. If true, | |||||
* all Resources returned from this ResourceCollection should be | |||||
* instances of FileResource. | |||||
* @return whether this is a filesystem-only resource collection. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public boolean isFilesystemOnly() { | |||||
return srcFile == null; | |||||
} | |||||
/** | |||||
* A 3 digit octal string, specify the user, group and | |||||
* other modes in the standard Unix fashion; | |||||
* optional, default=0644 | |||||
* @param octalString a <code>String</code> value | |||||
* @since Ant 1.5.2 | |||||
*/ | |||||
public void setFileMode(String octalString) { | |||||
fileModeHasBeenSet = true; | |||||
this.fileMode = | |||||
UnixStat.FILE_FLAG | Integer.parseInt(octalString, 8); | |||||
} | |||||
/** | |||||
* Get the mode of the zip fileset | |||||
* @param p the project to use | |||||
* @return the mode | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public int getFileMode(Project p) { | |||||
if (isReference()) { | |||||
return ((ZipFileSet) getRef(p)).getFileMode(p); | |||||
} | |||||
return fileMode; | |||||
} | |||||
/** | |||||
* @since Ant 1.5.2 | |||||
* @deprecated | |||||
*/ | |||||
public int getFileMode() { | |||||
return fileMode; | |||||
} | |||||
/** | |||||
* Whether the user has specified the mode explicitly. | |||||
* @return true if it has been set | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public boolean hasFileModeBeenSet() { | |||||
if (isReference()) { | |||||
return ((ZipFileSet) getRef(getProject())).hasFileModeBeenSet(); | |||||
} | |||||
return fileModeHasBeenSet; | |||||
} | |||||
/** | |||||
* A 3 digit octal string, specify the user, group and | |||||
* other modes in the standard Unix fashion; | |||||
* optional, default=0755 | |||||
* @param octalString a <code>String</code> value | |||||
* | |||||
* @since Ant 1.5.2 | |||||
*/ | |||||
public void setDirMode(String octalString) { | |||||
dirModeHasBeenSet = true; | |||||
this.dirMode = | |||||
UnixStat.DIR_FLAG | Integer.parseInt(octalString, 8); | |||||
} | |||||
/** | |||||
* Get the dir mode of the zip fileset | |||||
* @param p the project to use | |||||
* @return the mode | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public int getDirMode(Project p) { | |||||
if (isReference()) { | |||||
return ((ZipFileSet) getRef(p)).getDirMode(p); | |||||
} | |||||
return dirMode; | |||||
} | |||||
/** | |||||
* @since Ant 1.5.2 | |||||
* @deprecated | |||||
*/ | |||||
public int getDirMode() { | |||||
return dirMode; | |||||
} | |||||
/** | |||||
* Whether the user has specified the mode explicitly. | |||||
* | |||||
* @return true if it has been set | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public boolean hasDirModeBeenSet() { | |||||
if (isReference()) { | |||||
return ((ZipFileSet) getRef(getProject())).hasDirModeBeenSet(); | |||||
} | |||||
return dirModeHasBeenSet; | |||||
} | |||||
/** | /** | ||||
* A ZipFileset accepts another ZipFileSet or a FileSet as reference | * A ZipFileset accepts another ZipFileSet or a FileSet as reference | ||||
* FileSets are often used by the war task for the lib attribute | * FileSets are often used by the war task for the lib attribute | ||||
@@ -410,12 +97,7 @@ public class ZipFileSet extends FileSet { | |||||
return (AbstractFileSet) o; | return (AbstractFileSet) o; | ||||
} else if (o instanceof FileSet) { | } else if (o instanceof FileSet) { | ||||
ZipFileSet zfs = new ZipFileSet((FileSet) o); | ZipFileSet zfs = new ZipFileSet((FileSet) o); | ||||
zfs.setPrefix(prefix); | |||||
zfs.setFullpath(fullpath); | |||||
zfs.fileModeHasBeenSet = fileModeHasBeenSet; | |||||
zfs.fileMode = fileMode; | |||||
zfs.dirModeHasBeenSet = dirModeHasBeenSet; | |||||
zfs.dirMode = dirMode; | |||||
configureFileSet(zfs); | |||||
return zfs; | return zfs; | ||||
} else { | } else { | ||||
String msg = getRefid().getRefId() + " doesn\'t denote a zipfileset or a fileset"; | String msg = getRefid().getRefId() + " doesn\'t denote a zipfileset or a fileset"; | ||||
@@ -427,7 +109,6 @@ public class ZipFileSet extends FileSet { | |||||
* Return a ZipFileSet that has the same properties | * Return a ZipFileSet that has the same properties | ||||
* as this one. | * as this one. | ||||
* @return the cloned zipFileSet | * @return the cloned zipFileSet | ||||
* @since Ant 1.6 | |||||
*/ | */ | ||||
public Object clone() { | public Object clone() { | ||||
if (isReference()) { | if (isReference()) { | ||||
@@ -19,264 +19,50 @@ package org.apache.tools.ant.types; | |||||
import java.io.File; | import java.io.File; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.util.Set; | |||||
import java.util.TreeMap; | |||||
import java.util.Iterator; | |||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
import java.util.Map; | |||||
import java.util.zip.ZipException; | import java.util.zip.ZipException; | ||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.DirectoryScanner; | |||||
import org.apache.tools.ant.types.resources.FileResource; | |||||
import org.apache.tools.ant.types.resources.ZipResource; | import org.apache.tools.ant.types.resources.ZipResource; | ||||
import org.apache.tools.ant.types.resources.FileResourceIterator; | |||||
import org.apache.tools.zip.ZipEntry; | import org.apache.tools.zip.ZipEntry; | ||||
import org.apache.tools.zip.ZipFile; | import org.apache.tools.zip.ZipFile; | ||||
/** | /** | ||||
* 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 | |||||
* the matching Zip entries. | |||||
* | |||||
* Scans zip archives for resources. | |||||
*/ | */ | ||||
public class ZipScanner extends DirectoryScanner { | |||||
/** | |||||
* The zip file which should be scanned. | |||||
*/ | |||||
protected File srcFile; | |||||
/** | |||||
* to record the last scanned zip file with its modification date | |||||
*/ | |||||
private Resource lastScannedResource; | |||||
/** | |||||
* record list of all file zip entries | |||||
*/ | |||||
private TreeMap fileEntries = new TreeMap(); | |||||
/** | |||||
* record list of all directory zip entries | |||||
*/ | |||||
private TreeMap dirEntries = new TreeMap(); | |||||
/** | |||||
* record list of matching file zip entries | |||||
*/ | |||||
private TreeMap matchFileEntries = new TreeMap(); | |||||
/** | |||||
* record list of matching directory zip entries | |||||
*/ | |||||
private TreeMap matchDirEntries = new TreeMap(); | |||||
/** | |||||
* encoding of file names. | |||||
* | |||||
* @since Ant 1.6 | |||||
*/ | |||||
private String encoding; | |||||
/** | |||||
* Don't scan when we have no zipfile. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public void scan() { | |||||
if (srcFile == null) { | |||||
return; | |||||
} | |||||
super.scan(); | |||||
} | |||||
/** | |||||
* 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(File srcFile) { | |||||
this.srcFile = srcFile; | |||||
} | |||||
/** | |||||
* Sets encoding of file names. | |||||
* @param encoding the encoding format | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void setEncoding(String encoding) { | |||||
this.encoding = encoding; | |||||
} | |||||
/** | |||||
* Returns the names of the files which matched at least one of the | |||||
* include patterns and none of the exclude patterns. | |||||
* The names are relative to the base directory. | |||||
* | |||||
* @return the names of the files which matched at least one of the | |||||
* include patterns and none of the exclude patterns. | |||||
*/ | |||||
public String[] getIncludedFiles() { | |||||
if (srcFile == null) { | |||||
return super.getIncludedFiles(); | |||||
} | |||||
scanme(); | |||||
Set s = matchFileEntries.keySet(); | |||||
return (String[]) (s.toArray(new String[s.size()])); | |||||
} | |||||
/** | |||||
* Override parent implementation. | |||||
* @return count of included files. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public int getIncludedFilesCount() { | |||||
if (srcFile == null) { | |||||
return super.getIncludedFilesCount(); | |||||
} | |||||
scanme(); | |||||
return matchFileEntries.size(); | |||||
} | |||||
/** | |||||
* Returns the names of the directories which matched at least one of the | |||||
* include patterns and none of the exclude patterns. | |||||
* The names are relative to the base directory. | |||||
* | |||||
* @return the names of the directories which matched at least one of the | |||||
* include patterns and none of the exclude patterns. | |||||
*/ | |||||
public String[] getIncludedDirectories() { | |||||
if (srcFile == null) { | |||||
return super.getIncludedDirectories(); | |||||
} | |||||
scanme(); | |||||
Set s = matchDirEntries.keySet(); | |||||
return (String[]) (s.toArray(new String[s.size()])); | |||||
} | |||||
/** | |||||
* Override parent implementation. | |||||
* @return count of included directories. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public int getIncludedDirsCount() { | |||||
if (srcFile == null) { | |||||
return super.getIncludedDirsCount(); | |||||
} | |||||
scanme(); | |||||
return matchDirEntries.size(); | |||||
} | |||||
/** | |||||
* Get the set of Resources that represent files. | |||||
* @return an Iterator of Resources. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
/* package-private for now */ Iterator getResourceFiles() { | |||||
if (srcFile == null) { | |||||
return new FileResourceIterator(getBasedir(), getIncludedFiles()); | |||||
} | |||||
scanme(); | |||||
return matchFileEntries.values().iterator(); | |||||
} | |||||
/** | |||||
* Get the set of Resources that represent directories. | |||||
* @return an Iterator of Resources. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
/* package-private for now */ Iterator getResourceDirectories() { | |||||
if (srcFile == null) { | |||||
return new FileResourceIterator(getBasedir(), getIncludedDirectories()); | |||||
} | |||||
scanme(); | |||||
return matchDirEntries.values().iterator(); | |||||
} | |||||
/** | |||||
* 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]; | |||||
} | |||||
} | |||||
public class ZipScanner extends ArchiveScanner { | |||||
/** | /** | ||||
* Matches a jar entry against the includes/excludes list, | |||||
* normalizing the path separator. | |||||
* | |||||
* @param path the (non-null) path name to test for inclusion | |||||
* Fills the file and directory maps with resources read from the | |||||
* archive. | |||||
* | * | ||||
* @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); | |||||
} | |||||
/** | |||||
* Get the named Resource. | |||||
* @param name path name of the file sought in the archive | |||||
* @return the resource | |||||
* @since Ant 1.5.2 | |||||
*/ | |||||
public Resource getResource(String name) { | |||||
if (srcFile == null) { | |||||
return super.getResource(name); | |||||
} | |||||
if (name.equals("")) { | |||||
// special case in ZIPs, we do not want this thing included | |||||
return new Resource("", true, Long.MAX_VALUE, true); | |||||
} | |||||
// first check if the archive needs to be scanned again | |||||
scanme(); | |||||
if (fileEntries.containsKey(name)) { | |||||
return (Resource) fileEntries.get(name); | |||||
} | |||||
name = trimSeparator(name); | |||||
if (dirEntries.containsKey(name)) { | |||||
return (Resource) dirEntries.get(name); | |||||
} | |||||
return new Resource(name); | |||||
} | |||||
/** | |||||
* if the datetime of the archive did not change since | |||||
* lastScannedResource was initialized returns immediately else if | |||||
* the archive has not been scanned yet, then all the zip entries | |||||
* are put into the appropriate tables. | |||||
*/ | |||||
private void scanme() { | |||||
//do not use a FileResource b/c it pulls File info from the filesystem: | |||||
Resource thisresource = new Resource(srcFile.getAbsolutePath(), | |||||
srcFile.exists(), | |||||
srcFile.lastModified()); | |||||
// spare scanning again and again | |||||
if (lastScannedResource != null | |||||
&& lastScannedResource.getName().equals(thisresource.getName()) | |||||
&& lastScannedResource.getLastModified() | |||||
== thisresource.getLastModified()) { | |||||
return; | |||||
} | |||||
init(); | |||||
* @param src the archive to scan. | |||||
* @param encoding encoding used to encode file names inside the archive. | |||||
* @param fileEntries Map (name to resource) of non-directory | |||||
* resources found inside the archive. | |||||
* @param matchFileEntries Map (name to resource) of non-directory | |||||
* resources found inside the archive that matched all include | |||||
* patterns and didn't match any exclude patterns. | |||||
* @param dirEntries Map (name to resource) of directory | |||||
* resources found inside the archive. | |||||
* @param matchDirEntries Map (name to resource) of directory | |||||
* resources found inside the archive that matched all include | |||||
* patterns and didn't match any exclude patterns. | |||||
*/ | |||||
protected void fillMapsFromArchive(Resource src, String encoding, | |||||
Map fileEntries, Map matchFileEntries, | |||||
Map dirEntries, Map matchDirEntries) { | |||||
ZipEntry entry = null; | ZipEntry entry = null; | ||||
ZipFile zf = null; | ZipFile zf = null; | ||||
fileEntries.clear(); | |||||
dirEntries.clear(); | |||||
matchFileEntries.clear(); | |||||
matchDirEntries.clear(); | |||||
File srcFile = null; | |||||
if (src instanceof FileResource) { | |||||
srcFile = ((FileResource) src).getFile(); | |||||
} else { | |||||
throw new BuildException("only file resources are supported"); | |||||
} | |||||
try { | try { | ||||
try { | try { | ||||
@@ -313,12 +99,5 @@ public class ZipScanner extends DirectoryScanner { | |||||
} | } | ||||
} | } | ||||
} | } | ||||
// record data about the last scanned resource | |||||
lastScannedResource = thisresource; | |||||
} | } | ||||
private static String trimSeparator(String s) { | |||||
return s.endsWith("/") ? s.substring(0, s.length() - 1) : s; | |||||
} | |||||
} | } |
@@ -55,6 +55,7 @@ intersect=org.apache.tools.ant.types.resources.Intersect | |||||
sort=org.apache.tools.ant.types.resources.Sort | sort=org.apache.tools.ant.types.resources.Sort | ||||
resources=org.apache.tools.ant.types.resources.Resources | resources=org.apache.tools.ant.types.resources.Resources | ||||
first=org.apache.tools.ant.types.resources.First | first=org.apache.tools.ant.types.resources.First | ||||
tarfileset=org.apache.tools.ant.types.TarFileSet | |||||
#Resources (single-element ResourceCollections): | #Resources (single-element ResourceCollections): | ||||
resource=org.apache.tools.ant.types.Resource | resource=org.apache.tools.ant.types.Resource | ||||
@@ -63,3 +64,6 @@ url=org.apache.tools.ant.types.resources.URLResource | |||||
string=org.apache.tools.ant.types.resources.StringResource | string=org.apache.tools.ant.types.resources.StringResource | ||||
zipentry=org.apache.tools.ant.types.resources.ZipResource | zipentry=org.apache.tools.ant.types.resources.ZipResource | ||||
propertyresource=org.apache.tools.ant.types.resources.PropertyResource | propertyresource=org.apache.tools.ant.types.resources.PropertyResource | ||||
tarentry=org.apache.tools.ant.types.resources.TarResource | |||||
gzipresource=org.apache.tools.ant.types.resources.GZipResource | |||||
bzip2resource=org.apache.tools.ant.types.resources.BZip2Resource |
@@ -0,0 +1,244 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types.resources; | |||||
import java.io.File; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.types.Resource; | |||||
import org.apache.tools.ant.types.ResourceCollection; | |||||
import org.apache.tools.ant.types.Reference; | |||||
/** | |||||
* A Resource representation of an entry inside an archive. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public abstract class ArchiveResource extends Resource { | |||||
private static final int NULL_ARCHIVE | |||||
= Resource.getMagicNumber("null archive".getBytes()); | |||||
private Resource archive; | |||||
private boolean haveEntry = false; | |||||
/** | |||||
* Default constructor. | |||||
*/ | |||||
public ArchiveResource() { | |||||
} | |||||
/** | |||||
* Construct a ArchiveResource representing the specified | |||||
* entry in the specified archive. | |||||
* @param a the archive as File. | |||||
*/ | |||||
public ArchiveResource(File a) { | |||||
this(a, false); | |||||
} | |||||
/** | |||||
* Construct a ArchiveResource representing the specified | |||||
* entry in the specified archive. | |||||
* @param a the archive as File. | |||||
* @param withEntry if the entry has been specified. | |||||
*/ | |||||
public ArchiveResource(File a, boolean withEntry) { | |||||
setArchive(a); | |||||
haveEntry = withEntry; | |||||
} | |||||
/** | |||||
* Construct a ArchiveResource representing the specified | |||||
* entry in the specified archive. | |||||
* @param a the archive as Resource. | |||||
* @param withEntry if the entry has been specified. | |||||
*/ | |||||
public ArchiveResource(Resource a, boolean withEntry) { | |||||
addConfigured(a); | |||||
haveEntry = withEntry; | |||||
} | |||||
/** | |||||
* Set the archive that holds this Resource. | |||||
* @param a the archive as a File. | |||||
*/ | |||||
public void setArchive(File a) { | |||||
checkAttributesAllowed(); | |||||
archive = new FileResource(a); | |||||
} | |||||
/** | |||||
* Sets the archive that holds this as a single element Resource | |||||
* collection. | |||||
* @param a the archive as a single element Resource collection. | |||||
*/ | |||||
public void addConfigured(ResourceCollection a) { | |||||
checkChildrenAllowed(); | |||||
if (archive != null) { | |||||
throw new BuildException("you must not specify more than one" | |||||
+ " archive"); | |||||
} | |||||
if (a.size() != 1) { | |||||
throw new BuildException("only single argument resource collections" | |||||
+ " are supported as archives"); | |||||
} | |||||
archive = (Resource) a.iterator().next(); | |||||
} | |||||
/** | |||||
* Get the archive that holds this Resource. | |||||
* @return the archive as a Resource. | |||||
*/ | |||||
public Resource getArchive() { | |||||
return isReference() | |||||
? ((ArchiveResource) getCheckedRef()).getArchive() : archive; | |||||
} | |||||
/** | |||||
* Get the last modified date of this Resource. | |||||
* @return the last modification date. | |||||
*/ | |||||
public long getLastModified() { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).getLastModified(); | |||||
} | |||||
checkEntry(); | |||||
return super.getLastModified(); | |||||
} | |||||
/** | |||||
* Get the size of this Resource. | |||||
* @return the long size of this Resource. | |||||
*/ | |||||
public long getSize() { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).getSize(); | |||||
} | |||||
checkEntry(); | |||||
return super.getSize(); | |||||
} | |||||
/** | |||||
* Learn whether this Resource represents a directory. | |||||
* @return boolean flag indicating whether the entry is a directory. | |||||
*/ | |||||
public boolean isDirectory() { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).isDirectory(); | |||||
} | |||||
checkEntry(); | |||||
return super.isDirectory(); | |||||
} | |||||
/** | |||||
* Find out whether this Resource represents an existing Resource. | |||||
* @return boolean existence flag. | |||||
*/ | |||||
public boolean isExists() { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).isExists(); | |||||
} | |||||
checkEntry(); | |||||
return super.isExists(); | |||||
} | |||||
/** | |||||
* Overrides the super version. | |||||
* @param r the Reference to set. | |||||
*/ | |||||
public void setRefid(Reference r) { | |||||
if (archive != null) { | |||||
throw tooManyAttributes(); | |||||
} | |||||
super.setRefid(r); | |||||
} | |||||
/** | |||||
* Compare this ArchiveResource to another Resource. | |||||
* @param another the other Resource against which to compare. | |||||
* @return a negative integer, zero, or a positive integer as this Resource | |||||
* is less than, equal to, or greater than the specified Resource. | |||||
*/ | |||||
public int compareTo(Object another) { | |||||
return this.equals(another) ? 0 : super.compareTo(another); | |||||
} | |||||
/** | |||||
* Compare another Object to this ArchiveResource for equality. | |||||
* @param another the other Object to compare. | |||||
* @return true if another is a Resource representing | |||||
* the same entry in the same archive. | |||||
*/ | |||||
public boolean equals(Object another) { | |||||
if (this == another) { | |||||
return true; | |||||
} | |||||
if (isReference()) { | |||||
return getCheckedRef().equals(another); | |||||
} | |||||
if (!(another.getClass().equals(getClass()))) { | |||||
return false; | |||||
} | |||||
ArchiveResource r = (ArchiveResource) another; | |||||
return getArchive().equals(r.getArchive()) | |||||
&& getName().equals(r.getName()); | |||||
} | |||||
/** | |||||
* Get the hash code for this Resource. | |||||
* @return hash code as int. | |||||
*/ | |||||
public int hashCode() { | |||||
return super.hashCode() | |||||
* (getArchive() == null ? NULL_ARCHIVE : getArchive().hashCode()); | |||||
} | |||||
/** | |||||
* Format this Resource as a String. | |||||
* @return String representatation of this Resource. | |||||
*/ | |||||
public String toString() { | |||||
return isReference() ? getCheckedRef().toString() | |||||
: getArchive().toString() + ':' + getName(); | |||||
} | |||||
private synchronized void checkEntry() throws BuildException { | |||||
if (haveEntry) { | |||||
return; | |||||
} | |||||
String name = getName(); | |||||
if (name == null) { | |||||
throw new BuildException("entry name not set"); | |||||
} | |||||
Resource r = getArchive(); | |||||
if (r == null) { | |||||
throw new BuildException("archive attribute not set"); | |||||
} | |||||
if (!r.isExists()) { | |||||
throw new BuildException(r.toString() + " does not exist."); | |||||
} | |||||
if (r.isDirectory()) { | |||||
throw new BuildException(r + " denotes a directory."); | |||||
} | |||||
fetchEntry(); | |||||
haveEntry = true; | |||||
} | |||||
/** | |||||
* fetches information from the named entry inside the archive. | |||||
*/ | |||||
protected abstract void fetchEntry(); | |||||
} |
@@ -0,0 +1,61 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types.resources; | |||||
import java.io.InputStream; | |||||
import java.io.IOException; | |||||
import java.io.OutputStream; | |||||
import org.apache.tools.bzip2.CBZip2InputStream; | |||||
import org.apache.tools.bzip2.CBZip2OutputStream; | |||||
/** | |||||
* A Bzip2 compressed resource. | |||||
* | |||||
* <p>Wraps around another resource, delegates all quries to that | |||||
* other resource but uncompresses/compresses streams on the fly.</p> | |||||
* | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public class BZip2Resource extends CompressedResource { | |||||
private static final char[] MAGIC = new char[] {'B', 'Z'}; | |||||
public BZip2Resource() { | |||||
} | |||||
public BZip2Resource(org.apache.tools.ant.types.ResourceCollection other) { | |||||
super(other); | |||||
} | |||||
protected InputStream wrapStream(InputStream in) throws IOException { | |||||
for (int i = 0; i < MAGIC.length; i++) { | |||||
if (in.read() != MAGIC[i]) { | |||||
throw new IOException("Invalid bz2 stream."); | |||||
} | |||||
} | |||||
return new CBZip2InputStream(in); | |||||
} | |||||
protected OutputStream wrapStream(OutputStream out) throws IOException { | |||||
for (int i = 0; i < MAGIC.length; i++) { | |||||
out.write(MAGIC[i]); | |||||
} | |||||
return new CBZip2OutputStream(out); | |||||
} | |||||
protected String getCompressionName() { | |||||
return "Bzip2"; | |||||
} | |||||
} |
@@ -0,0 +1,244 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types.resources; | |||||
import java.io.InputStream; | |||||
import java.io.IOException; | |||||
import java.io.OutputStream; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.types.DataType; | |||||
import org.apache.tools.ant.types.Resource; | |||||
import org.apache.tools.ant.types.Reference; | |||||
import org.apache.tools.ant.types.ResourceCollection; | |||||
/** | |||||
* A compressed resource. | |||||
* | |||||
* <p>Wraps around another resource, delegates all queries to that | |||||
* other resource but uncompresses/compresses streams on the fly.</p> | |||||
* | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public abstract class CompressedResource extends Resource | |||||
implements ResourceCollection { | |||||
private Resource resource; | |||||
public CompressedResource() { | |||||
} | |||||
public CompressedResource(ResourceCollection other) { | |||||
addConfigured(other); | |||||
} | |||||
/** | |||||
* Sets the resource to wrap using a single-element collection. | |||||
* @param a the resource to wrap as a single element Resource collection. | |||||
*/ | |||||
public void addConfigured(ResourceCollection a) { | |||||
checkChildrenAllowed(); | |||||
if (resource != null) { | |||||
throw new BuildException("you must not specify more than one" | |||||
+ " resource"); | |||||
} | |||||
if (a.size() != 1) { | |||||
throw new BuildException("only single argument resource collections" | |||||
+ " are supported"); | |||||
} | |||||
resource = (Resource) a.iterator().next(); | |||||
} | |||||
public String getName() { | |||||
return getResource().getName(); | |||||
} | |||||
public void setName(String name) { | |||||
throw new BuildException("you can't change the name of a compressed" | |||||
+ " resource"); | |||||
} | |||||
/** | |||||
* The exists attribute tells whether a file exists. | |||||
* @return true if this resource exists. | |||||
*/ | |||||
public boolean isExists() { | |||||
return getResource().isExists(); | |||||
} | |||||
/** | |||||
* Set the exists attribute. | |||||
* @param exists if true, this resource exists. | |||||
*/ | |||||
public void setExists(boolean exists) { | |||||
throw new BuildException("you can't change the exists state of a " | |||||
+ " compressed resource"); | |||||
} | |||||
/** | |||||
* Tells the modification time in milliseconds since 01.01.1970 . | |||||
* | |||||
* @return 0 if the resource does not exist to mirror the behavior | |||||
* of {@link java.io.File File}. | |||||
*/ | |||||
public long getLastModified() { | |||||
return getResource().getLastModified(); | |||||
} | |||||
public void setLastModified(long lastmodified) { | |||||
throw new BuildException("you can't change the timestamp of a " | |||||
+ " compressed resource"); | |||||
} | |||||
/** | |||||
* Tells if the resource is a directory. | |||||
* @return boolean flag indicating if the resource is a directory. | |||||
*/ | |||||
public boolean isDirectory() { | |||||
return getResource().isDirectory(); | |||||
} | |||||
public void setDirectory(boolean directory) { | |||||
throw new BuildException("you can't change the directory state of a " | |||||
+ " compressed resource"); | |||||
} | |||||
/** | |||||
* Get the size of this Resource. | |||||
* @return the size, as a long, 0 if the Resource does not exist (for | |||||
* compatibility with java.io.File), or UNKNOWN_SIZE if not known. | |||||
*/ | |||||
public long getSize() { | |||||
return getResource().getSize(); | |||||
} | |||||
public void setSize(long size) { | |||||
throw new BuildException("you can't change the size of a " | |||||
+ " compressed resource"); | |||||
} | |||||
/** | |||||
* Delegates to a comparison of names. | |||||
* @param other the object to compare to. | |||||
* @return a negative integer, zero, or a positive integer as this Resource | |||||
* is less than, equal to, or greater than the specified Resource. | |||||
*/ | |||||
public int compareTo(Object other) { | |||||
return getResource().compareTo(other); | |||||
} | |||||
/** | |||||
* Get the hash code for this Resource. | |||||
* @return hash code as int. | |||||
*/ | |||||
public int hashCode() { | |||||
return getResource().hashCode(); | |||||
} | |||||
/** | |||||
* Get an InputStream for the Resource. | |||||
* @return an InputStream containing this Resource's content. | |||||
* @throws IOException if unable to provide the content of this | |||||
* Resource as a stream. | |||||
* @throws UnsupportedOperationException if InputStreams are not | |||||
* supported for this Resource type. | |||||
*/ | |||||
public InputStream getInputStream() throws IOException { | |||||
InputStream in = getResource().getInputStream(); | |||||
if (in != null) { | |||||
in = wrapStream(in); | |||||
} | |||||
return in; | |||||
} | |||||
/** | |||||
* Get an OutputStream for the Resource. | |||||
* @return an OutputStream to which content can be written. | |||||
* @throws IOException if unable to provide the content of this | |||||
* Resource as a stream. | |||||
* @throws UnsupportedOperationException if OutputStreams are not | |||||
* supported for this Resource type. | |||||
*/ | |||||
public OutputStream getOutputStream() throws IOException { | |||||
OutputStream out = getResource().getOutputStream(); | |||||
if (out != null) { | |||||
out = wrapStream(out); | |||||
} | |||||
return out; | |||||
} | |||||
/** | |||||
* Fulfill the ResourceCollection contract. | |||||
* @return whether this Resource is a FileResource. | |||||
*/ | |||||
public boolean isFilesystemOnly() { | |||||
return false; | |||||
} | |||||
/** | |||||
* Get the string representation of this Resource. | |||||
* @return this Resource formatted as a String. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public String toString() { | |||||
return getCompressionName() + " compressed " | |||||
+ getResource().toString(); | |||||
} | |||||
/** | |||||
* Overrides the base version. | |||||
* @param r the Reference to set. | |||||
*/ | |||||
public void setRefid(Reference r) { | |||||
if (resource != null) { | |||||
throw noChildrenAllowed(); | |||||
} | |||||
super.setRefid(r); | |||||
} | |||||
/** | |||||
* Is supposed to wrap the stream to allow decompression on the fly. | |||||
* | |||||
* @param in InputStream to wrap, will never be null. | |||||
*/ | |||||
protected abstract InputStream wrapStream(InputStream in) | |||||
throws IOException; | |||||
/** | |||||
* Is supposed to wrap the stream to allow compression on the fly. | |||||
* | |||||
* @param out OutputStream to wrap, will never be null. | |||||
*/ | |||||
protected abstract OutputStream wrapStream(OutputStream out) | |||||
throws IOException; | |||||
/** | |||||
* @return the name of the compression method. | |||||
*/ | |||||
protected abstract String getCompressionName(); | |||||
private Resource getResource() { | |||||
if (isReference()) { | |||||
return (Resource) getCheckedRef(); | |||||
} else if (resource == null) { | |||||
throw new BuildException("no resource specified"); | |||||
} | |||||
return resource; | |||||
} | |||||
} |
@@ -0,0 +1,51 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types.resources; | |||||
import java.io.InputStream; | |||||
import java.io.IOException; | |||||
import java.io.OutputStream; | |||||
import java.util.zip.GZIPInputStream; | |||||
import java.util.zip.GZIPOutputStream; | |||||
/** | |||||
* A GZip compressed resource. | |||||
* | |||||
* <p>Wraps around another resource, delegates all quries to that | |||||
* other resource but uncompresses/compresses streams on the fly.</p> | |||||
* | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public class GZipResource extends CompressedResource { | |||||
public GZipResource() { | |||||
} | |||||
public GZipResource(org.apache.tools.ant.types.ResourceCollection other) { | |||||
super(other); | |||||
} | |||||
protected InputStream wrapStream(InputStream in) throws IOException { | |||||
return new GZIPInputStream(in); | |||||
} | |||||
protected OutputStream wrapStream(OutputStream out) throws IOException { | |||||
return new GZIPOutputStream(out); | |||||
} | |||||
protected String getCompressionName() { | |||||
return "GZip"; | |||||
} | |||||
} |
@@ -0,0 +1,145 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types.resources; | |||||
import java.io.File; | |||||
import java.io.InputStream; | |||||
import java.io.OutputStream; | |||||
import java.io.IOException; | |||||
import java.io.FilterInputStream; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.types.Resource; | |||||
import org.apache.tools.ant.types.Reference; | |||||
import org.apache.tools.ant.util.FileUtils; | |||||
import org.apache.tools.tar.TarEntry; | |||||
import org.apache.tools.tar.TarInputStream; | |||||
/** | |||||
* A Resource representation of an entry in a tar archive. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public class TarResource extends ArchiveResource { | |||||
/** | |||||
* Default constructor. | |||||
*/ | |||||
public TarResource() { | |||||
} | |||||
/** | |||||
* Construct a TarResource representing the specified | |||||
* entry in the specified archive. | |||||
* @param a the archive as File. | |||||
* @param e the TarEntry. | |||||
*/ | |||||
public TarResource(File a, TarEntry e) { | |||||
super(a, true); | |||||
setEntry(e); | |||||
} | |||||
/** | |||||
* Construct a TarResource representing the specified | |||||
* entry in the specified archive. | |||||
* @param a the archive as Resource. | |||||
* @param e the TarEntry. | |||||
*/ | |||||
public TarResource(Resource a, TarEntry e) { | |||||
super(a, true); | |||||
setEntry(e); | |||||
} | |||||
/** | |||||
* Return an InputStream for reading the contents of this Resource. | |||||
* @return an InputStream object. | |||||
* @throws IOException if the tar file cannot be opened, | |||||
* or the entry cannot be read. | |||||
*/ | |||||
public InputStream getInputStream() throws IOException { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).getInputStream(); | |||||
} | |||||
Resource archive = getArchive(); | |||||
final TarInputStream i = new TarInputStream(archive.getInputStream()); | |||||
TarEntry te = null; | |||||
while ((te = i.getNextEntry()) != null) { | |||||
if (te.getName().equals(getName())) { | |||||
return i; | |||||
} | |||||
} | |||||
FileUtils.close(i); | |||||
throw new BuildException("no entry " + getName() + " in " | |||||
+ getArchive()); | |||||
} | |||||
/** | |||||
* Get an OutputStream for the Resource. | |||||
* @return an OutputStream to which content can be written. | |||||
* @throws IOException if unable to provide the content of this | |||||
* Resource as a stream. | |||||
* @throws UnsupportedOperationException if OutputStreams are not | |||||
* supported for this Resource type. | |||||
*/ | |||||
public OutputStream getOutputStream() throws IOException { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).getOutputStream(); | |||||
} | |||||
throw new UnsupportedOperationException( | |||||
"Use the tar task for tar output."); | |||||
} | |||||
/** | |||||
* fetches information from the named entry inside the archive. | |||||
*/ | |||||
protected void fetchEntry() { | |||||
Resource archive = getArchive(); | |||||
TarInputStream i = null; | |||||
try { | |||||
i = new TarInputStream(archive.getInputStream()); | |||||
TarEntry te = null; | |||||
while ((te = i.getNextEntry()) != null) { | |||||
if (te.getName().equals(getName())) { | |||||
setEntry(te); | |||||
return; | |||||
} | |||||
} | |||||
} catch (IOException e) { | |||||
log(e.getMessage(), Project.MSG_DEBUG); | |||||
throw new BuildException(e); | |||||
} finally { | |||||
if (i != null) { | |||||
FileUtils.close(i); | |||||
} | |||||
} | |||||
setEntry(null); | |||||
} | |||||
private void setEntry(TarEntry e) { | |||||
if (e == null) { | |||||
super.setExists(false); | |||||
return; | |||||
} | |||||
super.setName(e.getName()); | |||||
super.setExists(true); | |||||
super.setLastModified(e.getModTime().getTime()); | |||||
super.setDirectory(e.isDirectory()); | |||||
super.setSize(e.getSize()); | |||||
} | |||||
} |
@@ -25,6 +25,7 @@ import java.io.FilterInputStream; | |||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.types.Resource; | import org.apache.tools.ant.types.Resource; | ||||
import org.apache.tools.ant.types.ResourceCollection; | |||||
import org.apache.tools.ant.types.Reference; | import org.apache.tools.ant.types.Reference; | ||||
import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
import org.apache.tools.zip.ZipFile; | import org.apache.tools.zip.ZipFile; | ||||
@@ -34,13 +35,9 @@ import org.apache.tools.zip.ZipEntry; | |||||
* A Resource representation of an entry in a zipfile. | * A Resource representation of an entry in a zipfile. | ||||
* @since Ant 1.7 | * @since Ant 1.7 | ||||
*/ | */ | ||||
public class ZipResource extends Resource { | |||||
private static final int NULL_ZIPFILE | |||||
= Resource.getMagicNumber("null zipfile".getBytes()); | |||||
public class ZipResource extends ArchiveResource { | |||||
private String encoding; | private String encoding; | ||||
private File zipfile; | |||||
private boolean haveEntry = false; | |||||
/** | /** | ||||
* Default constructor. | * Default constructor. | ||||
@@ -56,9 +53,9 @@ public class ZipResource extends Resource { | |||||
* @param e the ZipEntry. | * @param e the ZipEntry. | ||||
*/ | */ | ||||
public ZipResource(File z, String enc, ZipEntry e) { | public ZipResource(File z, String enc, ZipEntry e) { | ||||
setEntry(e); | |||||
setZipfile(z); | |||||
super(z, true); | |||||
setEncoding(enc); | setEncoding(enc); | ||||
setEntry(e); | |||||
} | } | ||||
/** | /** | ||||
@@ -66,8 +63,7 @@ public class ZipResource extends Resource { | |||||
* @param z the zipfile as a File. | * @param z the zipfile as a File. | ||||
*/ | */ | ||||
public void setZipfile(File z) { | public void setZipfile(File z) { | ||||
checkAttributesAllowed(); | |||||
zipfile = z; | |||||
setArchive(z); | |||||
} | } | ||||
/** | /** | ||||
@@ -75,8 +71,20 @@ public class ZipResource extends Resource { | |||||
* @return the zipfile as a File. | * @return the zipfile as a File. | ||||
*/ | */ | ||||
public File getZipfile() { | public File getZipfile() { | ||||
return isReference() | |||||
? ((ZipResource) getCheckedRef()).getZipfile() : zipfile; | |||||
FileResource r = (FileResource) getArchive(); | |||||
return r.getFile(); | |||||
} | |||||
/** | |||||
* Sets the archive that holds this as a single element Resource | |||||
* collection. | |||||
* @param a the archive as a single element Resource collection. | |||||
*/ | |||||
public void addConfigured(ResourceCollection a) { | |||||
super.addConfigured(a); | |||||
if (!a.isFilesystemOnly()) { | |||||
throw new BuildException("only filesystem resources are supported"); | |||||
} | |||||
} | } | ||||
/** | /** | ||||
@@ -97,60 +105,12 @@ public class ZipResource extends Resource { | |||||
? ((ZipResource) getCheckedRef()).getEncoding() : encoding; | ? ((ZipResource) getCheckedRef()).getEncoding() : encoding; | ||||
} | } | ||||
/** | |||||
* Get the last modified date of this ZipResource. | |||||
* @return the last modification date. | |||||
*/ | |||||
public long getLastModified() { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).getLastModified(); | |||||
} | |||||
checkEntry(); | |||||
return super.getLastModified(); | |||||
} | |||||
/** | |||||
* Get the size of this ZipResource. | |||||
* @return the long size of this ZipResource. | |||||
*/ | |||||
public long getSize() { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).getSize(); | |||||
} | |||||
checkEntry(); | |||||
return super.getSize(); | |||||
} | |||||
/** | |||||
* Learn whether this ZipResource represents a directory. | |||||
* @return boolean flag indicating whether the zip entry is a directory. | |||||
*/ | |||||
public boolean isDirectory() { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).isDirectory(); | |||||
} | |||||
checkEntry(); | |||||
return super.isDirectory(); | |||||
} | |||||
/** | |||||
* Find out whether this ZipResource represents an existing Resource. | |||||
* @return boolean existence flag. | |||||
*/ | |||||
public boolean isExists() { | |||||
if (isReference()) { | |||||
return ((Resource) getCheckedRef()).isExists(); | |||||
} | |||||
checkEntry(); | |||||
return super.isExists(); | |||||
} | |||||
/** | /** | ||||
* Overrides the super version. | * Overrides the super version. | ||||
* @param r the Reference to set. | * @param r the Reference to set. | ||||
*/ | */ | ||||
public void setRefid(Reference r) { | public void setRefid(Reference r) { | ||||
if (encoding != null || zipfile != null) { | |||||
if (encoding != null) { | |||||
throw tooManyAttributes(); | throw tooManyAttributes(); | ||||
} | } | ||||
super.setRefid(r); | super.setRefid(r); | ||||
@@ -199,76 +159,13 @@ public class ZipResource extends Resource { | |||||
} | } | ||||
/** | /** | ||||
* Compare this ZipResource to another Resource. | |||||
* @param another the other Resource against which to compare. | |||||
* @return a negative integer, zero, or a positive integer as this ZipResource | |||||
* is less than, equal to, or greater than the specified Resource. | |||||
*/ | |||||
public int compareTo(Object another) { | |||||
return this.equals(another) ? 0 : super.compareTo(another); | |||||
} | |||||
/** | |||||
* Compare another Object to this ZipResource for equality. | |||||
* @param another the other Object to compare. | |||||
* @return true if another is a ZipResource representing | |||||
* the same entry in the same zipfile. | |||||
*/ | |||||
public boolean equals(Object another) { | |||||
if (this == another) { | |||||
return true; | |||||
} | |||||
if (isReference()) { | |||||
return getCheckedRef().equals(another); | |||||
} | |||||
if (!(another.getClass().equals(getClass()))) { | |||||
return false; | |||||
} | |||||
ZipResource r = (ZipResource) another; | |||||
return getZipfile().equals(r.getZipfile()) | |||||
&& getName().equals(r.getName()); | |||||
} | |||||
/** | |||||
* Get the hash code for this Resource. | |||||
* @return hash code as int. | |||||
* fetches information from the named entry inside the archive. | |||||
*/ | */ | ||||
public int hashCode() { | |||||
return super.hashCode() | |||||
* (getZipfile() == null ? NULL_ZIPFILE : getZipfile().hashCode()); | |||||
} | |||||
/** | |||||
* Format this ZipResource as a String. | |||||
* @return String representatation of this ZipResource. | |||||
*/ | |||||
public String toString() { | |||||
return isReference() ? getCheckedRef().toString() | |||||
: getZipfile().toString() + ':' + getName(); | |||||
} | |||||
private synchronized void checkEntry() throws BuildException { | |||||
if (haveEntry) { | |||||
return; | |||||
} | |||||
String name = getName(); | |||||
if (name == null) { | |||||
throw new BuildException("zip entry name not set"); | |||||
} | |||||
File f = getZipfile(); | |||||
if (f == null) { | |||||
throw new BuildException("zipfile attribute not set"); | |||||
} | |||||
if (!f.exists()) { | |||||
throw new BuildException(f.getAbsolutePath() + " does not exist."); | |||||
} | |||||
if (f.isDirectory()) { | |||||
throw new BuildException(f + " denotes a directory."); | |||||
} | |||||
protected void fetchEntry() { | |||||
ZipFile z = null; | ZipFile z = null; | ||||
try { | try { | ||||
z = new ZipFile(f, getEncoding()); | |||||
setEntry(z.getEntry(name)); | |||||
z = new ZipFile(getZipfile(), getEncoding()); | |||||
setEntry(z.getEntry(getName())); | |||||
} catch (IOException e) { | } catch (IOException e) { | ||||
log(e.getMessage(), Project.MSG_DEBUG); | log(e.getMessage(), Project.MSG_DEBUG); | ||||
throw new BuildException(e); | throw new BuildException(e); | ||||
@@ -283,8 +180,7 @@ public class ZipResource extends Resource { | |||||
} | } | ||||
} | } | ||||
private synchronized void setEntry(ZipEntry e) { | |||||
haveEntry = true; | |||||
private void setEntry(ZipEntry e) { | |||||
if (e == null) { | if (e == null) { | ||||
super.setExists(false); | super.setExists(false); | ||||
return; | return; | ||||
@@ -0,0 +1,118 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.Project; | |||||
import junit.framework.TestCase; | |||||
import junit.framework.AssertionFailedError; | |||||
import java.io.File; | |||||
/** | |||||
* JUnit 3 testcases for org.apache.tools.ant.types.TarFileSet. | |||||
* | |||||
* <p>This doesn't actually test much, mainly reference handling. | |||||
* | |||||
*/ | |||||
public class TarFileSetTest extends AbstractFileSetTest { | |||||
public TarFileSetTest(String name) { | |||||
super(name); | |||||
} | |||||
protected AbstractFileSet getInstance() { | |||||
return new TarFileSet(); | |||||
} | |||||
public final void testAttributes() { | |||||
TarFileSet f = (TarFileSet)getInstance(); | |||||
//check that dir and src are incompatible | |||||
f.setSrc(new File("example.tar")); | |||||
try { | |||||
f.setDir(new File("examples")); | |||||
fail("can add dir to " | |||||
+ f.getDataTypeName() | |||||
+ " when a src is already present"); | |||||
} catch (BuildException be) { | |||||
assertEquals("Cannot set both dir and src attributes",be.getMessage()); | |||||
} | |||||
f = (TarFileSet)getInstance(); | |||||
//check that dir and src are incompatible | |||||
f.setDir(new File("examples")); | |||||
try { | |||||
f.setSrc(new File("example.tar")); | |||||
fail("can add src to " | |||||
+ f.getDataTypeName() | |||||
+ " when a dir is already present"); | |||||
} catch (BuildException be) { | |||||
assertEquals("Cannot set both dir and src attributes",be.getMessage()); | |||||
} | |||||
//check that fullpath and prefix are incompatible | |||||
f = (TarFileSet)getInstance(); | |||||
f.setSrc(new File("example.tar")); | |||||
f.setPrefix("/examples"); | |||||
try { | |||||
f.setFullpath("/doc/manual/index.html"); | |||||
fail("Can add fullpath to " | |||||
+ f.getDataTypeName() | |||||
+ " when a prefix is already present"); | |||||
} catch (BuildException be) { | |||||
assertEquals("Cannot set both fullpath and prefix attributes", be.getMessage()); | |||||
} | |||||
f = (TarFileSet)getInstance(); | |||||
f.setSrc(new File("example.tar")); | |||||
f.setFullpath("/doc/manual/index.html"); | |||||
try { | |||||
f.setPrefix("/examples"); | |||||
fail("Can add prefix to " | |||||
+ f.getDataTypeName() | |||||
+ " when a fullpath is already present"); | |||||
} catch (BuildException be) { | |||||
assertEquals("Cannot set both fullpath and prefix attributes", be.getMessage()); | |||||
} | |||||
// check that reference tarfilesets cannot have specific attributes | |||||
f = (TarFileSet)getInstance(); | |||||
f.setRefid(new Reference("test")); | |||||
try { | |||||
f.setSrc(new File("example.tar")); | |||||
fail("Can add src to " | |||||
+ f.getDataTypeName() | |||||
+ " when a refid is already present"); | |||||
} catch (BuildException be) { | |||||
assertEquals("You must not specify more than one " | |||||
+ "attribute when using refid", be.getMessage()); | |||||
} | |||||
// check that a reference tarfileset gets the same attributes as the original | |||||
f = (TarFileSet)getInstance(); | |||||
f.setSrc(new File("example.tar")); | |||||
f.setPrefix("/examples"); | |||||
f.setFileMode("600"); | |||||
f.setDirMode("530"); | |||||
getProject().addReference("test",f); | |||||
TarFileSet zid=(TarFileSet)getInstance(); | |||||
zid.setRefid(new Reference("test")); | |||||
assertTrue("src attribute copied by copy constructor",zid.getSrc(getProject()).equals(f.getSrc(getProject()))); | |||||
assertTrue("prefix attribute copied by copy constructor",f.getPrefix(getProject()).equals(zid.getPrefix(getProject()))); | |||||
assertTrue("file mode attribute copied by copy constructor",f.getFileMode(getProject())==zid.getFileMode(getProject())); | |||||
assertTrue("dir mode attribute copied by copy constructor",f.getDirMode(getProject())==zid.getDirMode(getProject())); | |||||
} | |||||
} |
@@ -0,0 +1,43 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.types.resources; | |||||
import org.apache.tools.ant.BuildFileTest; | |||||
import org.apache.tools.ant.util.FileUtils; | |||||
public class TarResourceTest extends BuildFileTest { | |||||
private static final FileUtils FU = FileUtils.getFileUtils(); | |||||
public TarResourceTest(String name) { | |||||
super(name); | |||||
} | |||||
protected void setUp() throws Exception { | |||||
configureProject("src/etc/testcases/types/resources/tarentry.xml"); | |||||
} | |||||
protected void tearDown() throws Exception { | |||||
executeTarget("tearDown"); | |||||
} | |||||
public void testUncompressSource() throws java.io.IOException { | |||||
executeTarget("uncompressSource"); | |||||
assertTrue(FU.contentEquals(project.resolveFile("../../asf-logo.gif"), | |||||
project.resolveFile("testout/asf-logo.gif"))); | |||||
} | |||||
} |