From ad9c15103d9a4829b0c16c5187066008efd70f9b Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Thu, 3 Jul 2003 08:30:11 +0000 Subject: [PATCH] Finish implementation of ZipFile, use it in Expand (AKA ). git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274743 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/tools/ant/taskdefs/Expand.java | 52 +++-------- src/main/org/apache/tools/zip/ZipFile.java | 87 ++++++++++++++++++- .../apache/tools/ant/taskdefs/UnzipTest.java | 4 +- 3 files changed, 98 insertions(+), 45 deletions(-) diff --git a/src/main/org/apache/tools/ant/taskdefs/Expand.java b/src/main/org/apache/tools/ant/taskdefs/Expand.java index 7a5441f5d..cbea9be85 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Expand.java +++ b/src/main/org/apache/tools/ant/taskdefs/Expand.java @@ -56,16 +56,13 @@ package org.apache.tools.ant.taskdefs; import java.io.File; import java.io.FileInputStream; -import java.io.RandomAccessFile; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.IOException; -import java.util.Arrays; import java.util.Date; +import java.util.Enumeration; import java.util.Vector; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipEntry; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; @@ -74,6 +71,8 @@ import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.PatternSet; import org.apache.tools.ant.types.selectors.SelectorUtils; import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.zip.ZipEntry; +import org.apache.tools.zip.ZipFile; /** * Unzip a file. @@ -154,37 +153,13 @@ public class Expand extends Task { */ protected void expandFile(FileUtils fileUtils, File srcF, File dir) { log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO); - ZipInputStream zis = null; - FileInputStream fis = null; - RandomAccessFile raf = null; - byte[] buff = new byte[MARKER_SIZE]; + ZipFile zf = null; try { - raf = new RandomAccessFile(srcF, "r"); - long offset = 0; - int more = raf.read(buff); - boolean foundMarker = false; - while (more != -1 || offset < MAX_LOOKAHEAD) { - if (Arrays.equals(buff, ZIPMARKER)) { - foundMarker = true; - break; - } - raf.seek(++offset); - more = raf.read(buff); - } - raf.close(); - raf = null; - - fis = new FileInputStream(srcF); - if (foundMarker && offset > 0) { - log("found a preamble of " + offset - + " bytes, probably a self-extracting archive"); - fis.skip(offset); - } - - zis = new ZipInputStream(fis); - ZipEntry ze = null; - while ((ze = zis.getNextEntry()) != null) { - extractFile(fileUtils, srcF, dir, zis, + zf = new ZipFile(srcF, "UTF8"); + Enumeration enum = zf.getEntries(); + while (enum.hasMoreElements()) { + ZipEntry ze = (ZipEntry) enum.nextElement(); + extractFile(fileUtils, srcF, dir, zf.getInputStream(ze), ze.getName(), new Date(ze.getTime()), ze.isDirectory()); } @@ -194,14 +169,9 @@ public class Expand extends Task { throw new BuildException("Error while expanding " + srcF.getPath(), ioe); } finally { - if (raf != null) { - try { - raf.close(); - } catch (IOException e) {} - } - if (zis != null) { + if (zf != null) { try { - zis.close(); + zf.close(); } catch (IOException e) {} } } diff --git a/src/main/org/apache/tools/zip/ZipFile.java b/src/main/org/apache/tools/zip/ZipFile.java index 29ed4f21e..5fb74d219 100644 --- a/src/main/org/apache/tools/zip/ZipFile.java +++ b/src/main/org/apache/tools/zip/ZipFile.java @@ -63,6 +63,8 @@ import java.util.Calendar; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; +import java.util.zip.Inflater; +import java.util.zip.InflaterInputStream; import java.util.zip.ZipException; /** @@ -202,7 +204,22 @@ public class ZipFile { */ public InputStream getInputStream(ZipEntry ze) throws IOException, ZipException { - return null; + Long start = (Long) dataOffsets.get(ze); + if (start == null) { + return null; + } + BoundedInputStream bis = + new BoundedInputStream(start.longValue(), ze.getCompressedSize()); + switch (ze.getMethod()) { + case ZipEntry.STORED: + return bis; + case ZipEntry.DEFLATED: + bis.addDummy(); + return new InflaterInputStream(bis, new Inflater(true)); + default: + throw new ZipException("Found unsupported compression method " + + ze.getMethod()); + } } private static final int CFH_LEN = @@ -414,4 +431,72 @@ public class ZipFile { } } + /** + * InputStream that delegates requests to the underlying + * RandomAccessFile, making sure that only bytes from a certain + * range can be read. + */ + private class BoundedInputStream extends InputStream { + private long start, remaining; + private long loc; + private boolean addDummyByte = false; + + BoundedInputStream(long start, long remaining) { + this.start = start; + this.remaining = remaining; + loc = start; + } + + public int read() throws IOException { + if (remaining-- <= 0) { + if (addDummyByte) { + addDummyByte = false; + return 0; + } + return -1; + } + synchronized (archive) { + archive.seek(loc++); + return archive.read(); + } + } + + public int read(byte[] b, int off, int len) throws IOException { + if (remaining <= 0) { + if (addDummyByte) { + addDummyByte = false; + b[off] = 0; + return 1; + } + return -1; + } + + if (len <= 0) { + return 0; + } + + if (len > remaining) { + len = (int) remaining; + } + int ret = -1; + synchronized (archive) { + archive.seek(loc); + ret = archive.read(b, off, len); + } + if (ret > 0) { + loc += ret; + remaining -= ret; + } + return ret; + } + + /** + * Inflater needs an extra dummy byte for nowrap - see + * Inflater's javadocs. + */ + void addDummy() { + addDummyByte = true; + } + } + } diff --git a/src/testcases/org/apache/tools/ant/taskdefs/UnzipTest.java b/src/testcases/org/apache/tools/ant/taskdefs/UnzipTest.java index b7ec0cc29..103bfabec 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/UnzipTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/UnzipTest.java @@ -138,9 +138,7 @@ public class UnzipTest extends BuildFileTest { * PR 16213 */ public void testSelfExtractingArchive() { - expectLogContaining("selfExtractingArchive", - "found a preamble of 38439 bytes, " - + "probably a self-extracting archive"); + executeTarget("selfExtractingArchive"); }