git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@326643 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1231,6 +1231,10 @@ | |||
</zip> | |||
<tar longfile="gnu" | |||
destfile="${dist.base.binaries}/${dist.name}-bin.tar"> | |||
<!-- removes redundant definition of permissions, but seems to | |||
drop dirs (and to be slow) | |||
<zipfileset src="${dist.base.binaries}/${dist.name}-bin.zip"/> | |||
--> | |||
<tarfileset dir="${dist.name}/.." mode="755" username="ant" group="ant"> | |||
<include name="${dist.name}/bin/ant"/> | |||
<include name="${dist.name}/bin/antRun"/> | |||
@@ -1296,6 +1300,9 @@ | |||
</zip> | |||
<tar longfile="gnu" | |||
destfile="${dist.base.source}/${dist.name}-src.tar"> | |||
<!-- | |||
<zipfileset src="${dist.base.source}/${dist.name}-src.zip"/> | |||
--> | |||
<tarfileset dir="${dist.name}/.." mode="755" username="ant" group="ant"> | |||
<include name="${dist.name}/bootstrap.sh"/> | |||
<include name="${dist.name}/build.sh"/> | |||
@@ -18,7 +18,8 @@ defines which files, relative to the <i>basedir</i>, will be included in the | |||
archive. The tar task supports all the attributes of Fileset to refine the | |||
set of files to be included in the implicit fileset.</p> | |||
<p>In addition to the implicit fileset, the tar task supports nested filesets. These | |||
<p>In addition to the implicit fileset, the tar task supports nested | |||
resource collections and a special form of filesets. These | |||
filesets are extended to allow control over the access mode, username and groupname | |||
to be applied to the tar entries. This is useful, for example, when preparing archives for | |||
Unix systems where some files need to have execute permission.</p> | |||
@@ -110,8 +111,11 @@ or "bzip2".</p> | |||
</table> | |||
<h3>Nested Elements</h3> | |||
The tar task supports nested <a href="../CoreTypes/fileset.html">tarfileset</a> elements. These are | |||
extended Filesets which, in addition to the standard fileset elements, support three additional | |||
The tar task supports nested <a | |||
href="../CoreTypes/fileset.html">tarfileset</a> elements. These are | |||
extended <a href="../CoreTypes/tarfileset.html">TarFilesets</a> which, | |||
in addition to the standard elements, support one additional | |||
attributes | |||
<table border="1" cellpadding="2" cellspacing="0"> | |||
@@ -120,59 +124,6 @@ attributes | |||
<td valign="top"><b>Description</b></td> | |||
<td valign="top" align="center"><b>Required</b></td> | |||
</tr> | |||
<tr> | |||
<td valign="top">mode</td> | |||
<td valign="top">A 3 digit octal string, specify the user, group | |||
and other modes in the standard Unix fashion. Only applies to | |||
plain files. Default is 644.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">dirmode</td> | |||
<td valign="top">A 3 digit octal string, specify the user, group | |||
and other modes in the standard Unix fashion. Only applies to | |||
directories. Default is 755. <em>since Ant 1.6</em>.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">username</td> | |||
<td valign="top">The username for the tar entry. This is not the same as the UID. | |||
</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">group</td> | |||
<td valign="top">The groupname for the tar entry. This is not the same as the GID. | |||
</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">uid</td> | |||
<td valign="top">The user identifier (UID) for the tar entry. This is an integer value | |||
and is not the same as the username. <em>since Ant 1.6.2</em>. | |||
</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">gid</td> | |||
<td valign="top">The group identifier (GID) for the tar entry. <em>since Ant 1.6.2</em>. | |||
</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">prefix</td> | |||
<td valign="top">If the prefix attribute is set, all files in the fileset | |||
are prefixed with that path in the archive.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">fullpath</td> | |||
<td valign="top">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.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">preserveLeadingSlashes</td> | |||
<td valign="top">Indicates whether leading `/'s should | |||
@@ -181,6 +132,13 @@ attributes | |||
</tr> | |||
</table> | |||
<h4>any other resource collection</h4> | |||
<p><a href="../CoreTypes/resources.html#collection">Resource | |||
Collection</a>s are used to select groups of files to copy. To use a | |||
resource collection, the <code>todir</code> attribute must be set.</p> | |||
<p>Prior to Ant 1.7 only <code><fileset></code> has been | |||
supported as a nested element.</p> | |||
<h3>Examples</h3> | |||
<pre> | |||
<tar tarfile="${dist}/manual.tar" basedir="htdocs/manual"/> | |||
@@ -242,8 +200,10 @@ and the rest are use the default mode (read-write by owner). The first | |||
fileset selects just the executable files. The second fileset must exclude | |||
the executable files and include all others. </p> | |||
<p><strong>Note: </strong> The tar task does not ensure that a file is only selected | |||
by one fileset. If the same file is selected by more than one fileset, it will be included in the | |||
by one resource collection. If the same file is selected by more than one collection, it will be included in the | |||
tar file twice, with the same path.</p> | |||
<p><strong>Note:</strong> The patterns in the include and exclude | |||
@@ -253,6 +213,16 @@ attribute as with all other filesets. In the example above, | |||
of a directory, so <code>${dist.name}</code> is a valid path relative | |||
to <code>${dist.name}/..</code>.</p> | |||
<pre> | |||
<tar dest="release.tar.gz" compress="gzip"> | |||
<zipfileset src="release.zip"/> | |||
</tar> | |||
</pre> | |||
<p>Re-packages a ZIP archive as a GZip compressed tar archive. If | |||
Unix file permissions have been stored as part of the ZIP file, they | |||
will be retained in the resulting tar archive.</p> | |||
<hr> | |||
<p align="center">Copyright © 2000-2002,2004-2005 The Apache Software Foundation. All rights | |||
Reserved.</p> | |||
@@ -23,7 +23,7 @@ explicit use beginning in <b>Ant 1.7</b>. | |||
<ul> | |||
<li><a href="#basic">resource</a> - a basic resource.</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="#tarentry">tarentry</a> - an entry in a tar 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> | |||
@@ -0,0 +1,146 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | |||
<html> | |||
<head> | |||
<meta http-equiv="Content-Language" content="en-us"> | |||
<link rel="stylesheet" type="text/css" href="../stylesheets/style.css"> | |||
<title>TarFileSet Type</title> | |||
</head> | |||
<body> | |||
<h2><a name="fileset">TarFileSet</a></h2> | |||
<p><em>TarFileSet</em> has been added as a stand-alone type in Ant | |||
1.7.</p> | |||
<p>A <code><tarfileset></code> is a special form of a <code><<a | |||
href="fileset.html">fileset</a>></code> which can behave in 2 | |||
different ways : <br> | |||
</p> | |||
<ul> | |||
<li>When the <span style="font-style: italic;">src</span> attribute | |||
is used - or a nested resource collection has been specified, the | |||
tarfileset is populated with tar entries found in the file <span | |||
style="font-style: italic;">src</span>.<br> | |||
</li> | |||
<li>When the <span style="font-style: italic;">dir</span> attribute | |||
is used, the tarfileset is populated with filesystem files found under <span | |||
style="font-style: italic;">dir</span>.<br> | |||
</li> | |||
</ul> | |||
<p><code><tarfileset></code> supports all attributes of <code><<a | |||
href="fileset.html">fileset</a>></code> | |||
in addition to those listed below.<br> | |||
</p> | |||
<p>A tarfileset can be defined with the <span style="font-style: | |||
italic;">id </span>attribute and referred to with 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> | |||
<h3>Parameters</h3> | |||
<table border="1" cellpadding="2" cellspacing="0"> | |||
<tbody> | |||
<tr> | |||
<td valign="top"><b>Attribute</b></td> | |||
<td valign="top"><b>Description</b></td> | |||
<td valign="top" align="center"><b>Required</b></td> | |||
</tr> | |||
<tr> | |||
<td valign="top">prefix</td> | |||
<td valign="top">all files in the fileset are prefixed with that | |||
path in the archive.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">fullpath</td> | |||
<td valign="top">the file described by the fileset is placed at | |||
that exact location in the archive.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">src</td> | |||
<td valign="top">may be used in place of the <i>dir</i> attribute | |||
to specify a tar file whose contents will be extracted and included | |||
in the archive.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">filemode</td> | |||
<td valign="top">A 3 digit octal string, specify the user, group | |||
and other modes in the standard Unix fashion. Only applies to | |||
plain files. Default is 644.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">dirmode</td> | |||
<td valign="top">A 3 digit octal string, specify the user, group | |||
and other modes in the standard Unix fashion. Only applies to | |||
directories. Default is 755.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">username</td> | |||
<td valign="top">The username for the tar entry. This is not the same as the UID. | |||
</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">group</td> | |||
<td valign="top">The groupname for the tar entry. This is not the same as the GID. | |||
</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">uid</td> | |||
<td valign="top">The user identifier (UID) for the tar entry. This is an integer value | |||
and is not the same as the username. | |||
</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">gid</td> | |||
<td valign="top">The group identifier (GID) for the tar entry. | |||
</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
<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> | |||
attributes cannot both be set on the same fileset.</p> | |||
<p>When using the <i>src</i> attribute, include and exclude patterns | |||
may be used to specify a subset of the archive for inclusion in the | |||
archive as with the <i>dir</i> attribute.</p> | |||
<p>Please note that currently only the <a | |||
href="../CoreTasks/tar.html">tar</a> task uses the permission and | |||
ownership attributes.</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.</p> | |||
<h4>Examples</h4> | |||
<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> | |||
<p align="center">Copyright © 2005 The Apache Software Foundation. All | |||
rights Reserved.</p> | |||
</body> | |||
</html> |
@@ -6,35 +6,31 @@ | |||
<title>ZipFileSet Type</title> | |||
</head> | |||
<body> | |||
<h2><a name="fileset">ZipFileSet/TarFileSet</a></h2> | |||
<h2><a name="fileset">ZipFileSet</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 | |||
<p>A <code><zipfileset></code> is a special form of a <code><<a | |||
href="fileset.html">fileset</a>></code> which can behave in 2 | |||
different ways : <br> | |||
</p> | |||
<ul> | |||
<li>When the <span style="font-style: italic;">src</span> attribute | |||
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: | |||
(<em>since Ant 1.7</em>), the zipfileset is populated with | |||
zip entries found in the file <span style="font-style: | |||
italic;">src</span>.<br> | |||
</li> | |||
<li>When the <span style="font-style: italic;">dir</span> attribute | |||
is used, the tar/zipfileset is populated with filesystem files found under <span | |||
is used, the zipfileset is populated with filesystem files found under <span | |||
style="font-style: italic;">dir</span>.<br> | |||
</li> | |||
</ul> | |||
<p><code><tar/zipfileset></code> supports all attributes of <code><<a | |||
<p><code><zipfileset></code> supports all attributes of <code><<a | |||
href="fileset.html">fileset</a>></code> | |||
in addition to those listed below.<br> | |||
</p> | |||
<p>Since Ant 1.6, a zipfileset can be defined with the <span | |||
style="font-style: italic;">id </span>attribute and referred to with | |||
the <span style="font-style: italic;">refid</span> attribute. This is | |||
also true for tarfileset which has been added in Ant 1.7.<br> | |||
the <span style="font-style: italic;">refid</span> attribute.<br> | |||
</p> | |||
<h3>Parameters</h3> | |||
<table border="1" cellpadding="2" cellspacing="0"> | |||
@@ -95,14 +91,16 @@ attributes cannot both be set on the same fileset.</p> | |||
may be used to specify a subset of the archive for inclusion in the | |||
archive as with the <i>dir</i> attribute.</p> | |||
<p>Please note that currently only the <a | |||
href="../CoreTasks/tar.html">tar</a> and <a | |||
href="../CoreTaks/zip.html">zip</a> tasks use the permission.</p> | |||
<h3>Parameters specified as nested elements</h3> | |||
<h4>any <a href="resources.html">resource</a> or single element | |||
resource collection</h4> | |||
<h4>any file system based <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> | |||
<p>The specified resource will be used as src.</p> | |||
<h4>Examples</h4> | |||
<blockquote> | |||
@@ -117,24 +115,6 @@ docs/ChangeLog.txt<br> | |||
docs/examples/index.html<br> | |||
</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> | |||
<p align="center">Copyright © 2003-2005 The Apache Software Foundation. All | |||
rights Reserved.</p> | |||
@@ -34,7 +34,7 @@ | |||
<a href="CoreTypes/resources.html">Resources</a><br> | |||
<a href="CoreTypes/resources.html#collection">Resource Collections</a><br> | |||
<a href="CoreTypes/selectors.html">Selectors</a><br> | |||
<a href="CoreTypes/zipfileset.html">TarFileSet</a><br> | |||
<a href="CoreTypes/tarfileset.html">TarFileSet</a><br> | |||
<a href="CoreTypes/xmlcatalog.html">XMLCatalog</a><br> | |||
<a href="CoreTypes/zipfileset.html">ZipFileSet</a><br> | |||
@@ -44,6 +44,32 @@ | |||
<untar src="test7.tar" dest="."/> | |||
</target> | |||
<target name="test7UsingPlainFileSet"> | |||
<mkdir dir="test7dir"/> | |||
<tar destfile="test7.tar"> | |||
<tarfileset dir="." prefix="test7-prefix/"> | |||
<include name="test7dir"/> | |||
</tarfileset> | |||
<fileset dir="."> | |||
<include name="test7dir"/> | |||
</fileset> | |||
</tar> | |||
<untar src="test7.tar" dest="."/> | |||
</target> | |||
<target name="test7UsingFileList"> | |||
<mkdir dir="test7dir"/> | |||
<tar destfile="test7.tar"> | |||
<tarfileset dir="." prefix="test7-prefix/"> | |||
<include name="test7dir"/> | |||
</tarfileset> | |||
<filelist dir="."> | |||
<file name="test7dir"/> | |||
</filelist> | |||
</tar> | |||
<untar src="test7.tar" dest="."/> | |||
</target> | |||
<target name="test8"> | |||
<tar destfile="test8.tar"> | |||
<tarfileset dir="." fullpath="/test8.xml"> | |||
@@ -53,6 +79,45 @@ | |||
<untar src="test8.tar" dest="."/> | |||
</target> | |||
<target name="test8UsingZipFileset"> | |||
<tar destfile="test8.tar"> | |||
<zipfileset dir="." fullpath="/test8.xml"> | |||
<include name="tar.xml"/> | |||
</zipfileset> | |||
</tar> | |||
<untar src="test8.tar" dest="."/> | |||
</target> | |||
<target name="test8UsingZipFilesetSrc"> | |||
<zip destfile="test7.tar" basedir="." includes="tar.xml"/> | |||
<tar destfile="test8.tar"> | |||
<zipfileset src="test7.tar" fullpath="/test8.xml"> | |||
<include name="tar.xml"/> | |||
</zipfileset> | |||
</tar> | |||
<untar src="test8.tar" dest="."/> | |||
</target> | |||
<target name="test8UsingTarFilesetSrc"> | |||
<tar destfile="test7.tar" basedir="." includes="tar.xml"/> | |||
<tar destfile="test8.tar"> | |||
<tarfileset src="test7.tar" fullpath="/test8.xml"> | |||
<include name="tar.xml"/> | |||
</tarfileset> | |||
</tar> | |||
<untar src="test8.tar" dest="."/> | |||
</target> | |||
<target name="test8UsingZipEntry"> | |||
<zip destfile="test7.tar"> | |||
<zipfileset dir="." includes="tar.xml" fullpath="/test8.xml"/> | |||
</zip> | |||
<tar destfile="test8.tar"> | |||
<zipentry archive="test7.tar" name="/test8.xml"/> | |||
</tar> | |||
<untar src="test8.tar" dest="."/> | |||
</target> | |||
<target name="test9"> | |||
<tar destfile="blah" compression="Foo"/> | |||
</target> | |||
@@ -79,6 +144,7 @@ | |||
<delete file="test4.tar"/> | |||
<delete file="test5.tar"/> | |||
<delete file="asf-logo.gif.tar"/> | |||
<delete dir="testout"/> | |||
<delete dir="test5dir"/> | |||
<delete dir="test7dir"/> | |||
<delete dir="test7-prefix"/> | |||
@@ -107,5 +173,14 @@ | |||
compression="bzip2" /> | |||
</target> | |||
<target name="testGZipResource"> | |||
<mkdir dir="testout"/> | |||
<tar destfile="testout/test.tar"> | |||
<gzipresource> | |||
<file file="expected/asf-logo.gif.gz"/> | |||
</gzipresource> | |||
</tar> | |||
<untar src="testout/test.tar" dest="testout"/> | |||
</target> | |||
</project> |
@@ -64,7 +64,7 @@ import org.apache.tools.ant.util.FlatFileNameMapper; | |||
* @ant.task category="filesystem" | |||
*/ | |||
public class Copy extends Task { | |||
private static final File NULL_FILE_PLACEHOLDER = new File("/NULL_FILE"); | |||
static final File NULL_FILE_PLACEHOLDER = new File("/NULL_FILE"); | |||
protected File file = null; // the source file | |||
protected File destFile = null; // the destination file | |||
@@ -19,18 +19,29 @@ package org.apache.tools.ant.taskdefs; | |||
import java.io.BufferedOutputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.util.Enumeration; | |||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.Vector; | |||
import java.util.zip.GZIPOutputStream; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.DirectoryScanner; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.types.ArchiveFileSet; | |||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||
import org.apache.tools.ant.types.FileSet; | |||
import org.apache.tools.ant.types.Resource; | |||
import org.apache.tools.ant.types.ResourceCollection; | |||
import org.apache.tools.ant.types.resources.ArchiveResource; | |||
import org.apache.tools.ant.types.resources.FileResource; | |||
import org.apache.tools.ant.types.selectors.SelectorUtils; | |||
import org.apache.tools.ant.types.resources.TarResource; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import org.apache.tools.ant.util.MergingMapper; | |||
import org.apache.tools.ant.util.SourceFileScanner; | |||
import org.apache.tools.bzip2.CBZip2OutputStream; | |||
@@ -79,7 +90,12 @@ public class Tar extends MatchingTask { | |||
private TarLongFileMode longFileMode = new TarLongFileMode(); | |||
// need to keep the package private version for backwards compatibility | |||
Vector filesets = new Vector(); | |||
// we must keep two lists since other classes may modify the | |||
// filesets Vector (it is package private) without us noticing | |||
private Vector resourceCollections = new Vector(); | |||
Vector fileSetFiles = new Vector(); | |||
/** | |||
@@ -95,10 +111,19 @@ public class Tar extends MatchingTask { | |||
*/ | |||
public TarFileSet createTarFileSet() { | |||
TarFileSet fs = new TarFileSet(); | |||
fs.setProject(getProject()); | |||
filesets.addElement(fs); | |||
return fs; | |||
} | |||
/** | |||
* Add a collection of resources to archive. | |||
* @param res a resource collection to archive. | |||
* @since Ant 1.7 | |||
*/ | |||
public void add(ResourceCollection res) { | |||
resourceCollections.add(res); | |||
} | |||
/** | |||
* Set is the name/location of where to create the tar file. | |||
@@ -217,9 +242,10 @@ public class Tar extends MatchingTask { | |||
filesets.addElement(mainFileSet); | |||
} | |||
if (filesets.size() == 0) { | |||
if (filesets.size() == 0 && resourceCollections.size() == 0) { | |||
throw new BuildException("You must supply either a basedir " | |||
+ "attribute or some nested filesets.", | |||
+ "attribute or some nested resource" | |||
+ " collections.", | |||
getLocation()); | |||
} | |||
@@ -227,20 +253,11 @@ public class Tar extends MatchingTask { | |||
// fileset | |||
boolean upToDate = true; | |||
for (Enumeration e = filesets.elements(); e.hasMoreElements();) { | |||
TarFileSet fs = (TarFileSet) e.nextElement(); | |||
String[] files = fs.getFiles(getProject()); | |||
if (!archiveIsUpToDate(files, fs.getDir(getProject()))) { | |||
upToDate = false; | |||
} | |||
for (int i = 0; i < files.length; ++i) { | |||
if (tarFile.equals(new File(fs.getDir(getProject()), | |||
files[i]))) { | |||
throw new BuildException("A tar file cannot include " | |||
+ "itself", getLocation()); | |||
} | |||
} | |||
upToDate &= check((TarFileSet) e.nextElement()); | |||
} | |||
for (Enumeration e = resourceCollections.elements(); | |||
e.hasMoreElements();) { | |||
upToDate &= check((ResourceCollection) e.nextElement()); | |||
} | |||
if (upToDate) { | |||
@@ -271,19 +288,11 @@ public class Tar extends MatchingTask { | |||
longWarningGiven = false; | |||
for (Enumeration e = filesets.elements(); | |||
e.hasMoreElements();) { | |||
TarFileSet fs = (TarFileSet) e.nextElement(); | |||
String[] files = fs.getFiles(getProject()); | |||
if (files.length > 1 && fs.getFullpath().length() > 0) { | |||
throw new BuildException("fullpath attribute may only " | |||
+ "be specified for " | |||
+ "filesets that specify a " | |||
+ "single file."); | |||
} | |||
for (int i = 0; i < files.length; i++) { | |||
File f = new File(fs.getDir(getProject()), files[i]); | |||
String name = files[i].replace(File.separatorChar, '/'); | |||
tarFile(f, tOut, name, fs); | |||
} | |||
tar((TarFileSet) e.nextElement(), tOut); | |||
} | |||
for (Enumeration e = resourceCollections.elements(); | |||
e.hasMoreElements();) { | |||
tar((ResourceCollection) e.nextElement(), tOut); | |||
} | |||
} catch (IOException ioe) { | |||
String msg = "Problem creating TAR: " + ioe.getMessage(); | |||
@@ -314,95 +323,144 @@ public class Tar extends MatchingTask { | |||
protected void tarFile(File file, TarOutputStream tOut, String vPath, | |||
TarFileSet tarFileSet) | |||
throws IOException { | |||
FileInputStream fIn = null; | |||
tarResource(new FileResource(file), tOut, vPath, tarFileSet); | |||
} | |||
String fullpath = tarFileSet.getFullpath(); | |||
if (fullpath.length() > 0) { | |||
vPath = fullpath; | |||
} else { | |||
// don't add "" to the archive | |||
if (vPath.length() <= 0) { | |||
return; | |||
} | |||
/** | |||
* tar a resource | |||
* @param file the resource to tar | |||
* @param tOut the output stream | |||
* @param vPath the path name of the file to tar | |||
* @param tarFileSet the fileset that the file came from, may be null. | |||
* @throws IOException on error | |||
* @since Ant 1.7 | |||
*/ | |||
protected void tarResource(Resource r, TarOutputStream tOut, String vPath, | |||
TarFileSet tarFileSet) | |||
throws IOException { | |||
if (!r.isExists()) { | |||
return; | |||
} | |||
if (file.isDirectory() && !vPath.endsWith("/")) { | |||
vPath += "/"; | |||
if (tarFileSet != null) { | |||
String fullpath = tarFileSet.getFullpath(); | |||
if (fullpath.length() > 0) { | |||
vPath = fullpath; | |||
} else { | |||
// don't add "" to the archive | |||
if (vPath.length() <= 0) { | |||
return; | |||
} | |||
String prefix = tarFileSet.getPrefix(); | |||
// '/' is appended for compatibility with the zip task. | |||
if (prefix.length() > 0 && !prefix.endsWith("/")) { | |||
prefix = prefix + "/"; | |||
} | |||
vPath = prefix + vPath; | |||
} | |||
String prefix = tarFileSet.getPrefix(); | |||
// '/' is appended for compatibility with the zip task. | |||
if (prefix.length() > 0 && !prefix.endsWith("/")) { | |||
prefix = prefix + "/"; | |||
if (vPath.startsWith("/") | |||
&& !tarFileSet.getPreserveLeadingSlashes()) { | |||
int l = vPath.length(); | |||
if (l <= 1) { | |||
// we would end up adding "" to the archive | |||
return; | |||
} | |||
vPath = vPath.substring(1, l); | |||
} | |||
vPath = prefix + vPath; | |||
} | |||
if (vPath.startsWith("/") && !tarFileSet.getPreserveLeadingSlashes()) { | |||
int l = vPath.length(); | |||
if (l <= 1) { | |||
// we would end up adding "" to the archive | |||
return; | |||
} | |||
vPath = vPath.substring(1, l); | |||
if (r.isDirectory() && !vPath.endsWith("/")) { | |||
vPath += "/"; | |||
} | |||
try { | |||
if (vPath.length() >= TarConstants.NAMELEN) { | |||
if (longFileMode.isOmitMode()) { | |||
log("Omitting: " + vPath, Project.MSG_INFO); | |||
return; | |||
} else if (longFileMode.isWarnMode()) { | |||
log("Entry: " + vPath + " longer than " | |||
+ TarConstants.NAMELEN + " characters.", | |||
if (vPath.length() >= TarConstants.NAMELEN) { | |||
if (longFileMode.isOmitMode()) { | |||
log("Omitting: " + vPath, Project.MSG_INFO); | |||
return; | |||
} else if (longFileMode.isWarnMode()) { | |||
log("Entry: " + vPath + " longer than " | |||
+ TarConstants.NAMELEN + " characters.", | |||
Project.MSG_WARN); | |||
if (!longWarningGiven) { | |||
log("Resulting tar file can only be processed " | |||
+ "successfully by GNU compatible tar commands", | |||
Project.MSG_WARN); | |||
if (!longWarningGiven) { | |||
log("Resulting tar file can only be processed " | |||
+ "successfully by GNU compatible tar commands", | |||
Project.MSG_WARN); | |||
longWarningGiven = true; | |||
} | |||
} else if (longFileMode.isFailMode()) { | |||
throw new BuildException("Entry: " + vPath | |||
longWarningGiven = true; | |||
} | |||
} else if (longFileMode.isFailMode()) { | |||
throw new BuildException("Entry: " + vPath | |||
+ " longer than " + TarConstants.NAMELEN | |||
+ "characters.", getLocation()); | |||
} | |||
} | |||
} | |||
TarEntry te = new TarEntry(vPath); | |||
te.setModTime(file.lastModified()); | |||
if (!file.isDirectory()) { | |||
if (file.length() > TarConstants.MAXSIZE) { | |||
throw new BuildException("File: " + file + " larger than " + | |||
TarConstants.MAXSIZE + " bytes."); | |||
} | |||
te.setSize(file.length()); | |||
TarEntry te = new TarEntry(vPath); | |||
te.setModTime(r.getLastModified()); | |||
// preserve permissions | |||
if (r instanceof ArchiveResource) { | |||
ArchiveResource ar = (ArchiveResource) r; | |||
te.setMode(ar.getMode()); | |||
if (r instanceof TarResource) { | |||
TarResource tr = (TarResource) r; | |||
te.setUserName(tr.getUserName()); | |||
te.setUserId(tr.getUid()); | |||
te.setGroupName(tr.getGroup()); | |||
te.setGroupId(tr.getGid()); | |||
} | |||
} | |||
if (!r.isDirectory()) { | |||
if (r.size() > TarConstants.MAXSIZE) { | |||
throw new BuildException("Resource: " + r + " larger than " + | |||
TarConstants.MAXSIZE + " bytes."); | |||
} | |||
te.setSize(r.getSize()); | |||
// override permissions if set explicitly | |||
if (tarFileSet != null && tarFileSet.hasFileModeBeenSet()) { | |||
te.setMode(tarFileSet.getMode()); | |||
} else { | |||
te.setMode(tarFileSet.getDirMode()); | |||
} | |||
te.setUserName(tarFileSet.getUserName()); | |||
te.setGroupName(tarFileSet.getGroup()); | |||
te.setUserId(tarFileSet.getUid()); | |||
te.setGroupId(tarFileSet.getGid()); | |||
} else if (tarFileSet != null && tarFileSet.hasDirModeBeenSet()) { | |||
// override permissions if set explicitly | |||
te.setMode(tarFileSet.getDirMode()); | |||
} | |||
if (tarFileSet != null) { | |||
// only override permissions if set explicitly | |||
if (tarFileSet.hasUserNameBeenSet()) { | |||
te.setUserName(tarFileSet.getUserName()); | |||
} | |||
if (tarFileSet.hasGroupBeenSet()) { | |||
te.setGroupName(tarFileSet.getGroup()); | |||
} | |||
if (tarFileSet.hasUserIdBeenSet()) { | |||
te.setUserId(tarFileSet.getUid()); | |||
} | |||
if (tarFileSet.hasGroupIdBeenSet()) { | |||
te.setGroupId(tarFileSet.getGid()); | |||
} | |||
} | |||
InputStream in = null; | |||
try { | |||
tOut.putNextEntry(te); | |||
if (!file.isDirectory()) { | |||
fIn = new FileInputStream(file); | |||
if (!r.isDirectory()) { | |||
in = r.getInputStream(); | |||
byte[] buffer = new byte[8 * 1024]; | |||
int count = 0; | |||
do { | |||
tOut.write(buffer, 0, count); | |||
count = fIn.read(buffer, 0, buffer.length); | |||
count = in.read(buffer, 0, buffer.length); | |||
} while (count != -1); | |||
} | |||
tOut.closeEntry(); | |||
} finally { | |||
if (fIn != null) { | |||
fIn.close(); | |||
} | |||
FileUtils.close(in); | |||
} | |||
} | |||
@@ -430,6 +488,243 @@ public class Tar extends MatchingTask { | |||
return sfs.restrict(files, dir, null, mm).length == 0; | |||
} | |||
/** | |||
* Is the archive up to date in relationship to a list of files. | |||
* @param files the files to check | |||
* @return true if the archive is up to date. | |||
* @since Ant 1.7 | |||
*/ | |||
protected boolean archiveIsUpToDate(Resource r) { | |||
return SelectorUtils.isOutOfDate(new FileResource(tarFile), r, | |||
FileUtils.getFileUtils() | |||
.getFileTimestampGranularity()); | |||
} | |||
/** | |||
* Whether this task can deal with non-file resources. | |||
* | |||
* <p>This implementation returns true only if this task is | |||
* <tar>. Any subclass of this class that also wants to | |||
* support non-file resources needs to override this method. We | |||
* need to do so for backwards compatibility reasons since we | |||
* can't expect subclasses to support resources.</p> | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
protected boolean supportsNonFileResources() { | |||
return getClass().equals(Tar.class); | |||
} | |||
/** | |||
* Checks whether the archive is out-of-date with respect to the resources | |||
* of the given collection. | |||
* | |||
* <p>Also checks that either all collections only contain file | |||
* resources or this class supports non-file collections.</p> | |||
* | |||
* <p>And - in case of file-collections - ensures that the archive won't | |||
* contain itself.</p> | |||
* | |||
* @param rc the resource collection to check | |||
* @return whether the archive is up-to-date | |||
* @since Ant 1.7 | |||
*/ | |||
protected boolean check(ResourceCollection rc) { | |||
boolean upToDate = true; | |||
if (isFileFileSet(rc)) { | |||
FileSet fs = (FileSet) rc; | |||
upToDate = check(fs.getDir(getProject()), getFileNames(fs)); | |||
} else if (!rc.isFilesystemOnly() && !supportsNonFileResources()) { | |||
throw new BuildException("only filesystem resources are supported"); | |||
} else if (rc.isFilesystemOnly()) { | |||
HashSet basedirs = new HashSet(); | |||
HashMap basedirToFilesMap = new HashMap(); | |||
Iterator iter = rc.iterator(); | |||
while (iter.hasNext()) { | |||
FileResource r = (FileResource) iter.next(); | |||
File base = r.getBaseDir(); | |||
if (base == null) { | |||
base = Copy.NULL_FILE_PLACEHOLDER; | |||
} | |||
basedirs.add(base); | |||
Vector files = (Vector) basedirToFilesMap.get(base); | |||
if (files == null) { | |||
files = new Vector(); | |||
basedirToFilesMap.put(base, new Vector()); | |||
} | |||
files.add(r.getName()); | |||
} | |||
iter = basedirs.iterator(); | |||
while (iter.hasNext()) { | |||
File base = (File) iter.next(); | |||
Vector f = (Vector) basedirToFilesMap.get(base); | |||
String[] files = (String[]) f.toArray(new String[f.size()]); | |||
upToDate &= | |||
check(base == Copy.NULL_FILE_PLACEHOLDER ? null : base, | |||
files); | |||
} | |||
} else { // non-file resources | |||
Iterator iter = rc.iterator(); | |||
while (upToDate && iter.hasNext()) { | |||
Resource r = (Resource) iter.next(); | |||
upToDate &= archiveIsUpToDate(r); | |||
} | |||
} | |||
return upToDate; | |||
} | |||
/** | |||
* Checks whether the archive is out-of-date with respect to the | |||
* given files, ensures that the archive won't contain itself.</p> | |||
* | |||
* @param basedir base directory for file names | |||
* @param files array of relative file names | |||
* @return whether the archive is up-to-date | |||
* @since Ant 1.7 | |||
*/ | |||
protected boolean check(File basedir, String[] files) { | |||
boolean upToDate = true; | |||
if (!archiveIsUpToDate(files, basedir)) { | |||
upToDate = false; | |||
} | |||
for (int i = 0; i < files.length; ++i) { | |||
if (tarFile.equals(new File(basedir, files[i]))) { | |||
throw new BuildException("A tar file cannot include " | |||
+ "itself", getLocation()); | |||
} | |||
} | |||
return upToDate; | |||
} | |||
/** | |||
* Adds the resources contained in this collection to the archive. | |||
* | |||
* <p>Uses the file based methods for file resources for backwards | |||
* compatibility.</p> | |||
* | |||
* @param rc the collection containing resources to add | |||
* @param tOut stream writing to the archive. | |||
* @since Ant 1.7 | |||
*/ | |||
protected void tar(ResourceCollection rc, TarOutputStream tOut) | |||
throws IOException { | |||
ArchiveFileSet afs = null; | |||
if (rc instanceof ArchiveFileSet) { | |||
afs = (ArchiveFileSet) rc; | |||
} | |||
if (afs != null && afs.size() > 1 | |||
&& afs.getFullpath().length() > 0) { | |||
throw new BuildException("fullpath attribute may only " | |||
+ "be specified for " | |||
+ "filesets that specify a " | |||
+ "single file."); | |||
} | |||
TarFileSet tfs = asTarFileSet(afs); | |||
if (isFileFileSet(rc)) { | |||
FileSet fs = (FileSet) rc; | |||
String[] files = getFileNames(fs); | |||
for (int i = 0; i < files.length; i++) { | |||
File f = new File(fs.getDir(getProject()), files[i]); | |||
String name = files[i].replace(File.separatorChar, '/'); | |||
tarFile(f, tOut, name, tfs); | |||
} | |||
} else if (rc.isFilesystemOnly()) { | |||
Iterator iter = rc.iterator(); | |||
while (iter.hasNext()) { | |||
FileResource r = (FileResource) iter.next(); | |||
File f = r.getFile(); | |||
if (f == null) { | |||
f = new File(r.getBaseDir(), r.getName()); | |||
} | |||
tarFile(f, tOut, f.getName(), tfs); | |||
} | |||
} else { // non-file resources | |||
Iterator iter = rc.iterator(); | |||
while (iter.hasNext()) { | |||
Resource r = (Resource) iter.next(); | |||
tarResource(r, tOut, r.getName(), tfs); | |||
} | |||
} | |||
} | |||
/** | |||
* whether the given resource collection is a (subclass of) | |||
* FileSet that only contains file system resources. | |||
* @since Ant 1.7 | |||
*/ | |||
protected static final boolean isFileFileSet(ResourceCollection rc) { | |||
return rc instanceof FileSet && rc.isFilesystemOnly(); | |||
} | |||
/** | |||
* Grabs all included files and directors from the FileSet and | |||
* returns them as an array of (relative) file names. | |||
* | |||
* @since Ant 1.7 | |||
*/ | |||
protected static final String[] getFileNames(FileSet fs) { | |||
DirectoryScanner ds = fs.getDirectoryScanner(fs.getProject()); | |||
String[] directories = ds.getIncludedDirectories(); | |||
String[] filesPerSe = ds.getIncludedFiles(); | |||
String[] files = new String [directories.length + filesPerSe.length]; | |||
System.arraycopy(directories, 0, files, 0, directories.length); | |||
System.arraycopy(filesPerSe, 0, files, directories.length, | |||
filesPerSe.length); | |||
return files; | |||
} | |||
/** | |||
* Copies fullpath, prefix and permission attributes from the | |||
* ArchiveFileSet to a new TarFileSet (or returns it unchanged if | |||
* it already is a TarFileSet). | |||
* | |||
* @param archiveFileSet fileset to copy attributes from, may be null | |||
* @since Ant 1.7 | |||
*/ | |||
protected TarFileSet asTarFileSet(ArchiveFileSet archiveFileSet) { | |||
TarFileSet tfs = null; | |||
if (archiveFileSet != null && archiveFileSet instanceof TarFileSet) { | |||
tfs = (TarFileSet) archiveFileSet; | |||
} else { | |||
tfs = new TarFileSet(); | |||
tfs.setProject(getProject()); | |||
if (archiveFileSet != null) { | |||
tfs.setPrefix(archiveFileSet.getPrefix(getProject())); | |||
tfs.setFullpath(archiveFileSet.getFullpath(getProject())); | |||
if (archiveFileSet.hasFileModeBeenSet()) { | |||
tfs.integerSetFileMode(archiveFileSet | |||
.getFileMode(getProject())); | |||
} | |||
if (archiveFileSet.hasDirModeBeenSet()) { | |||
tfs.integerSetDirMode(archiveFileSet | |||
.getDirMode(getProject())); | |||
} | |||
if (archiveFileSet instanceof | |||
org.apache.tools.ant.types.TarFileSet) { | |||
org.apache.tools.ant.types.TarFileSet t = | |||
(org.apache.tools.ant.types.TarFileSet) archiveFileSet; | |||
if (t.hasUserNameBeenSet()) { | |||
tfs.setUserName(t.getUserName()); | |||
} | |||
if (t.hasGroupBeenSet()) { | |||
tfs.setGroup(t.getGroup()); | |||
} | |||
if (t.hasUserIdBeenSet()) { | |||
tfs.setUid(t.getUid()); | |||
} | |||
if (t.hasGroupIdBeenSet()) { | |||
tfs.setGid(t.getGid()); | |||
} | |||
} | |||
} | |||
} | |||
return tfs; | |||
} | |||
/** | |||
* This is a FileSet with the option to specify permissions | |||
* and other attributes. | |||
@@ -438,10 +733,6 @@ public class Tar extends MatchingTask { | |||
extends org.apache.tools.ant.types.TarFileSet { | |||
private String[] files = null; | |||
private String userName = ""; | |||
private String groupName = ""; | |||
private int uid; | |||
private int gid; | |||
private boolean preserveLeadingSlashes = false; | |||
/** | |||
@@ -470,13 +761,7 @@ public class Tar extends MatchingTask { | |||
*/ | |||
public String[] getFiles(Project p) { | |||
if (files == null) { | |||
DirectoryScanner ds = getDirectoryScanner(p); | |||
String[] directories = ds.getIncludedDirectories(); | |||
String[] filesPerSe = ds.getIncludedFiles(); | |||
files = new String [directories.length + filesPerSe.length]; | |||
System.arraycopy(directories, 0, files, 0, directories.length); | |||
System.arraycopy(filesPerSe, 0, files, directories.length, | |||
filesPerSe.length); | |||
files = getFileNames(this); | |||
} | |||
return files; | |||
@@ -499,70 +784,6 @@ public class Tar extends MatchingTask { | |||
return getFileMode(); | |||
} | |||
/** | |||
* The username for the tar entry | |||
* This is not the same as the UID. | |||
* @param userName the user name for the tar entry. | |||
*/ | |||
public void setUserName(String userName) { | |||
this.userName = userName; | |||
} | |||
/** | |||
* @return the user name for the tar entry | |||
*/ | |||
public String getUserName() { | |||
return userName; | |||
} | |||
/** | |||
* The uid for the tar entry | |||
* This is not the same as the User name. | |||
* @param uid the id of the user for the tar entry. | |||
*/ | |||
public void setUid(int uid) { | |||
this.uid = uid; | |||
} | |||
/** | |||
* @return the uid for the tar entry | |||
*/ | |||
public int getUid() { | |||
return uid; | |||
} | |||
/** | |||
* The groupname for the tar entry; optional, default="" | |||
* This is not the same as the GID. | |||
* @param groupName the group name string. | |||
*/ | |||
public void setGroup(String groupName) { | |||
this.groupName = groupName; | |||
} | |||
/** | |||
* @return the group name string. | |||
*/ | |||
public String getGroup() { | |||
return groupName; | |||
} | |||
/** | |||
* The GID for the tar entry; optional, default="0" | |||
* This is not the same as the group name. | |||
* @param gid the group id. | |||
*/ | |||
public void setGid(int gid) { | |||
this.gid = gid; | |||
} | |||
/** | |||
* @return the group identifier. | |||
*/ | |||
public int getGid() { | |||
return gid; | |||
} | |||
/** | |||
* Flag to indicates whether leading `/'s should | |||
* be preserved in the file names. | |||
@@ -310,9 +310,22 @@ public abstract class ArchiveFileSet extends FileSet { | |||
* @param octalString a <code>String</code> value | |||
*/ | |||
public void setFileMode(String octalString) { | |||
integerSetFileMode(Integer.parseInt(octalString, 8)); | |||
} | |||
/** | |||
* specify the user, group and | |||
* other modes in the standard Unix fashion; | |||
* optional, default=0644 | |||
* | |||
* <p>We use the strange name so this method doesn't appear in | |||
* IntrospectionHelpers list of attribute setters.</p> | |||
* @param mode a <code>int</code> value | |||
* @since Ant 1.7 | |||
*/ | |||
public void integerSetFileMode(int mode) { | |||
fileModeHasBeenSet = true; | |||
this.fileMode = | |||
UnixStat.FILE_FLAG | Integer.parseInt(octalString, 8); | |||
this.fileMode = UnixStat.FILE_FLAG | mode; | |||
} | |||
/** | |||
@@ -353,9 +366,21 @@ public abstract class ArchiveFileSet extends FileSet { | |||
* @param octalString a <code>String</code> value | |||
*/ | |||
public void setDirMode(String octalString) { | |||
integerSetDirMode(Integer.parseInt(octalString, 8)); | |||
} | |||
/** | |||
* specify the user, group and | |||
* other modes in the standard Unix fashion; | |||
* optional, default=0755 | |||
* <p>We use the strange name so this method doesn't appear in | |||
* IntrospectionHelpers list of attribute setters.</p> | |||
* @param mode a <code>int</code> value | |||
* @since Ant 1.7 | |||
*/ | |||
public void integerSetDirMode(int mode) { | |||
dirModeHasBeenSet = true; | |||
this.dirMode = | |||
UnixStat.DIR_FLAG | Integer.parseInt(octalString, 8); | |||
this.dirMode = UnixStat.DIR_FLAG | mode; | |||
} | |||
/** | |||
@@ -395,7 +420,7 @@ public abstract class ArchiveFileSet extends FileSet { | |||
* @param p the project to use | |||
* @return the abstract fileset instance | |||
*/ | |||
protected final void configureFileSet(ArchiveFileSet zfs) { | |||
protected void configureFileSet(ArchiveFileSet zfs) { | |||
zfs.setPrefix(prefix); | |||
zfs.setFullpath(fullpath); | |||
zfs.fileModeHasBeenSet = fileModeHasBeenSet; | |||
@@ -31,11 +31,19 @@ import org.apache.tools.zip.UnixStat; | |||
* 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 { | |||
private boolean userNameSet; | |||
private boolean groupNameSet; | |||
private boolean userIdSet; | |||
private boolean groupIdSet; | |||
private String userName = ""; | |||
private String groupName = ""; | |||
private int uid; | |||
private int gid; | |||
/** Constructor for TarFileSet */ | |||
public TarFileSet() { | |||
super(); | |||
@@ -57,11 +65,138 @@ public class TarFileSet extends ArchiveFileSet { | |||
super(fileset); | |||
} | |||
/** | |||
* The username for the tar entry | |||
* This is not the same as the UID. | |||
* @param userName the user name for the tar entry. | |||
*/ | |||
public void setUserName(String userName) { | |||
checkAttributesAllowed(); | |||
userNameSet = true; | |||
this.userName = userName; | |||
} | |||
/** | |||
* @return the user name for the tar entry | |||
*/ | |||
public String getUserName() { | |||
if (isReference()) { | |||
return ((TarFileSet) getCheckedRef()).getUserName(); | |||
} | |||
return userName; | |||
} | |||
/** | |||
* @return whether the user name has been explicitly set. | |||
*/ | |||
public boolean hasUserNameBeenSet() { | |||
return userNameSet; | |||
} | |||
/** | |||
* The uid for the tar entry | |||
* This is not the same as the User name. | |||
* @param uid the id of the user for the tar entry. | |||
*/ | |||
public void setUid(int uid) { | |||
checkAttributesAllowed(); | |||
userIdSet = true; | |||
this.uid = uid; | |||
} | |||
/** | |||
* @return the uid for the tar entry | |||
*/ | |||
public int getUid() { | |||
if (isReference()) { | |||
return ((TarFileSet) getCheckedRef()).getUid(); | |||
} | |||
return uid; | |||
} | |||
/** | |||
* @return whether the user id has been explicitly set. | |||
*/ | |||
public boolean hasUserIdBeenSet() { | |||
return userIdSet; | |||
} | |||
/** | |||
* The groupname for the tar entry; optional, default="" | |||
* This is not the same as the GID. | |||
* @param groupName the group name string. | |||
*/ | |||
public void setGroup(String groupName) { | |||
checkAttributesAllowed(); | |||
groupNameSet = true; | |||
this.groupName = groupName; | |||
} | |||
/** | |||
* @return the group name string. | |||
*/ | |||
public String getGroup() { | |||
if (isReference()) { | |||
return ((TarFileSet) getCheckedRef()).getGroup(); | |||
} | |||
return groupName; | |||
} | |||
/** | |||
* @return whether the group name has been explicitly set. | |||
*/ | |||
public boolean hasGroupBeenSet() { | |||
return groupNameSet; | |||
} | |||
/** | |||
* The GID for the tar entry; optional, default="0" | |||
* This is not the same as the group name. | |||
* @param gid the group id. | |||
*/ | |||
public void setGid(int gid) { | |||
checkAttributesAllowed(); | |||
groupIdSet = true; | |||
this.gid = gid; | |||
} | |||
/** | |||
* @return the group identifier. | |||
*/ | |||
public int getGid() { | |||
if (isReference()) { | |||
return ((TarFileSet) getCheckedRef()).getGid(); | |||
} | |||
return gid; | |||
} | |||
/** | |||
* @return whether the group id has been explicitly set. | |||
*/ | |||
public boolean hasGroupIdBeenSet() { | |||
return groupIdSet; | |||
} | |||
protected ArchiveScanner newArchiveScanner() { | |||
TarScanner zs = new TarScanner(); | |||
return zs; | |||
} | |||
/** | |||
* Makes this instance in effect a reference to another instance. | |||
* | |||
* <p>You must not set another attribute or nest elements inside | |||
* this element if you make it a reference.</p> | |||
* @param r the <code>Reference</code> to use. | |||
* @throws BuildException on error | |||
*/ | |||
public void setRefid(Reference r) throws BuildException { | |||
if (userNameSet || userIdSet || groupNameSet || groupIdSet) { | |||
throw tooManyAttributes(); | |||
} | |||
super.setRefid(r); | |||
} | |||
/** | |||
* A TarFileset accepts another TarFileSet or a FileSet as reference | |||
* FileSets are often used by the war task for the lib attribute | |||
@@ -83,6 +218,23 @@ public class TarFileSet extends ArchiveFileSet { | |||
} | |||
} | |||
/** | |||
* 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 void configureFileSet(ArchiveFileSet zfs) { | |||
super.configureFileSet(zfs); | |||
if (zfs instanceof TarFileSet) { | |||
TarFileSet tfs = (TarFileSet) zfs; | |||
tfs.setUserName(userName); | |||
tfs.setGroup(groupName); | |||
tfs.setUid(uid); | |||
tfs.setGid(gid); | |||
} | |||
} | |||
/** | |||
* Return a TarFileSet that has the same properties | |||
* as this one. | |||
@@ -33,6 +33,8 @@ public abstract class ArchiveResource extends Resource { | |||
private Resource archive; | |||
private boolean haveEntry = false; | |||
private boolean modeSet = false; | |||
private int mode = 0; | |||
/** | |||
* Default constructor. | |||
@@ -80,6 +82,16 @@ public abstract class ArchiveResource extends Resource { | |||
archive = new FileResource(a); | |||
} | |||
/** | |||
* Sets the file or dir mode for this resource. | |||
* @param integer representation of Unix permission mask. | |||
*/ | |||
public void setMode(int mode) { | |||
checkAttributesAllowed(); | |||
this.mode = mode; | |||
modeSet = true; | |||
} | |||
/** | |||
* Sets the archive that holds this as a single element Resource | |||
* collection. | |||
@@ -155,12 +167,24 @@ public abstract class ArchiveResource extends Resource { | |||
return super.isExists(); | |||
} | |||
/** | |||
* Get the file or dir mode for this Resource. | |||
* @return integer representation of Unix permission mask. | |||
*/ | |||
public int getMode() { | |||
if (isReference()) { | |||
return ((ArchiveResource) getCheckedRef()).getMode(); | |||
} | |||
checkEntry(); | |||
return mode; | |||
} | |||
/** | |||
* Overrides the super version. | |||
* @param r the Reference to set. | |||
*/ | |||
public void setRefid(Reference r) { | |||
if (archive != null) { | |||
if (archive != null || modeSet) { | |||
throw tooManyAttributes(); | |||
} | |||
super.setRefid(r); | |||
@@ -36,6 +36,11 @@ import org.apache.tools.tar.TarInputStream; | |||
*/ | |||
public class TarResource extends ArchiveResource { | |||
private String userName = ""; | |||
private String groupName = ""; | |||
private int uid; | |||
private int gid; | |||
/** | |||
* Default constructor. | |||
*/ | |||
@@ -104,6 +109,46 @@ public class TarResource extends ArchiveResource { | |||
"Use the tar task for tar output."); | |||
} | |||
/** | |||
* @return the user name for the tar entry | |||
*/ | |||
public String getUserName() { | |||
if (isReference()) { | |||
return ((TarResource) getCheckedRef()).getUserName(); | |||
} | |||
return userName; | |||
} | |||
/** | |||
* @return the group name for the tar entry | |||
*/ | |||
public String getGroup() { | |||
if (isReference()) { | |||
return ((TarResource) getCheckedRef()).getGroup(); | |||
} | |||
return groupName; | |||
} | |||
/** | |||
* @return the uid for the tar entry | |||
*/ | |||
public int getUid() { | |||
if (isReference()) { | |||
return ((TarResource) getCheckedRef()).getUid(); | |||
} | |||
return uid; | |||
} | |||
/** | |||
* @return the uid for the tar entry | |||
*/ | |||
public int getGid() { | |||
if (isReference()) { | |||
return ((TarResource) getCheckedRef()).getGid(); | |||
} | |||
return uid; | |||
} | |||
/** | |||
* fetches information from the named entry inside the archive. | |||
*/ | |||
@@ -132,14 +177,19 @@ public class TarResource extends ArchiveResource { | |||
private void setEntry(TarEntry e) { | |||
if (e == null) { | |||
super.setExists(false); | |||
setExists(false); | |||
return; | |||
} | |||
super.setName(e.getName()); | |||
super.setExists(true); | |||
super.setLastModified(e.getModTime().getTime()); | |||
super.setDirectory(e.isDirectory()); | |||
super.setSize(e.getSize()); | |||
setName(e.getName()); | |||
setExists(true); | |||
setLastModified(e.getModTime().getTime()); | |||
setDirectory(e.isDirectory()); | |||
setSize(e.getSize()); | |||
setMode(e.getMode()); | |||
userName = e.getUserName(); | |||
groupName = e.getGroupName(); | |||
uid = e.getUserId(); | |||
gid = e.getGroupId(); | |||
} | |||
} |
@@ -127,7 +127,13 @@ public class ZipResource extends ArchiveResource { | |||
return ((Resource) getCheckedRef()).getInputStream(); | |||
} | |||
final ZipFile z = new ZipFile(getZipfile(), getEncoding()); | |||
return new FilterInputStream(z.getInputStream(z.getEntry(getName()))) { | |||
ZipEntry ze = z.getEntry(getName()); | |||
if (ze == null) { | |||
z.close(); | |||
throw new BuildException("no entry " + getName() + " in " | |||
+ getArchive()); | |||
} | |||
return new FilterInputStream(z.getInputStream(ze)) { | |||
public void close() throws IOException { | |||
FileUtils.close(in); | |||
z.close(); | |||
@@ -182,14 +188,15 @@ public class ZipResource extends ArchiveResource { | |||
private void setEntry(ZipEntry e) { | |||
if (e == null) { | |||
super.setExists(false); | |||
setExists(false); | |||
return; | |||
} | |||
super.setName(e.getName()); | |||
super.setExists(true); | |||
super.setLastModified(e.getTime()); | |||
super.setDirectory(e.isDirectory()); | |||
super.setSize(e.getSize()); | |||
setName(e.getName()); | |||
setExists(true); | |||
setLastModified(e.getTime()); | |||
setDirectory(e.isDirectory()); | |||
setSize(e.getSize()); | |||
setMode(e.getUnixMode()); | |||
} | |||
} |
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright 2000-2002,2004 The Apache Software Foundation | |||
* Copyright 2000-2002,2004-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. | |||
@@ -17,8 +17,10 @@ | |||
package org.apache.tools.ant.taskdefs; | |||
import java.io.IOException; | |||
import java.io.File; | |||
import org.apache.tools.ant.BuildFileTest; | |||
import org.apache.tools.ant.util.FileUtils; | |||
/** | |||
*/ | |||
@@ -63,7 +65,19 @@ public class TarTest extends BuildFileTest { | |||
} | |||
public void test7() { | |||
executeTarget("test7"); | |||
test7("test7"); | |||
} | |||
public void test7UsingPlainFileSet() { | |||
test7("test7UsingPlainFileSet"); | |||
} | |||
public void test7UsingFileList() { | |||
test7("test7UsingFileList"); | |||
} | |||
private void test7(String target) { | |||
executeTarget(target); | |||
File f1 | |||
= new File(System.getProperty("root"), "src/etc/testcases/taskdefs/test7-prefix"); | |||
@@ -80,7 +94,27 @@ public class TarTest extends BuildFileTest { | |||
} | |||
public void test8() { | |||
executeTarget("test8"); | |||
test8("test8"); | |||
} | |||
public void test8UsingZipFileset() { | |||
test8("test8UsingZipFileset"); | |||
} | |||
public void test8UsingZipFilesetSrc() { | |||
test8("test8UsingZipFilesetSrc"); | |||
} | |||
public void test8UsingTarFilesetSrc() { | |||
test8("test8UsingTarFilesetSrc"); | |||
} | |||
public void test8UsingZipEntry() { | |||
test8("test8UsingZipEntry"); | |||
} | |||
private void test8(String target) { | |||
executeTarget(target); | |||
File f1 | |||
= new File(System.getProperty("root"), "src/etc/testcases/taskdefs/test8.xml"); | |||
if (! f1.exists()) { | |||
@@ -110,6 +144,12 @@ public class TarTest extends BuildFileTest { | |||
} | |||
} | |||
public void testGZipResource() throws IOException { | |||
executeTarget("testGZipResource"); | |||
assertTrue(FileUtils.getFileUtils() | |||
.contentEquals(getProject().resolveFile("../asf-logo.gif"), | |||
getProject().resolveFile("testout/asf-logo.gif.gz"))); | |||
} | |||
public void tearDown() { | |||
executeTarget("cleanup"); | |||