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