103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.http;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slack
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffer;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffers;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.ByteArrayBuffer;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EndPoint;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EofException;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.View;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
3103928aee4356845252ac6b662d5c72c29903813eJake Slack
3203928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
3303928aee4356845252ac6b662d5c72c29903813eJake Slack/**
3403928aee4356845252ac6b662d5c72c29903813eJake Slack * Abstract Generator. Builds HTTP Messages.
3503928aee4356845252ac6b662d5c72c29903813eJake Slack *
3603928aee4356845252ac6b662d5c72c29903813eJake Slack * Currently this class uses a system parameter "jetty.direct.writers" to control
3703928aee4356845252ac6b662d5c72c29903813eJake Slack * two optional writer to byte conversions. buffer.writers=true will probably be
3803928aee4356845252ac6b662d5c72c29903813eJake Slack * faster, but will consume more memory.   This option is just for testing and tuning.
3903928aee4356845252ac6b662d5c72c29903813eJake Slack *
4003928aee4356845252ac6b662d5c72c29903813eJake Slack */
4103928aee4356845252ac6b662d5c72c29903813eJake Slackpublic abstract class AbstractGenerator implements Generator
4203928aee4356845252ac6b662d5c72c29903813eJake Slack{
4303928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(AbstractGenerator.class);
4403928aee4356845252ac6b662d5c72c29903813eJake Slack
4503928aee4356845252ac6b662d5c72c29903813eJake Slack    // states
4603928aee4356845252ac6b662d5c72c29903813eJake Slack    public final static int STATE_HEADER = 0;
4703928aee4356845252ac6b662d5c72c29903813eJake Slack    public final static int STATE_CONTENT = 2;
4803928aee4356845252ac6b662d5c72c29903813eJake Slack    public final static int STATE_FLUSHING = 3;
4903928aee4356845252ac6b662d5c72c29903813eJake Slack    public final static int STATE_END = 4;
5003928aee4356845252ac6b662d5c72c29903813eJake Slack
5103928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final byte[] NO_BYTES = {};
5203928aee4356845252ac6b662d5c72c29903813eJake Slack
5303928aee4356845252ac6b662d5c72c29903813eJake Slack    // data
5403928aee4356845252ac6b662d5c72c29903813eJake Slack
5503928aee4356845252ac6b662d5c72c29903813eJake Slack    protected final Buffers _buffers; // source of buffers
5603928aee4356845252ac6b662d5c72c29903813eJake Slack    protected final EndPoint _endp;
5703928aee4356845252ac6b662d5c72c29903813eJake Slack
5803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected int _state = STATE_HEADER;
5903928aee4356845252ac6b662d5c72c29903813eJake Slack
6003928aee4356845252ac6b662d5c72c29903813eJake Slack    protected int _status = 0;
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected int _version = HttpVersions.HTTP_1_1_ORDINAL;
6203928aee4356845252ac6b662d5c72c29903813eJake Slack    protected  Buffer _reason;
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected  Buffer _method;
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    protected  String _uri;
6503928aee4356845252ac6b662d5c72c29903813eJake Slack
6603928aee4356845252ac6b662d5c72c29903813eJake Slack    protected long _contentWritten = 0;
6703928aee4356845252ac6b662d5c72c29903813eJake Slack    protected long _contentLength = HttpTokens.UNKNOWN_CONTENT;
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected boolean _last = false;
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    protected boolean _head = false;
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    protected boolean _noContent = false;
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected Boolean _persistent = null;
7203928aee4356845252ac6b662d5c72c29903813eJake Slack
7303928aee4356845252ac6b662d5c72c29903813eJake Slack    protected Buffer _header; // Buffer for HTTP header (and maybe small _content)
7403928aee4356845252ac6b662d5c72c29903813eJake Slack    protected Buffer _buffer; // Buffer for copy of passed _content
7503928aee4356845252ac6b662d5c72c29903813eJake Slack    protected Buffer _content; // Buffer passed to addContent
7603928aee4356845252ac6b662d5c72c29903813eJake Slack
7703928aee4356845252ac6b662d5c72c29903813eJake Slack    protected Buffer _date;
7803928aee4356845252ac6b662d5c72c29903813eJake Slack
7903928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _sendServerVersion;
8003928aee4356845252ac6b662d5c72c29903813eJake Slack
8103928aee4356845252ac6b662d5c72c29903813eJake Slack
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
8403928aee4356845252ac6b662d5c72c29903813eJake Slack     * Constructor.
8503928aee4356845252ac6b662d5c72c29903813eJake Slack     *
8603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param buffers buffer pool
8703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param io the end point
8803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    public AbstractGenerator(Buffers buffers, EndPoint io)
9003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9103928aee4356845252ac6b662d5c72c29903813eJake Slack        this._buffers = buffers;
9203928aee4356845252ac6b662d5c72c29903813eJake Slack        this._endp = io;
9303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9403928aee4356845252ac6b662d5c72c29903813eJake Slack
9503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
9603928aee4356845252ac6b662d5c72c29903813eJake Slack    public abstract boolean isRequest();
9703928aee4356845252ac6b662d5c72c29903813eJake Slack
9803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
9903928aee4356845252ac6b662d5c72c29903813eJake Slack    public abstract boolean isResponse();
10003928aee4356845252ac6b662d5c72c29903813eJake Slack
10103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isOpen()
10303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _endp.isOpen();
10503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10603928aee4356845252ac6b662d5c72c29903813eJake Slack
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
10803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void reset()
10903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11003928aee4356845252ac6b662d5c72c29903813eJake Slack        _state = STATE_HEADER;
11103928aee4356845252ac6b662d5c72c29903813eJake Slack        _status = 0;
11203928aee4356845252ac6b662d5c72c29903813eJake Slack        _version = HttpVersions.HTTP_1_1_ORDINAL;
11303928aee4356845252ac6b662d5c72c29903813eJake Slack        _reason = null;
11403928aee4356845252ac6b662d5c72c29903813eJake Slack        _last = false;
11503928aee4356845252ac6b662d5c72c29903813eJake Slack        _head = false;
11603928aee4356845252ac6b662d5c72c29903813eJake Slack        _noContent=false;
11703928aee4356845252ac6b662d5c72c29903813eJake Slack        _persistent = null;
11803928aee4356845252ac6b662d5c72c29903813eJake Slack        _contentWritten = 0;
11903928aee4356845252ac6b662d5c72c29903813eJake Slack        _contentLength = HttpTokens.UNKNOWN_CONTENT;
12003928aee4356845252ac6b662d5c72c29903813eJake Slack        _date = null;
12103928aee4356845252ac6b662d5c72c29903813eJake Slack
12203928aee4356845252ac6b662d5c72c29903813eJake Slack        _content = null;
12303928aee4356845252ac6b662d5c72c29903813eJake Slack        _method=null;
12403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12503928aee4356845252ac6b662d5c72c29903813eJake Slack
12603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
12703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void returnBuffers()
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer!=null && _buffer.length()==0)
13003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
13103928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffers.returnBuffer(_buffer);
13203928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer=null;
13303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
13403928aee4356845252ac6b662d5c72c29903813eJake Slack
13503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_header!=null && _header.length()==0)
13603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
13703928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffers.returnBuffer(_header);
13803928aee4356845252ac6b662d5c72c29903813eJake Slack            _header=null;
13903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
14003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14103928aee4356845252ac6b662d5c72c29903813eJake Slack
14203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------------------------- */
14303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void resetBuffer()
14403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
14503928aee4356845252ac6b662d5c72c29903813eJake Slack        if(_state>=STATE_FLUSHING)
14603928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("Flushed");
14703928aee4356845252ac6b662d5c72c29903813eJake Slack
14803928aee4356845252ac6b662d5c72c29903813eJake Slack        _last = false;
14903928aee4356845252ac6b662d5c72c29903813eJake Slack        _persistent=null;
15003928aee4356845252ac6b662d5c72c29903813eJake Slack        _contentWritten = 0;
15103928aee4356845252ac6b662d5c72c29903813eJake Slack        _contentLength = HttpTokens.UNKNOWN_CONTENT;
15203928aee4356845252ac6b662d5c72c29903813eJake Slack        _content=null;
15303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer!=null)
15403928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer.clear();
15503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15603928aee4356845252ac6b662d5c72c29903813eJake Slack
15703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
15803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
15903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the contentBufferSize.
16003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
16103928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getContentBufferSize()
16203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer==null)
16403928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer=_buffers.getBuffer();
16503928aee4356845252ac6b662d5c72c29903813eJake Slack        return _buffer.capacity();
16603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
16703928aee4356845252ac6b662d5c72c29903813eJake Slack
16803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
17003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param contentBufferSize The contentBufferSize to set.
17103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
17203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void increaseContentBufferSize(int contentBufferSize)
17303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer==null)
17503928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer=_buffers.getBuffer();
17603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (contentBufferSize > _buffer.capacity())
17703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
17803928aee4356845252ac6b662d5c72c29903813eJake Slack            Buffer nb = _buffers.getBuffer(contentBufferSize);
17903928aee4356845252ac6b662d5c72c29903813eJake Slack            nb.put(_buffer);
18003928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffers.returnBuffer(_buffer);
18103928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer = nb;
18203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
18303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
18403928aee4356845252ac6b662d5c72c29903813eJake Slack
18503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
18603928aee4356845252ac6b662d5c72c29903813eJake Slack    public Buffer getUncheckedBuffer()
18703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
18803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _buffer;
18903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19003928aee4356845252ac6b662d5c72c29903813eJake Slack
19103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
19203928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean getSendServerVersion ()
19303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
19403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _sendServerVersion;
19503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19603928aee4356845252ac6b662d5c72c29903813eJake Slack
19703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
19803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setSendServerVersion (boolean sendServerVersion)
19903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20003928aee4356845252ac6b662d5c72c29903813eJake Slack        _sendServerVersion = sendServerVersion;
20103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
20203928aee4356845252ac6b662d5c72c29903813eJake Slack
20303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20403928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getState()
20503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _state;
20703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
20803928aee4356845252ac6b662d5c72c29903813eJake Slack
20903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
21003928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isState(int state)
21103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
21203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _state == state;
21303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
21403928aee4356845252ac6b662d5c72c29903813eJake Slack
21503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
21603928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isComplete()
21703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
21803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _state == STATE_END;
21903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
22003928aee4356845252ac6b662d5c72c29903813eJake Slack
22103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
22203928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isIdle()
22303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
22403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _state == STATE_HEADER && _method==null && _status==0;
22503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
22603928aee4356845252ac6b662d5c72c29903813eJake Slack
22703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
22803928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isCommitted()
22903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
23003928aee4356845252ac6b662d5c72c29903813eJake Slack        return _state != STATE_HEADER;
23103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
23203928aee4356845252ac6b662d5c72c29903813eJake Slack
23303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
23403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
23503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the head.
23603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
23703928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isHead()
23803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
23903928aee4356845252ac6b662d5c72c29903813eJake Slack        return _head;
24003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
24103928aee4356845252ac6b662d5c72c29903813eJake Slack
24203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
24303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setContentLength(long value)
24403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
24503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (value<0)
24603928aee4356845252ac6b662d5c72c29903813eJake Slack            _contentLength=HttpTokens.UNKNOWN_CONTENT;
24703928aee4356845252ac6b662d5c72c29903813eJake Slack        else
24803928aee4356845252ac6b662d5c72c29903813eJake Slack            _contentLength=value;
24903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
25003928aee4356845252ac6b662d5c72c29903813eJake Slack
25103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
25203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
25303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param head The head to set.
25403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
25503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setHead(boolean head)
25603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
25703928aee4356845252ac6b662d5c72c29903813eJake Slack        _head = head;
25803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
25903928aee4356845252ac6b662d5c72c29903813eJake Slack
26003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
26103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
26203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return <code>false</code> if the connection should be closed after a request has been read,
26303928aee4356845252ac6b662d5c72c29903813eJake Slack     * <code>true</code> if it should be used for additional requests.
26403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
26503928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isPersistent()
26603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
26703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _persistent!=null
26803928aee4356845252ac6b662d5c72c29903813eJake Slack        ?_persistent.booleanValue()
26903928aee4356845252ac6b662d5c72c29903813eJake Slack        :(isRequest()?true:_version>HttpVersions.HTTP_1_0_ORDINAL);
27003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
27103928aee4356845252ac6b662d5c72c29903813eJake Slack
27203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setPersistent(boolean persistent)
27403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27503928aee4356845252ac6b662d5c72c29903813eJake Slack        _persistent=persistent;
27603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
27703928aee4356845252ac6b662d5c72c29903813eJake Slack
27803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
28003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param version The version of the client the response is being sent to (NB. Not the version
28103928aee4356845252ac6b662d5c72c29903813eJake Slack     *            in the response, which is the version of the server).
28203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
28303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setVersion(int version)
28403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
28503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_state != STATE_HEADER)
28603928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("STATE!=START "+_state);
28703928aee4356845252ac6b662d5c72c29903813eJake Slack        _version = version;
28803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null)
28903928aee4356845252ac6b662d5c72c29903813eJake Slack            _noContent=true;
29003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29103928aee4356845252ac6b662d5c72c29903813eJake Slack
29203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
29303928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getVersion()
29403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
29503928aee4356845252ac6b662d5c72c29903813eJake Slack        return _version;
29603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29703928aee4356845252ac6b662d5c72c29903813eJake Slack
29803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
29903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
30003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.Buffer)
30103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
30203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setDate(Buffer timeStampBuffer)
30303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30403928aee4356845252ac6b662d5c72c29903813eJake Slack        _date=timeStampBuffer;
30503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
30603928aee4356845252ac6b662d5c72c29903813eJake Slack
30703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
30803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
30903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
31003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setRequest(String method, String uri)
31103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
31203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (method==null || HttpMethods.GET.equals(method) )
31303928aee4356845252ac6b662d5c72c29903813eJake Slack            _method=HttpMethods.GET_BUFFER;
31403928aee4356845252ac6b662d5c72c29903813eJake Slack        else
31503928aee4356845252ac6b662d5c72c29903813eJake Slack            _method=HttpMethods.CACHE.lookup(method);
31603928aee4356845252ac6b662d5c72c29903813eJake Slack        _uri=uri;
31703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_version==HttpVersions.HTTP_0_9_ORDINAL)
31803928aee4356845252ac6b662d5c72c29903813eJake Slack            _noContent=true;
31903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
32003928aee4356845252ac6b662d5c72c29903813eJake Slack
32103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
32203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
32303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param status The status code to send.
32403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param reason the status message to send.
32503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
32603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setResponse(int status, String reason)
32703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
32803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START");
32903928aee4356845252ac6b662d5c72c29903813eJake Slack        _method=null;
33003928aee4356845252ac6b662d5c72c29903813eJake Slack        _status = status;
33103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (reason!=null)
33203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
33303928aee4356845252ac6b662d5c72c29903813eJake Slack            int len=reason.length();
33403928aee4356845252ac6b662d5c72c29903813eJake Slack
33503928aee4356845252ac6b662d5c72c29903813eJake Slack            // TODO don't hard code
33603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (len>1024)
33703928aee4356845252ac6b662d5c72c29903813eJake Slack                len=1024;
33803928aee4356845252ac6b662d5c72c29903813eJake Slack            _reason=new ByteArrayBuffer(len);
33903928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=0;i<len;i++)
34003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
34103928aee4356845252ac6b662d5c72c29903813eJake Slack                char ch = reason.charAt(i);
34203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (ch!='\r'&&ch!='\n')
34303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _reason.put((byte)ch);
34403928aee4356845252ac6b662d5c72c29903813eJake Slack                else
34503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _reason.put((byte)' ');
34603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
34703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
34803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
34903928aee4356845252ac6b662d5c72c29903813eJake Slack
35003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
35103928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Prepare buffer for unchecked writes.
35203928aee4356845252ac6b662d5c72c29903813eJake Slack     * Prepare the generator buffer to receive unchecked writes
35303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return the available space in the buffer.
35403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException
35503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
35603928aee4356845252ac6b662d5c72c29903813eJake Slack    public abstract int prepareUncheckedAddContent() throws IOException;
35703928aee4356845252ac6b662d5c72c29903813eJake Slack
35803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
35903928aee4356845252ac6b662d5c72c29903813eJake Slack    void uncheckedAddContent(int b)
36003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36103928aee4356845252ac6b662d5c72c29903813eJake Slack        _buffer.put((byte)b);
36203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36303928aee4356845252ac6b662d5c72c29903813eJake Slack
36403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
36503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void completeUncheckedAddContent()
36603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_noContent)
36803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
36903928aee4356845252ac6b662d5c72c29903813eJake Slack            if(_buffer!=null)
37003928aee4356845252ac6b662d5c72c29903813eJake Slack                _buffer.clear();
37103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
37203928aee4356845252ac6b662d5c72c29903813eJake Slack        else
37303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
37403928aee4356845252ac6b662d5c72c29903813eJake Slack            _contentWritten+=_buffer.length();
37503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_head)
37603928aee4356845252ac6b662d5c72c29903813eJake Slack                _buffer.clear();
37703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
37803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
37903928aee4356845252ac6b662d5c72c29903813eJake Slack
38003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
38103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isBufferFull()
38203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
38303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer != null && _buffer.space()==0)
38403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_buffer.length()==0 && !_buffer.isImmutable())
38603928aee4356845252ac6b662d5c72c29903813eJake Slack                _buffer.compact();
38703928aee4356845252ac6b662d5c72c29903813eJake Slack            return _buffer.space()==0;
38803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
38903928aee4356845252ac6b662d5c72c29903813eJake Slack
39003928aee4356845252ac6b662d5c72c29903813eJake Slack        return _content!=null && _content.length()>0;
39103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
39203928aee4356845252ac6b662d5c72c29903813eJake Slack
39303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
39403928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isWritten()
39503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
39603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _contentWritten>0;
39703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
39803928aee4356845252ac6b662d5c72c29903813eJake Slack
39903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
40003928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isAllContentWritten()
40103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
40203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _contentLength>=0 && _contentWritten>=_contentLength;
40303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
40403928aee4356845252ac6b662d5c72c29903813eJake Slack
40503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
40603928aee4356845252ac6b662d5c72c29903813eJake Slack    public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException;
40703928aee4356845252ac6b662d5c72c29903813eJake Slack
40803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
40903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
41003928aee4356845252ac6b662d5c72c29903813eJake Slack     * Complete the message.
41103928aee4356845252ac6b662d5c72c29903813eJake Slack     *
41203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException
41303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
41403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void complete() throws IOException
41503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
41603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_state == STATE_HEADER)
41703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
41803928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("State==HEADER");
41903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
42003928aee4356845252ac6b662d5c72c29903813eJake Slack
42103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_contentLength >= 0 && _contentLength != _contentWritten && !_head)
42203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
42303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
42403928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength);
42503928aee4356845252ac6b662d5c72c29903813eJake Slack            _persistent = false;
42603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
42703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
42803928aee4356845252ac6b662d5c72c29903813eJake Slack
42903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
43003928aee4356845252ac6b662d5c72c29903813eJake Slack    public abstract int flushBuffer() throws IOException;
43103928aee4356845252ac6b662d5c72c29903813eJake Slack
43203928aee4356845252ac6b662d5c72c29903813eJake Slack
43303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
43403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void flush(long maxIdleTime) throws IOException
43503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
43603928aee4356845252ac6b662d5c72c29903813eJake Slack        // block until everything is flushed
43703928aee4356845252ac6b662d5c72c29903813eJake Slack        long now=System.currentTimeMillis();
43803928aee4356845252ac6b662d5c72c29903813eJake Slack        long end=now+maxIdleTime;
43903928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer content = _content;
44003928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer buffer = _buffer;
44103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull())
44203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
44303928aee4356845252ac6b662d5c72c29903813eJake Slack            flushBuffer();
44403928aee4356845252ac6b662d5c72c29903813eJake Slack
44503928aee4356845252ac6b662d5c72c29903813eJake Slack            while (now<end && (content!=null && content.length()>0 ||buffer!=null && buffer.length()>0) && _endp.isOpen()&& !_endp.isOutputShutdown())
44603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
44703928aee4356845252ac6b662d5c72c29903813eJake Slack                blockForOutput(end-now);
44803928aee4356845252ac6b662d5c72c29903813eJake Slack                now=System.currentTimeMillis();
44903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
45003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
45103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
45203928aee4356845252ac6b662d5c72c29903813eJake Slack
45303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
45403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
45503928aee4356845252ac6b662d5c72c29903813eJake Slack     * Utility method to send an error response. If the builder is not committed, this call is
45603928aee4356845252ac6b662d5c72c29903813eJake Slack     * equivalent to a setResponse, addContent and complete call.
45703928aee4356845252ac6b662d5c72c29903813eJake Slack     *
45803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param code The error code
45903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param reason The error reason
46003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param content Contents of the error page
46103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param close True if the connection should be closed
46203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException if there is a problem flushing the response
46303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
46403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void sendError(int code, String reason, String content, boolean close) throws IOException
46503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
46603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (close)
46703928aee4356845252ac6b662d5c72c29903813eJake Slack            _persistent=false;
46803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (isCommitted())
46903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
47003928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("sendError on committed: {} {}",code,reason);
47103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
47203928aee4356845252ac6b662d5c72c29903813eJake Slack        else
47303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
47403928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("sendError: {} {}",code,reason);
47503928aee4356845252ac6b662d5c72c29903813eJake Slack            setResponse(code, reason);
47603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (content != null)
47703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
47803928aee4356845252ac6b662d5c72c29903813eJake Slack                completeHeader(null, false);
47903928aee4356845252ac6b662d5c72c29903813eJake Slack                addContent(new View(new ByteArrayBuffer(content)), Generator.LAST);
48003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
48103928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (code>=400)
48203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
48303928aee4356845252ac6b662d5c72c29903813eJake Slack                completeHeader(null, false);
48403928aee4356845252ac6b662d5c72c29903813eJake Slack                addContent(new View(new ByteArrayBuffer("Error: "+(reason==null?(""+code):reason))), Generator.LAST);
48503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
48603928aee4356845252ac6b662d5c72c29903813eJake Slack            else
48703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
48803928aee4356845252ac6b662d5c72c29903813eJake Slack                completeHeader(null, true);
48903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
49003928aee4356845252ac6b662d5c72c29903813eJake Slack            complete();
49103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
49203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
49303928aee4356845252ac6b662d5c72c29903813eJake Slack
49403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
49503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
49603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the contentWritten.
49703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
49803928aee4356845252ac6b662d5c72c29903813eJake Slack    public long getContentWritten()
49903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
50003928aee4356845252ac6b662d5c72c29903813eJake Slack        return _contentWritten;
50103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
50203928aee4356845252ac6b662d5c72c29903813eJake Slack
50303928aee4356845252ac6b662d5c72c29903813eJake Slack
50403928aee4356845252ac6b662d5c72c29903813eJake Slack
50503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
50603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void  blockForOutput(long maxIdleTime) throws IOException
50703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
50803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_endp.isBlocking())
50903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
51003928aee4356845252ac6b662d5c72c29903813eJake Slack            try
51103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
51203928aee4356845252ac6b662d5c72c29903813eJake Slack                flushBuffer();
51303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
51403928aee4356845252ac6b662d5c72c29903813eJake Slack            catch(IOException e)
51503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
51603928aee4356845252ac6b662d5c72c29903813eJake Slack                _endp.close();
51703928aee4356845252ac6b662d5c72c29903813eJake Slack                throw e;
51803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
51903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
52003928aee4356845252ac6b662d5c72c29903813eJake Slack        else
52103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
52203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!_endp.blockWritable(maxIdleTime))
52303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
52403928aee4356845252ac6b662d5c72c29903813eJake Slack                _endp.close();
52503928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new EofException("timeout");
52603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
52703928aee4356845252ac6b662d5c72c29903813eJake Slack
52803928aee4356845252ac6b662d5c72c29903813eJake Slack            flushBuffer();
52903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
53003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
53103928aee4356845252ac6b662d5c72c29903813eJake Slack
53203928aee4356845252ac6b662d5c72c29903813eJake Slack}
533