git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274743 13f79535-47bb-0310-9956-ffa450edef68master
@@ -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) {} | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||
} |
@@ -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"); | |||
} | |||