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