//
//  ========================================================================
//  Copyright (c) 1995-2017 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.server;

import static org.eclipse.jetty.util.QuotedStringTokenizer.isQuoted;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.channels.IllegalSelectorException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.eclipse.jetty.http.DateGenerator;
import org.eclipse.jetty.http.HttpContent;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpGenerator.ResponseInfo;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.util.ByteArrayISO8859Writer;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

/**
 * <p>{@link Response} provides the implementation for {@link HttpServletResponse}.</p>
 */
public class Response implements HttpServletResponse
{
    private static final Logger LOG = Log.getLogger(Response.class);    
    private static final String __COOKIE_DELIM="\",;\\ \t";
    private final static String __01Jan1970_COOKIE = DateGenerator.formatCookieDate(0).trim();
    private final static int __MIN_BUFFER_SIZE = 1;
    

    // Cookie building buffer. Reduce garbage for cookie using applications
    private static final ThreadLocal<StringBuilder> __cookieBuilder = new ThreadLocal<StringBuilder>()
    {
       @Override
       protected StringBuilder initialValue()
       {
          return new StringBuilder(128);
       }
    };

    /* ------------------------------------------------------------ */
    public static Response getResponse(HttpServletResponse response)
    {
        if (response instanceof Response)
            return (Response)response;
        return HttpChannel.getCurrentHttpChannel().getResponse();
    }
    
    
    public enum OutputType
    {
        NONE, STREAM, WRITER
    }

    /**
     * If a header name starts with this string,  the header (stripped of the prefix)
     * can be set during include using only {@link #setHeader(String, String)} or
     * {@link #addHeader(String, String)}.
     */
    public final static String SET_INCLUDE_HEADER_PREFIX = "org.eclipse.jetty.server.include.";

    /**
     * If this string is found within the comment of a cookie added with {@link #addCookie(Cookie)}, then the cookie
     * will be set as HTTP ONLY.
     */
    public final static String HTTP_ONLY_COMMENT = "__HTTP_ONLY__";

    private final HttpChannel<?> _channel;
    private final HttpFields _fields = new HttpFields();
    private final AtomicInteger _include = new AtomicInteger();
    private HttpOutput _out;
    private int _status = HttpStatus.OK_200;
    private String _reason;
    private Locale _locale;
    private MimeTypes.Type _mimeType;
    private String _characterEncoding;
    private boolean _explicitEncoding;
    private String _contentType;
    private OutputType _outputType = OutputType.NONE;
    private ResponseWriter _writer;
    private long _contentLength = -1;
    

    public Response(HttpChannel<?> channel, HttpOutput out)
    {
        _channel = channel;
        _out = out;
    }

    protected HttpChannel<?> getHttpChannel()
    {
        return _channel;
    }

    protected void recycle()
    {
        _status = HttpStatus.OK_200;
        _reason = null;
        _locale = null;
        _mimeType = null;
        _characterEncoding = null;
        _contentType = null;
        _outputType = OutputType.NONE;
        _contentLength = -1;
        _out.reset();
        _fields.clear();
        _explicitEncoding=false;
    }

    public void setHeaders(HttpContent httpContent)
    {
        Response response = _channel.getResponse();
        String contentType = httpContent.getContentType();
        if (contentType != null && !response.getHttpFields().containsKey(HttpHeader.CONTENT_TYPE.asString()))
            setContentType(contentType);
        
        if (httpContent.getContentLength() > 0)
            setLongContentLength(httpContent.getContentLength());

        String lm = httpContent.getLastModified();
        if (lm != null)
            response.getHttpFields().put(HttpHeader.LAST_MODIFIED, lm);
        else if (httpContent.getResource() != null)
        {
            long lml = httpContent.getResource().lastModified();
            if (lml != -1)
                response.getHttpFields().putDateField(HttpHeader.LAST_MODIFIED, lml);
        }

        String etag=httpContent.getETag();
        if (etag!=null)
            response.getHttpFields().put(HttpHeader.ETAG,etag);
    }
    
    public HttpOutput getHttpOutput()
    {
        return _out;
    }
    
    public void setHttpOutput(HttpOutput out)
    {
        _out=out;
    }

    public boolean isIncluding()
    {
        return _include.get() > 0;
    }

    public void include()
    {
        _include.incrementAndGet();
    }

    public void included()
    {
        _include.decrementAndGet();
        if (_outputType == OutputType.WRITER)
        {
            _writer.reopen();
        }
        _out.reopen();
    }

    public void addCookie(HttpCookie cookie)
    {
        addSetCookie(
                cookie.getName(),
                cookie.getValue(),
                cookie.getDomain(),
                cookie.getPath(),
                cookie.getMaxAge(),
                cookie.getComment(),
                cookie.isSecure(),
                cookie.isHttpOnly(),
                cookie.getVersion());;
    }

    @Override
    public void addCookie(Cookie cookie)
    {
        String comment = cookie.getComment();
        boolean httpOnly = false;

        if (comment != null)
        {
            int i = comment.indexOf(HTTP_ONLY_COMMENT);
            if (i >= 0)
            {
                httpOnly = true;
                comment = comment.replace(HTTP_ONLY_COMMENT, "").trim();
                if (comment.length() == 0)
                    comment = null;
            }
        }
        addSetCookie(cookie.getName(),
                cookie.getValue(),
                cookie.getDomain(),
                cookie.getPath(),
                cookie.getMaxAge(),
                comment,
                cookie.getSecure(),
                httpOnly || cookie.isHttpOnly(),
                cookie.getVersion());
    }


    /**
     * Format a set cookie value
     *
     * @param name the name
     * @param value the value
     * @param domain the domain
     * @param path the path
     * @param maxAge the maximum age
     * @param comment the comment (only present on versions > 0)
     * @param isSecure true if secure cookie
     * @param isHttpOnly true if for http only
     * @param version version of cookie logic to use (0 == default behavior)
     */
    public void addSetCookie(
            final String name,
            final String value,
            final String domain,
            final String path,
            final long maxAge,
            final String comment,
            final boolean isSecure,
            final boolean isHttpOnly,
            int version)
    {
        // Check arguments
        if (name == null || name.length() == 0)
            throw new IllegalArgumentException("Bad cookie name");

        // Format value and params
        StringBuilder buf = __cookieBuilder.get();
        buf.setLength(0);
        
        // Name is checked for legality by servlet spec, but can also be passed directly so check again for quoting
        boolean quote_name=isQuoteNeededForCookie(name);
        quoteOnlyOrAppend(buf,name,quote_name);
        
        buf.append('=');
        
        // Remember name= part to look for other matching set-cookie
        String name_equals=buf.toString();

        // Append the value
        boolean quote_value=isQuoteNeededForCookie(value);
        quoteOnlyOrAppend(buf,value,quote_value);

        // Look for domain and path fields and check if they need to be quoted
        boolean has_domain = domain!=null && domain.length()>0;
        boolean quote_domain = has_domain && isQuoteNeededForCookie(domain);
        boolean has_path = path!=null && path.length()>0;
        boolean quote_path = has_path && isQuoteNeededForCookie(path);
        
        // Upgrade the version if we have a comment or we need to quote value/path/domain or if they were already quoted
        if (version==0 && ( comment!=null || quote_name || quote_value || quote_domain || quote_path || isQuoted(name) || isQuoted(value) || isQuoted(path) || isQuoted(domain)))
            version=1;

        // Append version
        if (version==1)
            buf.append (";Version=1");
        else if (version>1)
            buf.append (";Version=").append(version);
        
        // Append path
        if (has_path)
        {
            buf.append(";Path=");
            quoteOnlyOrAppend(buf,path,quote_path);
        }
        
        // Append domain
        if (has_domain)
        {
            buf.append(";Domain=");
            quoteOnlyOrAppend(buf,domain,quote_domain);
        }

        // Handle max-age and/or expires
        if (maxAge >= 0)
        {
            // Always use expires
            // This is required as some browser (M$ this means you!) don't handle max-age even with v1 cookies
            buf.append(";Expires=");
            if (maxAge == 0)
                buf.append(__01Jan1970_COOKIE);
            else
                DateGenerator.formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge);
            
            // for v1 cookies, also send max-age
            if (version>=1)
            {
                buf.append(";Max-Age=");
                buf.append(maxAge);
            }
        }

        // add the other fields
        if (isSecure)
            buf.append(";Secure");
        if (isHttpOnly)
            buf.append(";HttpOnly");
        if (comment != null)
        {
            buf.append(";Comment=");
            quoteOnlyOrAppend(buf,comment,isQuoteNeededForCookie(comment));
        }

        // remove any existing set-cookie fields of same name
        Iterator<HttpField> i=_fields.iterator();
        while (i.hasNext())
        {
            HttpField field=i.next();
            if (field.getHeader()==HttpHeader.SET_COOKIE)
            {
                String val = field.getValue();
                if (val!=null && val.startsWith(name_equals))
                {
                    //existing cookie has same name, does it also match domain and path?
                    if (((!has_domain && !val.contains("Domain")) || (has_domain && val.contains(domain))) &&
                        ((!has_path && !val.contains("Path")) || (has_path && val.contains(path))))
                    {
                        i.remove();
                    }
                }
            }
        }
        
        // add the set cookie
        _fields.add(HttpHeader.SET_COOKIE.toString(), buf.toString());

        // Expire responses with set-cookie headers so they do not get cached.
        _fields.put(HttpHeader.EXPIRES.toString(), DateGenerator.__01Jan1970);
    }


    /* ------------------------------------------------------------ */
    /** Does a cookie value need to be quoted?
     * @param s value string
     * @return true if quoted;
     * @throws IllegalArgumentException If there a control characters in the string
     */
    private static boolean isQuoteNeededForCookie(String s)
    {
        if (s==null || s.length()==0)
            return true;
        
        if (QuotedStringTokenizer.isQuoted(s))
            return false;

        for (int i=0;i<s.length();i++)
        {
            char c = s.charAt(i);
            if (__COOKIE_DELIM.indexOf(c)>=0)
                return true;
            
            if (c<0x20 || c>=0x7f)
                throw new IllegalArgumentException("Illegal character in cookie value");
        }

        return false;
    }
    
    
    private static void quoteOnlyOrAppend(StringBuilder buf, String s, boolean quote)
    {
        if (quote)
            QuotedStringTokenizer.quoteOnly(buf,s);
        else
            buf.append(s);
    }
    
    @Override
    public boolean containsHeader(String name)
    {
        return _fields.containsKey(name);
    }

    @Override
    public String encodeURL(String url)
    {
        final Request request = _channel.getRequest();
        SessionManager sessionManager = request.getSessionManager();
        if (sessionManager == null)
            return url;

        HttpURI uri = null;
        if (sessionManager.isCheckingRemoteSessionIdEncoding() && URIUtil.hasScheme(url))
        {
            uri = new HttpURI(url);
            String path = uri.getPath();
            path = (path == null ? "" : path);
            int port = uri.getPort();
            if (port < 0)
                port = HttpScheme.HTTPS.asString().equalsIgnoreCase(uri.getScheme()) ? 443 : 80;
            if (!request.getServerName().equalsIgnoreCase(uri.getHost()) ||
                    request.getServerPort() != port ||
                    !path.startsWith(request.getContextPath())) //TODO the root context path is "", with which every non null string starts
                return url;
        }

        String sessionURLPrefix = sessionManager.getSessionIdPathParameterNamePrefix();
        if (sessionURLPrefix == null)
            return url;

        if (url == null)
            return null;

        // should not encode if cookies in evidence
        if ((sessionManager.isUsingCookies() && request.isRequestedSessionIdFromCookie()) || !sessionManager.isUsingURLs()) 
        {
            int prefix = url.indexOf(sessionURLPrefix);
            if (prefix != -1)
            {
                int suffix = url.indexOf("?", prefix);
                if (suffix < 0)
                    suffix = url.indexOf("#", prefix);

                if (suffix <= prefix)
                    return url.substring(0, prefix);
                return url.substring(0, prefix) + url.substring(suffix);
            }
            return url;
        }

        // get session;
        HttpSession session = request.getSession(false);

        // no session
        if (session == null)
            return url;

        // invalid session
        if (!sessionManager.isValid(session))
            return url;

        String id = sessionManager.getNodeId(session);

        if (uri == null)
            uri = new HttpURI(url);


        // Already encoded
        int prefix = url.indexOf(sessionURLPrefix);
        if (prefix != -1)
        {
            int suffix = url.indexOf("?", prefix);
            if (suffix < 0)
                suffix = url.indexOf("#", prefix);

            if (suffix <= prefix)
                return url.substring(0, prefix + sessionURLPrefix.length()) + id;
            return url.substring(0, prefix + sessionURLPrefix.length()) + id +
                    url.substring(suffix);
        }

        // edit the session
        int suffix = url.indexOf('?');
        if (suffix < 0)
            suffix = url.indexOf('#');
        if (suffix < 0)
        {
            return url +
                    ((HttpScheme.HTTPS.is(uri.getScheme()) || HttpScheme.HTTP.is(uri.getScheme())) && uri.getPath() == null ? "/" : "") + //if no path, insert the root path
                    sessionURLPrefix + id;
        }


        return url.substring(0, suffix) +
                ((HttpScheme.HTTPS.is(uri.getScheme()) || HttpScheme.HTTP.is(uri.getScheme())) && uri.getPath() == null ? "/" : "") + //if no path so insert the root path
                sessionURLPrefix + id + url.substring(suffix);
    }

    @Override
    public String encodeRedirectURL(String url)
    {
        return encodeURL(url);
    }

    @Override
    @Deprecated
    public String encodeUrl(String url)
    {
        return encodeURL(url);
    }

    @Override
    @Deprecated
    public String encodeRedirectUrl(String url)
    {
        return encodeRedirectURL(url);
    }

    @Override
    public void sendError(int sc) throws IOException
    {
        sendError(sc, null);
    }

    @Override
    public void sendError(int code, String message) throws IOException
    {
        if (isIncluding())
            return;

        switch(code)
        {
            case -1:
                _channel.abort();
                return;
            case 102:
                sendProcessing();
                return;
            default:
        }

        if (isCommitted())
            LOG.warn("Committed before "+code+" "+message);

        resetBuffer();
        _characterEncoding=null;
        setHeader(HttpHeader.EXPIRES,null);
        setHeader(HttpHeader.LAST_MODIFIED,null);
        setHeader(HttpHeader.CACHE_CONTROL,null);
        setHeader(HttpHeader.CONTENT_TYPE,null);
        setHeader(HttpHeader.CONTENT_LENGTH,null);

        _outputType = OutputType.NONE;
        setStatus(code);
        _reason=message;

        Request request = _channel.getRequest();
        Throwable cause = (Throwable)request.getAttribute(Dispatcher.ERROR_EXCEPTION);
        if (message==null)
            message=cause==null?HttpStatus.getMessage(code):cause.toString();

        // If we are allowed to have a body
        if (code!=SC_NO_CONTENT &&
            code!=SC_NOT_MODIFIED &&
            code!=SC_PARTIAL_CONTENT &&
            code>=SC_OK)
        {
            ErrorHandler error_handler = ErrorHandler.getErrorHandler(_channel.getServer(),request.getContext()==null?null:request.getContext().getContextHandler());
            if (error_handler!=null)
            {
                request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,new Integer(code));
                request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
                request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
                request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME,request.getServletName());
                error_handler.handle(null,_channel.getRequest(),_channel.getRequest(),this );
            }
            else
            {
                setHeader(HttpHeader.CACHE_CONTROL, "must-revalidate,no-cache,no-store");
                setContentType(MimeTypes.Type.TEXT_HTML_8859_1.toString());
                try (ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(2048);)
                {
                    message=StringUtil.sanitizeXmlString(message);
                    String uri= request.getRequestURI();
                    uri=StringUtil.sanitizeXmlString(uri);

                    writer.write("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\"/>\n");
                    writer.write("<title>Error ");
                    writer.write(Integer.toString(code));
                    writer.write(' ');
                    if (message==null)
                        writer.write(message);
                    writer.write("</title>\n</head>\n<body>\n<h2>HTTP ERROR: ");
                    writer.write(Integer.toString(code));
                    writer.write("</h2>\n<p>Problem accessing ");
                    writer.write(uri);
                    writer.write(". Reason:\n<pre>    ");
                    writer.write(message);
                    writer.write("</pre>");
                    writer.write("</p>\n<hr /><i><small>Powered by Jetty://</small></i>");
                    writer.write("\n</body>\n</html>\n");

                    writer.flush();
                    setContentLength(writer.size());
                    try (ServletOutputStream outputStream = getOutputStream())
                    {
                        writer.writeTo(outputStream);
                        writer.destroy();
                    }
                }
            }
        }
        else if (code!=SC_PARTIAL_CONTENT)
        {
            // TODO work out why this is required?
            _channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_TYPE);
            _channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_LENGTH);
            _characterEncoding=null;
            _mimeType=null;
        }

        closeOutput();
    }

    /**
     * Sends a 102-Processing response.
     * If the connection is a HTTP connection, the version is 1.1 and the
     * request has a Expect header starting with 102, then a 102 response is
     * sent. This indicates that the request still be processed and real response
     * can still be sent.   This method is called by sendError if it is passed 102.
     * @see javax.servlet.http.HttpServletResponse#sendError(int)
     */
    public void sendProcessing() throws IOException
    {
        if (_channel.isExpecting102Processing() && !isCommitted())
        {
            _channel.sendResponse(HttpGenerator.PROGRESS_102_INFO, null, true);
        }
    }
    
    /**
     * Sends a response with one of the 300 series redirection codes.
     * @param code
     * @param location
     * @throws IOException
     */
    public void sendRedirect(int code, String location) throws IOException
    {
        if ((code < HttpServletResponse.SC_MULTIPLE_CHOICES) || (code >= HttpServletResponse.SC_BAD_REQUEST))
            throw new IllegalArgumentException("Not a 3xx redirect code");
        
        if (isIncluding())
            return;

        if (location == null)
            throw new IllegalArgumentException();

        if (!URIUtil.hasScheme(location))
        {
            StringBuilder buf = _channel.getRequest().getRootURL();
            if (location.startsWith("/"))
            {
                // absolute in context
                location=URIUtil.canonicalPath(location);
            }
            else
            {
                // relative to request
                String path=_channel.getRequest().getRequestURI();
                String parent=(path.endsWith("/"))?path:URIUtil.parentPath(path);
                location=URIUtil.canonicalPath(URIUtil.addPaths(parent,location));
                if (!location.startsWith("/"))
                    buf.append('/');
            }
            
            if(location==null)
                throw new IllegalStateException("path cannot be above root");
            buf.append(location);
            
            location=buf.toString();
        }

        resetBuffer();
        setHeader(HttpHeader.LOCATION, location);
        setStatus(code);
        closeOutput();
    }

    @Override
    public void sendRedirect(String location) throws IOException
    {
        sendRedirect(HttpServletResponse.SC_MOVED_TEMPORARILY, location);
    }

    @Override
    public void setDateHeader(String name, long date)
    {
        if (!isIncluding())
            _fields.putDateField(name, date);
    }

    @Override
    public void addDateHeader(String name, long date)
    {
        if (!isIncluding())
            _fields.addDateField(name, date);
    }

    public void setHeader(HttpHeader name, String value)
    {
        if (HttpHeader.CONTENT_TYPE == name)
            setContentType(value);
        else
        {
            if (isIncluding())
                return;

            _fields.put(name, value);

            if (HttpHeader.CONTENT_LENGTH == name)
            {
                if (value == null)
                    _contentLength = -1l;
                else
                    _contentLength = Long.parseLong(value);
            }
        }
    }

    @Override
    public void setHeader(String name, String value)
    {
        if (HttpHeader.CONTENT_TYPE.is(name))
            setContentType(value);
        else
        {
            if (isIncluding())
            {
                if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
                    name = name.substring(SET_INCLUDE_HEADER_PREFIX.length());
                else
                    return;
            }
            _fields.put(name, value);
            if (HttpHeader.CONTENT_LENGTH.is(name))
            {
                if (value == null)
                    _contentLength = -1l;
                else
                    _contentLength = Long.parseLong(value);
            }
        }
    }

    @Override
    public Collection<String> getHeaderNames()
    {
        final HttpFields fields = _fields;
        return fields.getFieldNamesCollection();
    }

    @Override
    public String getHeader(String name)
    {
        return _fields.getStringField(name);
    }

    @Override
    public Collection<String> getHeaders(String name)
    {
        final HttpFields fields = _fields;
        Collection<String> i = fields.getValuesList(name);
        if (i == null)
            return Collections.emptyList();
        return i;
    }

    @Override
    public void addHeader(String name, String value)
    {
        if (isIncluding())
        {
            if (name.startsWith(SET_INCLUDE_HEADER_PREFIX))
                name = name.substring(SET_INCLUDE_HEADER_PREFIX.length());
            else
                return;
        }

        if (HttpHeader.CONTENT_TYPE.is(name))
        {
            setContentType(value);
            return;
        }
        
        if (HttpHeader.CONTENT_LENGTH.is(name))
        {
            setHeader(name,value);
            return;
        }
        
        _fields.add(name, value);
    }

    @Override
    public void setIntHeader(String name, int value)
    {
        if (!isIncluding())
        {
            _fields.putLongField(name, value);
            if (HttpHeader.CONTENT_LENGTH.is(name))
                _contentLength = value;
        }
    }

    @Override
    public void addIntHeader(String name, int value)
    {
        if (!isIncluding())
        {
            _fields.add(name, Integer.toString(value));
            if (HttpHeader.CONTENT_LENGTH.is(name))
                _contentLength = value;
        }
    }

    @Override
    public void setStatus(int sc)
    {
        if (sc <= 0)
            throw new IllegalArgumentException();
        if (!isIncluding())
        {
            _status = sc;
            _reason = null;
        }
    }

    @Override
    @Deprecated
    public void setStatus(int sc, String sm)
    {
        setStatusWithReason(sc,sm);
    }
    
    public void setStatusWithReason(int sc, String sm)
    {
        if (sc <= 0)
            throw new IllegalArgumentException();
        if (!isIncluding())
        {
            _status = sc;
            _reason = sm;
        }
    }

    @Override
    public String getCharacterEncoding()
    {
        if (_characterEncoding == null)
            _characterEncoding = StringUtil.__ISO_8859_1;
        return _characterEncoding;
    }

    @Override
    public String getContentType()
    {
        return _contentType;
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException
    {
        if (_outputType == OutputType.WRITER)
            throw new IllegalStateException("WRITER");
        _outputType = OutputType.STREAM;
        return _out;
    }

    public boolean isWriting()
    {
        return _outputType == OutputType.WRITER;
    }

    @Override
    public PrintWriter getWriter() throws IOException
    {
        if (_outputType == OutputType.STREAM)
            throw new IllegalStateException("STREAM");

        if (_outputType == OutputType.NONE)
        {
            /* get encoding from Content-Type header */
            String encoding = _characterEncoding;
            if (encoding == null)
            {
                if (_mimeType!=null && _mimeType.isCharsetAssumed())
                    encoding=_mimeType.getCharset().toString();
                else
                {
                    encoding = MimeTypes.inferCharsetFromContentType(_contentType);
                    if (encoding == null)
                        encoding = StringUtil.__ISO_8859_1;
                    setCharacterEncoding(encoding,false);
                }
            }
            
            if (_writer != null && _writer.isFor(encoding))
                _writer.reopen();
            else
            {
                if (StringUtil.__ISO_8859_1.equalsIgnoreCase(encoding))
                    _writer = new ResponseWriter(new Iso88591HttpWriter(_out),encoding);
                else if (StringUtil.__UTF8.equalsIgnoreCase(encoding))
                    _writer = new ResponseWriter(new Utf8HttpWriter(_out),encoding);
                else
                    _writer = new ResponseWriter(new EncodingHttpWriter(_out, encoding),encoding);
            }
            
            // Set the output type at the end, because setCharacterEncoding() checks for it
            _outputType = OutputType.WRITER;
        }
        return _writer;
    }

    @Override
    public void setContentLength(int len)
    {
        // Protect from setting after committed as default handling
        // of a servlet HEAD request ALWAYS sets _content length, even
        // if the getHandling committed the response!
        if (isCommitted() || isIncluding())
            return;

        _contentLength = len;
        if (_contentLength > 0)
        {
            long written = _out.getWritten();
            if (written > len)
                throw new IllegalArgumentException("setContentLength(" + len + ") when already written " + written);
            
            _fields.putLongField(HttpHeader.CONTENT_LENGTH, len);
            if (isAllContentWritten(written))
            {
                try
                {
                    closeOutput();
                }
                catch(IOException e)
                {
                    throw new RuntimeIOException(e);
                }
            }
        }
        else if (_contentLength==0)
        {
            long written = _out.getWritten();
            if (written > 0)
                throw new IllegalArgumentException("setContentLength(0) when already written " + written);
            _fields.put(HttpHeader.CONTENT_LENGTH, "0");
        }
        else
            _fields.remove(HttpHeader.CONTENT_LENGTH);
    }
    
    public long getContentLength()
    {
        return _contentLength;
    }

    public boolean isAllContentWritten(long written)
    {
        return (_contentLength >= 0 && written >= _contentLength);
    }

    public void closeOutput() throws IOException
    {
        switch (_outputType)
        {
            case WRITER:
                _writer.close();
                if (!_out.isClosed())
                    _out.close();
                break;
            case STREAM:
                getOutputStream().close();
                break;
            default:
                _out.close();
        }
    }

    public long getLongContentLength()
    {
        return _contentLength;
    }

    public void setLongContentLength(long len)
    {
        // Protect from setting after committed as default handling
        // of a servlet HEAD request ALWAYS sets _content length, even
        // if the getHandling committed the response!
        if (isCommitted() || isIncluding())
            return;
        _contentLength = len;
        _fields.putLongField(HttpHeader.CONTENT_LENGTH.toString(), len);
    }
    
    @Override
    public void setContentLengthLong(long length)
    {
        setLongContentLength(length);
    }

    @Override
    public void setCharacterEncoding(String encoding)
    {
        setCharacterEncoding(encoding,true);
    }
    
    private void setCharacterEncoding(String encoding, boolean explicit)
    {
        if (isIncluding() || isWriting())
            return;

        if (_outputType == OutputType.NONE && !isCommitted())
        {
            if (encoding == null)
            {
                _explicitEncoding=false;
                
                // Clear any encoding.
                if (_characterEncoding != null)
                {
                    _characterEncoding = null;
                    
                    if (_mimeType!=null)
                    {
                        _mimeType=_mimeType.getBaseType();
                        _contentType=_mimeType.asString();
                        _fields.put(_mimeType.getContentTypeField());
                    }
                    else if (_contentType != null)
                    {
                        _contentType = MimeTypes.getContentTypeWithoutCharset(_contentType);
                        _fields.put(HttpHeader.CONTENT_TYPE, _contentType);
                    }
                }
            }
            else
            {
                // No, so just add this one to the mimetype
                _explicitEncoding = explicit;
                _characterEncoding = HttpGenerator.__STRICT?encoding:StringUtil.normalizeCharset(encoding);
                if (_mimeType!=null)
                {
                    _contentType=_mimeType.getBaseType().asString()+ "; charset=" + _characterEncoding;
                    _mimeType = MimeTypes.CACHE.get(_contentType);
                    if (_mimeType==null || HttpGenerator.__STRICT)
                        _fields.put(HttpHeader.CONTENT_TYPE, _contentType);
                    else
                        _fields.put(_mimeType.getContentTypeField());
                }
                else if (_contentType != null)
                {
                    _contentType = MimeTypes.getContentTypeWithoutCharset(_contentType) + "; charset=" + _characterEncoding;
                    _fields.put(HttpHeader.CONTENT_TYPE, _contentType);
                }
            }
        }
    }

    @Override
    public void setContentType(String contentType)
    {
        if (isCommitted() || isIncluding())
            return;

        if (contentType == null)
        {
            if (isWriting() && _characterEncoding != null)
                throw new IllegalSelectorException();

            if (_locale == null)
                _characterEncoding = null;
            _mimeType = null;
            _contentType = null;
            _fields.remove(HttpHeader.CONTENT_TYPE);
        }
        else
        {
            _contentType = contentType;
            _mimeType = MimeTypes.CACHE.get(contentType);
            
            String charset;
            if (_mimeType!=null && _mimeType.getCharset()!=null && !_mimeType.isCharsetAssumed())
                charset=_mimeType.getCharset().toString();
            else
                charset = MimeTypes.getCharsetFromContentType(contentType);

            if (charset == null)
            {
                if (_characterEncoding != null)
                {
                    _contentType = contentType + "; charset=" + _characterEncoding;
                    _mimeType = null;
                }
            }
            else if (isWriting() && !charset.equals(_characterEncoding))
            {
                // too late to change the character encoding;
                _mimeType = null;
                _contentType = MimeTypes.getContentTypeWithoutCharset(_contentType);
                if (_characterEncoding != null)
                    _contentType = _contentType + "; charset=" + _characterEncoding;
            }
            else
            {
                _characterEncoding = charset;
                _explicitEncoding = true;
            }

            if (HttpGenerator.__STRICT || _mimeType==null)
                _fields.put(HttpHeader.CONTENT_TYPE, _contentType);
            else
            {
                _contentType=_mimeType.asString();
                _fields.put(_mimeType.getContentTypeField());
            }
        }
        
    }

    @Override
    public void setBufferSize(int size)
    {
        if (isCommitted() || getContentCount() > 0)
            throw new IllegalStateException("Committed or content written");
        if (size <= 0)
            size = __MIN_BUFFER_SIZE;
        _out.setBufferSize(size);
    }

    @Override
    public int getBufferSize()
    {
        return _out.getBufferSize();
    }

    @Override
    public void flushBuffer() throws IOException
    {
        if (!_out.isClosed())
            _out.flush();
    }

    @Override
    public void reset()
    {
        resetForForward();
        _status = 200;
        _reason = null;
        _contentLength = -1;
        _fields.clear();

        String connection = _channel.getRequest().getHttpFields().getStringField(HttpHeader.CONNECTION);
        if (connection != null)
        {
            for (String value: StringUtil.csvSplit(null,connection,0,connection.length()))
            {
                HttpHeaderValue cb = HttpHeaderValue.CACHE.get(value);

                if (cb != null)
                {
                    switch (cb)
                    {
                        case CLOSE:
                            _fields.put(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.toString());
                            break;

                        case KEEP_ALIVE:
                            if (HttpVersion.HTTP_1_0.is(_channel.getRequest().getProtocol()))
                                _fields.put(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.toString());
                            break;
                        case TE:
                            _fields.put(HttpHeader.CONNECTION, HttpHeaderValue.TE.toString());
                            break;
                        default:
                    }
                }
            }
        }
    }

    public void reset(boolean preserveCookies)
    { 
        if (!preserveCookies)
            reset();
        else
        {
            ArrayList<String> cookieValues = new ArrayList<String>(5);
            Enumeration<String> vals = _fields.getValues(HttpHeader.SET_COOKIE.asString());
            while (vals.hasMoreElements())
                cookieValues.add(vals.nextElement());
            reset();
            for (String v:cookieValues)
                _fields.add(HttpHeader.SET_COOKIE, v);
        }
    }

    public void resetForForward()
    {
        resetBuffer();
        _outputType = OutputType.NONE;
    }

    @Override
    public void resetBuffer()
    {
        if (isCommitted())
            throw new IllegalStateException("Committed");

        switch (_outputType)
        {
            case STREAM:
            case WRITER:
                _out.reset();
                break;
            default:
        }

        _out.resetBuffer();
    }

    protected ResponseInfo newResponseInfo()
    {
        return new ResponseInfo(_channel.getRequest().getHttpVersion(), _fields, getLongContentLength(), getStatus(), getReason(), _channel.getRequest().isHead());
    }

    @Override
    public boolean isCommitted()
    {
        return _channel.isCommitted();
    }

    @Override
    public void setLocale(Locale locale)
    {
        if (locale == null || isCommitted() || isIncluding())
            return;

        _locale = locale;
        _fields.put(HttpHeader.CONTENT_LANGUAGE, locale.toString().replace('_', '-'));

        if (_outputType != OutputType.NONE)
            return;

        if (_channel.getRequest().getContext() == null)
            return;

        String charset = _channel.getRequest().getContext().getContextHandler().getLocaleEncoding(locale);

        if (charset != null && charset.length() > 0 && !_explicitEncoding)
            setCharacterEncoding(charset,false);
    }

    @Override
    public Locale getLocale()
    {
        if (_locale == null)
            return Locale.getDefault();
        return _locale;
    }

    @Override
    public int getStatus()
    {
        return _status;
    }

    public String getReason()
    {
        return _reason;
    }

    public HttpFields getHttpFields()
    {
        return _fields;
    }

    public long getContentCount()
    {
        return _out.getWritten();
    }

    @Override
    public String toString()
    {
        return String.format("%s %d %s%n%s", _channel.getRequest().getHttpVersion(), _status, _reason == null ? "" : _reason, _fields);
    }
    

    private static class ResponseWriter extends PrintWriter
    {
        private final String _encoding;
        private final HttpWriter _httpWriter;
        
        public ResponseWriter(HttpWriter httpWriter,String encoding)
        {
            super(httpWriter);
            _httpWriter=httpWriter;
            _encoding=encoding;
        }

        public boolean isFor(String encoding)
        {
            return _encoding.equalsIgnoreCase(encoding);
        }
        
        protected void reopen()
        {
            super.clearError();
            out=_httpWriter;
        }
    }
}
