1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.compression;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.buffer.ChannelBuffers;
20 import org.jboss.netty.channel.Channel;
21 import org.jboss.netty.channel.ChannelHandlerContext;
22 import org.jboss.netty.handler.codec.oneone.OneToOneDecoder;
23 import org.jboss.netty.util.internal.jzlib.JZlib;
24 import org.jboss.netty.util.internal.jzlib.ZStream;
25
26
27
28
29
30
31
32 public class ZlibDecoder extends OneToOneDecoder {
33
34 private final ZStream z = new ZStream();
35 private byte[] dictionary;
36 private volatile boolean finished;
37
38
39
40
41
42
43 public ZlibDecoder() {
44 this(ZlibWrapper.ZLIB);
45 }
46
47
48
49
50
51
52 public ZlibDecoder(ZlibWrapper wrapper) {
53 if (wrapper == null) {
54 throw new NullPointerException("wrapper");
55 }
56
57 synchronized (z) {
58 int resultCode = z.inflateInit(ZlibUtil.convertWrapperType(wrapper));
59 if (resultCode != JZlib.Z_OK) {
60 ZlibUtil.fail(z, "initialization failure", resultCode);
61 }
62 }
63 }
64
65
66
67
68
69
70
71
72 public ZlibDecoder(byte[] dictionary) {
73 if (dictionary == null) {
74 throw new NullPointerException("dictionary");
75 }
76 this.dictionary = dictionary;
77
78 synchronized (z) {
79 int resultCode;
80 resultCode = z.inflateInit(JZlib.W_ZLIB);
81 if (resultCode != JZlib.Z_OK) {
82 ZlibUtil.fail(z, "initialization failure", resultCode);
83 }
84 }
85 }
86
87
88
89
90
91 public boolean isClosed() {
92 return finished;
93 }
94
95 @Override
96 protected Object decode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
97 if (!(msg instanceof ChannelBuffer) || finished) {
98 return msg;
99 }
100
101 synchronized (z) {
102 try {
103
104 ChannelBuffer compressed = (ChannelBuffer) msg;
105 byte[] in = new byte[compressed.readableBytes()];
106 compressed.readBytes(in);
107 z.next_in = in;
108 z.next_in_index = 0;
109 z.avail_in = in.length;
110
111
112 byte[] out = new byte[in.length << 1];
113 ChannelBuffer decompressed = ChannelBuffers.dynamicBuffer(
114 compressed.order(), out.length,
115 ctx.getChannel().getConfig().getBufferFactory());
116 z.next_out = out;
117 z.next_out_index = 0;
118 z.avail_out = out.length;
119
120
121 loop: for (;;) {
122
123 int resultCode = z.inflate(JZlib.Z_SYNC_FLUSH);
124 if (z.next_out_index > 0) {
125 decompressed.writeBytes(out, 0, z.next_out_index);
126 z.avail_out = out.length;
127 }
128 z.next_out_index = 0;
129
130 switch (resultCode) {
131 case JZlib.Z_NEED_DICT:
132 if (dictionary == null) {
133 ZlibUtil.fail(z, "decompression failure", resultCode);
134 } else {
135 resultCode = z.inflateSetDictionary(dictionary, dictionary.length);
136 if (resultCode != JZlib.Z_OK) {
137 ZlibUtil.fail(z, "failed to set the dictionary", resultCode);
138 }
139 }
140 break;
141 case JZlib.Z_STREAM_END:
142 finished = true;
143 z.inflateEnd();
144 break loop;
145 case JZlib.Z_OK:
146 break;
147 case JZlib.Z_BUF_ERROR:
148 if (z.avail_in <= 0) {
149 break loop;
150 }
151 break;
152 default:
153 ZlibUtil.fail(z, "decompression failure", resultCode);
154 }
155 }
156
157 if (decompressed.writerIndex() != 0) {
158 return decompressed;
159 } else {
160 return null;
161 }
162 } finally {
163
164
165
166
167 z.next_in = null;
168 z.next_out = null;
169 }
170 }
171 }
172 }