1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.handler.codec.compression.JdkZlibEncoder;
20 import org.jboss.netty.handler.codec.compression.ZlibEncoder;
21 import org.jboss.netty.handler.codec.compression.ZlibWrapper;
22 import org.jboss.netty.handler.codec.embedder.EncoderEmbedder;
23 import org.jboss.netty.logging.InternalLogger;
24 import org.jboss.netty.logging.InternalLoggerFactory;
25 import org.jboss.netty.util.internal.DetectionUtil;
26 import org.jboss.netty.util.internal.StringUtil;
27 import org.jboss.netty.util.internal.SystemPropertyUtil;
28
29
30
31
32
33
34
35
36 public class HttpContentCompressor extends HttpContentEncoder {
37
38 private static final InternalLogger logger = InternalLoggerFactory.getInstance(HttpContentCompressor.class);
39
40 private static final int DEFAULT_JDK_WINDOW_SIZE = 15;
41 private static final int DEFAULT_JDK_MEM_LEVEL = 8;
42
43 private static final boolean noJdkZlibEncoder;
44
45 static {
46 noJdkZlibEncoder = SystemPropertyUtil.getBoolean("io.netty.noJdkZlibEncoder", false);
47 if (logger.isDebugEnabled()) {
48 logger.debug("-Dio.netty.noJdkZlibEncoder: " + noJdkZlibEncoder);
49 }
50 }
51
52 private final int compressionLevel;
53 private final int windowBits;
54 private final int memLevel;
55
56
57
58
59
60 public HttpContentCompressor() {
61 this(6);
62 }
63
64
65
66
67
68
69
70
71
72
73 public HttpContentCompressor(int compressionLevel) {
74 this(compressionLevel, DEFAULT_JDK_WINDOW_SIZE, DEFAULT_JDK_MEM_LEVEL);
75 }
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 public HttpContentCompressor(int compressionLevel, int windowBits, int memLevel) {
96 if (compressionLevel < 0 || compressionLevel > 9) {
97 throw new IllegalArgumentException(
98 "compressionLevel: " + compressionLevel + " (expected: 0-9)");
99 }
100 if (windowBits < 9 || windowBits > 15) {
101 throw new IllegalArgumentException(
102 "windowBits: " + windowBits + " (expected: 9-15)");
103 }
104 if (memLevel < 1 || memLevel > 9) {
105 throw new IllegalArgumentException(
106 "memLevel: " + memLevel + " (expected: 1-9)");
107 }
108 this.compressionLevel = compressionLevel;
109 this.windowBits = windowBits;
110 this.memLevel = memLevel;
111 }
112
113 @Override
114 protected EncoderEmbedder<ChannelBuffer> newContentEncoder(
115 HttpMessage msg, String acceptEncoding) throws Exception {
116 String contentEncoding = msg.headers().get(HttpHeaders.Names.CONTENT_ENCODING);
117 if (contentEncoding != null &&
118 !HttpHeaders.Values.IDENTITY.equalsIgnoreCase(contentEncoding)) {
119
120 return null;
121 }
122
123 ZlibWrapper wrapper = determineWrapper(acceptEncoding);
124 if (wrapper == null) {
125 return null;
126 }
127
128 if (DetectionUtil.javaVersion() < 7 || noJdkZlibEncoder ||
129 windowBits != DEFAULT_JDK_WINDOW_SIZE || memLevel != DEFAULT_JDK_MEM_LEVEL) {
130 return new EncoderEmbedder<ChannelBuffer>(
131 new ZlibEncoder(wrapper, compressionLevel, windowBits, memLevel));
132 } else {
133 return new EncoderEmbedder<ChannelBuffer>(
134 new JdkZlibEncoder(wrapper, compressionLevel));
135 }
136 }
137
138 @Override
139 protected String getTargetContentEncoding(String acceptEncoding) throws Exception {
140 ZlibWrapper wrapper = determineWrapper(acceptEncoding);
141 if (wrapper == null) {
142 return null;
143 }
144
145 switch (wrapper) {
146 case GZIP:
147 return "gzip";
148 case ZLIB:
149 return "deflate";
150 default:
151 throw new Error();
152 }
153 }
154
155 private static ZlibWrapper determineWrapper(String acceptEncoding) {
156 float starQ = -1.0f;
157 float gzipQ = -1.0f;
158 float deflateQ = -1.0f;
159 for (String encoding: StringUtil.split(acceptEncoding, ',')) {
160 float q = 1.0f;
161 int equalsPos = encoding.indexOf('=');
162 if (equalsPos != -1) {
163 try {
164 q = Float.valueOf(encoding.substring(equalsPos + 1));
165 } catch (NumberFormatException e) {
166
167 q = 0.0f;
168 }
169 }
170 if (encoding.indexOf('*') >= 0) {
171 starQ = q;
172 } else if (encoding.contains("gzip") && q > gzipQ) {
173 gzipQ = q;
174 } else if (encoding.contains("deflate") && q > deflateQ) {
175 deflateQ = q;
176 }
177 }
178 if (gzipQ > 0.0f || deflateQ > 0.0f) {
179 if (gzipQ >= deflateQ) {
180 return ZlibWrapper.GZIP;
181 } else {
182 return ZlibWrapper.ZLIB;
183 }
184 }
185 if (starQ > 0.0f) {
186 if (gzipQ == -1.0f) {
187 return ZlibWrapper.GZIP;
188 }
189 if (deflateQ == -1.0f) {
190 return ZlibWrapper.ZLIB;
191 }
192 }
193 return null;
194 }
195 }