ASF Bugzilla – Attachment 27924 Details for
Bug 52121
corrupt gzip output when compression=on in server.xml
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
2011-11-11_tc6_FlushableGZIPOutputStream-v2.patch
2011-11-11_tc6_FlushableGZIPOutputStream-v2.patch (text/plain), 4.44 KB, created by
Konstantin Kolinko
on 2011-11-11 02:38:54 UTC
(
hide
)
Description:
2011-11-11_tc6_FlushableGZIPOutputStream-v2.patch
Filename:
MIME Type:
Creator:
Konstantin Kolinko
Created:
2011-11-11 02:38:54 UTC
Size:
4.44 KB
patch
obsolete
>Index: java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java >=================================================================== >--- java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java (revision 1200698) >+++ java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.java (working copy) >@@ -35,58 +35,93 @@ > super(os); > } > >- private static final byte[] EMPTYBYTEARRAY = new byte[0]; >- private boolean hasData = false; >- > /** >- * Here we make sure we have received data, so that the header has been for >- * sure written to the output stream already. >+ * It is used to reserve one byte of real data so that it can be used when >+ * flushing the stream. > */ >+ private byte[] lastByte = new byte[1]; >+ private boolean hasLastByte = false; >+ > @Override >- public synchronized void write(byte[] bytes, int i, int i1) >+ public void write(byte[] bytes) throws IOException { >+ write(bytes, 0, bytes.length); >+ } >+ >+ @Override >+ public synchronized void write(byte[] bytes, int offset, int length) > throws IOException { >- super.write(bytes, i, i1); >- hasData = true; >+ if (length > 0) { >+ flushLastByte(); >+ if (length > 1) { >+ super.write(bytes, offset, length - 1); >+ } >+ rememberLastByte(bytes[offset + length - 1]); >+ } > } > > @Override > public synchronized void write(int i) throws IOException { >- super.write(i); >- hasData = true; >+ flushLastByte(); >+ rememberLastByte((byte) i); > } > > @Override >- public synchronized void write(byte[] bytes) throws IOException { >- super.write(bytes); >- hasData = true; >+ public synchronized void finish() throws IOException { >+ try { >+ flushLastByte(); >+ } catch (IOException ignore) { >+ // If our write failed, then trailer write in finish() will fail >+ // with IOException as well, but it will leave Deflater in more >+ // consistent state. >+ } >+ super.finish(); > } > > @Override >- public synchronized void flush() throws IOException { >- if (!hasData) { >- return; // do not allow the gzip header to be flushed on its own >+ public synchronized void close() throws IOException { >+ try { >+ flushLastByte(); >+ } catch (IOException ignored) { >+ // Ignore. As OutputStream#close() says, the contract of close() >+ // is to close the stream. It does not matter much if the >+ // stream is not writable any more. > } >+ super.close(); >+ } > >- // trick the deflater to flush >- /** >- * Now this is tricky: We force the Deflater to flush its data by >- * switching compression level. As yet, a perplexingly simple workaround >- * for >- * http://developer.java.sun.com/developer/bugParade/bugs/4255743.html >- */ >- if (!def.finished()) { >- def.setInput(EMPTYBYTEARRAY, 0, 0); >+ private void rememberLastByte(byte b) { >+ lastByte[0] = b; >+ hasLastByte = true; >+ } > >- def.setLevel(Deflater.NO_COMPRESSION); >- deflate(); >+ private void flushLastByte() throws IOException { >+ if (hasLastByte) { >+ // Clear the flag first, because write() may fail >+ hasLastByte = false; >+ super.write(lastByte, 0, 1); >+ } >+ } > >- def.setLevel(Deflater.DEFAULT_COMPRESSION); >- deflate(); >+ @Override >+ public synchronized void flush() throws IOException { >+ if (hasLastByte) { >+ // - do not allow the gzip header to be flushed on its own >+ // - do not do anything if there is no data to send > >- out.flush(); >+ // trick the deflater to flush >+ /** >+ * Now this is tricky: We force the Deflater to flush its data by >+ * switching compression level. As yet, a perplexingly simple workaround >+ * for >+ * http://developer.java.sun.com/developer/bugParade/bugs/4255743.html >+ */ >+ if (!def.finished()) { >+ def.setLevel(Deflater.NO_COMPRESSION); >+ flushLastByte(); >+ def.setLevel(Deflater.DEFAULT_COMPRESSION); >+ } > } >- >- hasData = false; // no more data to flush >+ out.flush(); > } > > /*
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 52121
:
27886
|
27887
|
27905
| 27924