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