# HG changeset patch # User sherman # Date 1274123989 25200 # Node ID f01eda72e178e82308c6ca82a2b1a1cfd4316597 # Parent 63aa4b61c0a88019552b0062824024967033e4dd 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 diff -r 63aa4b61c0a8 -r f01eda72e178 jdk/src/share/classes/java/util/zip/GZIPOutputStream.java --- 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. + * + *

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. + * + *

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); } /** diff -r 63aa4b61c0a8 -r f01eda72e178 jdk/test/java/util/zip/InflateIn_DeflateOut.java --- 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 ---------------------------