From b22ebbe4309f37a80cbed53b58e9982c9273f65c Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Thu, 1 Mar 2012 15:33:39 -0800 Subject: [PATCH] Make #211 work with Java 5 * Use java.util.zip.Deflater only when running under Java 7 --- .../handler/codec/spdy/SpdyFrameDecoder.java | 3 +- .../handler/codec/spdy/SpdyFrameEncoder.java | 4 +- .../codec/spdy/SpdyHeaderBlockCompressor.java | 51 ++++++++ .../spdy/SpdyHeaderBlockDecompressor.java | 28 +++++ .../handler/codec/spdy/SpdyJZlibDecoder.java | 18 +-- .../handler/codec/spdy/SpdyJZlibEncoder.java | 113 ++++++++++++++++++ .../handler/codec/spdy/SpdyZlibEncoder.java | 9 +- pom.xml | 32 ++++- .../handler/codec/spdy/SpdyZlibEncoder.java | 69 ----------- 9 files changed, 241 insertions(+), 86 deletions(-) create mode 100644 codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockCompressor.java create mode 100644 codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockDecompressor.java rename src/main/java/org/jboss/netty/handler/codec/spdy/SpdyZlibDecoder.java => codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyJZlibDecoder.java (85%) create mode 100644 codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyJZlibEncoder.java delete mode 100644 src/main/java/org/jboss/netty/handler/codec/spdy/SpdyZlibEncoder.java diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java index 997dc0ad74..d202f19bbf 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java @@ -34,7 +34,8 @@ public class SpdyFrameDecoder extends FrameDecoder { private final int maxFrameSize; private final int maxHeaderSize; - private final SpdyZlibDecoder headerBlockDecompressor = new SpdyZlibDecoder(); + private final SpdyHeaderBlockDecompressor headerBlockDecompressor = + SpdyHeaderBlockDecompressor.newInstance(); /** * Creates a new instance with the default {@code maxChunkSize (8192)}, diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameEncoder.java index 750c8f9595..878dacf405 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameEncoder.java @@ -34,7 +34,7 @@ import io.netty.handler.codec.oneone.OneToOneEncoder; public class SpdyFrameEncoder extends OneToOneEncoder { private volatile boolean finished; - private final SpdyZlibEncoder headerBlockCompressor; + private final SpdyHeaderBlockCompressor headerBlockCompressor; /** * Creates a new instance with the default {@code compressionLevel (6)}, @@ -49,7 +49,7 @@ public class SpdyFrameEncoder extends OneToOneEncoder { */ public SpdyFrameEncoder(int compressionLevel, int windowBits, int memLevel) { super(); - headerBlockCompressor = new SpdyZlibEncoder(compressionLevel); + headerBlockCompressor = SpdyHeaderBlockCompressor.newInstance(compressionLevel, windowBits, memLevel); } @Override diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockCompressor.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockCompressor.java new file mode 100644 index 0000000000..69b823d405 --- /dev/null +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockCompressor.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.spdy; + +import java.util.zip.Deflater; + +import io.netty.buffer.ChannelBuffer; + +abstract class SpdyHeaderBlockCompressor { + + private static final boolean USE_ZLIB; + + static { + boolean java7 = false; + try { + Deflater.class.getDeclaredMethod( + "deflate", + new Class[] { byte[].class, int.class, int.class, int.class }); + java7 = true; + } catch (Exception e) { + // Ignore + } + + USE_ZLIB = java7; + } + + static SpdyHeaderBlockCompressor newInstance(int compressionLevel, int windowBits, int memLevel) { + if (USE_ZLIB) { + return new SpdyZlibEncoder(compressionLevel); + } else { + return new SpdyJZlibEncoder(compressionLevel, windowBits, memLevel); + } + } + + abstract void setInput(ChannelBuffer decompressed); + abstract void encode(ChannelBuffer compressed); + abstract void end(); +} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockDecompressor.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockDecompressor.java new file mode 100644 index 0000000000..76dc1acdf1 --- /dev/null +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockDecompressor.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.spdy; + +import io.netty.buffer.ChannelBuffer; + +abstract class SpdyHeaderBlockDecompressor { + + static SpdyHeaderBlockDecompressor newInstance() { + return new SpdyJZlibDecoder(); + } + + abstract void setInput(ChannelBuffer compressed); + abstract void decode(ChannelBuffer decompressed); +} diff --git a/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyZlibDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyJZlibDecoder.java similarity index 85% rename from src/main/java/org/jboss/netty/handler/codec/spdy/SpdyZlibDecoder.java rename to codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyJZlibDecoder.java index 458b0e255a..38bd2aaee0 100644 --- a/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyZlibDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyJZlibDecoder.java @@ -28,21 +28,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jboss.netty.handler.codec.spdy; +package io.netty.handler.codec.spdy; -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.handler.codec.compression.CompressionException; -import org.jboss.netty.util.internal.jzlib.JZlib; -import org.jboss.netty.util.internal.jzlib.ZStream; +import io.netty.buffer.ChannelBuffer; +import io.netty.handler.codec.compression.CompressionException; +import io.netty.util.internal.jzlib.JZlib; +import io.netty.util.internal.jzlib.ZStream; -import static org.jboss.netty.handler.codec.spdy.SpdyCodecUtil.*; +import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; -class SpdyZlibDecoder { +class SpdyJZlibDecoder extends SpdyHeaderBlockDecompressor { private final byte[] out = new byte[8192]; private final ZStream z = new ZStream(); - public SpdyZlibDecoder() { + public SpdyJZlibDecoder() { int resultCode; resultCode = z.inflateInit(JZlib.W_ZLIB); if (resultCode != JZlib.Z_OK) { @@ -51,6 +51,7 @@ class SpdyZlibDecoder { z.next_out = out; } + @Override public void setInput(ChannelBuffer compressed) { byte[] in = new byte[compressed.readableBytes()]; compressed.readBytes(in); @@ -59,6 +60,7 @@ class SpdyZlibDecoder { z.avail_in = in.length; } + @Override public void decode(ChannelBuffer decompressed) { z.next_out_index = 0; z.avail_out = out.length; diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyJZlibEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyJZlibEncoder.java new file mode 100644 index 0000000000..b3ea627c1f --- /dev/null +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyJZlibEncoder.java @@ -0,0 +1,113 @@ +/* + * Copyright 2012 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +/* + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.netty.handler.codec.spdy; + +import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; + +import io.netty.buffer.ChannelBuffer; +import io.netty.handler.codec.compression.CompressionException; +import io.netty.util.internal.jzlib.JZlib; +import io.netty.util.internal.jzlib.ZStream; + +class SpdyJZlibEncoder extends SpdyHeaderBlockCompressor { + + private final ZStream z = new ZStream(); + + public SpdyJZlibEncoder(int compressionLevel, int windowBits, int memLevel) { + if (compressionLevel < 0 || compressionLevel > 9) { + throw new IllegalArgumentException( + "compressionLevel: " + compressionLevel + " (expected: 0-9)"); + } + if (windowBits < 9 || windowBits > 15) { + throw new IllegalArgumentException( + "windowBits: " + windowBits + " (expected: 9-15)"); + } + if (memLevel < 1 || memLevel > 9) { + throw new IllegalArgumentException( + "memLevel: " + memLevel + " (expected: 1-9)"); + } + + int resultCode = z.deflateInit( + compressionLevel, windowBits, memLevel, JZlib.W_ZLIB); + if (resultCode != JZlib.Z_OK) { + throw new CompressionException( + "failed to initialize an SPDY header block deflater: " + resultCode); + } else { + resultCode = z.deflateSetDictionary(SPDY_DICT, SPDY_DICT.length); + if (resultCode != JZlib.Z_OK) { + throw new CompressionException( + "failed to set the SPDY dictionary: " + resultCode); + } + } + } + + @Override + public void setInput(ChannelBuffer decompressed) { + byte[] in = new byte[decompressed.readableBytes()]; + decompressed.readBytes(in); + z.next_in = in; + z.next_in_index = 0; + z.avail_in = in.length; + } + + @Override + public void encode(ChannelBuffer compressed) { + try { + byte[] out = new byte[(int) Math.ceil(z.next_in.length * 1.001) + 12]; + z.next_out = out; + z.next_out_index = 0; + z.avail_out = out.length; + + int resultCode = z.deflate(JZlib.Z_SYNC_FLUSH); + if (resultCode != JZlib.Z_OK) { + throw new CompressionException("compression failure: " + resultCode); + } + + if (z.next_out_index != 0) { + compressed.writeBytes(out, 0, z.next_out_index); + } + } finally { + // Deference the external references explicitly to tell the VM that + // the allocated byte arrays are temporary so that the call stack + // can be utilized. + // I'm not sure if the modern VMs do this optimization though. + z.next_in = null; + z.next_out = null; + } + } + + @Override + public void end() { + z.deflateEnd(); + z.next_in = null; + z.next_out = null; + } +} diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyZlibEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyZlibEncoder.java index 9a900f41ad..b455a64531 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyZlibEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyZlibEncoder.java @@ -30,13 +30,13 @@ */ package io.netty.handler.codec.spdy; -import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; - import java.util.zip.Deflater; import io.netty.buffer.ChannelBuffer; -class SpdyZlibEncoder { +import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; + +class SpdyZlibEncoder extends SpdyHeaderBlockCompressor { private final byte[] out = new byte[8192]; private final Deflater compressor; @@ -50,12 +50,14 @@ class SpdyZlibEncoder { compressor.setDictionary(SPDY_DICT); } + @Override public void setInput(ChannelBuffer decompressed) { byte[] in = new byte[decompressed.readableBytes()]; decompressed.readBytes(in); compressor.setInput(in); } + @Override public void encode(ChannelBuffer compressed) { while (!compressor.needsInput()) { int numBytes = compressor.deflate(out, 0, out.length, Deflater.SYNC_FLUSH); @@ -63,6 +65,7 @@ class SpdyZlibEncoder { } } + @Override public void end() { compressor.end(); } diff --git a/pom.xml b/pom.xml index 7c47545104..e8b52f861f 100644 --- a/pom.xml +++ b/pom.xml @@ -212,9 +212,9 @@ - - - [1.6.0,) + + + [1.7.0,) [3.0.2,) @@ -237,6 +237,32 @@ true + + + org.codehaus.mojo + animal-sniffer-maven-plugin + 1.7 + + + org.codehaus.mojo.signature + java16 + 1.0 + + + sun.misc.Unsafe + java.util.zip.Deflater + + + + + process-classes + + check + + + + maven-checkstyle-plugin 2.8 diff --git a/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyZlibEncoder.java b/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyZlibEncoder.java deleted file mode 100644 index 4b78a49ca5..0000000000 --- a/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyZlibEncoder.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -/* - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jboss.netty.handler.codec.spdy; - -import java.util.zip.Deflater; - -import org.jboss.netty.buffer.ChannelBuffer; - -import static org.jboss.netty.handler.codec.spdy.SpdyCodecUtil.*; - -class SpdyZlibEncoder { - - private final byte[] out = new byte[8192]; - private final Deflater compressor; - - public SpdyZlibEncoder(int compressionLevel) { - if (compressionLevel < 0 || compressionLevel > 9) { - throw new IllegalArgumentException( - "compressionLevel: " + compressionLevel + " (expected: 0-9)"); - } - compressor = new Deflater(compressionLevel); - compressor.setDictionary(SPDY_DICT); - } - - public void setInput(ChannelBuffer decompressed) { - byte[] in = new byte[decompressed.readableBytes()]; - decompressed.readBytes(in); - compressor.setInput(in); - } - - public void encode(ChannelBuffer compressed) { - while (!compressor.needsInput()) { - int numBytes = compressor.deflate(out, 0, out.length, Deflater.SYNC_FLUSH); - compressed.writeBytes(out, 0, numBytes); - } - } - - public void end() { - compressor.end(); - } -}