1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.http.gzip;
15
16 import java.io.IOException;
17 import java.io.OutputStream;
18 import java.io.OutputStreamWriter;
19 import java.io.PrintWriter;
20 import java.io.UnsupportedEncodingException;
21 import java.util.Set;
22
23 import javax.servlet.ServletOutputStream;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26 import javax.servlet.http.HttpServletResponseWrapper;
27
28 import org.eclipse.jetty.util.StringUtil;
29
30
31
32
33 public abstract class CompressedResponseWrapper extends HttpServletResponseWrapper
34 {
35
36 public static final int DEFAULT_BUFFER_SIZE = 8192;
37 public static final int DEFAULT_MIN_COMPRESS_SIZE = 256;
38
39 private Set<String> _mimeTypes;
40 private int _bufferSize=DEFAULT_BUFFER_SIZE;
41 private int _minCompressSize=DEFAULT_MIN_COMPRESS_SIZE;
42 protected HttpServletRequest _request;
43
44 private PrintWriter _writer;
45 private AbstractCompressedStream _compressedStream;
46 private long _contentLength=-1;
47 private boolean _noCompression;
48
49 public CompressedResponseWrapper(HttpServletRequest request, HttpServletResponse response)
50 {
51 super(response);
52 _request = request;
53 }
54
55
56
57
58
59 public void setMimeTypes(Set<String> mimeTypes)
60 {
61 _mimeTypes = mimeTypes;
62 }
63
64
65
66
67
68 @Override
69 public void setBufferSize(int bufferSize)
70 {
71 _bufferSize = bufferSize;
72 }
73
74
75
76
77
78 public void setMinCompressSize(int minCompressSize)
79 {
80 _minCompressSize = minCompressSize;
81 }
82
83
84
85
86
87 @Override
88 public void setContentType(String ct)
89 {
90 super.setContentType(ct);
91
92 if (ct!=null)
93 {
94 int colon=ct.indexOf(";");
95 if (colon>0)
96 ct=ct.substring(0,colon);
97 }
98
99 if ((_compressedStream==null || _compressedStream.getOutputStream()==null) &&
100 (_mimeTypes==null && ct!=null && ct.contains("gzip") ||
101 _mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
102 {
103 noCompression();
104 }
105 }
106
107
108
109
110
111 @Override
112 public void setStatus(int sc, String sm)
113 {
114 super.setStatus(sc,sm);
115 if (sc<200 || sc==204 || sc==205 || sc>=300)
116 noCompression();
117 }
118
119
120
121
122
123 @Override
124 public void setStatus(int sc)
125 {
126 super.setStatus(sc);
127 if (sc<200 || sc==204 || sc==205 || sc>=300)
128 noCompression();
129 }
130
131
132
133
134
135 @Override
136 public void setContentLength(int length)
137 {
138 setContentLength((long)length);
139 }
140
141
142 protected void setContentLength(long length)
143 {
144 _contentLength=length;
145 if (_compressedStream!=null)
146 _compressedStream.setContentLength(length);
147 else if (_noCompression && _contentLength>=0)
148 {
149 HttpServletResponse response = (HttpServletResponse)getResponse();
150 if(_contentLength<Integer.MAX_VALUE)
151 {
152 response.setContentLength((int)_contentLength);
153 }
154 else
155 {
156 response.setHeader("Content-Length", Long.toString(_contentLength));
157 }
158 }
159 }
160
161
162
163
164
165 @Override
166 public void addHeader(String name, String value)
167 {
168 if ("content-length".equalsIgnoreCase(name))
169 {
170 _contentLength=Long.parseLong(value);
171 if (_compressedStream!=null)
172 _compressedStream.setContentLength(_contentLength);
173 }
174 else if ("content-type".equalsIgnoreCase(name))
175 {
176 setContentType(value);
177 }
178 else if ("content-encoding".equalsIgnoreCase(name))
179 {
180 super.addHeader(name,value);
181 if (!isCommitted())
182 {
183 noCompression();
184 }
185 }
186 else
187 super.addHeader(name,value);
188 }
189
190
191
192
193
194 @Override
195 public void flushBuffer() throws IOException
196 {
197 if (_writer!=null)
198 _writer.flush();
199 if (_compressedStream!=null)
200 _compressedStream.finish();
201 else
202 getResponse().flushBuffer();
203 }
204
205
206
207
208
209 @Override
210 public void reset()
211 {
212 super.reset();
213 if (_compressedStream!=null)
214 _compressedStream.resetBuffer();
215 _writer=null;
216 _compressedStream=null;
217 _noCompression=false;
218 _contentLength=-1;
219 }
220
221
222
223
224
225 @Override
226 public void resetBuffer()
227 {
228 super.resetBuffer();
229 if (_compressedStream!=null)
230 _compressedStream.resetBuffer();
231 _writer=null;
232 _compressedStream=null;
233 }
234
235
236
237
238
239 @Override
240 public void sendError(int sc, String msg) throws IOException
241 {
242 resetBuffer();
243 super.sendError(sc,msg);
244 }
245
246
247
248
249
250 @Override
251 public void sendError(int sc) throws IOException
252 {
253 resetBuffer();
254 super.sendError(sc);
255 }
256
257
258
259
260
261 @Override
262 public void sendRedirect(String location) throws IOException
263 {
264 resetBuffer();
265 super.sendRedirect(location);
266 }
267
268
269
270
271
272 public void noCompression()
273 {
274 _noCompression=true;
275 if (_compressedStream!=null)
276 {
277 try
278 {
279 _compressedStream.doNotCompress();
280 }
281 catch (IOException e)
282 {
283 throw new IllegalStateException(e);
284 }
285 }
286 }
287
288
289
290
291
292 public void finish() throws IOException
293 {
294 if (_writer!=null && !_compressedStream.isClosed())
295 _writer.flush();
296 if (_compressedStream!=null)
297 _compressedStream.finish();
298 }
299
300
301
302
303
304 @Override
305 public void setHeader(String name, String value)
306 {
307 if ("content-length".equalsIgnoreCase(name))
308 {
309 setContentLength(Long.parseLong(value));
310 }
311 else if ("content-type".equalsIgnoreCase(name))
312 {
313 setContentType(value);
314 }
315 else if ("content-encoding".equalsIgnoreCase(name))
316 {
317 super.setHeader(name,value);
318 if (!isCommitted())
319 {
320 noCompression();
321 }
322 }
323 else
324 super.setHeader(name,value);
325 }
326
327
328
329
330
331 @Override
332 public ServletOutputStream getOutputStream() throws IOException
333 {
334 if (_compressedStream==null)
335 {
336 if (getResponse().isCommitted() || _noCompression)
337 {
338 setContentLength(_contentLength);
339 return getResponse().getOutputStream();
340 }
341
342 _compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
343 }
344 else if (_writer!=null)
345 throw new IllegalStateException("getWriter() called");
346
347 return _compressedStream;
348 }
349
350
351
352
353
354 @Override
355 public PrintWriter getWriter() throws IOException
356 {
357 if (_writer==null)
358 {
359 if (_compressedStream!=null)
360 throw new IllegalStateException("getOutputStream() called");
361
362 if (getResponse().isCommitted() || _noCompression)
363 {
364 setContentLength(_contentLength);
365 return getResponse().getWriter();
366 }
367
368 _compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
369 _writer=newWriter(_compressedStream,getCharacterEncoding());
370 }
371 return _writer;
372 }
373
374
375
376
377
378 @Override
379 public void setIntHeader(String name, int value)
380 {
381 if ("content-length".equalsIgnoreCase(name))
382 {
383 _contentLength=value;
384 if (_compressedStream!=null)
385 _compressedStream.setContentLength(_contentLength);
386 }
387 else
388 super.setIntHeader(name,value);
389 }
390
391
392
393
394
395
396
397
398
399
400 protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
401 {
402 return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
403 }
404
405
406
407
408
409 protected abstract AbstractCompressedStream newCompressedStream(HttpServletRequest _request, HttpServletResponse response, long _contentLength2, int _bufferSize2, int _minCompressedSize2) throws IOException;
410
411 }