Add ZLIB_OR_NONE support to JdkZlibDecoder [#2016]

This commit is contained in:
Jakob Buchgraber 2014-02-27 19:41:48 +01:00 committed by Norman Maurer
parent fcc6b544a4
commit 9fb235459e
5 changed files with 43 additions and 42 deletions

View File

@ -36,7 +36,7 @@ public class JdkZlibDecoder extends ZlibDecoder {
private static final int FCOMMENT = 0x10; private static final int FCOMMENT = 0x10;
private static final int FRESERVED = 0xE0; private static final int FRESERVED = 0xE0;
private final Inflater inflater; private Inflater inflater;
private final byte[] dictionary; private final byte[] dictionary;
// GZIP related // GZIP related
@ -59,6 +59,8 @@ public class JdkZlibDecoder extends ZlibDecoder {
private volatile boolean finished; private volatile boolean finished;
private boolean decideZlibOrNone;
/** /**
* Creates a new instance with the default wrapper ({@link ZlibWrapper#ZLIB}). * Creates a new instance with the default wrapper ({@link ZlibWrapper#ZLIB}).
*/ */
@ -101,6 +103,11 @@ public class JdkZlibDecoder extends ZlibDecoder {
inflater = new Inflater(); inflater = new Inflater();
crc = null; crc = null;
break; break;
case ZLIB_OR_NONE:
// Postpone the decision until decode(...) is called.
decideZlibOrNone = true;
crc = null;
break;
default: default:
throw new IllegalArgumentException("Only GZIP or ZLIB is supported, but you used " + wrapper); throw new IllegalArgumentException("Only GZIP or ZLIB is supported, but you used " + wrapper);
} }
@ -124,6 +131,17 @@ public class JdkZlibDecoder extends ZlibDecoder {
return; return;
} }
if (decideZlibOrNone) {
// First two bytes are needed to decide if it's a ZLIB stream.
if (in.readableBytes() < 2) {
return;
}
boolean nowrap = !looksLikeZlib(in.getShort(0));
inflater = new Inflater(nowrap);
decideZlibOrNone = false;
}
if (crc != null) { if (crc != null) {
switch (gzipState) { switch (gzipState) {
case FOOTER_START: case FOOTER_START:
@ -215,7 +233,9 @@ public class JdkZlibDecoder extends ZlibDecoder {
@Override @Override
protected void handlerRemoved0(ChannelHandlerContext ctx) throws Exception { protected void handlerRemoved0(ChannelHandlerContext ctx) throws Exception {
super.handlerRemoved0(ctx); super.handlerRemoved0(ctx);
inflater.end(); if (inflater != null) {
inflater.end();
}
} }
private boolean readGZIPHeader(ByteBuf in) { private boolean readGZIPHeader(ByteBuf in) {
@ -357,4 +377,16 @@ public class JdkZlibDecoder extends ZlibDecoder {
"CRC value missmatch. Expected: " + crcValue + ", Got: " + readCrc); "CRC value missmatch. Expected: " + crcValue + ", Got: " + readCrc);
} }
} }
/*
* Returns true if the cmf_flg parameter (think: first two bytes of a zlib stream)
* indicates that this is a zlib stream.
* <p>
* You can lookup the details in the ZLIB RFC:
* <a href="http://tools.ietf.org/html/rfc1950#section-2.2">RFC 1950</a>.
*/
private boolean looksLikeZlib(short cmf_flg) {
return (cmf_flg & 0x7800) == 0x7800 &&
cmf_flg % 31 == 0;
}
} }

View File

@ -98,15 +98,10 @@ public final class ZlibCodecFactory {
} }
public static ZlibDecoder newZlibDecoder(ZlibWrapper wrapper) { public static ZlibDecoder newZlibDecoder(ZlibWrapper wrapper) {
switch (wrapper) { if (PlatformDependent.javaVersion() < 7 || noJdkZlibDecoder) {
case ZLIB_OR_NONE: return new JZlibDecoder(wrapper);
return new JZlibDecoder(wrapper); } else {
default: return new JdkZlibDecoder(wrapper);
if (PlatformDependent.javaVersion() < 7 || noJdkZlibDecoder) {
return new JZlibDecoder(wrapper);
} else {
return new JdkZlibDecoder(wrapper);
}
} }
} }

View File

@ -30,21 +30,8 @@ public class JdkZlibTest extends ZlibTest {
return new JdkZlibDecoder(wrapper); return new JdkZlibDecoder(wrapper);
} }
@Override @Test(expected = DecompressionException.class)
@Test(expected = IllegalArgumentException.class)
public void testZLIB_OR_NONE() throws Exception {
new JdkZlibDecoder(ZlibWrapper.ZLIB_OR_NONE);
}
@Override
@Test(expected = IllegalArgumentException.class)
public void testZLIB_OR_NONE2() throws Exception {
new JdkZlibDecoder(ZlibWrapper.ZLIB_OR_NONE);
}
@Override
@Test(expected = IllegalArgumentException.class)
public void testZLIB_OR_NONE3() throws Exception { public void testZLIB_OR_NONE3() throws Exception {
new JdkZlibDecoder(ZlibWrapper.ZLIB_OR_NONE); super.testZLIB_OR_NONE3();
} }
} }

View File

@ -29,21 +29,8 @@ public class ZlibCrossTest2 extends ZlibTest {
return new JdkZlibDecoder(wrapper); return new JdkZlibDecoder(wrapper);
} }
@Override @Test(expected = DecompressionException.class)
@Test(expected = IllegalArgumentException.class)
public void testZLIB_OR_NONE() throws Exception {
new JdkZlibDecoder(ZlibWrapper.ZLIB_OR_NONE);
}
@Override
@Test(expected = IllegalArgumentException.class)
public void testZLIB_OR_NONE2() throws Exception {
new JdkZlibDecoder(ZlibWrapper.ZLIB_OR_NONE);
}
@Override
@Test(expected = IllegalArgumentException.class)
public void testZLIB_OR_NONE3() throws Exception { public void testZLIB_OR_NONE3() throws Exception {
new JdkZlibDecoder(ZlibWrapper.ZLIB_OR_NONE); super.testZLIB_OR_NONE3();
} }
} }

View File

@ -179,7 +179,7 @@ public abstract class ZlibTest {
public void testZLIB_OR_NONE2() throws Exception { public void testZLIB_OR_NONE2() throws Exception {
testCompressNone(ZlibWrapper.ZLIB, ZlibWrapper.ZLIB_OR_NONE); testCompressNone(ZlibWrapper.ZLIB, ZlibWrapper.ZLIB_OR_NONE);
testCompressSmall(ZlibWrapper.ZLIB, ZlibWrapper.ZLIB_OR_NONE); testCompressSmall(ZlibWrapper.ZLIB, ZlibWrapper.ZLIB_OR_NONE);
testCompressLarge(ZlibWrapper.GZIP, ZlibWrapper.ZLIB_OR_NONE); testCompressLarge(ZlibWrapper.ZLIB, ZlibWrapper.ZLIB_OR_NONE);
} }
@Test @Test