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 loop: for (;;) {
121
122 int resultCode = z.inflate(JZlib.Z_SYNC_FLUSH);
123 if (z.next_out_index > 0) {
124 decompressed.writeBytes(out, 0, z.next_out_index);
125 z.avail_out = out.length;
126 }
127 z.next_out_index = 0;
128
129 switch (resultCode) {
130 case JZlib.Z_NEED_DICT:
131 if (dictionary == null) {
132 ZlibUtil.fail(z, "decompression failure", resultCode);
133 } else {
134 resultCode = z.inflateSetDictionary(dictionary, dictionary.length);
135 if (resultCode != JZlib.Z_OK) {
136 ZlibUtil.fail(z, "failed to set the dictionary", resultCode);
137 }
138 }
139 break;
140 case JZlib.Z_STREAM_END:
141 finished = true;
142 z.inflateEnd();
143 break loop;
144 case JZlib.Z_OK:
145 break;
146 case JZlib.Z_BUF_ERROR:
147 if (z.avail_in <= 0) {
148 break loop;
149 }
150 break;
151 default:
152 ZlibUtil.fail(z, "decompression failure", resultCode);
153 }
154 }
155
156 if (decompressed.writerIndex() != 0) {
157 return decompressed;
158 } else {
159 return null;
160 }
161 } finally {
162
163
164
165
166 z.next_in = null;
167 z.next_out = null;
168 }
169 }
170 }
171 }