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