net.lightbody.bmp.proxy.jetty.jetty.servlet.ServletHttpResponse.java Source code

Java tutorial

Introduction

Here is the source code for net.lightbody.bmp.proxy.jetty.jetty.servlet.ServletHttpResponse.java

Source

// ========================================================================
// $Id: ServletHttpResponse.java,v 1.65 2006/04/04 22:28:05 gregwilkins Exp $
// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at 
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================

package net.lightbody.bmp.proxy.jetty.jetty.servlet;

import net.lightbody.bmp.proxy.jetty.http.HttpContext;
import net.lightbody.bmp.proxy.jetty.http.HttpFields;
import net.lightbody.bmp.proxy.jetty.http.HttpOutputStream;
import net.lightbody.bmp.proxy.jetty.http.HttpResponse;
import net.lightbody.bmp.proxy.jetty.log.LogFactory;
import net.lightbody.bmp.proxy.jetty.util.*;
import org.apache.commons.logging.Log;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Locale;

/* ------------------------------------------------------------ */
/** Servlet Response Wrapper.
 * This class wraps a Jetty HTTP response as a 2.2 Servlet
 * response.
 *
 * Note that this wrapper is not synchronized and if a response is to
 * be operated on by multiple threads, then higher level
 * synchronizations may be required.
 *
 * @version $Id: ServletHttpResponse.java,v 1.65 2006/04/04 22:28:05 gregwilkins Exp $
 * @author Greg Wilkins (gregw)
 */
public class ServletHttpResponse implements HttpServletResponse {
    private static Log log = LogFactory.getLog(ServletHttpResponse.class);

    public static final int DISABLED = -1, NO_OUT = 0, OUTPUTSTREAM_OUT = 1, WRITER_OUT = 2;

    private static ServletWriter __nullServletWriter;
    private static ServletOut __nullServletOut;
    static {
        try {
            __nullServletWriter = new ServletWriter(IO.getNullStream());
            __nullServletOut = new ServletOut(IO.getNullStream());
        } catch (Exception e) {
            log.fatal(e);
            System.exit(1);
        }
    }

    /* ------------------------------------------------------------ */
    private HttpResponse _httpResponse;
    private ServletHttpRequest _servletHttpRequest;
    private int _outputState = NO_OUT;
    private ServletOut _out = null;
    private ServletWriter _writer = null;
    private HttpSession _session = null;
    private boolean _noSession = false;
    private Locale _locale = null;
    private boolean _charEncodingSetInContentType = false;

    /* ------------------------------------------------------------ */
    public ServletHttpResponse(ServletHttpRequest request, HttpResponse response) {
        _servletHttpRequest = request;
        _servletHttpRequest.setServletHttpResponse(this);
        _httpResponse = response;
    }

    /* ------------------------------------------------------------ */
    void recycle() {
        _outputState = NO_OUT;
        _out = null;
        _writer = null;
        _session = null;
        _noSession = false;
        _locale = null;
        _charEncodingSetInContentType = false;
    }

    /* ------------------------------------------------------------ */
    int getOutputState() {
        return _outputState;
    }

    /* ------------------------------------------------------------ */
    void setOutputState(int s) throws IOException {
        if (s < 0) {
            _outputState = DISABLED;
            if (_writer != null)
                _writer.disable();
            _writer = null;
            if (_out != null)
                _out.disable();
            _out = null;
        } else
            _outputState = s;
    }

    /* ------------------------------------------------------------ */
    HttpResponse getHttpResponse() {
        return _httpResponse;
    }

    /* ------------------------------------------------------------ */
    void commit() throws IOException {
        if (_writer != null && _writer.isWritten())
            _writer.flush();
        else
            _httpResponse.commit();
    }

    /* ------------------------------------------------------------ */
    void complete() throws IOException {
        _httpResponse.completing();
        commit();
        setOutputState(DISABLED);
    }

    /* ------------------------------------------------------------ */
    public boolean isCommitted() {
        return _httpResponse.isCommitted();
    }

    /* ------------------------------------------------------------ */
    boolean isDirty() {
        return _httpResponse.isDirty();
    }

    /* ------------------------------------------------------------ */
    public void setBufferSize(int size) {
        HttpOutputStream out = (HttpOutputStream) _httpResponse.getOutputStream();
        if (out.isWritten() || _writer != null && _writer.isWritten())
            throw new IllegalStateException("Output written");
        out.setBufferSize(size);
    }

    /* ------------------------------------------------------------ */
    public int getBufferSize() {
        return ((HttpOutputStream) _httpResponse.getOutputStream()).getBufferSize();
    }

    /* ------------------------------------------------------------ */
    public void flushBuffer() throws IOException {
        if (((HttpOutputStream) _httpResponse.getOutputStream()).isClosed())
            return;

        if (_writer != null)
            _writer.flush();
        if (_out != null)
            _out.flush();
        if (_writer == null && _out == null)
            _httpResponse.getOutputStream().flush();
        if (!_httpResponse.isCommitted())
            _httpResponse.commit();
    }

    /* ------------------------------------------------------------ */
    public void resetBuffer() {
        if (isCommitted())
            throw new IllegalStateException("Committed");

        ((HttpOutputStream) _httpResponse.getOutputStream()).resetBuffer();
        if (_writer != null)
            _writer.reset();
    }

    /* ------------------------------------------------------------ */
    public void reset() {
        resetBuffer();
        _httpResponse.reset();
    }

    /* ------------------------------------------------------------ */
    /**
     * Sets the locale of the response, setting the headers (including the
     * Content-Type's charset) as appropriate.  This method should be called
     * before a call to {@link #getWriter}.  By default, the response locale
     * is the default locale for the server.
     * 
     * @see   #getLocale
     * @param locale the Locale of the response
     */
    public void setLocale(Locale locale) {
        if (locale == null || isCommitted())
            return;

        _locale = locale;
        setHeader(HttpFields.__ContentLanguage, locale.toString().replace('_', '-'));

        if (this._outputState == 0) {
            /* get current MIME type from Content-Type header */
            String type = _httpResponse.getField(HttpFields.__ContentType);
            if (type == null) {
                // servlet did not set Content-Type yet
                // so lets assume default one
                type = "application/octet-stream";
            }

            HttpContext httpContext = _servletHttpRequest.getServletHandler().getHttpContext();
            if (httpContext instanceof ServletHttpContext) {
                String charset = ((ServletHttpContext) httpContext).getLocaleEncoding(locale);
                if (charset != null && charset.length() > 0) {
                    int semi = type.indexOf(';');
                    if (semi < 0)
                        type += "; charset=" + charset;
                    else if (!_charEncodingSetInContentType)
                        type = type.substring(0, semi) + "; charset=" + charset;

                    setHeader(HttpFields.__ContentType, type);
                }

            }
        }
    }

    /* ------------------------------------------------------------ */
    public Locale getLocale() {
        if (_locale == null)
            return Locale.getDefault();
        return _locale;
    }

    /* ------------------------------------------------------------ */
    public void addCookie(Cookie cookie) {
        _httpResponse.addSetCookie(cookie);
    }

    /* ------------------------------------------------------------ */
    public boolean containsHeader(String name) {
        return _httpResponse.containsField(name);
    }

    /* ------------------------------------------------------------ */
    public String encodeURL(String url) {
        // should not encode if cookies in evidence
        if (_servletHttpRequest == null || _servletHttpRequest.isRequestedSessionIdFromCookie()
                && _servletHttpRequest.getServletHandler().isUsingCookies())
            return url;

        // get session;
        if (_session == null && !_noSession) {
            _session = _servletHttpRequest.getSession(false);
            _noSession = (_session == null);
        }

        // no session or no url
        if (_session == null || url == null)
            return url;

        // invalid session
        String id = _session.getId();
        if (id == null)
            return url;

        // Check host and port are for this server
        // TODO not implemented

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

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

        // edit the session
        int suffix = url.indexOf('?');
        if (suffix < 0)
            suffix = url.indexOf('#');
        if (suffix < 0)
            return url + SessionManager.__SessionUrlPrefix + id;
        return url.substring(0, suffix) + SessionManager.__SessionUrlPrefix + id + url.substring(suffix);
    }

    /* ------------------------------------------------------------ */
    public String encodeRedirectURL(String url) {
        return encodeURL(url);
    }

    /* ------------------------------------------------------------ */
    /**
     * @deprecated   As of version 2.1, use encodeURL(String url) instead
     */
    public String encodeUrl(String url) {
        return encodeURL(url);
    }

    /* ------------------------------------------------------------ */
    /**
     * @deprecated   As of version 2.1, use 
     *         encodeRedirectURL(String url) instead
     */
    public String encodeRedirectUrl(String url) {
        return encodeRedirectURL(url);
    }

    /* ------------------------------------------------------------ */
    public void sendError(int status, String message) throws IOException {
        // Find  error page.
        String error_page = _servletHttpRequest.getServletHandler().getErrorPage(status, _servletHttpRequest);

        resetBuffer();

        // Handle error page?
        if (error_page == null) {
            // handle normally
            _httpResponse.sendError(status, message);
        } else {
            _httpResponse.setStatus(status, message);

            if (message == null) {
                message = (String) HttpResponse.__statusMsg.get(TypeUtil.newInteger(status));
                if (message == null)
                    message = "" + status;
            }

            // handle error page
            ServletHolder holder = _servletHttpRequest.getServletHolder();
            if (holder != null)
                _servletHttpRequest.setAttribute(ServletHandler.__J_S_ERROR_SERVLET_NAME, holder.getName());
            _servletHttpRequest.setAttribute(ServletHandler.__J_S_ERROR_REQUEST_URI,
                    _servletHttpRequest.getRequestURI());
            _servletHttpRequest.setAttribute(ServletHandler.__J_S_ERROR_STATUS_CODE, new Integer(status));
            _servletHttpRequest.setAttribute(ServletHandler.__J_S_ERROR_MESSAGE, message);

            RequestDispatcher dispatcher = _servletHttpRequest.getServletHandler().getServletContext()
                    .getRequestDispatcher(error_page);

            try {
                ((Dispatcher) dispatcher).error(_servletHttpRequest, this);
            } catch (ServletException e) {
                log.warn(LogSupport.EXCEPTION, e);
                _httpResponse.sendError(status, message);
            }
        }
        complete();
    }

    /* ------------------------------------------------------------ */
    public void sendError(int status) throws IOException {
        sendError(status, null);
    }

    /* ------------------------------------------------------------ */
    public void sendRedirect(String url) throws IOException {
        if (url == null)
            throw new IllegalArgumentException();

        if (!URI.hasScheme(url)) {
            StringBuffer buf = _servletHttpRequest.getHttpRequest().getRootURL();
            if (url.startsWith("/"))
                buf.append(URI.canonicalPath(url));
            else {
                String path = _servletHttpRequest.getRequestURI();
                String parent = (path.endsWith("/")) ? path : URI.parentPath(path);
                url = URI.canonicalPath(URI.addPaths(parent, url));
                if (!url.startsWith("/"))
                    buf.append('/');
                buf.append(url);
            }

            url = buf.toString();
        }

        resetBuffer();

        _httpResponse.setField(HttpFields.__Location, url);
        _httpResponse.setStatus(HttpResponse.__302_Moved_Temporarily);
        complete();
    }

    /* ------------------------------------------------------------ */
    public void setDateHeader(String name, long value) {
        try {
            _httpResponse.setDateField(name, value);
        } catch (IllegalStateException e) {
            LogSupport.ignore(log, e);
        }
    }

    /* ------------------------------------------------------------ */
    public void setHeader(String name, String value) {
        try {
            _httpResponse.setField(name, value);
        } catch (IllegalStateException e) {
            LogSupport.ignore(log, e);
        }
    }

    /* ------------------------------------------------------------ */
    public void setIntHeader(String name, int value) {
        try {
            _httpResponse.setIntField(name, value);
        } catch (IllegalStateException e) {
            LogSupport.ignore(log, e);
        }
    }

    /* ------------------------------------------------------------ */
    public void addDateHeader(String name, long value) {
        try {
            _httpResponse.addDateField(name, value);
        } catch (IllegalStateException e) {
            LogSupport.ignore(log, e);
        }
    }

    /* ------------------------------------------------------------ */
    public void addHeader(String name, String value) {
        try {
            _httpResponse.addField(name, value);
        } catch (IllegalStateException e) {
            LogSupport.ignore(log, e);
        }
    }

    /* ------------------------------------------------------------ */
    public void addIntHeader(String name, int value) {
        try {
            _httpResponse.addIntField(name, value);
        } catch (IllegalStateException e) {
            LogSupport.ignore(log, e);
        }
    }

    /* ------------------------------------------------------------ */
    public void setStatus(int status) {
        _httpResponse.setStatus(status);
    }

    /* ------------------------------------------------------------ */
    /**
    * @deprecated As of version 2.1 of the Servlet spec.
    * To set a status code 
    * use <code>setStatus(int)</code>, to send an error with a description
    * use <code>sendError(int, String)</code>.
    *
    * Sets the status code and message for this response.
    * 
    * @param status the status code
    * @param message the status message
    */
    public void setStatus(int status, String message) {
        setStatus(status);
        _httpResponse.setReason(message);
    }

    /* ------------------------------------------------------------ */
    public ServletOutputStream getOutputStream() {
        if (_outputState == DISABLED)
            return __nullServletOut;

        if (_outputState != NO_OUT && _outputState != OUTPUTSTREAM_OUT)
            throw new IllegalStateException();

        if (_writer != null) {
            _writer.flush();
            _writer.disable();
            _writer = null;
        }

        if (_out == null)
            _out = new ServletOut(_servletHttpRequest.getHttpRequest().getOutputStream());
        _outputState = OUTPUTSTREAM_OUT;
        return _out;
    }

    /* ------------------------------------------------------------ */
    public PrintWriter getWriter() throws java.io.IOException {
        if (_outputState == DISABLED)
            return __nullServletWriter;

        if (_outputState != NO_OUT && _outputState != WRITER_OUT)
            throw new IllegalStateException();

        // If we are switching modes, flush output to try avoid overlaps.
        if (_out != null)
            _out.flush();

        /* if there is no writer yet */
        if (_writer == null) {
            /* get encoding from Content-Type header */
            String encoding = _httpResponse.getCharacterEncoding();

            if (encoding == null) {
                if (_servletHttpRequest != null) {
                    /* implementation of educated defaults */
                    String mimeType = _httpResponse.getMimeType();
                    encoding = _servletHttpRequest.getServletHandler().getHttpContext()
                            .getEncodingByMimeType(mimeType);
                }
                if (encoding == null)
                    encoding = StringUtil.__ISO_8859_1;
                _httpResponse.setCharacterEncoding(encoding, true);
            }

            /* construct Writer using correct encoding */
            _writer = new ServletWriter(_httpResponse.getOutputStream(), encoding);
        }
        _outputState = WRITER_OUT;
        return _writer;
    }

    /* ------------------------------------------------------------ */
    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())
            setIntHeader(HttpFields.__ContentLength, len);
    }

    /* ------------------------------------------------------------ */
    public String getContentType() {
        return _httpResponse.getContentType();
    }

    /* ------------------------------------------------------------ */
    public void setContentType(String contentType) {
        if (isCommitted() || contentType == null)
            return;

        int semi = contentType.indexOf(';');
        if (semi > 0) {
            int charset0 = contentType.indexOf("charset=", semi);
            if (charset0 > 0) {
                if (_outputState == WRITER_OUT) {
                    // need to strip charset= from params
                    int charset1 = contentType.indexOf(' ', charset0);

                    if ((charset0 == semi + 1 && charset1 < 0)
                            || (charset0 == semi + 2 && charset1 < 0 && contentType.charAt(semi + 1) == ' '))
                        _httpResponse.setContentType(contentType.substring(0, semi));
                    else if (charset1 < 0)
                        _httpResponse.setContentType(contentType.substring(0, charset0).trim());
                    else
                        _httpResponse.setContentType(
                                contentType.substring(0, charset0) + contentType.substring(charset1));
                } else {
                    _charEncodingSetInContentType = true;
                    _httpResponse.setContentType(contentType);
                }
            } else
                _httpResponse.setContentType(contentType);
        } else
            _httpResponse.setContentType(contentType);

        if (_locale != null)
            setLocale(_locale);
    }

    /* ------------------------------------------------------------ */
    public void setCharacterEncoding(String encoding) {
        if (this._outputState == 0 && !isCommitted()) {
            _charEncodingSetInContentType = true;
            _httpResponse.setCharacterEncoding(encoding, true);
        }
    }

    /* ------------------------------------------------------------ */
    public String getCharacterEncoding() {
        String encoding = _httpResponse.getCharacterEncoding();
        return (encoding == null) ? StringUtil.__ISO_8859_1 : encoding;
    }

    /* ------------------------------------------------------------ */
    public String toString() {
        return _httpResponse.toString();
    }

    /* ------------------------------------------------------------ */
    /** Unwrap a ServletResponse.
     *
     * @see javax.servlet.ServletResponseWrapper
     * @see javax.servlet.http.HttpServletResponseWrapper
     * @param response 
     * @return The core ServletHttpResponse which must be the
     * underlying response object 
     */
    public static ServletHttpResponse unwrap(ServletResponse response) {
        while (!(response instanceof ServletHttpResponse)) {
            if (response instanceof ServletResponseWrapper) {
                ServletResponseWrapper wrapper = (ServletResponseWrapper) response;
                response = wrapper.getResponse();
            } else
                throw new IllegalArgumentException("Does not wrap ServletHttpResponse");
        }

        return (ServletHttpResponse) response;
    }

}