Mercurial Hosting > luan
changeset 1057:afc9610dc12e
remove AbstractGenerator
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 08 Nov 2016 04:05:04 -0700 |
parents | 7d872cc72ec2 |
children | 419bf9c03d84 |
files | src/org/eclipse/jetty/http/AbstractGenerator.java src/org/eclipse/jetty/http/HttpGenerator.java |
diffstat | 2 files changed, 326 insertions(+), 397 deletions(-) [+] |
line wrap: on
line diff
--- a/src/org/eclipse/jetty/http/AbstractGenerator.java Tue Nov 08 01:19:36 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,384 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.http; - -import java.io.IOException; - -import org.eclipse.jetty.io.JBuffer; -import org.eclipse.jetty.io.Buffers; -import org.eclipse.jetty.io.BufferUtil; -import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.io.EofException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/* ------------------------------------------------------------ */ -/** - * Abstract Generator. Builds HTTP Messages. - * - * Currently this class uses a system parameter "jetty.direct.writers" to control - * two optional writer to byte conversions. buffer.writers=true will probably be - * faster, but will consume more memory. This option is just for testing and tuning. - * - */ -abstract class AbstractGenerator -{ - private static final Logger LOG = LoggerFactory.getLogger(AbstractGenerator.class); - - public static final boolean LAST=true; - public static final boolean MORE=false; - - // states - final static int STATE_HEADER = 0; - final static int STATE_CONTENT = 2; - final static int STATE_FLUSHING = 3; - final static int STATE_END = 4; - - // data - - final Buffers _buffers; // source of buffers - final EndPoint _endp; - - int _state = STATE_HEADER; - - int _status = 0; - int _version = HttpVersions.HTTP_1_1_ORDINAL; - JBuffer _reason; - JBuffer _method; - String _uri; - - long _contentWritten = 0; - long _contentLength = HttpTokens.UNKNOWN_CONTENT; - boolean _last = false; - boolean _head = false; - boolean _noContent = false; - Boolean _persistent = null; - - JBuffer _header; // JBuffer for HTTP header (and maybe small _content) - JBuffer _buffer; // JBuffer for copy of passed _content - JBuffer _content; // JBuffer passed to addContent - - - /* ------------------------------------------------------------------------------- */ - /** - * Constructor. - * - * @param buffers buffer pool - * @param io the end point - */ - AbstractGenerator(Buffers buffers, EndPoint io) - { - this._buffers = buffers; - this._endp = io; - } - - /* ------------------------------------------------------------ */ - /** - * Add content. - * - * @param content - * @param last - * @throws IllegalArgumentException if <code>content</code> is {@link JBuffer#isImmutable immutable}. - * @throws IllegalStateException If the request is not expecting any more content, - * or if the buffers are full and cannot be flushed. - * @throws IOException if there is a problem flushing the buffers. - */ - public abstract void addContent(JBuffer content, boolean last) throws IOException; - - abstract boolean isRequest(); - - 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(); - } - } - - public boolean isBufferFull() - { - 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; - } - - public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException; - - /* ------------------------------------------------------------ */ - /** - * Complete the message. - * - * @throws IOException - */ - public void complete() 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 abstract int flushBuffer() throws IOException; - - - 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(); - } - } - -}
--- 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(); + } + } + }