diff --git a/docs/manual/CoreTasks/unzip.html b/docs/manual/CoreTasks/unzip.html index 5e578404b..8f9bbfe9a 100644 --- a/docs/manual/CoreTasks/unzip.html +++ b/docs/manual/CoreTasks/unzip.html @@ -15,9 +15,12 @@ carried from the archive file.

PatternSets are used to select files to extract from the archive. If no patternset is used, all files are extracted.

-

FileSets may be used used to select archived files +

FileSets may be used to select archived files to perform unarchival upon.

+

You can define filename transformations by using a nested mapper element. The default mapper is the +identity mapper. +

File permissions will not be restored on extracted files.

The untar task recognizes the long pathname entries used by GNU tar.

Parameters

@@ -102,6 +105,16 @@ to perform unarchival upon. </unzip>

+
+

+<unzip src="apache-ant-bin.zip" dest="${tools.home}">
+    <patternset>
+        <include name="apache-ant/lib/ant.jar"/>
+    </patternset>
+    <mapper type="flatten"/>
+</unzip>
+

+

Copyright © 2000-2004 The Apache Software Foundation. All rights Reserved.

diff --git a/src/etc/testcases/taskdefs/unzip.xml b/src/etc/testcases/taskdefs/unzip.xml index 80f902b17..18d2345da 100644 --- a/src/etc/testcases/taskdefs/unzip.xml +++ b/src/etc/testcases/taskdefs/unzip.xml @@ -93,4 +93,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/org/apache/tools/ant/taskdefs/Expand.java b/src/main/org/apache/tools/ant/taskdefs/Expand.java index 3af5a1264..b4f547814 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Expand.java +++ b/src/main/org/apache/tools/ant/taskdefs/Expand.java @@ -30,9 +30,13 @@ import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.Mapper; import org.apache.tools.ant.types.PatternSet; import org.apache.tools.ant.types.selectors.SelectorUtils; +import org.apache.tools.ant.util.FileNameMapper; import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.util.FlatFileNameMapper; +import org.apache.tools.ant.util.IdentityMapper; import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipFile; @@ -50,12 +54,14 @@ public class Expand extends Task { private File dest; //req private File source; // req private boolean overwrite = true; + private Mapper mapperElement = null; private Vector patternsets = new Vector(); private Vector filesets = new Vector(); private static final String NATIVE_ENCODING = "native-encoding"; private String encoding = "UTF8"; + public static final String ERROR_MULTIPLE_MAPPERS = "Cannot define more than one mapper"; /** * Do the work. @@ -106,12 +112,17 @@ public class Expand extends Task { } } - /* + /** * This method is to be overridden by extending unarchival tasks. + * + * @param fileUtils + * @param srcF + * @param dir */ protected void expandFile(FileUtils fileUtils, File srcF, File dir) { log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO); ZipFile zf = null; + FileNameMapper mapper = getMapper(); try { zf = new ZipFile(srcF, encoding); Enumeration e = zf.getEntries(); @@ -119,7 +130,7 @@ public class Expand extends Task { ZipEntry ze = (ZipEntry) e.nextElement(); extractFile(fileUtils, srcF, dir, zf.getInputStream(ze), ze.getName(), new Date(ze.getTime()), - ze.isDirectory()); + ze.isDirectory(), mapper); } log("expand complete", Project.MSG_VERBOSE); @@ -127,20 +138,40 @@ public class Expand extends Task { throw new BuildException("Error while expanding " + srcF.getPath(), ioe); } finally { - if (zf != null) { - try { - zf.close(); - } catch (IOException e) { - //ignore - } - } + ZipFile.closeQuietly(zf); + } + } + + /** + * get a mapper for a file + * @return + */ + protected FileNameMapper getMapper() { + FileNameMapper mapper = null; + if (mapperElement != null) { + mapper = mapperElement.getImplementation(); + } else { + mapper = new IdentityMapper(); } + return mapper; } + /** + * extract a file to a directory + * @param fileUtils + * @param srcF + * @param dir + * @param compressedInputStream + * @param entryName + * @param entryDate + * @param isDirectory + * @param mapper + * @throws IOException + */ protected void extractFile(FileUtils fileUtils, File srcF, File dir, InputStream compressedInputStream, - String entryName, - Date entryDate, boolean isDirectory) + String entryName, Date entryDate, + boolean isDirectory, FileNameMapper mapper) throws IOException { if (patternsets != null && patternsets.size() > 0) { @@ -194,7 +225,11 @@ public class Expand extends Task { return; } } - File f = fileUtils.resolveFile(dir, entryName); + String[] mappedNames = mapper.mapFileName(entryName); + if (mappedNames == null || mappedNames.length == 0) { + mappedNames = new String[] { entryName }; + } + File f = fileUtils.resolveFile(dir, mappedNames[0]); try { if (!overwrite && f.exists() && f.lastModified() >= entryDate.getTime()) { @@ -286,6 +321,21 @@ public class Expand extends Task { filesets.addElement(set); } + /** + * Defines the mapper to map source entries to destination files. + * @return a mapper to be configured + * @exception BuildException if more than one mapper is defined + * @since Ant1.7 + */ + public Mapper createMapper() throws BuildException { + if (mapperElement != null) { + throw new BuildException(ERROR_MULTIPLE_MAPPERS, + getLocation()); + } + mapperElement = new Mapper(getProject()); + return mapperElement; + } + /** * Sets the encoding to assume for file names and comments. * diff --git a/src/main/org/apache/tools/ant/taskdefs/Untar.java b/src/main/org/apache/tools/ant/taskdefs/Untar.java index 06f6b401e..fce05146e 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Untar.java +++ b/src/main/org/apache/tools/ant/taskdefs/Untar.java @@ -26,7 +26,10 @@ import java.util.zip.GZIPInputStream; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.util.FileNameMapper; import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.util.FlatFileNameMapper; +import org.apache.tools.ant.util.IdentityMapper; import org.apache.tools.bzip2.CBZip2InputStream; import org.apache.tools.tar.TarEntry; import org.apache.tools.tar.TarInputStream; @@ -92,10 +95,11 @@ public class Untar extends Expand { new BufferedInputStream( new FileInputStream(srcF)))); TarEntry te = null; - + FileNameMapper mapper = getMapper(); while ((te = tis.getNextEntry()) != null) { extractFile(fileUtils, srcF, dir, tis, - te.getName(), te.getModTime(), te.isDirectory()); + te.getName(), te.getModTime(), + te.isDirectory(), mapper); } log("expand complete", Project.MSG_VERBOSE); @@ -103,13 +107,7 @@ public class Untar extends Expand { throw new BuildException("Error while expanding " + srcF.getPath(), ioe, getLocation()); } finally { - if (tis != null) { - try { - tis.close(); - } catch (IOException e) { - // ignore - } - } + FileUtils.close(tis); } } diff --git a/src/main/org/apache/tools/zip/ZipFile.java b/src/main/org/apache/tools/zip/ZipFile.java index 6afa720dd..6710c7412 100644 --- a/src/main/org/apache/tools/zip/ZipFile.java +++ b/src/main/org/apache/tools/zip/ZipFile.java @@ -160,6 +160,21 @@ public class ZipFile { archive.close(); } + /** + * close a zipfile quietly; throw no io fault, do nothing + * on a null parameter + * @param zipfile file to close, can be null + */ + public static void closeQuietly(ZipFile zipfile) { + if (zipfile != null) { + try { + zipfile.close(); + } catch (IOException e) { + //ignore + } + } + } + /** * Returns all entries. * @return all entries as {@link ZipEntry} instances diff --git a/src/testcases/org/apache/tools/ant/taskdefs/UnzipTest.java b/src/testcases/org/apache/tools/ant/taskdefs/UnzipTest.java index 5326bcb9f..9b7010f42 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/UnzipTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/UnzipTest.java @@ -19,6 +19,8 @@ package org.apache.tools.ant.taskdefs; import org.apache.tools.ant.BuildFileTest; import org.apache.tools.ant.util.FileUtils; +import java.io.IOException; + /** */ public class UnzipTest extends BuildFileTest { @@ -49,24 +51,28 @@ public class UnzipTest extends BuildFileTest { public void testRealTest() throws java.io.IOException { - FileUtils fileUtils = FileUtils.newFileUtils(); executeTarget("realTest"); + assertLogoUncorrupted(); + } + + /** + * test that the logo gif file has not been corrupted + * @throws IOException + */ + private void assertLogoUncorrupted() throws IOException { + FileUtils fileUtils = FileUtils.newFileUtils(); assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), project.resolveFile("asf-logo.gif"))); } public void testTestZipTask() throws java.io.IOException { - FileUtils fileUtils = FileUtils.newFileUtils(); executeTarget("testZipTask"); - assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), - project.resolveFile("asf-logo.gif"))); + assertLogoUncorrupted(); } public void testTestUncompressedZipTask() throws java.io.IOException { - FileUtils fileUtils = FileUtils.newFileUtils(); executeTarget("testUncompressedZipTask"); - assertTrue(fileUtils.contentEquals(project.resolveFile("../asf-logo.gif"), - project.resolveFile("asf-logo.gif"))); + assertLogoUncorrupted(); } /* @@ -74,10 +80,8 @@ public class UnzipTest extends BuildFileTest { */ public void testPatternSetExcludeOnly() { executeTarget("testPatternSetExcludeOnly"); - assertTrue("1/foo is excluded", - !getProject().resolveFile("unziptestout/1/foo").exists()); - assertTrue("2/bar is not excluded", - getProject().resolveFile("unziptestout/2/bar").exists()); + assertFileMissing("1/foo is excluded", "unziptestout/1/foo"); + assertFileExists("2/bar is not excluded", "unziptestout/2/bar"); } /* @@ -85,10 +89,8 @@ public class UnzipTest extends BuildFileTest { */ public void testPatternSetIncludeOnly() { executeTarget("testPatternSetIncludeOnly"); - assertTrue("1/foo is not included", - !getProject().resolveFile("unziptestout/1/foo").exists()); - assertTrue("2/bar is included", - getProject().resolveFile("unziptestout/2/bar").exists()); + assertFileMissing("1/foo is not included", "unziptestout/1/foo"); + assertFileExists("2/bar is included", "unziptestout/2/bar"); } /* @@ -96,10 +98,8 @@ public class UnzipTest extends BuildFileTest { */ public void testPatternSetIncludeAndExclude() { executeTarget("testPatternSetIncludeAndExclude"); - assertTrue("1/foo is not included", - !getProject().resolveFile("unziptestout/1/foo").exists()); - assertTrue("2/bar is excluded", - !getProject().resolveFile("unziptestout/2/bar").exists()); + assertFileMissing("1/foo is not included", "unziptestout/1/foo"); + assertFileMissing("2/bar is excluded", "unziptestout/2/bar"); } /* @@ -115,19 +115,60 @@ public class UnzipTest extends BuildFileTest { */ public void testPatternSetSlashOnly() { executeTarget("testPatternSetSlashOnly"); - assertTrue("1/foo is not included", - !getProject().resolveFile("unziptestout/1/foo").exists()); - assertTrue("2/bar is included", - getProject().resolveFile("unziptestout/2/bar").exists()); + assertFileMissing("1/foo is not included", "unziptestout/1/foo"); + assertFileExists("\"2/bar is included", "unziptestout/2/bar"); } + /* * PR 10504 */ public void testEncoding() { executeTarget("encodingTest"); - assertTrue("foo has been properly named", - getProject().resolveFile("unziptestout/foo").exists()); + assertFileExists("foo has been properly named", "unziptestout/foo"); + } + + /* + * PR 21996 + */ + public void testFlattenMapper() { + executeTarget("testFlattenMapper"); + assertFileMissing("1/foo is not flattened", "unziptestout/1/foo"); + assertFileExists("foo is flattened", "unziptestout/foo"); + } + + /** + * assert that a file exists, relative to the project + * @param message message if there is no mpatch + * @param filename filename to resolve against the project + */ + private void assertFileExists(String message, String filename) { + assertTrue(message, + getProject().resolveFile(filename).exists()); + } + + /** + * assert that a file doesnt exist, relative to the project + * + * @param message message if there is no mpatch + * @param filename filename to resolve against the project + */ + private void assertFileMissing(String message, String filename) { + assertTrue(message, + !getProject().resolveFile(filename).exists()); + } + + /** + * PR 21996 + */ + public void testGlobMapper() { + executeTarget("testGlobMapper"); + assertFileMissing("1/foo is not mapped", "unziptestout/1/foo"); + assertFileExists("1/foo is mapped", "unziptestout/1/foo.txt"); + } + + public void testTwoMappers() { + expectBuildException("testTwoMappers",Expand.ERROR_MULTIPLE_MAPPERS); } }