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 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 }
111
112
113
114
115
116 public void setMinCompressSize(int minCompressSize)
117 {
118 _minCompressSize = minCompressSize;
119 }
120
121
122
123
124
125 @Override
126 public void setContentType(String ct)
127 {
128 super.setContentType(ct);
129
130 if (ct!=null)
131 {
132 int colon=ct.indexOf(";");
133 if (colon>0)
134 ct=ct.substring(0,colon);
135 }
136
137 if ((_compressedStream==null || _compressedStream.getOutputStream()==null) &&
138 (_mimeTypes==null && ct!=null && ct.contains("gzip") ||
139 _mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
140 {
141 noCompression();
142 }
143 }
144
145
146
147
148
149 @Override
150 public void setStatus(int sc, String sm)
151 {
152 super.setStatus(sc,sm);
153 if (sc<200 || sc==204 || sc==205 || sc>=300)
154 noCompression();
155 }
156
157
158
159
160
161 @Override
162 public void setStatus(int sc)
163 {
164 super.setStatus(sc);
165 if (sc<200 || sc==204 || sc==205 || sc>=300)
166 noCompression();
167 }
168
169
170
171
172
173 @Override
174 public void setContentLength(int length)
175 {
176 setContentLength((long)length);
177 }
178
179
180 protected void setContentLength(long length)
181 {
182 _contentLength=length;
183 if (_compressedStream!=null)
184 _compressedStream.setContentLength();
185 else if (_noCompression && _contentLength>=0)
186 {
187 HttpServletResponse response = (HttpServletResponse)getResponse();
188 if(_contentLength<Integer.MAX_VALUE)
189 {
190 response.setContentLength((int)_contentLength);
191 }
192 else
193 {
194 response.setHeader("Content-Length", Long.toString(_contentLength));
195 }
196 }
197 }
198
199
200
201
202
203 @Override
204 public void addHeader(String name, String value)
205 {
206 if ("content-length".equalsIgnoreCase(name))
207 {
208 _contentLength=Long.parseLong(value);
209 if (_compressedStream!=null)
210 _compressedStream.setContentLength();
211 }
212 else if ("content-type".equalsIgnoreCase(name))
213 {
214 setContentType(value);
215 }
216 else if ("content-encoding".equalsIgnoreCase(name))
217 {
218 super.addHeader(name,value);
219 if (!isCommitted())
220 {
221 noCompression();
222 }
223 }
224 else if ("etag".equalsIgnoreCase(name))
225 _etag=value;
226 else
227 super.addHeader(name,value);
228 }
229
230
231
232
233
234 @Override
235 public void flushBuffer() throws IOException
236 {
237 if (_writer!=null)
238 _writer.flush();
239 if (_compressedStream!=null)
240 _compressedStream.finish();
241 else
242 getResponse().flushBuffer();
243 }
244
245
246
247
248
249 @Override
250 public void reset()
251 {
252 super.reset();
253 if (_compressedStream!=null)
254 _compressedStream.resetBuffer();
255 _writer=null;
256 _compressedStream=null;
257 _noCompression=false;
258 _contentLength=-1;
259 }
260
261
262
263
264
265 @Override
266 public void resetBuffer()
267 {
268 super.resetBuffer();
269 if (_compressedStream!=null)
270 _compressedStream.resetBuffer();
271 _writer=null;
272 _compressedStream=null;
273 }
274
275
276
277
278
279 @Override
280 public void sendError(int sc, String msg) throws IOException
281 {
282 resetBuffer();
283 super.sendError(sc,msg);
284 }
285
286
287
288
289
290 @Override
291 public void sendError(int sc) throws IOException
292 {
293 resetBuffer();
294 super.sendError(sc);
295 }
296
297
298
299
300
301 @Override
302 public void sendRedirect(String location) throws IOException
303 {
304 resetBuffer();
305 super.sendRedirect(location);
306 }
307
308
309
310
311
312 public void noCompression()
313 {
314 _noCompression=true;
315 if (_compressedStream!=null)
316 {
317 try
318 {
319 _compressedStream.doNotCompress(false);
320 }
321 catch (IOException e)
322 {
323 throw new IllegalStateException(e);
324 }
325 }
326 }
327
328
329
330
331
332 public void finish() throws IOException
333 {
334 if (_writer!=null && !_compressedStream.isClosed())
335 _writer.flush();
336 if (_compressedStream!=null)
337 _compressedStream.finish();
338 }
339
340
341
342
343
344 @Override
345 public void setHeader(String name, String value)
346 {
347 if ("content-length".equalsIgnoreCase(name))
348 {
349 setContentLength(Long.parseLong(value));
350 }
351 else if ("content-type".equalsIgnoreCase(name))
352 {
353 setContentType(value);
354 }
355 else if ("content-encoding".equalsIgnoreCase(name))
356 {
357 super.setHeader(name,value);
358 if (!isCommitted())
359 {
360 noCompression();
361 }
362 }
363 else if ("etag".equalsIgnoreCase(name))
364 _etag=value;
365 else
366 super.setHeader(name,value);
367 }
368
369
370 @Override
371 public boolean containsHeader(String name)
372 {
373 if ("etag".equalsIgnoreCase(name) && _etag!=null)
374 return true;
375 return super.containsHeader(name);
376 }
377
378
379
380
381
382 @Override
383 public ServletOutputStream getOutputStream() throws IOException
384 {
385 if (_compressedStream==null)
386 {
387 if (getResponse().isCommitted() || _noCompression)
388 {
389 setContentLength(_contentLength);
390 return getResponse().getOutputStream();
391 }
392
393 _compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
394 }
395 else if (_writer!=null)
396 throw new IllegalStateException("getWriter() called");
397
398 return _compressedStream;
399 }
400
401
402
403
404
405 @Override
406 public PrintWriter getWriter() throws IOException
407 {
408 if (_writer==null)
409 {
410 if (_compressedStream!=null)
411 throw new IllegalStateException("getOutputStream() called");
412
413 if (getResponse().isCommitted() || _noCompression)
414 {
415 setContentLength(_contentLength);
416 return getResponse().getWriter();
417 }
418
419 _compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
420 _writer=newWriter(_compressedStream,getCharacterEncoding());
421 }
422 return _writer;
423 }
424
425
426
427
428
429 @Override
430 public void setIntHeader(String name, int value)
431 {
432 if ("content-length".equalsIgnoreCase(name))
433 {
434 _contentLength=value;
435 if (_compressedStream!=null)
436 _compressedStream.setContentLength();
437 }
438 else
439 super.setIntHeader(name,value);
440 }
441
442
443
444
445
446
447
448
449
450
451 protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
452 {
453 return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
454 }
455
456
457
458
459
460 protected abstract AbstractCompressedStream newCompressedStream(HttpServletRequest _request, HttpServletResponse response) throws IOException;
461
462 }