Mercurial Hosting > luan
comparison src/org/eclipse/jetty/http/AbstractGenerator.java @ 877:fef4392f4905
remove sendServerVersion
| author | Franklin Schmidt <fschmidt@gmail.com> |
|---|---|
| date | Tue, 04 Oct 2016 14:36:51 -0600 |
| parents | 8e9db0bbf4f9 |
| children | dbecd7faa1f5 |
comparison
equal
deleted
inserted
replaced
| 876:2efdb98f3543 | 877:fef4392f4905 |
|---|---|
| 38 * faster, but will consume more memory. This option is just for testing and tuning. | 38 * faster, but will consume more memory. This option is just for testing and tuning. |
| 39 * | 39 * |
| 40 */ | 40 */ |
| 41 public abstract class AbstractGenerator implements Generator | 41 public abstract class AbstractGenerator implements Generator |
| 42 { | 42 { |
| 43 private static final Logger LOG = LoggerFactory.getLogger(AbstractGenerator.class); | 43 private static final Logger LOG = LoggerFactory.getLogger(AbstractGenerator.class); |
| 44 | 44 |
| 45 // states | 45 // states |
| 46 public final static int STATE_HEADER = 0; | 46 public final static int STATE_HEADER = 0; |
| 47 public final static int STATE_CONTENT = 2; | 47 public final static int STATE_CONTENT = 2; |
| 48 public final static int STATE_FLUSHING = 3; | 48 public final static int STATE_FLUSHING = 3; |
| 49 public final static int STATE_END = 4; | 49 public final static int STATE_END = 4; |
| 50 | 50 |
| 51 public static final byte[] NO_BYTES = {}; | 51 public static final byte[] NO_BYTES = {}; |
| 52 | 52 |
| 53 // data | 53 // data |
| 54 | 54 |
| 55 protected final Buffers _buffers; // source of buffers | 55 protected final Buffers _buffers; // source of buffers |
| 56 protected final EndPoint _endp; | 56 protected final EndPoint _endp; |
| 57 | 57 |
| 58 protected int _state = STATE_HEADER; | 58 protected int _state = STATE_HEADER; |
| 59 | 59 |
| 60 protected int _status = 0; | 60 protected int _status = 0; |
| 61 protected int _version = HttpVersions.HTTP_1_1_ORDINAL; | 61 protected int _version = HttpVersions.HTTP_1_1_ORDINAL; |
| 62 protected Buffer _reason; | 62 protected Buffer _reason; |
| 63 protected Buffer _method; | 63 protected Buffer _method; |
| 64 protected String _uri; | 64 protected String _uri; |
| 65 | 65 |
| 66 protected long _contentWritten = 0; | 66 protected long _contentWritten = 0; |
| 67 protected long _contentLength = HttpTokens.UNKNOWN_CONTENT; | 67 protected long _contentLength = HttpTokens.UNKNOWN_CONTENT; |
| 68 protected boolean _last = false; | 68 protected boolean _last = false; |
| 69 protected boolean _head = false; | 69 protected boolean _head = false; |
| 70 protected boolean _noContent = false; | 70 protected boolean _noContent = false; |
| 71 protected Boolean _persistent = null; | 71 protected Boolean _persistent = null; |
| 72 | 72 |
| 73 protected Buffer _header; // Buffer for HTTP header (and maybe small _content) | 73 protected Buffer _header; // Buffer for HTTP header (and maybe small _content) |
| 74 protected Buffer _buffer; // Buffer for copy of passed _content | 74 protected Buffer _buffer; // Buffer for copy of passed _content |
| 75 protected Buffer _content; // Buffer passed to addContent | 75 protected Buffer _content; // Buffer passed to addContent |
| 76 | 76 |
| 77 protected Buffer _date; | 77 protected Buffer _date; |
| 78 | 78 |
| 79 private boolean _sendServerVersion; | 79 |
| 80 | 80 /* ------------------------------------------------------------------------------- */ |
| 81 | 81 /** |
| 82 /* ------------------------------------------------------------------------------- */ | 82 * Constructor. |
| 83 /** | 83 * |
| 84 * Constructor. | 84 * @param buffers buffer pool |
| 85 * | 85 * @param io the end point |
| 86 * @param buffers buffer pool | 86 */ |
| 87 * @param io the end point | 87 public AbstractGenerator(Buffers buffers, EndPoint io) |
| 88 */ | 88 { |
| 89 public AbstractGenerator(Buffers buffers, EndPoint io) | 89 this._buffers = buffers; |
| 90 { | 90 this._endp = io; |
| 91 this._buffers = buffers; | 91 } |
| 92 this._endp = io; | 92 |
| 93 } | 93 /* ------------------------------------------------------------------------------- */ |
| 94 | 94 public abstract boolean isRequest(); |
| 95 /* ------------------------------------------------------------------------------- */ | 95 |
| 96 public abstract boolean isRequest(); | 96 /* ------------------------------------------------------------------------------- */ |
| 97 | 97 public abstract boolean isResponse(); |
| 98 /* ------------------------------------------------------------------------------- */ | 98 |
| 99 public abstract boolean isResponse(); | 99 /* ------------------------------------------------------------------------------- */ |
| 100 | 100 public boolean isOpen() |
| 101 /* ------------------------------------------------------------------------------- */ | 101 { |
| 102 public boolean isOpen() | 102 return _endp.isOpen(); |
| 103 { | 103 } |
| 104 return _endp.isOpen(); | 104 |
| 105 } | 105 /* ------------------------------------------------------------------------------- */ |
| 106 | 106 public void reset() |
| 107 /* ------------------------------------------------------------------------------- */ | 107 { |
| 108 public void reset() | 108 _state = STATE_HEADER; |
| 109 { | 109 _status = 0; |
| 110 _state = STATE_HEADER; | 110 _version = HttpVersions.HTTP_1_1_ORDINAL; |
| 111 _status = 0; | 111 _reason = null; |
| 112 _version = HttpVersions.HTTP_1_1_ORDINAL; | 112 _last = false; |
| 113 _reason = null; | 113 _head = false; |
| 114 _last = false; | 114 _noContent=false; |
| 115 _head = false; | 115 _persistent = null; |
| 116 _noContent=false; | 116 _contentWritten = 0; |
| 117 _persistent = null; | 117 _contentLength = HttpTokens.UNKNOWN_CONTENT; |
| 118 _contentWritten = 0; | 118 _date = null; |
| 119 _contentLength = HttpTokens.UNKNOWN_CONTENT; | 119 |
| 120 _date = null; | 120 _content = null; |
| 121 | 121 _method=null; |
| 122 _content = null; | 122 } |
| 123 _method=null; | 123 |
| 124 } | 124 /* ------------------------------------------------------------------------------- */ |
| 125 | 125 public void returnBuffers() |
| 126 /* ------------------------------------------------------------------------------- */ | 126 { |
| 127 public void returnBuffers() | 127 if (_buffer!=null && _buffer.length()==0) |
| 128 { | 128 { |
| 129 if (_buffer!=null && _buffer.length()==0) | 129 _buffers.returnBuffer(_buffer); |
| 130 { | 130 _buffer=null; |
| 131 _buffers.returnBuffer(_buffer); | 131 } |
| 132 _buffer=null; | 132 |
| 133 } | 133 if (_header!=null && _header.length()==0) |
| 134 | 134 { |
| 135 if (_header!=null && _header.length()==0) | 135 _buffers.returnBuffer(_header); |
| 136 { | 136 _header=null; |
| 137 _buffers.returnBuffer(_header); | 137 } |
| 138 _header=null; | 138 } |
| 139 } | 139 |
| 140 } | 140 /* ------------------------------------------------------------------------------- */ |
| 141 | 141 public void resetBuffer() |
| 142 /* ------------------------------------------------------------------------------- */ | 142 { |
| 143 public void resetBuffer() | 143 if(_state>=STATE_FLUSHING) |
| 144 { | 144 throw new IllegalStateException("Flushed"); |
| 145 if(_state>=STATE_FLUSHING) | 145 |
| 146 throw new IllegalStateException("Flushed"); | 146 _last = false; |
| 147 | 147 _persistent=null; |
| 148 _last = false; | 148 _contentWritten = 0; |
| 149 _persistent=null; | 149 _contentLength = HttpTokens.UNKNOWN_CONTENT; |
| 150 _contentWritten = 0; | 150 _content=null; |
| 151 _contentLength = HttpTokens.UNKNOWN_CONTENT; | 151 if (_buffer!=null) |
| 152 _content=null; | 152 _buffer.clear(); |
| 153 if (_buffer!=null) | 153 } |
| 154 _buffer.clear(); | 154 |
| 155 } | 155 /* ------------------------------------------------------------ */ |
| 156 | 156 /** |
| 157 /* ------------------------------------------------------------ */ | 157 * @return Returns the contentBufferSize. |
| 158 /** | 158 */ |
| 159 * @return Returns the contentBufferSize. | 159 public int getContentBufferSize() |
| 160 */ | 160 { |
| 161 public int getContentBufferSize() | 161 if (_buffer==null) |
| 162 { | 162 _buffer=_buffers.getBuffer(); |
| 163 if (_buffer==null) | 163 return _buffer.capacity(); |
| 164 _buffer=_buffers.getBuffer(); | 164 } |
| 165 return _buffer.capacity(); | 165 |
| 166 } | 166 /* ------------------------------------------------------------ */ |
| 167 | 167 /** |
| 168 /* ------------------------------------------------------------ */ | 168 * @param contentBufferSize The contentBufferSize to set. |
| 169 /** | 169 */ |
| 170 * @param contentBufferSize The contentBufferSize to set. | 170 public void increaseContentBufferSize(int contentBufferSize) |
| 171 */ | 171 { |
| 172 public void increaseContentBufferSize(int contentBufferSize) | 172 if (_buffer==null) |
| 173 { | 173 _buffer=_buffers.getBuffer(); |
| 174 if (_buffer==null) | 174 if (contentBufferSize > _buffer.capacity()) |
| 175 _buffer=_buffers.getBuffer(); | 175 { |
| 176 if (contentBufferSize > _buffer.capacity()) | 176 Buffer nb = _buffers.getBuffer(contentBufferSize); |
| 177 { | 177 nb.put(_buffer); |
| 178 Buffer nb = _buffers.getBuffer(contentBufferSize); | 178 _buffers.returnBuffer(_buffer); |
| 179 nb.put(_buffer); | 179 _buffer = nb; |
| 180 _buffers.returnBuffer(_buffer); | 180 } |
| 181 _buffer = nb; | 181 } |
| 182 } | 182 |
| 183 } | 183 /* ------------------------------------------------------------ */ |
| 184 | 184 public Buffer getUncheckedBuffer() |
| 185 /* ------------------------------------------------------------ */ | 185 { |
| 186 public Buffer getUncheckedBuffer() | 186 return _buffer; |
| 187 { | 187 } |
| 188 return _buffer; | 188 |
| 189 } | 189 /* ------------------------------------------------------------ */ |
| 190 | 190 public int getState() |
| 191 /* ------------------------------------------------------------ */ | 191 { |
| 192 public boolean getSendServerVersion () | 192 return _state; |
| 193 { | 193 } |
| 194 return _sendServerVersion; | 194 |
| 195 } | 195 /* ------------------------------------------------------------ */ |
| 196 | 196 public boolean isState(int state) |
| 197 /* ------------------------------------------------------------ */ | 197 { |
| 198 public void setSendServerVersion (boolean sendServerVersion) | 198 return _state == state; |
| 199 { | 199 } |
| 200 _sendServerVersion = sendServerVersion; | 200 |
| 201 } | 201 /* ------------------------------------------------------------ */ |
| 202 | 202 public boolean isComplete() |
| 203 /* ------------------------------------------------------------ */ | 203 { |
| 204 public int getState() | 204 return _state == STATE_END; |
| 205 { | 205 } |
| 206 return _state; | 206 |
| 207 } | 207 /* ------------------------------------------------------------ */ |
| 208 | 208 public boolean isIdle() |
| 209 /* ------------------------------------------------------------ */ | 209 { |
| 210 public boolean isState(int state) | 210 return _state == STATE_HEADER && _method==null && _status==0; |
| 211 { | 211 } |
| 212 return _state == state; | 212 |
| 213 } | 213 /* ------------------------------------------------------------ */ |
| 214 | 214 public boolean isCommitted() |
| 215 /* ------------------------------------------------------------ */ | 215 { |
| 216 public boolean isComplete() | 216 return _state != STATE_HEADER; |
| 217 { | 217 } |
| 218 return _state == STATE_END; | 218 |
| 219 } | 219 /* ------------------------------------------------------------ */ |
| 220 | 220 /** |
| 221 /* ------------------------------------------------------------ */ | 221 * @return Returns the head. |
| 222 public boolean isIdle() | 222 */ |
| 223 { | 223 public boolean isHead() |
| 224 return _state == STATE_HEADER && _method==null && _status==0; | 224 { |
| 225 } | 225 return _head; |
| 226 | 226 } |
| 227 /* ------------------------------------------------------------ */ | 227 |
| 228 public boolean isCommitted() | 228 /* ------------------------------------------------------------ */ |
| 229 { | 229 public void setContentLength(long value) |
| 230 return _state != STATE_HEADER; | 230 { |
| 231 } | 231 if (value<0) |
| 232 | 232 _contentLength=HttpTokens.UNKNOWN_CONTENT; |
| 233 /* ------------------------------------------------------------ */ | 233 else |
| 234 /** | 234 _contentLength=value; |
| 235 * @return Returns the head. | 235 } |
| 236 */ | 236 |
| 237 public boolean isHead() | 237 /* ------------------------------------------------------------ */ |
| 238 { | 238 /** |
| 239 return _head; | 239 * @param head The head to set. |
| 240 } | 240 */ |
| 241 | 241 public void setHead(boolean head) |
| 242 /* ------------------------------------------------------------ */ | 242 { |
| 243 public void setContentLength(long value) | 243 _head = head; |
| 244 { | 244 } |
| 245 if (value<0) | 245 |
| 246 _contentLength=HttpTokens.UNKNOWN_CONTENT; | 246 /* ------------------------------------------------------------ */ |
| 247 else | 247 /** |
| 248 _contentLength=value; | 248 * @return <code>false</code> if the connection should be closed after a request has been read, |
| 249 } | 249 * <code>true</code> if it should be used for additional requests. |
| 250 | 250 */ |
| 251 /* ------------------------------------------------------------ */ | 251 public boolean isPersistent() |
| 252 /** | 252 { |
| 253 * @param head The head to set. | 253 return _persistent!=null |
| 254 */ | 254 ?_persistent.booleanValue() |
| 255 public void setHead(boolean head) | 255 :(isRequest()?true:_version>HttpVersions.HTTP_1_0_ORDINAL); |
| 256 { | 256 } |
| 257 _head = head; | 257 |
| 258 } | 258 /* ------------------------------------------------------------ */ |
| 259 | 259 public void setPersistent(boolean persistent) |
| 260 /* ------------------------------------------------------------ */ | 260 { |
| 261 /** | 261 _persistent=persistent; |
| 262 * @return <code>false</code> if the connection should be closed after a request has been read, | 262 } |
| 263 * <code>true</code> if it should be used for additional requests. | 263 |
| 264 */ | 264 /* ------------------------------------------------------------ */ |
| 265 public boolean isPersistent() | 265 /** |
| 266 { | 266 * @param version The version of the client the response is being sent to (NB. Not the version |
| 267 return _persistent!=null | 267 * in the response, which is the version of the server). |
| 268 ?_persistent.booleanValue() | 268 */ |
| 269 :(isRequest()?true:_version>HttpVersions.HTTP_1_0_ORDINAL); | 269 public void setVersion(int version) |
| 270 } | 270 { |
| 271 | 271 if (_state != STATE_HEADER) |
| 272 /* ------------------------------------------------------------ */ | 272 throw new IllegalStateException("STATE!=START "+_state); |
| 273 public void setPersistent(boolean persistent) | 273 _version = version; |
| 274 { | 274 if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null) |
| 275 _persistent=persistent; | 275 _noContent=true; |
| 276 } | 276 } |
| 277 | 277 |
| 278 /* ------------------------------------------------------------ */ | 278 /* ------------------------------------------------------------ */ |
| 279 /** | 279 public int getVersion() |
| 280 * @param version The version of the client the response is being sent to (NB. Not the version | 280 { |
| 281 * in the response, which is the version of the server). | 281 return _version; |
| 282 */ | 282 } |
| 283 public void setVersion(int version) | 283 |
| 284 { | 284 /* ------------------------------------------------------------ */ |
| 285 if (_state != STATE_HEADER) | 285 /** |
| 286 throw new IllegalStateException("STATE!=START "+_state); | 286 * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.Buffer) |
| 287 _version = version; | 287 */ |
| 288 if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null) | 288 public void setDate(Buffer timeStampBuffer) |
| 289 _noContent=true; | 289 { |
| 290 } | 290 _date=timeStampBuffer; |
| 291 | 291 } |
| 292 /* ------------------------------------------------------------ */ | 292 |
| 293 public int getVersion() | 293 /* ------------------------------------------------------------ */ |
| 294 { | 294 /** |
| 295 return _version; | 295 */ |
| 296 } | 296 public void setRequest(String method, String uri) |
| 297 | 297 { |
| 298 /* ------------------------------------------------------------ */ | 298 if (method==null || HttpMethods.GET.equals(method) ) |
| 299 /** | 299 _method=HttpMethods.GET_BUFFER; |
| 300 * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.Buffer) | 300 else |
| 301 */ | 301 _method=HttpMethods.CACHE.lookup(method); |
| 302 public void setDate(Buffer timeStampBuffer) | 302 _uri=uri; |
| 303 { | 303 if (_version==HttpVersions.HTTP_0_9_ORDINAL) |
| 304 _date=timeStampBuffer; | 304 _noContent=true; |
| 305 } | 305 } |
| 306 | 306 |
| 307 /* ------------------------------------------------------------ */ | 307 /* ------------------------------------------------------------ */ |
| 308 /** | 308 /** |
| 309 */ | 309 * @param status The status code to send. |
| 310 public void setRequest(String method, String uri) | 310 * @param reason the status message to send. |
| 311 { | 311 */ |
| 312 if (method==null || HttpMethods.GET.equals(method) ) | 312 public void setResponse(int status, String reason) |
| 313 _method=HttpMethods.GET_BUFFER; | 313 { |
| 314 else | 314 if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START"); |
| 315 _method=HttpMethods.CACHE.lookup(method); | 315 _method=null; |
| 316 _uri=uri; | 316 _status = status; |
| 317 if (_version==HttpVersions.HTTP_0_9_ORDINAL) | 317 if (reason!=null) |
| 318 _noContent=true; | 318 { |
| 319 } | 319 int len=reason.length(); |
| 320 | 320 |
| 321 /* ------------------------------------------------------------ */ | 321 // TODO don't hard code |
| 322 /** | 322 if (len>1024) |
| 323 * @param status The status code to send. | 323 len=1024; |
| 324 * @param reason the status message to send. | 324 _reason=new ByteArrayBuffer(len); |
| 325 */ | 325 for (int i=0;i<len;i++) |
| 326 public void setResponse(int status, String reason) | 326 { |
| 327 { | 327 char ch = reason.charAt(i); |
| 328 if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START"); | 328 if (ch!='\r'&&ch!='\n') |
| 329 _method=null; | 329 _reason.put((byte)ch); |
| 330 _status = status; | 330 else |
| 331 if (reason!=null) | 331 _reason.put((byte)' '); |
| 332 { | 332 } |
| 333 int len=reason.length(); | 333 } |
| 334 | 334 } |
| 335 // TODO don't hard code | 335 |
| 336 if (len>1024) | 336 /* ------------------------------------------------------------ */ |
| 337 len=1024; | 337 /** Prepare buffer for unchecked writes. |
| 338 _reason=new ByteArrayBuffer(len); | 338 * Prepare the generator buffer to receive unchecked writes |
| 339 for (int i=0;i<len;i++) | 339 * @return the available space in the buffer. |
| 340 { | 340 * @throws IOException |
| 341 char ch = reason.charAt(i); | 341 */ |
| 342 if (ch!='\r'&&ch!='\n') | 342 public abstract int prepareUncheckedAddContent() throws IOException; |
| 343 _reason.put((byte)ch); | 343 |
| 344 else | 344 /* ------------------------------------------------------------ */ |
| 345 _reason.put((byte)' '); | 345 void uncheckedAddContent(int b) |
| 346 } | 346 { |
| 347 } | 347 _buffer.put((byte)b); |
| 348 } | 348 } |
| 349 | 349 |
| 350 /* ------------------------------------------------------------ */ | 350 /* ------------------------------------------------------------ */ |
| 351 /** Prepare buffer for unchecked writes. | 351 public void completeUncheckedAddContent() |
| 352 * Prepare the generator buffer to receive unchecked writes | 352 { |
| 353 * @return the available space in the buffer. | 353 if (_noContent) |
| 354 * @throws IOException | 354 { |
| 355 */ | 355 if(_buffer!=null) |
| 356 public abstract int prepareUncheckedAddContent() throws IOException; | 356 _buffer.clear(); |
| 357 | 357 } |
| 358 /* ------------------------------------------------------------ */ | 358 else |
| 359 void uncheckedAddContent(int b) | 359 { |
| 360 { | 360 _contentWritten+=_buffer.length(); |
| 361 _buffer.put((byte)b); | 361 if (_head) |
| 362 } | 362 _buffer.clear(); |
| 363 | 363 } |
| 364 /* ------------------------------------------------------------ */ | 364 } |
| 365 public void completeUncheckedAddContent() | 365 |
| 366 { | 366 /* ------------------------------------------------------------ */ |
| 367 if (_noContent) | 367 public boolean isBufferFull() |
| 368 { | 368 { |
| 369 if(_buffer!=null) | 369 if (_buffer != null && _buffer.space()==0) |
| 370 _buffer.clear(); | 370 { |
| 371 } | 371 if (_buffer.length()==0 && !_buffer.isImmutable()) |
| 372 else | 372 _buffer.compact(); |
| 373 { | 373 return _buffer.space()==0; |
| 374 _contentWritten+=_buffer.length(); | 374 } |
| 375 if (_head) | 375 |
| 376 _buffer.clear(); | 376 return _content!=null && _content.length()>0; |
| 377 } | 377 } |
| 378 } | 378 |
| 379 | 379 /* ------------------------------------------------------------ */ |
| 380 /* ------------------------------------------------------------ */ | 380 public boolean isWritten() |
| 381 public boolean isBufferFull() | 381 { |
| 382 { | 382 return _contentWritten>0; |
| 383 if (_buffer != null && _buffer.space()==0) | 383 } |
| 384 { | 384 |
| 385 if (_buffer.length()==0 && !_buffer.isImmutable()) | 385 /* ------------------------------------------------------------ */ |
| 386 _buffer.compact(); | 386 public boolean isAllContentWritten() |
| 387 return _buffer.space()==0; | 387 { |
| 388 } | 388 return _contentLength>=0 && _contentWritten>=_contentLength; |
| 389 | 389 } |
| 390 return _content!=null && _content.length()>0; | 390 |
| 391 } | 391 /* ------------------------------------------------------------ */ |
| 392 | 392 public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException; |
| 393 /* ------------------------------------------------------------ */ | 393 |
| 394 public boolean isWritten() | 394 /* ------------------------------------------------------------ */ |
| 395 { | 395 /** |
| 396 return _contentWritten>0; | 396 * Complete the message. |
| 397 } | 397 * |
| 398 | 398 * @throws IOException |
| 399 /* ------------------------------------------------------------ */ | 399 */ |
| 400 public boolean isAllContentWritten() | 400 public void complete() throws IOException |
| 401 { | 401 { |
| 402 return _contentLength>=0 && _contentWritten>=_contentLength; | 402 if (_state == STATE_HEADER) |
| 403 } | 403 { |
| 404 | 404 throw new IllegalStateException("State==HEADER"); |
| 405 /* ------------------------------------------------------------ */ | 405 } |
| 406 public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException; | 406 |
| 407 | 407 if (_contentLength >= 0 && _contentLength != _contentWritten && !_head) |
| 408 /* ------------------------------------------------------------ */ | 408 { |
| 409 /** | 409 if (LOG.isDebugEnabled()) |
| 410 * Complete the message. | 410 LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength); |
| 411 * | 411 _persistent = false; |
| 412 * @throws IOException | 412 } |
| 413 */ | 413 } |
| 414 public void complete() throws IOException | 414 |
| 415 { | 415 /* ------------------------------------------------------------ */ |
| 416 if (_state == STATE_HEADER) | 416 public abstract int flushBuffer() throws IOException; |
| 417 { | 417 |
| 418 throw new IllegalStateException("State==HEADER"); | 418 |
| 419 } | 419 /* ------------------------------------------------------------ */ |
| 420 | 420 public void flush(long maxIdleTime) throws IOException |
| 421 if (_contentLength >= 0 && _contentLength != _contentWritten && !_head) | 421 { |
| 422 { | 422 // block until everything is flushed |
| 423 if (LOG.isDebugEnabled()) | 423 long now=System.currentTimeMillis(); |
| 424 LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength); | 424 long end=now+maxIdleTime; |
| 425 _persistent = false; | 425 Buffer content = _content; |
| 426 } | 426 Buffer buffer = _buffer; |
| 427 } | 427 if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull()) |
| 428 | 428 { |
| 429 /* ------------------------------------------------------------ */ | 429 flushBuffer(); |
| 430 public abstract int flushBuffer() throws IOException; | 430 |
| 431 | 431 while (now<end && (content!=null && content.length()>0 ||buffer!=null && buffer.length()>0) && _endp.isOpen()&& !_endp.isOutputShutdown()) |
| 432 | 432 { |
| 433 /* ------------------------------------------------------------ */ | 433 blockForOutput(end-now); |
| 434 public void flush(long maxIdleTime) throws IOException | 434 now=System.currentTimeMillis(); |
| 435 { | 435 } |
| 436 // block until everything is flushed | 436 } |
| 437 long now=System.currentTimeMillis(); | 437 } |
| 438 long end=now+maxIdleTime; | 438 |
| 439 Buffer content = _content; | 439 /* ------------------------------------------------------------ */ |
| 440 Buffer buffer = _buffer; | 440 /** |
| 441 if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull()) | 441 * Utility method to send an error response. If the builder is not committed, this call is |
| 442 { | 442 * equivalent to a setResponse, addContent and complete call. |
| 443 flushBuffer(); | 443 * |
| 444 | 444 * @param code The error code |
| 445 while (now<end && (content!=null && content.length()>0 ||buffer!=null && buffer.length()>0) && _endp.isOpen()&& !_endp.isOutputShutdown()) | 445 * @param reason The error reason |
| 446 { | 446 * @param content Contents of the error page |
| 447 blockForOutput(end-now); | 447 * @param close True if the connection should be closed |
| 448 now=System.currentTimeMillis(); | 448 * @throws IOException if there is a problem flushing the response |
| 449 } | 449 */ |
| 450 } | 450 public void sendError(int code, String reason, String content, boolean close) throws IOException |
| 451 } | 451 { |
| 452 | 452 if (close) |
| 453 /* ------------------------------------------------------------ */ | 453 _persistent=false; |
| 454 /** | 454 if (isCommitted()) |
| 455 * Utility method to send an error response. If the builder is not committed, this call is | 455 { |
| 456 * equivalent to a setResponse, addContent and complete call. | 456 LOG.debug("sendError on committed: {} {}",code,reason); |
| 457 * | 457 } |
| 458 * @param code The error code | 458 else |
| 459 * @param reason The error reason | 459 { |
| 460 * @param content Contents of the error page | 460 LOG.debug("sendError: {} {}",code,reason); |
| 461 * @param close True if the connection should be closed | 461 setResponse(code, reason); |
| 462 * @throws IOException if there is a problem flushing the response | 462 if (content != null) |
| 463 */ | 463 { |
| 464 public void sendError(int code, String reason, String content, boolean close) throws IOException | 464 completeHeader(null, false); |
| 465 { | 465 addContent(new View(new ByteArrayBuffer(content)), Generator.LAST); |
| 466 if (close) | 466 } |
| 467 _persistent=false; | 467 else if (code>=400) |
| 468 if (isCommitted()) | 468 { |
| 469 { | 469 completeHeader(null, false); |
| 470 LOG.debug("sendError on committed: {} {}",code,reason); | 470 addContent(new View(new ByteArrayBuffer("Error: "+(reason==null?(""+code):reason))), Generator.LAST); |
| 471 } | 471 } |
| 472 else | 472 else |
| 473 { | 473 { |
| 474 LOG.debug("sendError: {} {}",code,reason); | 474 completeHeader(null, true); |
| 475 setResponse(code, reason); | 475 } |
| 476 if (content != null) | 476 complete(); |
| 477 { | 477 } |
| 478 completeHeader(null, false); | 478 } |
| 479 addContent(new View(new ByteArrayBuffer(content)), Generator.LAST); | 479 |
| 480 } | 480 /* ------------------------------------------------------------ */ |
| 481 else if (code>=400) | 481 /** |
| 482 { | 482 * @return Returns the contentWritten. |
| 483 completeHeader(null, false); | 483 */ |
| 484 addContent(new View(new ByteArrayBuffer("Error: "+(reason==null?(""+code):reason))), Generator.LAST); | 484 public long getContentWritten() |
| 485 } | 485 { |
| 486 else | 486 return _contentWritten; |
| 487 { | 487 } |
| 488 completeHeader(null, true); | 488 |
| 489 } | 489 |
| 490 complete(); | 490 |
| 491 } | 491 /* ------------------------------------------------------------ */ |
| 492 } | 492 public void blockForOutput(long maxIdleTime) throws IOException |
| 493 | 493 { |
| 494 /* ------------------------------------------------------------ */ | 494 if (_endp.isBlocking()) |
| 495 /** | 495 { |
| 496 * @return Returns the contentWritten. | 496 try |
| 497 */ | 497 { |
| 498 public long getContentWritten() | 498 flushBuffer(); |
| 499 { | 499 } |
| 500 return _contentWritten; | 500 catch(IOException e) |
| 501 } | 501 { |
| 502 | 502 _endp.close(); |
| 503 | 503 throw e; |
| 504 | 504 } |
| 505 /* ------------------------------------------------------------ */ | 505 } |
| 506 public void blockForOutput(long maxIdleTime) throws IOException | 506 else |
| 507 { | 507 { |
| 508 if (_endp.isBlocking()) | 508 if (!_endp.blockWritable(maxIdleTime)) |
| 509 { | 509 { |
| 510 try | 510 _endp.close(); |
| 511 { | 511 throw new EofException("timeout"); |
| 512 flushBuffer(); | 512 } |
| 513 } | 513 |
| 514 catch(IOException e) | 514 flushBuffer(); |
| 515 { | 515 } |
| 516 _endp.close(); | 516 } |
| 517 throw e; | |
| 518 } | |
| 519 } | |
| 520 else | |
| 521 { | |
| 522 if (!_endp.blockWritable(maxIdleTime)) | |
| 523 { | |
| 524 _endp.close(); | |
| 525 throw new EofException("timeout"); | |
| 526 } | |
| 527 | |
| 528 flushBuffer(); | |
| 529 } | |
| 530 } | |
| 531 | 517 |
| 532 } | 518 } |
