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."); | |||