1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.nested;
20
21 import java.io.IOException;
22
23 import javax.servlet.http.HttpServletResponse;
24
25 import org.eclipse.jetty.http.AbstractGenerator;
26 import org.eclipse.jetty.http.HttpFields;
27 import org.eclipse.jetty.http.HttpHeaders;
28 import org.eclipse.jetty.http.HttpVersions;
29 import org.eclipse.jetty.io.Buffer;
30 import org.eclipse.jetty.io.Buffers;
31 import org.eclipse.jetty.io.EndPoint;
32 import org.eclipse.jetty.server.Server;
33 import org.eclipse.jetty.util.log.Log;
34 import org.eclipse.jetty.util.log.Logger;
35
36 public class NestedGenerator extends AbstractGenerator
37 {
38 private static final Logger LOG = Log.getLogger(NestedGenerator.class);
39
40 final HttpServletResponse _response;
41 final String _nestedIn;
42
43 public NestedGenerator(Buffers buffers, EndPoint io, HttpServletResponse response, String nestedIn)
44 {
45 super(buffers,io);
46 _response=response;
47 _nestedIn=nestedIn;
48 }
49
50 public void addContent(Buffer content, boolean last) throws IOException
51 {
52 LOG.debug("addContent {} {}",content.length(),last);
53 if (_noContent)
54 {
55 content.clear();
56 return;
57 }
58
59 if (content.isImmutable())
60 throw new IllegalArgumentException("immutable");
61
62 if (_last || _state == STATE_END)
63 {
64 LOG.debug("Ignoring extra content {}", content);
65 content.clear();
66 return;
67 }
68 _last = last;
69
70 if(!_endp.isOpen())
71 {
72 _state = STATE_END;
73 return;
74 }
75
76
77 if (_content != null && _content.length() > 0)
78 {
79 flushBuffer();
80 if (_content != null && _content.length() > 0)
81 throw new IllegalStateException("FULL");
82 }
83
84 _content = content;
85
86 _contentWritten += content.length();
87
88
89 if (_head)
90 {
91 content.clear();
92 _content = null;
93 }
94 else if (!last || _buffer!=null)
95 {
96
97 initBuffer();
98
99 int len = 0;
100 len = _buffer.put(_content);
101
102
103 if (len > 0 && _buffer.space() == 0)
104 {
105 len--;
106 _buffer.setPutIndex(_buffer.putIndex() - 1);
107 }
108
109 LOG.debug("copied {} to buffer",len);
110
111 _content.skip(len);
112
113 if (_content.length() == 0)
114 _content = null;
115 }
116 }
117
118 public boolean addContent(byte b) throws IOException
119 {
120
121 if (_noContent)
122 return false;
123
124 if (_last || _state == STATE_END)
125 throw new IllegalStateException("Closed");
126
127
128 if(!_endp.isOpen())
129 {
130 _state = STATE_END;
131 return false;
132 }
133
134
135 if (_content != null && _content.length() > 0)
136 {
137 flushBuffer();
138 if (_content != null && _content.length() > 0)
139 throw new IllegalStateException("FULL");
140 }
141
142 _contentWritten++;
143
144
145 if (_head)
146 return false;
147
148
149 initBuffer();
150
151
152
153 _buffer.put(b);
154
155 return _buffer.space() <= 1;
156 }
157
158
159 private void initBuffer() throws IOException
160 {
161 if (_buffer == null)
162 {
163
164 _buffer = _buffers.getBuffer();
165 }
166 }
167
168
169 @Override
170 public boolean isRequest()
171 {
172 return false;
173 }
174
175
176 @Override
177 public boolean isResponse()
178 {
179 return true;
180 }
181
182
183 @Override
184 public int prepareUncheckedAddContent() throws IOException
185 {
186 initBuffer();
187 return _buffer.space();
188 }
189
190
191 @Override
192 public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
193 {
194 if (LOG.isDebugEnabled())
195 LOG.debug("completeHeader: {}",fields.toString().trim().replace("\r\n","|"));
196 if (_state != STATE_HEADER)
197 return;
198
199 if (_last && !allContentAdded)
200 throw new IllegalStateException("last?");
201 _last = _last | allContentAdded;
202
203 if (_persistent==null)
204 _persistent=(_version > HttpVersions.HTTP_1_0_ORDINAL);
205
206
207 if (_reason == null)
208 _response.setStatus(_status);
209 else
210 _response.setStatus(_status,_reason.toString());
211
212 if (_status == 100 || _status == 204 || _status == 304)
213 {
214 _noContent = true;
215 _content = null;
216 }
217
218
219 boolean has_server = false;
220 if (fields != null)
221 {
222
223 int s=fields.size();
224 for (int f=0;f<s;f++)
225 {
226 HttpFields.Field field = fields.getField(f);
227 if (field==null)
228 continue;
229 _response.setHeader(field.getName(),field.getValue());
230 }
231 }
232
233 if (!has_server && _status > 100 && getSendServerVersion())
234 _response.setHeader(HttpHeaders.SERVER,"Jetty("+Server.getVersion()+",nested in "+_nestedIn+")");
235
236 _state = STATE_CONTENT;
237 }
238
239
240
241
242
243
244
245 @Override
246 public void complete() throws IOException
247 {
248 if (_state == STATE_END)
249 return;
250
251 super.complete();
252
253 if (_state < STATE_FLUSHING)
254 _state = STATE_FLUSHING;
255
256 flushBuffer();
257 }
258
259
260 @Override
261 public int flushBuffer() throws IOException
262 {
263 if (_state == STATE_HEADER)
264 throw new IllegalStateException("State==HEADER");
265
266 int len = 0;
267
268 if (_buffer==null)
269 {
270
271 if (_content!=null && _content.length()>0)
272 {
273
274 len = _endp.flush(_content);
275 if (len>0)
276 _content.skip(len);
277 }
278 }
279 else
280 {
281 if (_buffer.length()==0 && _content!=null && _content.length()>0)
282 {
283
284 _content.skip(_buffer.put(_content));
285 }
286
287 int size=_buffer.length();
288 len =_endp.flush(_buffer);
289 LOG.debug("flushBuffer {} of {}",len,size);
290 if (len>0)
291 _buffer.skip(len);
292 }
293
294 if (_content!=null && _content.length()==0)
295 _content=null;
296 if (_buffer!=null && _buffer.length()==0 && _content==null)
297 {
298 _buffers.returnBuffer(_buffer);
299 _buffer=null;
300 }
301
302 if (_state==STATE_FLUSHING && _buffer==null && _content==null)
303 _state=STATE_END;
304
305 return len;
306 }
307
308 }