Mercurial Hosting > luan
diff src/org/eclipse/jetty/http/HttpGenerator.java @ 1057:afc9610dc12e
remove AbstractGenerator
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 08 Nov 2016 04:05:04 -0700 |
parents | 2b769da7f67d |
children | 419bf9c03d84 |
line wrap: on
line diff
--- a/src/org/eclipse/jetty/http/HttpGenerator.java Tue Nov 08 01:19:36 2016 -0700 +++ b/src/org/eclipse/jetty/http/HttpGenerator.java Tue Nov 08 04:05:04 2016 -0700 @@ -39,7 +39,7 @@ * * */ -public final class HttpGenerator extends AbstractGenerator +public final class HttpGenerator { private static final Logger LOG = LoggerFactory.getLogger(HttpGenerator.class); @@ -101,11 +101,6 @@ private boolean _bufferChunked = false; - public HttpGenerator(Buffers buffers, EndPoint io) - { - super(buffers,io); - } - public void shutdown() { if (_persistent!=null && !_persistent && _endp!=null && !_endp.isOutputShutdown()) { @@ -235,11 +230,10 @@ return _buffer.space()-(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0); } - @Override public boolean isBufferFull() { // Should we flush the buffers? - return super.isBufferFull() || _bufferChunked || _bypass || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE); + return isBufferFull2() || _bufferChunked || _bypass || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE); } public void send1xx(int code) throws IOException @@ -279,7 +273,6 @@ } } - @Override boolean isRequest() { return _method!=null; @@ -290,7 +283,6 @@ return _method==null; } - @Override public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException { if (_state != STATE_HEADER) @@ -701,13 +693,12 @@ * * @throws IOException */ - @Override public void complete() throws IOException { if (_state == STATE_END) return; - super.complete(); + complete2(); if (_state < STATE_FLUSHING) { @@ -719,7 +710,6 @@ flushBuffer(); } - @Override public int flushBuffer() throws IOException { try @@ -993,4 +983,327 @@ buffer == null ? -1 : buffer.remaining(), content == null ? -1 : content.remaining()); } + + + + + + + + + + + + + // AbstractGenerator + + public static final boolean LAST=true; + public static final boolean MORE=false; + + // states + private final static int STATE_HEADER = 0; + private final static int STATE_CONTENT = 2; + private final static int STATE_FLUSHING = 3; + private final static int STATE_END = 4; + + // data + + private final Buffers _buffers; // source of buffers + private final EndPoint _endp; + + private int _state = STATE_HEADER; + + private int _status = 0; + private int _version = HttpVersions.HTTP_1_1_ORDINAL; + private JBuffer _reason; + private JBuffer _method; + private String _uri; + + private long _contentWritten = 0; + private long _contentLength = HttpTokens.UNKNOWN_CONTENT; + private boolean _last = false; + private boolean _head = false; + private boolean _noContent = false; + private Boolean _persistent = null; + + private JBuffer _header; // JBuffer for HTTP header (and maybe small _content) + private JBuffer _buffer; // JBuffer for copy of passed _content + private JBuffer _content; // JBuffer passed to addContent + + + public HttpGenerator(Buffers buffers, EndPoint io) + { + this._buffers = buffers; + this._endp = io; + } + + public final boolean isOpen() + { + return _endp.isOpen(); + } + + public final void resetBuffer() + { + if(_state>=STATE_FLUSHING) + throw new IllegalStateException("Flushed"); + + _last = false; + _persistent = null; + _contentWritten = 0; + _contentLength = HttpTokens.UNKNOWN_CONTENT; + _content=null; + if (_buffer!=null) + _buffer.clear(); + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the contentBufferSize. + */ + public final int getContentBufferSize() + { + if (_buffer==null) + _buffer = _buffers.getBuffer(); + return _buffer.capacity(); + } + + public final JBuffer getUncheckedBuffer() + { + return _buffer; + } + + public final boolean isComplete() + { + return _state == STATE_END; + } + + public final boolean isIdle() + { + return _state == STATE_HEADER && _method==null && _status==0; + } + + public final boolean isCommitted() + { + return _state != STATE_HEADER; + } + + public final void setContentLength(long value) + { + if (value<0) + _contentLength=HttpTokens.UNKNOWN_CONTENT; + else + _contentLength=value; + } + + public final void setHead(boolean head) + { + _head = head; + } + + /* ------------------------------------------------------------ */ + /** + * @return <code>false</code> if the connection should be closed after a request has been read, + * <code>true</code> if it should be used for additional requests. + */ + public final boolean isPersistent() + { + return _persistent!=null + ?_persistent.booleanValue() + :(isRequest()?true:_version>HttpVersions.HTTP_1_0_ORDINAL); + } + + public final void setPersistent(boolean persistent) + { + _persistent = persistent; + } + + /* ------------------------------------------------------------ */ + /** + * @param version The version of the client the response is being sent to (NB. Not the version + * in the response, which is the version of the server). + */ + public final void setVersion(int version) + { + if (_state != STATE_HEADER) + throw new IllegalStateException("STATE!=START "+_state); + _version = version; + if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null) + _noContent=true; + } + + /* ------------------------------------------------------------ */ + /** + * @param status The status code to send. + * @param reason the status message to send. + */ + public final void setResponse(int status, String reason) + { + if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START"); + _method=null; + _status = status; + if (reason!=null) + { + int len=reason.length(); + + // TODO don't hard code + if (len>1024) + len=1024; + _reason = BufferUtil.newBuffer(len); + for (int i=0;i<len;i++) + { + char ch = reason.charAt(i); + if (ch!='\r'&&ch!='\n') + _reason.put((byte)ch); + else + _reason.put((byte)' '); + } + } + } + + public final void completeUncheckedAddContent() + { + if (_noContent) + { + if(_buffer!=null) + _buffer.clear(); + } + else + { + _contentWritten+=_buffer.remaining(); + if (_head) + _buffer.clear(); + } + } + + private boolean isBufferFull2() + { + if (_buffer != null && _buffer.space()==0) + { + if (_buffer.remaining()==0) + _buffer.compact(); + return _buffer.space()==0; + } + + return _content!=null && _content.remaining()>0; + } + + public final boolean isWritten() + { + return _contentWritten>0; + } + + public final boolean isAllContentWritten() + { + return _contentLength>=0 && _contentWritten>=_contentLength; + } + + + private void complete2() throws IOException + { + if (_state == STATE_HEADER) + { + throw new IllegalStateException("State==HEADER"); + } + + if (_contentLength >= 0 && _contentLength != _contentWritten && !_head) + { + if (LOG.isDebugEnabled()) + LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength); + _persistent = false; + } + } + + + public final void flush(long maxIdleTime) throws IOException + { + // block until everything is flushed + long now=System.currentTimeMillis(); + long end=now+maxIdleTime; + JBuffer content = _content; + JBuffer buffer = _buffer; + if (content!=null && content.remaining()>0 || buffer!=null && buffer.remaining()>0 || isBufferFull()) + { + flushBuffer(); + + while (now<end && (content!=null && content.remaining()>0 ||buffer!=null && buffer.remaining()>0) && _endp.isOpen()&& !_endp.isOutputShutdown()) + { + blockForOutput(end-now); + now=System.currentTimeMillis(); + } + } + } + + /* ------------------------------------------------------------ */ + /** + * Utility method to send an error response. If the builder is not committed, this call is + * equivalent to a setResponse, addContent and complete call. + * + * @param code The error code + * @param reason The error reason + * @param content Contents of the error page + * @param close True if the connection should be closed + * @throws IOException if there is a problem flushing the response + */ + public final void sendError(int code, String reason, String content, boolean close) throws IOException + { + if (close) + _persistent=false; + if (isCommitted()) + { + LOG.debug("sendError on committed: {} {}",code,reason); + } + else + { + LOG.debug("sendError: {} {}",code,reason); + setResponse(code, reason); + if (content != null) + { + completeHeader(null, false); + addContent(BufferUtil.wrap(content), LAST); + } + else if (code>=400) + { + completeHeader(null, false); + addContent(BufferUtil.wrap("Error: "+(reason==null?(""+code):reason)), LAST); + } + else + { + completeHeader(null, true); + } + complete(); + } + } + + public final long getContentWritten() + { + return _contentWritten; + } + + + public final void blockForOutput(long maxIdleTime) throws IOException + { + if (_endp.isBlocking()) + { + try + { + flushBuffer(); + } + catch(IOException e) + { + _endp.close(); + throw e; + } + } + else + { + if (!_endp.blockWritable(maxIdleTime)) + { + _endp.close(); + throw new EofException("timeout"); + } + + flushBuffer(); + } + } + }