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
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
74 flushBuffer();
75 if (_content != null && _content.length() > 0)
76 throw new IllegalStateException("FULL");
77 }
78
79 _content = content;
80
81 _contentWritten += content.length();
82
83
84 if (_head)
85 {
86 content.clear();
87 _content = null;
88 }
89 else
90 {
91
92 initContent();
93
94 int len = 0;
95 len = _buffer.put(_content);
96
97
98 if (len > 0 && _buffer.space() == 0)
99 {
100 len--;
101 _buffer.setPutIndex(_buffer.putIndex() - 1);
102 }
103
104 _content.skip(len);
105
106 if (_content.length() == 0)
107 _content = null;
108 }
109 }
110
111 public boolean addContent(byte b) throws IOException
112 {
113
114 if (_noContent)
115 return false;
116
117 if (_last || _state == STATE_END)
118 throw new IllegalStateException("Closed");
119
120
121 if(!_endp.isOpen())
122 {
123 _state = STATE_END;
124 return false;
125 }
126
127
128 if (_content != null && _content.length() > 0)
129 {
130 flushBuffer();
131 if (_content != null && _content.length() > 0)
132 throw new IllegalStateException("FULL");
133 }
134
135 _contentWritten++;
136
137
138 if (_head)
139 return false;
140
141
142 initContent();
143
144
145
146 _buffer.put(b);
147
148 return _buffer.space() <= 1;
149 }
150
151
152 private void initContent() throws IOException
153 {
154 if (_buffer == null)
155 {
156
157 _buffer = _buffers.getBuffer();
158 }
159 }
160
161
162 @Override
163 public boolean isRequest()
164 {
165 return false;
166 }
167
168
169 @Override
170 public boolean isResponse()
171 {
172 return true;
173 }
174
175
176 @Override
177 public int prepareUncheckedAddContent() throws IOException
178 {
179 initContent();
180 return _buffer.space();
181 }
182
183
184 @Override
185 public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
186 {
187 if (LOG.isDebugEnabled())
188 LOG.debug("completeHeader: {}",fields.toString().trim().replace("\r\n","|"));
189 if (_state != STATE_HEADER)
190 return;
191
192 if (_last && !allContentAdded)
193 throw new IllegalStateException("last?");
194 _last = _last | allContentAdded;
195
196 if (_persistent==null)
197 _persistent=(_version > HttpVersions.HTTP_1_0_ORDINAL);
198
199
200 if (_reason == null)
201 _response.setStatus(_status);
202 else
203 _response.setStatus(_status,_reason.toString());
204
205 if (_status == 100 || _status == 204 || _status == 304)
206 {
207 _noContent = true;
208 _content = null;
209 }
210
211
212 boolean has_server = false;
213 if (fields != null)
214 {
215
216 int s=fields.size();
217 for (int f=0;f<s;f++)
218 {
219 HttpFields.Field field = fields.getField(f);
220 if (field==null)
221 continue;
222 _response.setHeader(field.getName(),field.getValue());
223 }
224 }
225
226 if (!has_server && _status > 100 && getSendServerVersion())
227 _response.setHeader(HttpHeaders.SERVER,"Jetty("+Server.getVersion()+",nested in "+_nestedIn+")");
228
229 _state = STATE_CONTENT;
230 }
231
232
233 @Override
234 public long flushBuffer() throws IOException
235 {
236 if (_state == STATE_HEADER)
237 throw new IllegalStateException("State==HEADER");
238
239
240 if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
241 {
242 initContent();
243 _buffer.put(_content);
244 _content.clear();
245 _content = null;
246 }
247
248 if (_buffer==null)
249 return 0;
250
251 int size=_buffer.length();
252 int len = _buffer==null?0:_endp.flush(_buffer);
253 LOG.debug("flushBuffer {} of {}",len,size);
254 if (len>0)
255 _buffer.skip(len);
256
257 return len;
258 }
259
260 }