4813885: RFE: GZIPOutputStream should implement flush using Z_SYNC_FLUSH
Summary: Added new constructors to allow flush() work in Z_SYNC_FLUSH mode
Reviewed-by: martin
--- a/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java Sun May 16 21:22:07 2010 -0700
+++ b/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java Mon May 17 12:19:49 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-2002 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1996-2010 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
@@ -54,25 +54,82 @@
/**
* Creates a new output stream with the specified buffer size.
+ *
+ * <p>The new output stream instance is created as if by invoking
+ * the 3-argument constructor GZIPOutputStream(out, size, false).
+ *
* @param out the output stream
* @param size the output buffer size
* @exception IOException If an I/O error has occurred.
* @exception IllegalArgumentException if size is <= 0
+
*/
public GZIPOutputStream(OutputStream out, int size) throws IOException {
- super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size);
+ this(out, size, false);
+ }
+
+ /**
+ * Creates a new output stream with the specified buffer size and
+ * flush mode.
+ *
+ * @param out the output stream
+ * @param size the output buffer size
+ * @param syncFlush
+ * if {@code true} invocation of the inherited
+ * {@link DeflaterOutputStream#flush() flush()} method of
+ * this instance flushes the compressor with flush mode
+ * {@link Deflater#SYNC_FLUSH} before flushing the output
+ * stream, otherwise only flushes the output stream
+ * @exception IOException If an I/O error has occurred.
+ * @exception IllegalArgumentException if size is <= 0
+ *
+ * @since 1.7
+ */
+ public GZIPOutputStream(OutputStream out, int size, boolean syncFlush)
+ throws IOException
+ {
+ super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true),
+ size,
+ syncFlush);
usesDefaultDeflater = true;
writeHeader();
crc.reset();
}
+
/**
* Creates a new output stream with a default buffer size.
+ *
+ * <p>The new output stream instance is created as if by invoking
+ * the 2-argument constructor GZIPOutputStream(out, false).
+ *
* @param out the output stream
* @exception IOException If an I/O error has occurred.
*/
public GZIPOutputStream(OutputStream out) throws IOException {
- this(out, 512);
+ this(out, 512, false);
+ }
+
+ /**
+ * Creates a new output stream with a default buffer size and
+ * the specified flush mode.
+ *
+ * @param out the output stream
+ * @param syncFlush
+ * if {@code true} invocation of the inherited
+ * {@link DeflaterOutputStream#flush() flush()} method of
+ * this instance flushes the compressor with flush mode
+ * {@link Deflater#SYNC_FLUSH} before flushing the output
+ * stream, otherwise only flushes the output stream
+ *
+ * @exception IOException If an I/O error has occurred.
+ *
+ * @since 1.7
+ */
+ public GZIPOutputStream(OutputStream out, boolean syncFlush)
+ throws IOException
+ {
+ this(out, 512, syncFlush);
}
/**
--- a/jdk/test/java/util/zip/InflateIn_DeflateOut.java Sun May 16 21:22:07 2010 -0700
+++ b/jdk/test/java/util/zip/InflateIn_DeflateOut.java Mon May 17 12:19:49 2010 -0700
@@ -23,8 +23,8 @@
/**
* @test
- * @bug 4206909
- * @summary Test basic functionality of DeflaterOutputStream and InflaterInputStream including flush
+ * @bug 4206909 4813885
+ * @summary Test basic functionality of DeflaterOutputStream/InflaterInputStream and GZIPOutputStream/GZIPInputStream, including flush
*/
import java.io.*;
@@ -79,23 +79,23 @@
}
private static class PairedOutputStream extends ByteArrayOutputStream {
- private PairedInputStream pairedStream = null;
+ private PairedInputStream pairedStream = null;
- public PairedOutputStream(PairedInputStream inputPair) {
- super();
- this.pairedStream = inputPair;
- }
+ public PairedOutputStream(PairedInputStream inputPair) {
+ super();
+ this.pairedStream = inputPair;
+ }
- public void flush() {
- if (count > 0) {
- pairedStream.addBytes(buf, count);
- reset();
+ public void flush() {
+ if (count > 0) {
+ pairedStream.addBytes(buf, count);
+ reset();
+ }
}
- }
- public void close() {
- flush();
- }
+ public void close() {
+ flush();
+ }
}
private static boolean readFully(InputStream in, byte[] buf, int length)
@@ -146,27 +146,20 @@
check(Arrays.equals(data, buf));
}
- /** Check that written, flushed and read */
- private static void WriteFlushRead() throws Throwable {
+ private static void check(InputStream is, OutputStream os)
+ throws Throwable
+ {
Random random = new Random(new Date().getTime());
-
- PairedInputStream pis = new PairedInputStream();
- InflaterInputStream iis = new InflaterInputStream(pis);
-
- PairedOutputStream pos = new PairedOutputStream(pis);
- pis.setPairedOutputStream(pos);
- DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
-
- // Large writes
+ // Large writes
for (int x = 0; x < 200 ; x++) {
// byte[] data = new byte[random.nextInt(1024 * 1024)];
byte[] data = new byte[1024];
byte[] buf = new byte[data.length];
random.nextBytes(data);
- dos.write(data);
- dos.flush();
- check(readFully(iis, buf, buf.length));
+ os.write(data);
+ os.flush();
+ check(readFully(is, buf, buf.length));
check(Arrays.equals(data, buf));
}
@@ -176,9 +169,9 @@
byte[] buf = new byte[data.length];
random.nextBytes(data);
- dos.write(data);
- dos.flush();
- if (!readFully(iis, buf, buf.length)) {
+ os.write(data);
+ os.flush();
+ if (!readFully(is, buf, buf.length)) {
fail("Didn't read full buffer of " + buf.length);
}
check(Arrays.equals(data, buf));
@@ -187,14 +180,62 @@
String quit = "QUIT\r\n";
// Close it out
- dos.write(quit.getBytes());
- dos.close();
+ os.write(quit.getBytes());
+ os.close();
StringBuilder sb = new StringBuilder();
- check(readLineIfAvailable(iis, sb));
+ check(readLineIfAvailable(is, sb));
equal(sb.toString(), quit);
}
+ /** Check that written, flushed and read */
+ private static void WriteFlushRead() throws Throwable {
+ PairedInputStream pis = new PairedInputStream();
+ InflaterInputStream iis = new InflaterInputStream(pis);
+
+ PairedOutputStream pos = new PairedOutputStream(pis);
+ pis.setPairedOutputStream(pos);
+ DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
+
+ check(iis, dos);
+ }
+
+ private static void GZWriteFlushRead() throws Throwable {
+ PairedInputStream pis = new PairedInputStream();
+ PairedOutputStream pos = new PairedOutputStream(pis);
+ pis.setPairedOutputStream(pos);
+
+ GZIPOutputStream gos = new GZIPOutputStream(pos, true);
+ gos.flush(); // flush the head out, so gis can read
+ GZIPInputStream gis = new GZIPInputStream(pis);
+
+ check(gis, gos);
+ }
+
+ private static void checkLOP(InputStream is, OutputStream os)
+ throws Throwable
+ {
+ boolean flushed = false;
+ int count = 0;
+
+ // Do at least a certain number of lines, but too many without a
+ // flush means this test isn't testing anything
+ while ((count < 10 && flushed) || (count < 1000 && !flushed)) {
+ String command = "PING " + count + "\r\n";
+ os.write(command.getBytes());
+
+ StringBuilder buf = new StringBuilder();
+ if (!readLineIfAvailable(is, buf)) {
+ flushed = true;
+ os.flush();
+ check(readLineIfAvailable(is, buf));
+ }
+ equal(buf.toString(), command);
+ count++;
+ }
+ check(flushed);
+ }
+
/** Validate that we need to use flush at least once on a line
* oriented protocol */
private static void LineOrientedProtocol() throws Throwable {
@@ -205,33 +246,27 @@
pis.setPairedOutputStream(pos);
DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
- boolean flushed = false;
- int count = 0;
-
- // Do at least a certain number of lines, but too many without a
- // flush means this test isn't testing anything
- while ((count < 10 && flushed) || (count < 1000 && !flushed)) {
- String command = "PING " + count + "\r\n";
- dos.write(command.getBytes());
+ checkLOP(iis, dos);
+ }
- StringBuilder buf = new StringBuilder();
- if (!readLineIfAvailable(iis, buf)) {
- flushed = true;
- dos.flush();
- check(readLineIfAvailable(iis, buf));
- }
- equal(buf.toString(), command);
- count++;
- }
- check(flushed);
+ private static void GZLineOrientedProtocol() throws Throwable {
+ PairedInputStream pis = new PairedInputStream();
+ PairedOutputStream pos = new PairedOutputStream(pis);
+ pis.setPairedOutputStream(pos);
+
+ GZIPOutputStream gos = new GZIPOutputStream(pos, true);
+ gos.flush(); // flush the head out, so gis can read
+ GZIPInputStream gis = new GZIPInputStream(pis);
+
+ checkLOP(gis, gos);
}
public static void realMain(String[] args) throws Throwable {
WriteCloseRead();
-
WriteFlushRead();
-
LineOrientedProtocol();
+ GZWriteFlushRead();
+ GZLineOrientedProtocol();
}
//--------------------- Infrastructure ---------------------------