1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.http;
15
16 import java.io.IOException;
17
18 import org.eclipse.jetty.io.Buffer;
19 import org.eclipse.jetty.io.Buffers;
20 import org.eclipse.jetty.io.ByteArrayBuffer;
21 import org.eclipse.jetty.io.EndPoint;
22 import org.eclipse.jetty.io.EofException;
23 import org.eclipse.jetty.io.View;
24 import org.eclipse.jetty.util.log.Log;
25
26
27
28
29
30
31
32
33
34
35
36
37 public abstract class AbstractGenerator implements Generator
38 {
39
40 public final static int STATE_HEADER = 0;
41 public final static int STATE_CONTENT = 2;
42 public final static int STATE_FLUSHING = 3;
43 public final static int STATE_END = 4;
44
45 public static final byte[] NO_BYTES = {};
46
47
48
49 protected final Buffers _buffers;
50 protected final EndPoint _endp;
51
52 protected int _state = STATE_HEADER;
53
54 protected int _status = 0;
55 protected int _version = HttpVersions.HTTP_1_1_ORDINAL;
56 protected Buffer _reason;
57 protected Buffer _method;
58 protected String _uri;
59
60 protected long _contentWritten = 0;
61 protected long _contentLength = HttpTokens.UNKNOWN_CONTENT;
62 protected boolean _last = false;
63 protected boolean _head = false;
64 protected boolean _noContent = false;
65 protected boolean _close = false;
66
67
68 protected Buffer _header;
69 protected Buffer _buffer;
70 protected Buffer _content;
71
72 protected Buffer _date;
73
74 private boolean _sendServerVersion;
75
76
77
78
79
80
81
82
83
84
85 public AbstractGenerator(Buffers buffers, EndPoint io)
86 {
87 this._buffers = buffers;
88 this._endp = io;
89 }
90
91
92 public boolean isOpen()
93 {
94 return _endp.isOpen();
95 }
96
97
98 public void reset(boolean returnBuffers)
99 {
100 _state = STATE_HEADER;
101 _status = 0;
102 _version = HttpVersions.HTTP_1_1_ORDINAL;
103 _reason = null;
104 _last = false;
105 _head = false;
106 _noContent=false;
107 _close = false;
108 _contentWritten = 0;
109 _contentLength = HttpTokens.UNKNOWN_CONTENT;
110 _date = null;
111
112
113 if (_buffer!=null)
114 _buffers.returnBuffer(_buffer);
115 _buffer=null;
116
117 if (returnBuffers)
118 {
119 if (_header!=null)
120 _buffers.returnBuffer(_header);
121 _header=null;
122 }
123 else if (_header != null)
124 _header.clear();
125
126 _content = null;
127 _method=null;
128 }
129
130
131 public void resetBuffer()
132 {
133 if(_state>=STATE_FLUSHING)
134 throw new IllegalStateException("Flushed");
135
136 _last = false;
137 _close = false;
138 _contentWritten = 0;
139 _contentLength = HttpTokens.UNKNOWN_CONTENT;
140 _content=null;
141 if (_buffer!=null)
142 _buffer.clear();
143 }
144
145
146
147
148
149 public int getContentBufferSize()
150 {
151 if (_buffer==null)
152 _buffer=_buffers.getBuffer();
153 return _buffer.capacity();
154 }
155
156
157
158
159
160 public void increaseContentBufferSize(int contentBufferSize)
161 {
162 if (_buffer==null)
163 _buffer=_buffers.getBuffer();
164 if (contentBufferSize > _buffer.capacity())
165 {
166 Buffer nb = _buffers.getBuffer(contentBufferSize);
167 nb.put(_buffer);
168 _buffers.returnBuffer(_buffer);
169 _buffer = nb;
170 }
171 }
172
173
174 public Buffer getUncheckedBuffer()
175 {
176 return _buffer;
177 }
178
179
180 public boolean getSendServerVersion ()
181 {
182 return _sendServerVersion;
183 }
184
185
186 public void setSendServerVersion (boolean sendServerVersion)
187 {
188 _sendServerVersion = sendServerVersion;
189 }
190
191
192 public int getState()
193 {
194 return _state;
195 }
196
197
198 public boolean isState(int state)
199 {
200 return _state == state;
201 }
202
203
204 public boolean isComplete()
205 {
206 return _state == STATE_END;
207 }
208
209
210 public boolean isIdle()
211 {
212 return _state == STATE_HEADER && _method==null && _status==0;
213 }
214
215
216 public boolean isCommitted()
217 {
218 return _state != STATE_HEADER;
219 }
220
221
222
223
224
225 public boolean isHead()
226 {
227 return _head;
228 }
229
230
231 public void setContentLength(long value)
232 {
233 if (value<0)
234 _contentLength=HttpTokens.UNKNOWN_CONTENT;
235 else
236 _contentLength=value;
237 }
238
239
240
241
242
243 public void setHead(boolean head)
244 {
245 _head = head;
246 }
247
248
249
250
251
252
253 public boolean isPersistent()
254 {
255 return !_close;
256 }
257
258
259 public void setPersistent(boolean persistent)
260 {
261 _close=!persistent;
262 }
263
264
265
266
267
268
269 public void setVersion(int version)
270 {
271 if (_state != STATE_HEADER)
272 throw new IllegalStateException("STATE!=START "+_state);
273 _version = version;
274 if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null)
275 _noContent=true;
276 }
277
278
279 public int getVersion()
280 {
281 return _version;
282 }
283
284
285
286
287
288 public void setDate(Buffer timeStampBuffer)
289 {
290 _date=timeStampBuffer;
291 }
292
293
294
295
296 public void setRequest(String method, String uri)
297 {
298 if (method==null || HttpMethods.GET.equals(method) )
299 _method=HttpMethods.GET_BUFFER;
300 else
301 _method=HttpMethods.CACHE.lookup(method);
302 _uri=uri;
303 if (_version==HttpVersions.HTTP_0_9_ORDINAL)
304 _noContent=true;
305 }
306
307
308
309
310
311
312 public void setResponse(int status, String reason)
313 {
314 if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START");
315 _method=null;
316 _status = status;
317 if (reason!=null)
318 {
319 int len=reason.length();
320
321
322 if (len>1024)
323 len=1024;
324 _reason=new ByteArrayBuffer(len);
325 for (int i=0;i<len;i++)
326 {
327 char ch = reason.charAt(i);
328 if (ch!='\r'&&ch!='\n')
329 _reason.put((byte)ch);
330 else
331 _reason.put((byte)' ');
332 }
333 }
334 }
335
336
337
338
339
340
341
342 public abstract int prepareUncheckedAddContent() throws IOException;
343
344
345 void uncheckedAddContent(int b)
346 {
347 _buffer.put((byte)b);
348 }
349
350
351 public void completeUncheckedAddContent()
352 {
353 if (_noContent)
354 {
355 if(_buffer!=null)
356 _buffer.clear();
357 }
358 else
359 {
360 _contentWritten+=_buffer.length();
361 if (_head)
362 _buffer.clear();
363 }
364 }
365
366
367 public boolean isBufferFull()
368 {
369 if (_buffer != null && _buffer.space()==0)
370 {
371 if (_buffer.length()==0 && !_buffer.isImmutable())
372 _buffer.compact();
373 return _buffer.space()==0;
374 }
375
376 return _content!=null && _content.length()>0;
377 }
378
379
380 public boolean isContentWritten()
381 {
382 return _contentLength>=0 && _contentWritten>=_contentLength;
383 }
384
385
386 public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException;
387
388
389
390
391
392
393
394 public void complete() throws IOException
395 {
396 if (_state == STATE_HEADER)
397 {
398 throw new IllegalStateException("State==HEADER");
399 }
400
401 if (_contentLength >= 0 && _contentLength != _contentWritten && !_head)
402 {
403 if (Log.isDebugEnabled())
404 Log.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength);
405 _close = true;
406 }
407 }
408
409
410 public abstract long flushBuffer() throws IOException;
411
412
413
414 public void flush(long maxIdleTime) throws IOException
415 {
416
417 Buffer content = _content;
418 Buffer buffer = _buffer;
419 if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull())
420 {
421 flushBuffer();
422
423 while ((content!=null && content.length()>0 ||buffer!=null && buffer.length()>0) && _endp.isOpen())
424 blockForOutput(maxIdleTime);
425 }
426 }
427
428
429
430
431
432
433
434
435
436
437
438
439 public void sendError(int code, String reason, String content, boolean close) throws IOException
440 {
441 if (!isCommitted())
442 {
443 setResponse(code, reason);
444 _close = close;
445 completeHeader(null, false);
446 if (content != null)
447 addContent(new View(new ByteArrayBuffer(content)), Generator.LAST);
448 complete();
449 }
450 }
451
452
453
454
455
456 public long getContentWritten()
457 {
458 return _contentWritten;
459 }
460
461
462
463
464 public void blockForOutput(long maxIdleTime) throws IOException
465 {
466 if (_endp.isBlocking())
467 {
468 try
469 {
470 flushBuffer();
471 }
472 catch(IOException e)
473 {
474 _endp.close();
475 throw e;
476 }
477 }
478 else
479 {
480 if (!_endp.blockWritable(maxIdleTime))
481 {
482 _endp.close();
483 throw new EofException("timeout");
484 }
485
486 flushBuffer();
487 }
488 }
489
490 }