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