# HG changeset patch # User Jaroslav Tulach # Date 1359550817 -3600 # Node ID 48ef38e9677e68cc73af3a8ae86e0f6dab7f7f40 # Parent 5198affdb9157ecab40ee80ff76476d49c2d1f69 Adding classes necessary for usage of ZipInputStream diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/CRC32.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/CRC32.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +/** + * A class that can be used to compute the CRC-32 of a data stream. + * + * @see Checksum + * @author David Connelly + */ +public +class CRC32 implements Checksum { + private int crc; + + /** + * Creates a new CRC32 object. + */ + public CRC32() { + } + + + /** + * Updates the CRC-32 checksum with the specified byte (the low + * eight bits of the argument b). + * + * @param b the byte to update the checksum with + */ + public void update(int b) { + crc = update(crc, b); + } + + /** + * Updates the CRC-32 checksum with the specified array of bytes. + */ + public void update(byte[] b, int off, int len) { + if (b == null) { + throw new NullPointerException(); + } + if (off < 0 || len < 0 || off > b.length - len) { + throw new ArrayIndexOutOfBoundsException(); + } + crc = updateBytes(crc, b, off, len); + } + + /** + * Updates the CRC-32 checksum with the specified array of bytes. + * + * @param b the array of bytes to update the checksum with + */ + public void update(byte[] b) { + crc = updateBytes(crc, b, 0, b.length); + } + + /** + * Resets CRC-32 to initial value. + */ + public void reset() { + crc = 0; + } + + /** + * Returns CRC-32 value. + */ + public long getValue() { + return (long)crc & 0xffffffffL; + } + + private native static int update(int crc, int b); + private native static int updateBytes(int crc, byte[] b, int off, int len); +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/Checksum.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/Checksum.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +/** + * An interface representing a data checksum. + * + * @author David Connelly + */ +public +interface Checksum { + /** + * Updates the current checksum with the specified byte. + * + * @param b the byte to update the checksum with + */ + public void update(int b); + + /** + * Updates the current checksum with the specified array of bytes. + * @param b the byte array to update the checksum with + * @param off the start offset of the data + * @param len the number of bytes to use for the update + */ + public void update(byte[] b, int off, int len); + + /** + * Returns the current checksum value. + * @return the current checksum value + */ + public long getValue(); + + /** + * Resets the checksum to its initial value. + */ + public void reset(); +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/DataFormatException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/DataFormatException.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +/** + * Signals that a data format error has occurred. + * + * @author David Connelly + */ +public +class DataFormatException extends Exception { + private static final long serialVersionUID = 2219632870893641452L; + + /** + * Constructs a DataFormatException with no detail message. + */ + public DataFormatException() { + super(); + } + + /** + * Constructs a DataFormatException with the specified detail message. + * A detail message is a String that describes this particular exception. + * @param s the String containing a detail message + */ + public DataFormatException(String s) { + super(s); + } +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/Inflater.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/Inflater.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,402 @@ +/* + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +/** + * This class provides support for general purpose decompression using the + * popular ZLIB compression library. The ZLIB compression library was + * initially developed as part of the PNG graphics standard and is not + * protected by patents. It is fully described in the specifications at + * the java.util.zip + * package description. + * + *

The following code fragment demonstrates a trivial compression + * and decompression of a string using Deflater and + * Inflater. + * + *

+ * try {
+ *     // Encode a String into bytes
+ *     String inputString = "blahblahblah\u20AC\u20AC";
+ *     byte[] input = inputString.getBytes("UTF-8");
+ *
+ *     // Compress the bytes
+ *     byte[] output = new byte[100];
+ *     Deflater compresser = new Deflater();
+ *     compresser.setInput(input);
+ *     compresser.finish();
+ *     int compressedDataLength = compresser.deflate(output);
+ *
+ *     // Decompress the bytes
+ *     Inflater decompresser = new Inflater();
+ *     decompresser.setInput(output, 0, compressedDataLength);
+ *     byte[] result = new byte[100];
+ *     int resultLength = decompresser.inflate(result);
+ *     decompresser.end();
+ *
+ *     // Decode the bytes into a String
+ *     String outputString = new String(result, 0, resultLength, "UTF-8");
+ * } catch(java.io.UnsupportedEncodingException ex) {
+ *     // handle
+ * } catch (java.util.zip.DataFormatException ex) {
+ *     // handle
+ * }
+ * 
+ * + * @see Deflater + * @author David Connelly + * + */ +public +class Inflater { + + private final ZStreamRef zsRef; + private byte[] buf = defaultBuf; + private int off, len; + private boolean finished; + private boolean needDict; + + private static final byte[] defaultBuf = new byte[0]; + + static { + /* Zip library is loaded from System.initializeSystemClass */ + initIDs(); + } + + /** + * Creates a new decompressor. If the parameter 'nowrap' is true then + * the ZLIB header and checksum fields will not be used. This provides + * compatibility with the compression format used by both GZIP and PKZIP. + *

+ * Note: When using the 'nowrap' option it is also necessary to provide + * an extra "dummy" byte as input. This is required by the ZLIB native + * library in order to support certain optimizations. + * + * @param nowrap if true then support GZIP compatible compression + */ + public Inflater(boolean nowrap) { + zsRef = new ZStreamRef(init(nowrap)); + } + + /** + * Creates a new decompressor. + */ + public Inflater() { + this(false); + } + + /** + * Sets input data for decompression. Should be called whenever + * needsInput() returns true indicating that more input data is + * required. + * @param b the input data bytes + * @param off the start offset of the input data + * @param len the length of the input data + * @see Inflater#needsInput + */ + public void setInput(byte[] b, int off, int len) { + if (b == null) { + throw new NullPointerException(); + } + if (off < 0 || len < 0 || off > b.length - len) { + throw new ArrayIndexOutOfBoundsException(); + } + synchronized (zsRef) { + this.buf = b; + this.off = off; + this.len = len; + } + } + + /** + * Sets input data for decompression. Should be called whenever + * needsInput() returns true indicating that more input data is + * required. + * @param b the input data bytes + * @see Inflater#needsInput + */ + public void setInput(byte[] b) { + setInput(b, 0, b.length); + } + + /** + * Sets the preset dictionary to the given array of bytes. Should be + * called when inflate() returns 0 and needsDictionary() returns true + * indicating that a preset dictionary is required. The method getAdler() + * can be used to get the Adler-32 value of the dictionary needed. + * @param b the dictionary data bytes + * @param off the start offset of the data + * @param len the length of the data + * @see Inflater#needsDictionary + * @see Inflater#getAdler + */ + public void setDictionary(byte[] b, int off, int len) { + if (b == null) { + throw new NullPointerException(); + } + if (off < 0 || len < 0 || off > b.length - len) { + throw new ArrayIndexOutOfBoundsException(); + } + synchronized (zsRef) { + ensureOpen(); + setDictionary(zsRef.address(), b, off, len); + needDict = false; + } + } + + /** + * Sets the preset dictionary to the given array of bytes. Should be + * called when inflate() returns 0 and needsDictionary() returns true + * indicating that a preset dictionary is required. The method getAdler() + * can be used to get the Adler-32 value of the dictionary needed. + * @param b the dictionary data bytes + * @see Inflater#needsDictionary + * @see Inflater#getAdler + */ + public void setDictionary(byte[] b) { + setDictionary(b, 0, b.length); + } + + /** + * Returns the total number of bytes remaining in the input buffer. + * This can be used to find out what bytes still remain in the input + * buffer after decompression has finished. + * @return the total number of bytes remaining in the input buffer + */ + public int getRemaining() { + synchronized (zsRef) { + return len; + } + } + + /** + * Returns true if no data remains in the input buffer. This can + * be used to determine if #setInput should be called in order + * to provide more input. + * @return true if no data remains in the input buffer + */ + public boolean needsInput() { + synchronized (zsRef) { + return len <= 0; + } + } + + /** + * Returns true if a preset dictionary is needed for decompression. + * @return true if a preset dictionary is needed for decompression + * @see Inflater#setDictionary + */ + public boolean needsDictionary() { + synchronized (zsRef) { + return needDict; + } + } + + /** + * Returns true if the end of the compressed data stream has been + * reached. + * @return true if the end of the compressed data stream has been + * reached + */ + public boolean finished() { + synchronized (zsRef) { + return finished; + } + } + + /** + * Uncompresses bytes into specified buffer. Returns actual number + * of bytes uncompressed. A return value of 0 indicates that + * needsInput() or needsDictionary() should be called in order to + * determine if more input data or a preset dictionary is required. + * In the latter case, getAdler() can be used to get the Adler-32 + * value of the dictionary required. + * @param b the buffer for the uncompressed data + * @param off the start offset of the data + * @param len the maximum number of uncompressed bytes + * @return the actual number of uncompressed bytes + * @exception DataFormatException if the compressed data format is invalid + * @see Inflater#needsInput + * @see Inflater#needsDictionary + */ + public int inflate(byte[] b, int off, int len) + throws DataFormatException + { + if (b == null) { + throw new NullPointerException(); + } + if (off < 0 || len < 0 || off > b.length - len) { + throw new ArrayIndexOutOfBoundsException(); + } + synchronized (zsRef) { + ensureOpen(); + return inflateBytes(zsRef.address(), b, off, len); + } + } + + /** + * Uncompresses bytes into specified buffer. Returns actual number + * of bytes uncompressed. A return value of 0 indicates that + * needsInput() or needsDictionary() should be called in order to + * determine if more input data or a preset dictionary is required. + * In the latter case, getAdler() can be used to get the Adler-32 + * value of the dictionary required. + * @param b the buffer for the uncompressed data + * @return the actual number of uncompressed bytes + * @exception DataFormatException if the compressed data format is invalid + * @see Inflater#needsInput + * @see Inflater#needsDictionary + */ + public int inflate(byte[] b) throws DataFormatException { + return inflate(b, 0, b.length); + } + + /** + * Returns the ADLER-32 value of the uncompressed data. + * @return the ADLER-32 value of the uncompressed data + */ + public int getAdler() { + synchronized (zsRef) { + ensureOpen(); + return getAdler(zsRef.address()); + } + } + + /** + * Returns the total number of compressed bytes input so far. + * + *

Since the number of bytes may be greater than + * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now + * the preferred means of obtaining this information.

+ * + * @return the total number of compressed bytes input so far + */ + public int getTotalIn() { + return (int) getBytesRead(); + } + + /** + * Returns the total number of compressed bytes input so far.

+ * + * @return the total (non-negative) number of compressed bytes input so far + * @since 1.5 + */ + public long getBytesRead() { + synchronized (zsRef) { + ensureOpen(); + return getBytesRead(zsRef.address()); + } + } + + /** + * Returns the total number of uncompressed bytes output so far. + * + *

Since the number of bytes may be greater than + * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now + * the preferred means of obtaining this information.

+ * + * @return the total number of uncompressed bytes output so far + */ + public int getTotalOut() { + return (int) getBytesWritten(); + } + + /** + * Returns the total number of uncompressed bytes output so far.

+ * + * @return the total (non-negative) number of uncompressed bytes output so far + * @since 1.5 + */ + public long getBytesWritten() { + synchronized (zsRef) { + ensureOpen(); + return getBytesWritten(zsRef.address()); + } + } + + /** + * Resets inflater so that a new set of input data can be processed. + */ + public void reset() { + synchronized (zsRef) { + ensureOpen(); + reset(zsRef.address()); + buf = defaultBuf; + finished = false; + needDict = false; + off = len = 0; + } + } + + /** + * Closes the decompressor and discards any unprocessed input. + * This method should be called when the decompressor is no longer + * being used, but will also be called automatically by the finalize() + * method. Once this method is called, the behavior of the Inflater + * object is undefined. + */ + public void end() { + synchronized (zsRef) { + long addr = zsRef.address(); + zsRef.clear(); + if (addr != 0) { + end(addr); + buf = null; + } + } + } + + /** + * Closes the decompressor when garbage is collected. + */ + protected void finalize() { + end(); + } + + private void ensureOpen () { + assert Thread.holdsLock(zsRef); + if (zsRef.address() == 0) + throw new NullPointerException("Inflater has been closed"); + } + + boolean ended() { + synchronized (zsRef) { + return zsRef.address() == 0; + } + } + + private native static void initIDs(); + private native static long init(boolean nowrap); + private native static void setDictionary(long addr, byte[] b, int off, + int len); + private native int inflateBytes(long addr, byte[] b, int off, int len) + throws DataFormatException; + private native static int getAdler(long addr); + private native static long getBytesRead(long addr); + private native static long getBytesWritten(long addr); + private native static void reset(long addr); + private native static void end(long addr); +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/InflaterInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/InflaterInputStream.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,288 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +import java.io.FilterInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.EOFException; + +/** + * This class implements a stream filter for uncompressing data in the + * "deflate" compression format. It is also used as the basis for other + * decompression filters, such as GZIPInputStream. + * + * @see Inflater + * @author David Connelly + */ +public +class InflaterInputStream extends FilterInputStream { + /** + * Decompressor for this stream. + */ + protected Inflater inf; + + /** + * Input buffer for decompression. + */ + protected byte[] buf; + + /** + * Length of input buffer. + */ + protected int len; + + private boolean closed = false; + // this flag is set to true after EOF has reached + private boolean reachEOF = false; + + /** + * Check to make sure that this stream has not been closed + */ + private void ensureOpen() throws IOException { + if (closed) { + throw new IOException("Stream closed"); + } + } + + + /** + * Creates a new input stream with the specified decompressor and + * buffer size. + * @param in the input stream + * @param inf the decompressor ("inflater") + * @param size the input buffer size + * @exception IllegalArgumentException if size is <= 0 + */ + public InflaterInputStream(InputStream in, Inflater inf, int size) { + super(in); + if (in == null || inf == null) { + throw new NullPointerException(); + } else if (size <= 0) { + throw new IllegalArgumentException("buffer size <= 0"); + } + this.inf = inf; + buf = new byte[size]; + } + + /** + * Creates a new input stream with the specified decompressor and a + * default buffer size. + * @param in the input stream + * @param inf the decompressor ("inflater") + */ + public InflaterInputStream(InputStream in, Inflater inf) { + this(in, inf, 512); + } + + boolean usesDefaultInflater = false; + + /** + * Creates a new input stream with a default decompressor and buffer size. + * @param in the input stream + */ + public InflaterInputStream(InputStream in) { + this(in, new Inflater()); + usesDefaultInflater = true; + } + + private byte[] singleByteBuf = new byte[1]; + + /** + * Reads a byte of uncompressed data. This method will block until + * enough input is available for decompression. + * @return the byte read, or -1 if end of compressed input is reached + * @exception IOException if an I/O error has occurred + */ + public int read() throws IOException { + ensureOpen(); + return read(singleByteBuf, 0, 1) == -1 ? -1 : singleByteBuf[0] & 0xff; + } + + /** + * Reads uncompressed data into an array of bytes. If len is not + * zero, the method will block until some input can be decompressed; otherwise, + * no bytes are read and 0 is returned. + * @param b the buffer into which the data is read + * @param off the start offset in the destination array b + * @param len the maximum number of bytes read + * @return the actual number of bytes read, or -1 if the end of the + * compressed input is reached or a preset dictionary is needed + * @exception NullPointerException If b is null. + * @exception IndexOutOfBoundsException If off is negative, + * len is negative, or len is greater than + * b.length - off + * @exception ZipException if a ZIP format error has occurred + * @exception IOException if an I/O error has occurred + */ + public int read(byte[] b, int off, int len) throws IOException { + ensureOpen(); + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + try { + int n; + while ((n = inf.inflate(b, off, len)) == 0) { + if (inf.finished() || inf.needsDictionary()) { + reachEOF = true; + return -1; + } + if (inf.needsInput()) { + fill(); + } + } + return n; + } catch (DataFormatException e) { + String s = e.getMessage(); + throw new ZipException(s != null ? s : "Invalid ZLIB data format"); + } + } + + /** + * Returns 0 after EOF has been reached, otherwise always return 1. + *

+ * Programs should not count on this method to return the actual number + * of bytes that could be read without blocking. + * + * @return 1 before EOF and 0 after EOF. + * @exception IOException if an I/O error occurs. + * + */ + public int available() throws IOException { + ensureOpen(); + if (reachEOF) { + return 0; + } else { + return 1; + } + } + + private byte[] b = new byte[512]; + + /** + * Skips specified number of bytes of uncompressed data. + * @param n the number of bytes to skip + * @return the actual number of bytes skipped. + * @exception IOException if an I/O error has occurred + * @exception IllegalArgumentException if n < 0 + */ + public long skip(long n) throws IOException { + if (n < 0) { + throw new IllegalArgumentException("negative skip length"); + } + ensureOpen(); + int max = (int)Math.min(n, Integer.MAX_VALUE); + int total = 0; + while (total < max) { + int len = max - total; + if (len > b.length) { + len = b.length; + } + len = read(b, 0, len); + if (len == -1) { + reachEOF = true; + break; + } + total += len; + } + return total; + } + + /** + * Closes this input stream and releases any system resources associated + * with the stream. + * @exception IOException if an I/O error has occurred + */ + public void close() throws IOException { + if (!closed) { + if (usesDefaultInflater) + inf.end(); + in.close(); + closed = true; + } + } + + /** + * Fills input buffer with more data to decompress. + * @exception IOException if an I/O error has occurred + */ + protected void fill() throws IOException { + ensureOpen(); + len = in.read(buf, 0, buf.length); + if (len == -1) { + throw new EOFException("Unexpected end of ZLIB input stream"); + } + inf.setInput(buf, 0, len); + } + + /** + * Tests if this input stream supports the mark and + * reset methods. The markSupported + * method of InflaterInputStream returns + * false. + * + * @return a boolean indicating if this stream type supports + * the mark and reset methods. + * @see java.io.InputStream#mark(int) + * @see java.io.InputStream#reset() + */ + public boolean markSupported() { + return false; + } + + /** + * Marks the current position in this input stream. + * + *

The mark method of InflaterInputStream + * does nothing. + * + * @param readlimit the maximum limit of bytes that can be read before + * the mark position becomes invalid. + * @see java.io.InputStream#reset() + */ + public synchronized void mark(int readlimit) { + } + + /** + * Repositions this stream to the position at the time the + * mark method was last called on this input stream. + * + *

The method reset for class + * InflaterInputStream does nothing except throw an + * IOException. + * + * @exception IOException if this method is invoked. + * @see java.io.InputStream#mark(int) + * @see java.io.IOException + */ + public synchronized void reset() throws IOException { + throw new IOException("mark/reset not supported"); + } +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZStreamRef.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/ZStreamRef.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +/** + * A reference to the native zlib's z_stream structure. + */ + +class ZStreamRef { + + private long address; + ZStreamRef (long address) { + this.address = address; + } + + long address() { + return address; + } + + void clear() { + address = 0; + } +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipConstants.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/ZipConstants.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +/* + * This interface defines the constants that are used by the classes + * which manipulate ZIP files. + * + * @author David Connelly + */ +interface ZipConstants { + /* + * Header signatures + */ + static long LOCSIG = 0x04034b50L; // "PK\003\004" + static long EXTSIG = 0x08074b50L; // "PK\007\008" + static long CENSIG = 0x02014b50L; // "PK\001\002" + static long ENDSIG = 0x06054b50L; // "PK\005\006" + + /* + * Header sizes in bytes (including signatures) + */ + static final int LOCHDR = 30; // LOC header size + static final int EXTHDR = 16; // EXT header size + static final int CENHDR = 46; // CEN header size + static final int ENDHDR = 22; // END header size + + /* + * Local file (LOC) header field offsets + */ + static final int LOCVER = 4; // version needed to extract + static final int LOCFLG = 6; // general purpose bit flag + static final int LOCHOW = 8; // compression method + static final int LOCTIM = 10; // modification time + static final int LOCCRC = 14; // uncompressed file crc-32 value + static final int LOCSIZ = 18; // compressed size + static final int LOCLEN = 22; // uncompressed size + static final int LOCNAM = 26; // filename length + static final int LOCEXT = 28; // extra field length + + /* + * Extra local (EXT) header field offsets + */ + static final int EXTCRC = 4; // uncompressed file crc-32 value + static final int EXTSIZ = 8; // compressed size + static final int EXTLEN = 12; // uncompressed size + + /* + * Central directory (CEN) header field offsets + */ + static final int CENVEM = 4; // version made by + static final int CENVER = 6; // version needed to extract + static final int CENFLG = 8; // encrypt, decrypt flags + static final int CENHOW = 10; // compression method + static final int CENTIM = 12; // modification time + static final int CENCRC = 16; // uncompressed file crc-32 value + static final int CENSIZ = 20; // compressed size + static final int CENLEN = 24; // uncompressed size + static final int CENNAM = 28; // filename length + static final int CENEXT = 30; // extra field length + static final int CENCOM = 32; // comment length + static final int CENDSK = 34; // disk number start + static final int CENATT = 36; // internal file attributes + static final int CENATX = 38; // external file attributes + static final int CENOFF = 42; // LOC header offset + + /* + * End of central directory (END) header field offsets + */ + static final int ENDSUB = 8; // number of entries on this disk + static final int ENDTOT = 10; // total number of entries + static final int ENDSIZ = 12; // central directory size in bytes + static final int ENDOFF = 16; // offset of first CEN header + static final int ENDCOM = 20; // zip file comment length +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipConstants64.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/ZipConstants64.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +/* + * This class defines the constants that are used by the classes + * which manipulate Zip64 files. + */ + +class ZipConstants64 { + + /* + * ZIP64 constants + */ + static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006" + static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007" + static final int ZIP64_ENDHDR = 56; // ZIP64 end header size + static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size + static final int ZIP64_EXTHDR = 24; // EXT header size + static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID + + static final int ZIP64_MAGICCOUNT = 0xFFFF; + static final long ZIP64_MAGICVAL = 0xFFFFFFFFL; + + /* + * Zip64 End of central directory (END) header field offsets + */ + static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir + static final int ZIP64_ENDVEM = 12; // version made by + static final int ZIP64_ENDVER = 14; // version needed to extract + static final int ZIP64_ENDNMD = 16; // number of this disk + static final int ZIP64_ENDDSK = 20; // disk number of start + static final int ZIP64_ENDTOD = 24; // total number of entries on this disk + static final int ZIP64_ENDTOT = 32; // total number of entries + static final int ZIP64_ENDSIZ = 40; // central directory size in bytes + static final int ZIP64_ENDOFF = 48; // offset of first CEN header + static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector + + /* + * Zip64 End of central directory locator field offsets + */ + static final int ZIP64_LOCDSK = 4; // disk number start + static final int ZIP64_LOCOFF = 8; // offset of zip64 end + static final int ZIP64_LOCTOT = 16; // total number of disks + + /* + * Zip64 Extra local (EXT) header field offsets + */ + static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value + static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte + static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte + + /* + * Language encoding flag EFS + */ + static final int EFS = 0x800; // If this bit is set the filename and + // comment fields for this file must be + // encoded using UTF-8. + + private ZipConstants64() {} +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipEntry.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/ZipEntry.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,327 @@ +/* + * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +import java.util.Date; + +/** + * This class is used to represent a ZIP file entry. + * + * @author David Connelly + */ +public +class ZipEntry implements ZipConstants, Cloneable { + String name; // entry name + long time = -1; // modification time (in DOS time) + long crc = -1; // crc-32 of entry data + long size = -1; // uncompressed size of entry data + long csize = -1; // compressed size of entry data + int method = -1; // compression method + int flag = 0; // general purpose flag + byte[] extra; // optional extra field data for entry + String comment; // optional comment string for entry + + /** + * Compression method for uncompressed entries. + */ + public static final int STORED = 0; + + /** + * Compression method for compressed (deflated) entries. + */ + public static final int DEFLATED = 8; + + /** + * Creates a new zip entry with the specified name. + * + * @param name the entry name + * @exception NullPointerException if the entry name is null + * @exception IllegalArgumentException if the entry name is longer than + * 0xFFFF bytes + */ + public ZipEntry(String name) { + if (name == null) { + throw new NullPointerException(); + } + if (name.length() > 0xFFFF) { + throw new IllegalArgumentException("entry name too long"); + } + this.name = name; + } + + /** + * Creates a new zip entry with fields taken from the specified + * zip entry. + * @param e a zip Entry object + */ + public ZipEntry(ZipEntry e) { + name = e.name; + time = e.time; + crc = e.crc; + size = e.size; + csize = e.csize; + method = e.method; + flag = e.flag; + extra = e.extra; + comment = e.comment; + } + + /* + * Creates a new un-initialized zip entry + */ + ZipEntry() {} + + /** + * Returns the name of the entry. + * @return the name of the entry + */ + public String getName() { + return name; + } + + /** + * Sets the modification time of the entry. + * @param time the entry modification time in number of milliseconds + * since the epoch + * @see #getTime() + */ + public void setTime(long time) { + this.time = javaToDosTime(time); + } + + /** + * Returns the modification time of the entry, or -1 if not specified. + * @return the modification time of the entry, or -1 if not specified + * @see #setTime(long) + */ + public long getTime() { + return time != -1 ? dosToJavaTime(time) : -1; + } + + /** + * Sets the uncompressed size of the entry data. + * @param size the uncompressed size in bytes + * @exception IllegalArgumentException if the specified size is less + * than 0, is greater than 0xFFFFFFFF when + * ZIP64 format is not supported, + * or is less than 0 when ZIP64 is supported + * @see #getSize() + */ + public void setSize(long size) { + if (size < 0) { + throw new IllegalArgumentException("invalid entry size"); + } + this.size = size; + } + + /** + * Returns the uncompressed size of the entry data, or -1 if not known. + * @return the uncompressed size of the entry data, or -1 if not known + * @see #setSize(long) + */ + public long getSize() { + return size; + } + + /** + * Returns the size of the compressed entry data, or -1 if not known. + * In the case of a stored entry, the compressed size will be the same + * as the uncompressed size of the entry. + * @return the size of the compressed entry data, or -1 if not known + * @see #setCompressedSize(long) + */ + public long getCompressedSize() { + return csize; + } + + /** + * Sets the size of the compressed entry data. + * @param csize the compressed size to set to + * @see #getCompressedSize() + */ + public void setCompressedSize(long csize) { + this.csize = csize; + } + + /** + * Sets the CRC-32 checksum of the uncompressed entry data. + * @param crc the CRC-32 value + * @exception IllegalArgumentException if the specified CRC-32 value is + * less than 0 or greater than 0xFFFFFFFF + * @see #getCrc() + */ + public void setCrc(long crc) { + if (crc < 0 || crc > 0xFFFFFFFFL) { + throw new IllegalArgumentException("invalid entry crc-32"); + } + this.crc = crc; + } + + /** + * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if + * not known. + * @return the CRC-32 checksum of the uncompressed entry data, or -1 if + * not known + * @see #setCrc(long) + */ + public long getCrc() { + return crc; + } + + /** + * Sets the compression method for the entry. + * @param method the compression method, either STORED or DEFLATED + * @exception IllegalArgumentException if the specified compression + * method is invalid + * @see #getMethod() + */ + public void setMethod(int method) { + if (method != STORED && method != DEFLATED) { + throw new IllegalArgumentException("invalid compression method"); + } + this.method = method; + } + + /** + * Returns the compression method of the entry, or -1 if not specified. + * @return the compression method of the entry, or -1 if not specified + * @see #setMethod(int) + */ + public int getMethod() { + return method; + } + + /** + * Sets the optional extra field data for the entry. + * @param extra the extra field data bytes + * @exception IllegalArgumentException if the length of the specified + * extra field data is greater than 0xFFFF bytes + * @see #getExtra() + */ + public void setExtra(byte[] extra) { + if (extra != null && extra.length > 0xFFFF) { + throw new IllegalArgumentException("invalid extra field length"); + } + this.extra = extra; + } + + /** + * Returns the extra field data for the entry, or null if none. + * @return the extra field data for the entry, or null if none + * @see #setExtra(byte[]) + */ + public byte[] getExtra() { + return extra; + } + + /** + * Sets the optional comment string for the entry. + * + *

ZIP entry comments have maximum length of 0xffff. If the length of the + * specified comment string is greater than 0xFFFF bytes after encoding, only + * the first 0xFFFF bytes are output to the ZIP file entry. + * + * @param comment the comment string + * + * @see #getComment() + */ + public void setComment(String comment) { + this.comment = comment; + } + + /** + * Returns the comment string for the entry, or null if none. + * @return the comment string for the entry, or null if none + * @see #setComment(String) + */ + public String getComment() { + return comment; + } + + /** + * Returns true if this is a directory entry. A directory entry is + * defined to be one whose name ends with a '/'. + * @return true if this is a directory entry + */ + public boolean isDirectory() { + return name.endsWith("/"); + } + + /** + * Returns a string representation of the ZIP entry. + */ + public String toString() { + return getName(); + } + + /* + * Converts DOS time to Java time (number of milliseconds since epoch). + */ + private static long dosToJavaTime(long dtime) { + Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80), + (int)(((dtime >> 21) & 0x0f) - 1), + (int)((dtime >> 16) & 0x1f), + (int)((dtime >> 11) & 0x1f), + (int)((dtime >> 5) & 0x3f), + (int)((dtime << 1) & 0x3e)); + return d.getTime(); + } + + /* + * Converts Java time to DOS time. + */ + private static long javaToDosTime(long time) { + Date d = new Date(time); + int year = d.getYear() + 1900; + if (year < 1980) { + return (1 << 21) | (1 << 16); + } + return (year - 1980) << 25 | (d.getMonth() + 1) << 21 | + d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 | + d.getSeconds() >> 1; + } + + /** + * Returns the hash code value for this entry. + */ + public int hashCode() { + return name.hashCode(); + } + + /** + * Returns a copy of this entry. + */ + public Object clone() { + try { + ZipEntry e = (ZipEntry)super.clone(); + e.extra = (extra == null) ? null : extra.clone(); + return e; + } catch (CloneNotSupportedException e) { + // This should never happen, since we are Cloneable + throw new InternalError(); + } + } +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/ZipException.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +import java.io.IOException; + +/** + * Signals that a Zip exception of some sort has occurred. + * + * @author unascribed + * @see java.io.IOException + * @since JDK1.0 + */ + +public +class ZipException extends IOException { + private static final long serialVersionUID = 8000196834066748623L; + + /** + * Constructs a ZipException with null + * as its error detail message. + */ + public ZipException() { + super(); + } + + /** + * Constructs a ZipException with the specified detail + * message. + * + * @param s the detail message. + */ + + public ZipException(String s) { + super(s); + } +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,456 @@ +/* + * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +import java.io.InputStream; +import java.io.IOException; +import java.io.EOFException; +import java.io.PushbackInputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import static java.util.zip.ZipConstants64.*; + +/** + * This class implements an input stream filter for reading files in the + * ZIP file format. Includes support for both compressed and uncompressed + * entries. + * + * @author David Connelly + */ +public +class ZipInputStream extends InflaterInputStream implements ZipConstants { + private ZipEntry entry; + private int flag; + private CRC32 crc = new CRC32(); + private long remaining; + private byte[] tmpbuf = new byte[512]; + + private static final int STORED = ZipEntry.STORED; + private static final int DEFLATED = ZipEntry.DEFLATED; + + private boolean closed = false; + // this flag is set to true after EOF has reached for + // one entry + private boolean entryEOF = false; + + private ZipCoder zc; + + /** + * Check to make sure that this stream has not been closed + */ + private void ensureOpen() throws IOException { + if (closed) { + throw new IOException("Stream closed"); + } + } + + /** + * Creates a new ZIP input stream. + * + *

The UTF-8 {@link java.nio.charset.Charset charset} is used to + * decode the entry names. + * + * @param in the actual input stream + */ + public ZipInputStream(InputStream in) { + this(in, StandardCharsets.UTF_8); + } + + /** + * Creates a new ZIP input stream. + * + * @param in the actual input stream + * + * @param charset + * The {@linkplain java.nio.charset.Charset charset} to be + * used to decode the ZIP entry name (ignored if the + * language + * encoding bit of the ZIP entry's general purpose bit + * flag is set). + * + * @since 1.7 + */ + public ZipInputStream(InputStream in, Charset charset) { + super(new PushbackInputStream(in, 512), new Inflater(true), 512); + usesDefaultInflater = true; + if(in == null) { + throw new NullPointerException("in is null"); + } + if (charset == null) + throw new NullPointerException("charset is null"); + this.zc = ZipCoder.get(charset); + } + + /** + * Reads the next ZIP file entry and positions the stream at the + * beginning of the entry data. + * @return the next ZIP file entry, or null if there are no more entries + * @exception ZipException if a ZIP file error has occurred + * @exception IOException if an I/O error has occurred + */ + public ZipEntry getNextEntry() throws IOException { + ensureOpen(); + if (entry != null) { + closeEntry(); + } + crc.reset(); + inf.reset(); + if ((entry = readLOC()) == null) { + return null; + } + if (entry.method == STORED) { + remaining = entry.size; + } + entryEOF = false; + return entry; + } + + /** + * Closes the current ZIP entry and positions the stream for reading the + * next entry. + * @exception ZipException if a ZIP file error has occurred + * @exception IOException if an I/O error has occurred + */ + public void closeEntry() throws IOException { + ensureOpen(); + while (read(tmpbuf, 0, tmpbuf.length) != -1) ; + entryEOF = true; + } + + /** + * Returns 0 after EOF has reached for the current entry data, + * otherwise always return 1. + *

+ * Programs should not count on this method to return the actual number + * of bytes that could be read without blocking. + * + * @return 1 before EOF and 0 after EOF has reached for current entry. + * @exception IOException if an I/O error occurs. + * + */ + public int available() throws IOException { + ensureOpen(); + if (entryEOF) { + return 0; + } else { + return 1; + } + } + + /** + * Reads from the current ZIP entry into an array of bytes. + * If len is not zero, the method + * blocks until some input is available; otherwise, no + * bytes are read and 0 is returned. + * @param b the buffer into which the data is read + * @param off the start offset in the destination array b + * @param len the maximum number of bytes read + * @return the actual number of bytes read, or -1 if the end of the + * entry is reached + * @exception NullPointerException if b is null. + * @exception IndexOutOfBoundsException if off is negative, + * len is negative, or len is greater than + * b.length - off + * @exception ZipException if a ZIP file error has occurred + * @exception IOException if an I/O error has occurred + */ + public int read(byte[] b, int off, int len) throws IOException { + ensureOpen(); + if (off < 0 || len < 0 || off > b.length - len) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + + if (entry == null) { + return -1; + } + switch (entry.method) { + case DEFLATED: + len = super.read(b, off, len); + if (len == -1) { + readEnd(entry); + entryEOF = true; + entry = null; + } else { + crc.update(b, off, len); + } + return len; + case STORED: + if (remaining <= 0) { + entryEOF = true; + entry = null; + return -1; + } + if (len > remaining) { + len = (int)remaining; + } + len = in.read(b, off, len); + if (len == -1) { + throw new ZipException("unexpected EOF"); + } + crc.update(b, off, len); + remaining -= len; + if (remaining == 0 && entry.crc != crc.getValue()) { + throw new ZipException( + "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) + + " but got 0x" + Long.toHexString(crc.getValue()) + ")"); + } + return len; + default: + throw new ZipException("invalid compression method"); + } + } + + /** + * Skips specified number of bytes in the current ZIP entry. + * @param n the number of bytes to skip + * @return the actual number of bytes skipped + * @exception ZipException if a ZIP file error has occurred + * @exception IOException if an I/O error has occurred + * @exception IllegalArgumentException if n < 0 + */ + public long skip(long n) throws IOException { + if (n < 0) { + throw new IllegalArgumentException("negative skip length"); + } + ensureOpen(); + int max = (int)Math.min(n, Integer.MAX_VALUE); + int total = 0; + while (total < max) { + int len = max - total; + if (len > tmpbuf.length) { + len = tmpbuf.length; + } + len = read(tmpbuf, 0, len); + if (len == -1) { + entryEOF = true; + break; + } + total += len; + } + return total; + } + + /** + * Closes this input stream and releases any system resources associated + * with the stream. + * @exception IOException if an I/O error has occurred + */ + public void close() throws IOException { + if (!closed) { + super.close(); + closed = true; + } + } + + private byte[] b = new byte[256]; + + /* + * Reads local file (LOC) header for next entry. + */ + private ZipEntry readLOC() throws IOException { + try { + readFully(tmpbuf, 0, LOCHDR); + } catch (EOFException e) { + return null; + } + if (get32(tmpbuf, 0) != LOCSIG) { + return null; + } + // get flag first, we need check EFS. + flag = get16(tmpbuf, LOCFLG); + // get the entry name and create the ZipEntry first + int len = get16(tmpbuf, LOCNAM); + int blen = b.length; + if (len > blen) { + do + blen = blen * 2; + while (len > blen); + b = new byte[blen]; + } + readFully(b, 0, len); + // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8 + ZipEntry e = createZipEntry(((flag & EFS) != 0) + ? zc.toStringUTF8(b, len) + : zc.toString(b, len)); + // now get the remaining fields for the entry + if ((flag & 1) == 1) { + throw new ZipException("encrypted ZIP entry not supported"); + } + e.method = get16(tmpbuf, LOCHOW); + e.time = get32(tmpbuf, LOCTIM); + if ((flag & 8) == 8) { + /* "Data Descriptor" present */ + if (e.method != DEFLATED) { + throw new ZipException( + "only DEFLATED entries can have EXT descriptor"); + } + } else { + e.crc = get32(tmpbuf, LOCCRC); + e.csize = get32(tmpbuf, LOCSIZ); + e.size = get32(tmpbuf, LOCLEN); + } + len = get16(tmpbuf, LOCEXT); + if (len > 0) { + byte[] bb = new byte[len]; + readFully(bb, 0, len); + e.setExtra(bb); + // extra fields are in "HeaderID(2)DataSize(2)Data... format + if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) { + int off = 0; + while (off + 4 < len) { + int sz = get16(bb, off + 2); + if (get16(bb, off) == ZIP64_EXTID) { + off += 4; + // LOC extra zip64 entry MUST include BOTH original and + // compressed file size fields + if (sz < 16 || (off + sz) > len ) { + // Invalid zip64 extra fields, simply skip. Even it's + // rare, it's possible the entry size happens to be + // the magic value and it "accidnetly" has some bytes + // in extra match the id. + return e; + } + e.size = get64(bb, off); + e.csize = get64(bb, off + 8); + break; + } + off += (sz + 4); + } + } + } + return e; + } + + /** + * Creates a new ZipEntry object for the specified + * entry name. + * + * @param name the ZIP file entry name + * @return the ZipEntry just created + */ + protected ZipEntry createZipEntry(String name) { + return new ZipEntry(name); + } + + /* + * Reads end of deflated entry as well as EXT descriptor if present. + */ + private void readEnd(ZipEntry e) throws IOException { + int n = inf.getRemaining(); + if (n > 0) { + ((PushbackInputStream)in).unread(buf, len - n, n); + } + if ((flag & 8) == 8) { + /* "Data Descriptor" present */ + if (inf.getBytesWritten() > ZIP64_MAGICVAL || + inf.getBytesRead() > ZIP64_MAGICVAL) { + // ZIP64 format + readFully(tmpbuf, 0, ZIP64_EXTHDR); + long sig = get32(tmpbuf, 0); + if (sig != EXTSIG) { // no EXTSIG present + e.crc = sig; + e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC); + e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC); + ((PushbackInputStream)in).unread( + tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC); + } else { + e.crc = get32(tmpbuf, ZIP64_EXTCRC); + e.csize = get64(tmpbuf, ZIP64_EXTSIZ); + e.size = get64(tmpbuf, ZIP64_EXTLEN); + } + } else { + readFully(tmpbuf, 0, EXTHDR); + long sig = get32(tmpbuf, 0); + if (sig != EXTSIG) { // no EXTSIG present + e.crc = sig; + e.csize = get32(tmpbuf, EXTSIZ - EXTCRC); + e.size = get32(tmpbuf, EXTLEN - EXTCRC); + ((PushbackInputStream)in).unread( + tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC); + } else { + e.crc = get32(tmpbuf, EXTCRC); + e.csize = get32(tmpbuf, EXTSIZ); + e.size = get32(tmpbuf, EXTLEN); + } + } + } + if (e.size != inf.getBytesWritten()) { + throw new ZipException( + "invalid entry size (expected " + e.size + + " but got " + inf.getBytesWritten() + " bytes)"); + } + if (e.csize != inf.getBytesRead()) { + throw new ZipException( + "invalid entry compressed size (expected " + e.csize + + " but got " + inf.getBytesRead() + " bytes)"); + } + if (e.crc != crc.getValue()) { + throw new ZipException( + "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) + + " but got 0x" + Long.toHexString(crc.getValue()) + ")"); + } + } + + /* + * Reads bytes, blocking until all bytes are read. + */ + private void readFully(byte[] b, int off, int len) throws IOException { + while (len > 0) { + int n = in.read(b, off, len); + if (n == -1) { + throw new EOFException(); + } + off += n; + len -= n; + } + } + + /* + * Fetches unsigned 16-bit value from byte array at specified offset. + * The bytes are assumed to be in Intel (little-endian) byte order. + */ + private static final int get16(byte b[], int off) { + return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8); + } + + /* + * Fetches unsigned 32-bit value from byte array at specified offset. + * The bytes are assumed to be in Intel (little-endian) byte order. + */ + private static final long get32(byte b[], int off) { + return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL; + } + + /* + * Fetches signed 64-bit value from byte array at specified offset. + * The bytes are assumed to be in Intel (little-endian) byte order. + */ + private static final long get64(byte b[], int off) { + return get32(b, off) | (get32(b, off+4) << 32); + } +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/package.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/package.html Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,98 @@ + + + + + + + + +Provides classes for reading and writing the standard ZIP and GZIP +file formats. Also includes classes for compressing and decompressing +data using the DEFLATE compression algorithm, which is used by the +ZIP and GZIP file formats. Additionally, there are utility classes +for computing the CRC-32 and Adler-32 checksums of arbitrary +input streams. + + +

Package Specification

+ + + + + + + +@since JDK1.1 + + + +