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