Browse Source

Implement and document a compression attribute for the tar and untar tasks.

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-ffa450edef68
master
Magesh Umasankar 23 years ago
parent
commit
ccef0f8982
12 changed files with 337 additions and 20 deletions
  1. +5
    -0
      WHATSNEW
  2. +9
    -2
      docs/manual/CoreTasks/tar.html
  3. +9
    -1
      docs/manual/CoreTasks/unzip.html
  4. BIN
      src/etc/testcases/taskdefs/expected/asf-logo.gif.tar.bz2
  5. BIN
      src/etc/testcases/taskdefs/expected/asf-logo.gif.tar.gz
  6. +35
    -0
      src/etc/testcases/taskdefs/tar.xml
  7. +21
    -0
      src/etc/testcases/taskdefs/untar.xml
  8. +97
    -13
      src/main/org/apache/tools/ant/taskdefs/Tar.java
  9. +100
    -2
      src/main/org/apache/tools/ant/taskdefs/Untar.java
  10. +9
    -1
      src/main/org/apache/tools/bzip2/CBZip2InputStream.java
  11. +23
    -0
      src/testcases/org/apache/tools/ant/taskdefs/TarTest.java
  12. +29
    -1
      src/testcases/org/apache/tools/ant/taskdefs/UntarTest.java

+ 5
- 0
WHATSNEW View File

@@ -109,6 +109,11 @@ Fixed bugs:


Other changes: 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. * New optional type, <classfileset> added.


* <ejbjar> now allows control over which additional classes and interfaces * <ejbjar> now allows control over which additional classes and interfaces


+ 9
- 2
docs/manual/CoreTasks/tar.html View File

@@ -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 that it produces a warning for each file path encountered that does not match
the limit.</p> 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> <h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0"> <table border="1" cellpadding="2" cellspacing="0">
@@ -99,6 +99,13 @@ the limit.</p>
(&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td> (&quot;yes&quot;/&quot;no&quot;). Default excludes are used when omitted.</td>
<td valign="top" align="center">No</td> <td valign="top" align="center">No</td>
</tr> </tr>
<tr>
<td valign="top">compression</td>
<td valign="top">compression method. Allowable values are
&quot;none&quot;, &quot;gzip&quot; and &quot;bzip2&quot;. Default is
&quot;none&quot;.</td>
<td valign="top" align="center">No</td>
</tr>
</table> </table>


<h3>Nested Elements</h3> <h3>Nested Elements</h3>


+ 9
- 1
docs/manual/CoreTasks/unzip.html View File

@@ -44,6 +44,14 @@ to perform unarchival upon.
true).</td> true).</td>
<td align="center" valign="top">No</td> <td align="center" valign="top">No</td>
</tr> </tr>
<tr>
<td valign="top">compression</td>
<td valign="top">compression method for untar. Allowable values are
&quot;none&quot;, &quot;gzip&quot; and &quot;bzip2&quot;. Default is
&quot;none&quot;.</td>
<td valign="top" align="center">No</td>
</tr>

</table> </table>
<h3>Examples</h3> <h3>Examples</h3>
<blockquote> <blockquote>
@@ -82,7 +90,7 @@ to perform unarchival upon.
</pre></p> </pre></p>
</blockquote> </blockquote>
<hr> <hr>
<p align="center">Copyright &copy; 2001 Apache Software Foundation. All rights
<p align="center">Copyright &copy; 2001-2002 Apache Software Foundation. All rights
Reserved.</p> Reserved.</p>


</body> </body>


BIN
src/etc/testcases/taskdefs/expected/asf-logo.gif.tar.bz2 View File


BIN
src/etc/testcases/taskdefs/expected/asf-logo.gif.tar.gz View File


+ 35
- 0
src/etc/testcases/taskdefs/tar.xml View File

@@ -53,6 +53,28 @@
<untar src="test8.tar" dest="."/> <untar src="test8.tar" dest="."/>
</target> </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"> <target name="cleanup">
<delete file="test4.tar"/> <delete file="test4.tar"/>
<delete file="test5.tar"/> <delete file="test5.tar"/>
@@ -63,12 +85,25 @@
<delete file="test7.tar"/> <delete file="test7.tar"/>
<delete file="test8.tar"/> <delete file="test8.tar"/>
<delete file="test8.xml"/> <delete file="test8.xml"/>
<delete file="test10.tar.gz"/>
<delete file="test10.xml"/>
<delete file="test11.tar.bz2"/>
<delete file="test11.xml"/>
</target> </target>


<target name="feather"> <target name="feather">
<tar destfile="asf-logo.gif.tar" <tar destfile="asf-logo.gif.tar"
basedir=".." basedir=".."
includes="asf-logo.gif" /> 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> </target>



</project> </project>

+ 21
- 0
src/etc/testcases/taskdefs/untar.xml View File

@@ -12,10 +12,31 @@
<ant antfile="tar.xml" target="cleanup" /> <ant antfile="tar.xml" target="cleanup" />
</target> </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"> <target name="realTest">
<untar src="expected/asf-logo.gif.tar" dest="." /> <untar src="expected/asf-logo.gif.tar" dest="." />
</target> </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"> <target name="srcDirTest">
<untar src="." dest="." /> <untar src="." dest="." />
</target> </target>


+ 97
- 13
src/main/org/apache/tools/ant/taskdefs/Tar.java View File

@@ -57,7 +57,9 @@ package org.apache.tools.ant.taskdefs;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.BufferedOutputStream;
import java.util.Vector; import java.util.Vector;
import java.util.Enumeration; import java.util.Enumeration;
import org.apache.tools.ant.BuildException; 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.TarOutputStream;
import org.apache.tools.tar.TarConstants; import org.apache.tools.tar.TarConstants;
import org.apache.tools.tar.TarEntry; import org.apache.tools.tar.TarEntry;
import java.util.zip.GZIPOutputStream;
import org.apache.tools.bzip2.CBZip2OutputStream;




/** /**
* Creates a TAR archive. * Creates a TAR archive.
* *
* @author Stefano Mazzocchi
* @author Stefano Mazzocchi
* <a href="mailto:stefano@apache.org">stefano@apache.org</a> * <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:stefan.bodewig@epost.de">Stefan Bodewig</a>
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</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 boolean longWarningGiven = false;


private TarCompressionMethod compression = new TarCompressionMethod();

public TarFileSet createTarFileSet() { public TarFileSet createTarFileSet() {
TarFileSet fileset = new TarFileSet(); TarFileSet fileset = new TarFileSet();
filesets.addElement(fileset); filesets.addElement(fileset);
@@ -191,6 +199,18 @@ public class Tar extends MatchingTask {
this.longFileMode = mode; 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 { public void execute() throws BuildException {
if (tarFile == null) { if (tarFile == null) {
throw new BuildException("tarfile attribute must be set!", throw new BuildException("tarfile attribute must be set!",
@@ -211,7 +231,7 @@ public class Tar extends MatchingTask {
try { try {
if (baseDir != null) { if (baseDir != null) {
if (!baseDir.exists()) { if (!baseDir.exists()) {
throw new BuildException("basedir does not exist!",
throw new BuildException("basedir does not exist!",
location); location);
} }


@@ -226,7 +246,7 @@ public class Tar extends MatchingTask {
+ "attribute or some nested filesets.", + "attribute or some nested filesets.",
location); location);
} }
// check if tar is out of date with respect to each // check if tar is out of date with respect to each
// fileset // fileset
boolean upToDate = true; boolean upToDate = true;
@@ -239,7 +259,7 @@ public class Tar extends MatchingTask {
} }


for (int i = 0; i < files.length; ++i) { 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]))) { files[i]))) {
throw new BuildException("A tar file cannot include " throw new BuildException("A tar file cannot include "
+ "itself", location); + "itself", location);
@@ -257,7 +277,10 @@ public class Tar extends MatchingTask {


TarOutputStream tOut = null; TarOutputStream tOut = null;
try { try {
tOut = new TarOutputStream(new FileOutputStream(tarFile));
tOut = new TarOutputStream(
compression.compress(
new BufferedOutputStream(
new FileOutputStream(tarFile))));
tOut.setDebug(true); tOut.setDebug(true);
if (longFileMode.isTruncateMode()) { if (longFileMode.isTruncateMode()) {
tOut.setLongFileMode(TarOutputStream.LONGFILE_TRUNCATE); tOut.setLongFileMode(TarOutputStream.LONGFILE_TRUNCATE);
@@ -270,13 +293,13 @@ public class Tar extends MatchingTask {
} }


longWarningGiven = false; longWarningGiven = false;
for (Enumeration e = filesets.elements();
for (Enumeration e = filesets.elements();
e.hasMoreElements();) { e.hasMoreElements();) {
TarFileSet fs = (TarFileSet) e.nextElement(); TarFileSet fs = (TarFileSet) e.nextElement();
String[] files = fs.getFiles(project); String[] files = fs.getFiles(project);
if (files.length > 1 && fs.getFullpath().length() > 0) { if (files.length > 1 && fs.getFullpath().length() > 0) {
throw new BuildException("fullpath attribute may only " throw new BuildException("fullpath attribute may only "
+ "be specified for "
+ "be specified for "
+ "filesets that specify a " + "filesets that specify a "
+ "single file."); + "single file.");
} }
@@ -315,11 +338,11 @@ public class Tar extends MatchingTask {
if (vPath.length() <= 0) { if (vPath.length() <= 0) {
return; return;
} }
if (file.isDirectory() && !vPath.endsWith("/")) { if (file.isDirectory() && !vPath.endsWith("/")) {
vPath += "/"; vPath += "/";
} }
String prefix = tarFileSet.getPrefix(); String prefix = tarFileSet.getPrefix();
// '/' is appended for compatibility with the zip task. // '/' is appended for compatibility with the zip task.
if (prefix.length() > 0 && !prefix.endsWith("/")) { if (prefix.length() > 0 && !prefix.endsWith("/")) {
@@ -333,7 +356,7 @@ public class Tar extends MatchingTask {
if (l <= 1) { if (l <= 1) {
// we would end up adding "" to the archive // we would end up adding "" to the archive
return; return;
}
}
vPath = vPath.substring(1, l); vPath = vPath.substring(1, l);
} }


@@ -344,11 +367,11 @@ public class Tar extends MatchingTask {
return; return;
} else if (longFileMode.isWarnMode()) { } else if (longFileMode.isWarnMode()) {
log("Entry: " + vPath + " longer than " + log("Entry: " + vPath + " longer than " +
TarConstants.NAMELEN + " characters.",
TarConstants.NAMELEN + " characters.",
Project.MSG_WARN); Project.MSG_WARN);
if (!longWarningGiven) { if (!longWarningGiven) {
log("Resulting tar file can only be processed " log("Resulting tar file can only be processed "
+ "successfully by GNU compatible tar commands",
+ "successfully by GNU compatible tar commands",
Project.MSG_WARN); Project.MSG_WARN);
longWarningGiven = true; longWarningGiven = true;
} }
@@ -406,7 +429,7 @@ public class Tar extends MatchingTask {
private String prefix = ""; private String prefix = "";
private String fullpath = ""; private String fullpath = "";
private boolean preserveLeadingSlashes = false; private boolean preserveLeadingSlashes = false;
public TarFileSet(FileSet fileset) { public TarFileSet(FileSet fileset) {
super(fileset); super(fileset);
} }
@@ -528,4 +551,65 @@ public class Tar extends MatchingTask {
return OMIT.equalsIgnoreCase(getValue()); 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;
}
}
} }

+ 100
- 2
src/main/org/apache/tools/ant/taskdefs/Untar.java View File

@@ -61,7 +61,13 @@ import org.apache.tools.tar.TarEntry;
import org.apache.tools.ant.util.FileUtils; import org.apache.tools.ant.util.FileUtils;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.IOException; 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" * @ant.task category="packaging"
*/ */
public class Untar extends Expand { 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) { protected void expandFile(FileUtils fileUtils, File srcF, File dir) {
TarInputStream tis = null; TarInputStream tis = null;
try { try {
log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO); 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; TarEntry te = null;


while ((te = tis.getNextEntry()) != 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;
}
}
} }

+ 9
- 1
src/main/org/apache/tools/bzip2/CBZip2InputStream.java View File

@@ -298,7 +298,15 @@ public class CBZip2InputStream extends InputStream implements BZip2Constants {
} }


private void bsFinishedWithStream() { 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) { private void bsSetStream(InputStream f) {


+ 23
- 0
src/testcases/org/apache/tools/ant/taskdefs/TarTest.java View File

@@ -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() { public void tearDown() {
executeTarget("cleanup"); executeTarget("cleanup");
} }


+ 29
- 1
src/testcases/org/apache/tools/ant/taskdefs/UntarTest.java View File

@@ -1,7 +1,7 @@
/* /*
* The Apache Software License, Version 1.1 * 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. * reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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"))); 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 { public void testTestTarTask() throws java.io.IOException {
FileUtils fileUtils = FileUtils.newFileUtils(); FileUtils fileUtils = FileUtils.newFileUtils();
executeTarget("testTarTask"); executeTarget("testTarTask");
@@ -89,6 +103,20 @@ public class UntarTest extends BuildFileTest {
project.resolveFile("asf-logo.gif"))); 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 { public void testSrcDirTest() throws java.io.IOException {
FileUtils fileUtils = FileUtils.newFileUtils(); FileUtils fileUtils = FileUtils.newFileUtils();
expectBuildException("srcDirTest", "Src cannot be a directory."); expectBuildException("srcDirTest", "Src cannot be a directory.");


Loading…
Cancel
Save