--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/zip/InflaterOutputStream.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.util.zip;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Implements an output stream filter for uncompressing data stored in the
+ * "deflate" compression format.
+ *
+ * @since 1.6
+ * @author David R Tribble (david@tribble.com)
+ *
+ * @see InflaterInputStream
+ * @see DeflaterInputStream
+ * @see DeflaterOutputStream
+ */
+
+public class InflaterOutputStream extends FilterOutputStream {
+ /** Decompressor for this stream. */
+ protected final Inflater inf;
+
+ /** Output buffer for writing uncompressed data. */
+ protected final byte[] buf;
+
+ /** Temporary write buffer. */
+ private final byte[] wbuf = new byte[1];
+
+ /** Default decompressor is used. */
+ private boolean usesDefaultInflater = false;
+
+ /** true iff {@link #close()} has been called. */
+ private boolean closed = false;
+
+ /**
+ * Checks 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 output stream with a default decompressor and buffer
+ * size.
+ *
+ * @param out output stream to write the uncompressed data to
+ * @throws NullPointerException if {@code out} is null
+ */
+ public InflaterOutputStream(OutputStream out) {
+ this(out, new Inflater());
+ usesDefaultInflater = true;
+ }
+
+ /**
+ * Creates a new output stream with the specified decompressor and a
+ * default buffer size.
+ *
+ * @param out output stream to write the uncompressed data to
+ * @param infl decompressor ("inflater") for this stream
+ * @throws NullPointerException if {@code out} or {@code infl} is null
+ */
+ public InflaterOutputStream(OutputStream out, Inflater infl) {
+ this(out, infl, 512);
+ }
+
+ /**
+ * Creates a new output stream with the specified decompressor and
+ * buffer size.
+ *
+ * @param out output stream to write the uncompressed data to
+ * @param infl decompressor ("inflater") for this stream
+ * @param bufLen decompression buffer size
+ * @throws IllegalArgumentException if {@code bufLen} is <= 0
+ * @throws NullPointerException if {@code out} or {@code infl} is null
+ */
+ public InflaterOutputStream(OutputStream out, Inflater infl, int bufLen) {
+ super(out);
+
+ // Sanity checks
+ if (out == null)
+ throw new NullPointerException("Null output");
+ if (infl == null)
+ throw new NullPointerException("Null inflater");
+ if (bufLen <= 0)
+ throw new IllegalArgumentException("Buffer size < 1");
+
+ // Initialize
+ inf = infl;
+ buf = new byte[bufLen];
+ }
+
+ /**
+ * Writes any remaining uncompressed data to the output stream and closes
+ * the underlying output stream.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ public void close() throws IOException {
+ if (!closed) {
+ // Complete the uncompressed output
+ try {
+ finish();
+ } finally {
+ out.close();
+ closed = true;
+ }
+ }
+ }
+
+ /**
+ * Flushes this output stream, forcing any pending buffered output bytes to be
+ * written.
+ *
+ * @throws IOException if an I/O error occurs or this stream is already
+ * closed
+ */
+ public void flush() throws IOException {
+ ensureOpen();
+
+ // Finish decompressing and writing pending output data
+ if (!inf.finished()) {
+ try {
+ while (!inf.finished() && !inf.needsInput()) {
+ int n;
+
+ // Decompress pending output data
+ n = inf.inflate(buf, 0, buf.length);
+ if (n < 1) {
+ break;
+ }
+
+ // Write the uncompressed output data block
+ out.write(buf, 0, n);
+ }
+ super.flush();
+ } catch (DataFormatException ex) {
+ // Improperly formatted compressed (ZIP) data
+ String msg = ex.getMessage();
+ if (msg == null) {
+ msg = "Invalid ZLIB data format";
+ }
+ throw new ZipException(msg);
+ }
+ }
+ }
+
+ /**
+ * Finishes writing uncompressed data to the output stream without closing
+ * the underlying stream. Use this method when applying multiple filters in
+ * succession to the same output stream.
+ *
+ * @throws IOException if an I/O error occurs or this stream is already
+ * closed
+ */
+ public void finish() throws IOException {
+ ensureOpen();
+
+ // Finish decompressing and writing pending output data
+ flush();
+ if (usesDefaultInflater) {
+ inf.end();
+ }
+ }
+
+ /**
+ * Writes a byte to the uncompressed output stream.
+ *
+ * @param b a single byte of compressed data to decompress and write to
+ * the output stream
+ * @throws IOException if an I/O error occurs or this stream is already
+ * closed
+ * @throws ZipException if a compression (ZIP) format error occurs
+ */
+ public void write(int b) throws IOException {
+ // Write a single byte of data
+ wbuf[0] = (byte) b;
+ write(wbuf, 0, 1);
+ }
+
+ /**
+ * Writes an array of bytes to the uncompressed output stream.
+ *
+ * @param b buffer containing compressed data to decompress and write to
+ * the output stream
+ * @param off starting offset of the compressed data within {@code b}
+ * @param len number of bytes to decompress from {@code b}
+ * @throws IndexOutOfBoundsException if {@code off} < 0, or if
+ * {@code len} < 0, or if {@code len} > {@code b.length - off}
+ * @throws IOException if an I/O error occurs or this stream is already
+ * closed
+ * @throws NullPointerException if {@code b} is null
+ * @throws ZipException if a compression (ZIP) format error occurs
+ */
+ public void write(byte[] b, int off, int len) throws IOException {
+ // Sanity checks
+ ensureOpen();
+ if (b == null) {
+ throw new NullPointerException("Null buffer for read");
+ } else if (off < 0 || len < 0 || len > b.length - off) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return;
+ }
+
+ // Write uncompressed data to the output stream
+ try {
+ for (;;) {
+ int n;
+
+ // Fill the decompressor buffer with output data
+ if (inf.needsInput()) {
+ int part;
+
+ if (len < 1) {
+ break;
+ }
+
+ part = (len < 512 ? len : 512);
+ inf.setInput(b, off, part);
+ off += part;
+ len -= part;
+ }
+
+ // Decompress and write blocks of output data
+ do {
+ n = inf.inflate(buf, 0, buf.length);
+ if (n > 0) {
+ out.write(buf, 0, n);
+ }
+ } while (n > 0);
+
+ // Check the decompressor
+ if (inf.finished()) {
+ break;
+ }
+ if (inf.needsDictionary()) {
+ throw new ZipException("ZLIB dictionary missing");
+ }
+ }
+ } catch (DataFormatException ex) {
+ // Improperly formatted compressed (ZIP) data
+ String msg = ex.getMessage();
+ if (msg == null) {
+ msg = "Invalid ZLIB data format";
+ }
+ throw new ZipException(msg);
+ }
+ }
+}