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