1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.eclipse.jetty.http.gzip;
16
17 import java.io.IOException;
18 import java.io.OutputStream;
19 import java.io.OutputStreamWriter;
20 import java.io.PrintWriter;
21 import java.io.UnsupportedEncodingException;
22 import java.util.zip.GZIPOutputStream;
23
24 import javax.servlet.ServletOutputStream;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27
28 import org.eclipse.jetty.util.ByteArrayOutputStream2;
29
30
31
32
33
34 public class GzipStream extends ServletOutputStream
35 {
36 protected HttpServletRequest _request;
37 protected HttpServletResponse _response;
38 protected OutputStream _out;
39 protected ByteArrayOutputStream2 _bOut;
40 protected GZIPOutputStream _gzOut;
41 protected boolean _closed;
42 protected int _bufferSize;
43 protected int _minGzipSize;
44 protected long _contentLength;
45 protected boolean _doNotGzip;
46
47
48
49
50
51
52
53
54
55
56
57 public GzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
58 {
59 _request=request;
60 _response=response;
61 _contentLength=contentLength;
62 _bufferSize=bufferSize;
63 _minGzipSize=minGzipSize;
64 if (minGzipSize==0)
65 doGzip();
66 }
67
68
69
70
71 public void resetBuffer()
72 {
73 if (_response.isCommitted())
74 throw new IllegalStateException("Committed");
75 _closed=false;
76 _out=null;
77 _bOut=null;
78 if (_gzOut!=null)
79 _response.setHeader("Content-Encoding",null);
80 _gzOut=null;
81 _doNotGzip=false;
82 }
83
84
85
86
87
88
89 public void setContentLength(long length)
90 {
91 _contentLength=length;
92 if (_doNotGzip && length>=0)
93 {
94 if(_contentLength<Integer.MAX_VALUE)
95 _response.setContentLength((int)_contentLength);
96 else
97 _response.setHeader("Content-Length",Long.toString(_contentLength));
98 }
99 }
100
101
102
103
104
105 public void flush() throws IOException
106 {
107 if (_out==null || _bOut!=null)
108 {
109 if (_contentLength>0 && _contentLength<_minGzipSize)
110 doNotGzip();
111 else
112 doGzip();
113 }
114
115 _out.flush();
116 }
117
118
119
120
121
122 public void close() throws IOException
123 {
124 if (_closed)
125 return;
126
127 if (_request.getAttribute("javax.servlet.include.request_uri")!=null)
128 flush();
129 else
130 {
131 if (_bOut!=null)
132 {
133 if (_contentLength<0)
134 _contentLength=_bOut.getCount();
135 if (_contentLength<_minGzipSize)
136 doNotGzip();
137 else
138 doGzip();
139 }
140 else if (_out==null)
141 {
142 doNotGzip();
143 }
144
145 if (_gzOut!=null)
146 _gzOut.close();
147 else
148 _out.close();
149 _closed=true;
150 }
151 }
152
153
154
155
156
157
158 public void finish() throws IOException
159 {
160 if (!_closed)
161 {
162 if (_out==null || _bOut!=null)
163 {
164 if (_contentLength>0 && _contentLength<_minGzipSize)
165 doNotGzip();
166 else
167 doGzip();
168 }
169
170 if (_gzOut!=null && !_closed)
171 {
172 _closed=true;
173 _gzOut.close();
174 }
175 }
176 }
177
178
179
180
181
182 public void write(int b) throws IOException
183 {
184 checkOut(1);
185 _out.write(b);
186 }
187
188
189
190
191
192 public void write(byte b[]) throws IOException
193 {
194 checkOut(b.length);
195 _out.write(b);
196 }
197
198
199
200
201
202 public void write(byte b[], int off, int len) throws IOException
203 {
204 checkOut(len);
205 _out.write(b,off,len);
206 }
207
208
209
210
211
212
213 protected boolean setContentEncodingGzip()
214 {
215 _response.setHeader("Content-Encoding", "gzip");
216 return _response.containsHeader("Content-Encoding");
217 }
218
219
220
221
222
223
224 public void doGzip() throws IOException
225 {
226 if (_gzOut==null)
227 {
228 if (_response.isCommitted())
229 throw new IllegalStateException();
230
231 if (setContentEncodingGzip())
232 {
233 _out=_gzOut=new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
234
235 if (_bOut!=null)
236 {
237 _out.write(_bOut.getBuf(),0,_bOut.getCount());
238 _bOut=null;
239 }
240 }
241 else
242 doNotGzip();
243 }
244 }
245
246
247
248
249
250
251 public void doNotGzip() throws IOException
252 {
253 if (_gzOut!=null)
254 throw new IllegalStateException();
255 if (_out==null || _bOut!=null )
256 {
257 _doNotGzip = true;
258
259 _out=_response.getOutputStream();
260 setContentLength(_contentLength);
261
262 if (_bOut!=null)
263 _out.write(_bOut.getBuf(),0,_bOut.getCount());
264 _bOut=null;
265 }
266 }
267
268
269
270
271
272
273
274 private void checkOut(int length) throws IOException
275 {
276 if (_closed)
277 throw new IOException("CLOSED");
278
279 if (_out==null)
280 {
281 if (_response.isCommitted() || (_contentLength>=0 && _contentLength<_minGzipSize))
282 doNotGzip();
283 else if (length>_minGzipSize)
284 doGzip();
285 else
286 _out=_bOut=new ByteArrayOutputStream2(_bufferSize);
287 }
288 else if (_bOut!=null)
289 {
290 if (_response.isCommitted() || (_contentLength>=0 && _contentLength<_minGzipSize))
291 doNotGzip();
292 else if (length>=(_bOut.getBuf().length -_bOut.getCount()))
293 doGzip();
294 }
295 }
296
297
298
299
300 protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
301 {
302 return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
303 }
304 }
305