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