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