Submitted by: Curt Arnold <carnold@houston.rr.com> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272562 13f79535-47bb-0310-9956-ffa450edef68master
@@ -109,6 +109,11 @@ Fixed bugs: | |||
Other changes: | |||
-------------- | |||
* Gzip and Bzip2 files can now be constructed in the fly when using | |||
the tar task without having to create the intermediate tar file on | |||
disk. The Untar task can also untar GZip and BZip2 files on the fly | |||
without creating the intermediate tar file. | |||
* New optional type, <classfileset> added. | |||
* <ejbjar> now allows control over which additional classes and interfaces | |||
@@ -41,8 +41,8 @@ attribute is <code>warn</code> which behaves just like the gnu option except | |||
that it produces a warning for each file path encountered that does not match | |||
the limit.</p> | |||
<p>Note that this task does not perform compression. You might want to use the | |||
<a href="gzip.html">GZip</a> task to prepare a .tar.gz package.</p> | |||
<p>This task can perform compression by setting the compression attribute to "gzip" | |||
or "bzip2".</p> | |||
<h3>Parameters</h3> | |||
<table border="1" cellpadding="2" cellspacing="0"> | |||
@@ -99,6 +99,13 @@ the limit.</p> | |||
("yes"/"no"). Default excludes are used when omitted.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">compression</td> | |||
<td valign="top">compression method. Allowable values are | |||
"none", "gzip" and "bzip2". Default is | |||
"none".</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
</table> | |||
<h3>Nested Elements</h3> | |||
@@ -44,6 +44,14 @@ to perform unarchival upon. | |||
true).</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">compression</td> | |||
<td valign="top">compression method for untar. Allowable values are | |||
"none", "gzip" and "bzip2". Default is | |||
"none".</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
</table> | |||
<h3>Examples</h3> | |||
<blockquote> | |||
@@ -82,7 +90,7 @@ to perform unarchival upon. | |||
</pre></p> | |||
</blockquote> | |||
<hr> | |||
<p align="center">Copyright © 2001 Apache Software Foundation. All rights | |||
<p align="center">Copyright © 2001-2002 Apache Software Foundation. All rights | |||
Reserved.</p> | |||
</body> | |||
@@ -53,6 +53,28 @@ | |||
<untar src="test8.tar" dest="."/> | |||
</target> | |||
<target name="test9"> | |||
<tar destfile="blah" compression="Foo"/> | |||
</target> | |||
<target name="test10"> | |||
<tar destfile="test10.tar.gz" compression="gzip"> | |||
<tarfileset dir="." fullpath="/test10.xml"> | |||
<include name="tar.xml"/> | |||
</tarfileset> | |||
</tar> | |||
<untar src="test10.tar.gz" dest="." compression="gzip"/> | |||
</target> | |||
<target name="test11"> | |||
<tar destfile="test11.tar.bz2" compression="bzip2"> | |||
<tarfileset dir="." fullpath="/test11.xml"> | |||
<include name="tar.xml"/> | |||
</tarfileset> | |||
</tar> | |||
<untar src="test11.tar.bz2" dest="." compression="bzip2"/> | |||
</target> | |||
<target name="cleanup"> | |||
<delete file="test4.tar"/> | |||
<delete file="test5.tar"/> | |||
@@ -63,12 +85,25 @@ | |||
<delete file="test7.tar"/> | |||
<delete file="test8.tar"/> | |||
<delete file="test8.xml"/> | |||
<delete file="test10.tar.gz"/> | |||
<delete file="test10.xml"/> | |||
<delete file="test11.tar.bz2"/> | |||
<delete file="test11.xml"/> | |||
</target> | |||
<target name="feather"> | |||
<tar destfile="asf-logo.gif.tar" | |||
basedir=".." | |||
includes="asf-logo.gif" /> | |||
<tar destfile="asf-logo.gif.tar.gz" | |||
basedir=".." | |||
includes="asf-logo.gif" | |||
compression="gzip"/> | |||
<tar destfile="asf-logo.gif.tar.bz2" | |||
basedir=".." | |||
includes="asf-logo.gif" | |||
compression="bzip2" /> | |||
</target> | |||
</project> |
@@ -12,10 +12,31 @@ | |||
<ant antfile="tar.xml" target="cleanup" /> | |||
</target> | |||
<target name="testGzipTarTask"> | |||
<ant antfile="tar.xml" target="feather" /> | |||
<untar src="asf-logo.gif.tar.gz" dest="." compression="gzip" /> | |||
<ant antfile="tar.xml" target="cleanup" /> | |||
</target> | |||
<target name="testBzip2TarTask"> | |||
<ant antfile="tar.xml" target="feather" /> | |||
<untar src="asf-logo.gif.tar.bz2" dest="." compression="bzip2"/> | |||
<ant antfile="tar.xml" target="cleanup" /> | |||
</target> | |||
<target name="realTest"> | |||
<untar src="expected/asf-logo.gif.tar" dest="." /> | |||
</target> | |||
<target name="realGzipTest"> | |||
<untar src="expected/asf-logo.gif.tar.gz" dest="." compression="gzip" /> | |||
</target> | |||
<target name="realBzip2Test"> | |||
<untar src="expected/asf-logo.gif.tar.bz2" dest="." compression="bzip2"/> | |||
</target> | |||
<target name="srcDirTest"> | |||
<untar src="." dest="." /> | |||
</target> | |||
@@ -57,7 +57,9 @@ package org.apache.tools.ant.taskdefs; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.FileOutputStream; | |||
import java.io.OutputStream; | |||
import java.io.FileInputStream; | |||
import java.io.BufferedOutputStream; | |||
import java.util.Vector; | |||
import java.util.Enumeration; | |||
import org.apache.tools.ant.BuildException; | |||
@@ -70,11 +72,15 @@ import org.apache.tools.ant.util.MergingMapper; | |||
import org.apache.tools.tar.TarOutputStream; | |||
import org.apache.tools.tar.TarConstants; | |||
import org.apache.tools.tar.TarEntry; | |||
import java.util.zip.GZIPOutputStream; | |||
import org.apache.tools.bzip2.CBZip2OutputStream; | |||
/** | |||
* Creates a TAR archive. | |||
* | |||
* @author Stefano Mazzocchi | |||
* @author Stefano Mazzocchi | |||
* <a href="mailto:stefano@apache.org">stefano@apache.org</a> | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a> | |||
@@ -125,6 +131,8 @@ public class Tar extends MatchingTask { | |||
*/ | |||
private boolean longWarningGiven = false; | |||
private TarCompressionMethod compression = new TarCompressionMethod(); | |||
public TarFileSet createTarFileSet() { | |||
TarFileSet fileset = new TarFileSet(); | |||
filesets.addElement(fileset); | |||
@@ -191,6 +199,18 @@ public class Tar extends MatchingTask { | |||
this.longFileMode = mode; | |||
} | |||
/** | |||
* Set compression method. | |||
* | |||
* Allowable values are | |||
* none - no compression | |||
* gzip - Gzip compression | |||
* bzip2 - Bzip2 compression | |||
*/ | |||
public void setCompression(TarCompressionMethod mode) { | |||
this.compression = mode; | |||
} | |||
public void execute() throws BuildException { | |||
if (tarFile == null) { | |||
throw new BuildException("tarfile attribute must be set!", | |||
@@ -211,7 +231,7 @@ public class Tar extends MatchingTask { | |||
try { | |||
if (baseDir != null) { | |||
if (!baseDir.exists()) { | |||
throw new BuildException("basedir does not exist!", | |||
throw new BuildException("basedir does not exist!", | |||
location); | |||
} | |||
@@ -226,7 +246,7 @@ public class Tar extends MatchingTask { | |||
+ "attribute or some nested filesets.", | |||
location); | |||
} | |||
// check if tar is out of date with respect to each | |||
// fileset | |||
boolean upToDate = true; | |||
@@ -239,7 +259,7 @@ public class Tar extends MatchingTask { | |||
} | |||
for (int i = 0; i < files.length; ++i) { | |||
if (tarFile.equals(new File(fs.getDir(project), | |||
if (tarFile.equals(new File(fs.getDir(project), | |||
files[i]))) { | |||
throw new BuildException("A tar file cannot include " | |||
+ "itself", location); | |||
@@ -257,7 +277,10 @@ public class Tar extends MatchingTask { | |||
TarOutputStream tOut = null; | |||
try { | |||
tOut = new TarOutputStream(new FileOutputStream(tarFile)); | |||
tOut = new TarOutputStream( | |||
compression.compress( | |||
new BufferedOutputStream( | |||
new FileOutputStream(tarFile)))); | |||
tOut.setDebug(true); | |||
if (longFileMode.isTruncateMode()) { | |||
tOut.setLongFileMode(TarOutputStream.LONGFILE_TRUNCATE); | |||
@@ -270,13 +293,13 @@ public class Tar extends MatchingTask { | |||
} | |||
longWarningGiven = false; | |||
for (Enumeration e = filesets.elements(); | |||
for (Enumeration e = filesets.elements(); | |||
e.hasMoreElements();) { | |||
TarFileSet fs = (TarFileSet) e.nextElement(); | |||
String[] files = fs.getFiles(project); | |||
if (files.length > 1 && fs.getFullpath().length() > 0) { | |||
throw new BuildException("fullpath attribute may only " | |||
+ "be specified for " | |||
+ "be specified for " | |||
+ "filesets that specify a " | |||
+ "single file."); | |||
} | |||
@@ -315,11 +338,11 @@ public class Tar extends MatchingTask { | |||
if (vPath.length() <= 0) { | |||
return; | |||
} | |||
if (file.isDirectory() && !vPath.endsWith("/")) { | |||
vPath += "/"; | |||
} | |||
String prefix = tarFileSet.getPrefix(); | |||
// '/' is appended for compatibility with the zip task. | |||
if (prefix.length() > 0 && !prefix.endsWith("/")) { | |||
@@ -333,7 +356,7 @@ public class Tar extends MatchingTask { | |||
if (l <= 1) { | |||
// we would end up adding "" to the archive | |||
return; | |||
} | |||
} | |||
vPath = vPath.substring(1, l); | |||
} | |||
@@ -344,11 +367,11 @@ public class Tar extends MatchingTask { | |||
return; | |||
} else if (longFileMode.isWarnMode()) { | |||
log("Entry: " + vPath + " longer than " + | |||
TarConstants.NAMELEN + " characters.", | |||
TarConstants.NAMELEN + " characters.", | |||
Project.MSG_WARN); | |||
if (!longWarningGiven) { | |||
log("Resulting tar file can only be processed " | |||
+ "successfully by GNU compatible tar commands", | |||
+ "successfully by GNU compatible tar commands", | |||
Project.MSG_WARN); | |||
longWarningGiven = true; | |||
} | |||
@@ -406,7 +429,7 @@ public class Tar extends MatchingTask { | |||
private String prefix = ""; | |||
private String fullpath = ""; | |||
private boolean preserveLeadingSlashes = false; | |||
public TarFileSet(FileSet fileset) { | |||
super(fileset); | |||
} | |||
@@ -528,4 +551,65 @@ public class Tar extends MatchingTask { | |||
return OMIT.equalsIgnoreCase(getValue()); | |||
} | |||
} | |||
/** | |||
* Valid Modes for Compression attribute to Tar Task | |||
* | |||
*/ | |||
public static final class TarCompressionMethod extends EnumeratedAttribute { | |||
// permissable values for compression attribute | |||
/** | |||
* No compression | |||
*/ | |||
private static final String NONE = "none"; | |||
/** | |||
* GZIP compression | |||
*/ | |||
private static final String GZIP = "gzip"; | |||
/** | |||
* BZIP2 compression | |||
*/ | |||
private static final String BZIP2 = "bzip2"; | |||
/** | |||
* Default constructor | |||
*/ | |||
public TarCompressionMethod() { | |||
super(); | |||
setValue(NONE); | |||
} | |||
/** | |||
* Get valid enumeration values. | |||
* @return valid enumeration values | |||
*/ | |||
public String[] getValues() { | |||
return new String[] { NONE, GZIP, BZIP2 }; | |||
} | |||
/** | |||
* This method wraps the output stream with the | |||
* corresponding compression method | |||
* | |||
* @param ostream output stream | |||
* @return output stream with on-the-fly compression | |||
* @exception IOException thrown if file is not writable | |||
*/ | |||
private OutputStream compress(final OutputStream ostream) | |||
throws IOException { | |||
final String value = getValue(); | |||
if (GZIP.equals(value)) { | |||
return new GZIPOutputStream(ostream); | |||
} else { | |||
if (BZIP2.equals(value)) { | |||
ostream.write('B'); | |||
ostream.write('Z'); | |||
return new CBZip2OutputStream(ostream); | |||
} | |||
} | |||
return ostream; | |||
} | |||
} | |||
} |
@@ -61,7 +61,13 @@ import org.apache.tools.tar.TarEntry; | |||
import org.apache.tools.ant.util.FileUtils; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.BufferedInputStream; | |||
import java.io.InputStream; | |||
import java.io.IOException; | |||
import java.util.zip.GZIPInputStream; | |||
import org.apache.tools.bzip2.CBZip2InputStream; | |||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||
/** | |||
@@ -75,13 +81,33 @@ import java.io.IOException; | |||
* @ant.task category="packaging" | |||
*/ | |||
public class Untar extends Expand { | |||
/** | |||
* compression method | |||
*/ | |||
private UntarCompressionMethod compression = new UntarCompressionMethod(); | |||
/** | |||
* Set compression method. | |||
* | |||
* Allowable values are | |||
* none - no compression | |||
* gzip - Gzip compression | |||
* bzip2 - Bzip2 compression | |||
* | |||
* @param method compression method | |||
*/ | |||
public void setCompression(UntarCompressionMethod method) { | |||
compression = method; | |||
} | |||
protected void expandFile(FileUtils fileUtils, File srcF, File dir) { | |||
TarInputStream tis = null; | |||
try { | |||
log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO); | |||
tis = new TarInputStream(new FileInputStream(srcF)); | |||
tis = new TarInputStream( | |||
compression.decompress(srcF, | |||
new BufferedInputStream( | |||
new FileInputStream(srcF)))); | |||
TarEntry te = null; | |||
while ((te = tis.getNextEntry()) != null) { | |||
@@ -101,4 +127,76 @@ public class Untar extends Expand { | |||
} | |||
} | |||
} | |||
/** | |||
* Valid Modes for Compression attribute to Untar Task | |||
* | |||
*/ | |||
public static final class UntarCompressionMethod | |||
extends EnumeratedAttribute { | |||
// permissable values for compression attribute | |||
/** | |||
* No compression | |||
*/ | |||
private static final String NONE = "none"; | |||
/** | |||
* GZIP compression | |||
*/ | |||
private static final String GZIP = "gzip"; | |||
/** | |||
* BZIP2 compression | |||
*/ | |||
private static final String BZIP2 = "bzip2"; | |||
/** | |||
* Constructor | |||
*/ | |||
public UntarCompressionMethod() { | |||
super(); | |||
setValue(NONE); | |||
} | |||
/** | |||
* Get valid enumeration values | |||
* | |||
* @return valid values | |||
*/ | |||
public String[] getValues() { | |||
return new String[] { NONE, GZIP, BZIP2 }; | |||
} | |||
/** | |||
* This method wraps the input stream with the | |||
* corresponding decompression method | |||
* | |||
* @param file provides location information for BuildException | |||
* @param istream input stream | |||
* @return input stream with on-the-fly decompression | |||
* @exception IOException thrown by GZIPInputStream constructor | |||
* @exception BuildException thrown if bzip stream does not | |||
* start with expected magic values | |||
*/ | |||
private InputStream decompress(final File file, | |||
final InputStream istream) | |||
throws IOException, BuildException { | |||
final String value = getValue(); | |||
if (GZIP.equals(value)) { | |||
return new GZIPInputStream(istream); | |||
} else { | |||
if (BZIP2.equals(value)) { | |||
final char[] magic = new char[] { 'B', 'Z' }; | |||
for (int i = 0; i < magic.length; i++) { | |||
if (istream.read() != magic[i]) { | |||
throw new BuildException( | |||
"Invalid bz2 file." + file.toString()); | |||
} | |||
} | |||
return new CBZip2InputStream(istream); | |||
} | |||
} | |||
return istream; | |||
} | |||
} | |||
} |
@@ -298,7 +298,15 @@ public class CBZip2InputStream extends InputStream implements BZip2Constants { | |||
} | |||
private void bsFinishedWithStream() { | |||
bsStream = null; | |||
try { | |||
if (this.bsStream != null) { | |||
if (this.bsStream != System.in) { | |||
this.bsStream.close(); | |||
this.bsStream= null; | |||
} | |||
} | |||
} catch (IOException ioe) { | |||
} | |||
} | |||
private void bsSetStream(InputStream f) { | |||
@@ -124,6 +124,29 @@ public class TarTest extends BuildFileTest { | |||
} | |||
} | |||
public void test9() { | |||
expectBuildException("test9", "Invalid value specified for compression attribute."); | |||
} | |||
public void test10() { | |||
executeTarget("test10"); | |||
java.io.File f1 | |||
= new java.io.File("src/etc/testcases/taskdefs/test10.xml"); | |||
if (! f1.exists()) { | |||
fail("The fullpath attribute or the preserveLeadingSlashes attribute does not work propertly"); | |||
} | |||
} | |||
public void test11() { | |||
executeTarget("test11"); | |||
java.io.File f1 | |||
= new java.io.File("src/etc/testcases/taskdefs/test11.xml"); | |||
if (! f1.exists()) { | |||
fail("The fullpath attribute or the preserveLeadingSlashes attribute does not work propertly"); | |||
} | |||
} | |||
public void tearDown() { | |||
executeTarget("cleanup"); | |||
} | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2001 The Apache Software Foundation. All rights | |||
* Copyright (c) 2001-2002 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
@@ -82,6 +82,20 @@ public class UntarTest extends BuildFileTest { | |||
project.resolveFile("asf-logo.gif"))); | |||
} | |||
public void testRealGzipTest() throws java.io.IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
executeTarget("realGzipTest"); | |||
assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), | |||
project.resolveFile("asf-logo.gif"))); | |||
} | |||
public void testRealBzip2Test() throws java.io.IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
executeTarget("realBzip2Test"); | |||
assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), | |||
project.resolveFile("asf-logo.gif"))); | |||
} | |||
public void testTestTarTask() throws java.io.IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
executeTarget("testTarTask"); | |||
@@ -89,6 +103,20 @@ public class UntarTest extends BuildFileTest { | |||
project.resolveFile("asf-logo.gif"))); | |||
} | |||
public void testTestGzipTarTask() throws java.io.IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
executeTarget("testGzipTarTask"); | |||
assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), | |||
project.resolveFile("asf-logo.gif"))); | |||
} | |||
public void testTestBzip2TarTask() throws java.io.IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
executeTarget("testBzip2TarTask"); | |||
assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), | |||
project.resolveFile("asf-logo.gif"))); | |||
} | |||
public void testSrcDirTest() throws java.io.IOException { | |||
FileUtils fileUtils = FileUtils.newFileUtils(); | |||
expectBuildException("srcDirTest", "Src cannot be a directory."); | |||