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 do {
129
130 int resultCode = z.inflate(JZlib.Z_SYNC_FLUSH);
131 switch (resultCode) {
132 case JZlib.Z_STREAM_END:
133 case JZlib.Z_OK:
134 case JZlib.Z_BUF_ERROR:
135 decompressed.writeBytes(out, 0, z.next_out_index);
136 z.next_out_index = 0;
137 z.avail_out = out.length;
138 if (resultCode == JZlib.Z_STREAM_END) {
139 finished = true;
140 z.inflateEnd();
141 }
142 break;
143 default:
144 ZlibUtil.fail(z, "decompression failure", resultCode);
145 }
146 } while (z.avail_in > 0);
147
148 if (decompressed.writerIndex() != 0) {
149 return decompressed;
150 } else {
151 return null;
152 }
153 } finally {
154
155
156
157
158 z.next_in = null;
159 z.next_out = null;
160 }
161 }
162 }
163 }