abstracthttpresponse.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 2,408 行 · 第 1/4 页

JAVA
2,408
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.server.connection;import com.caucho.server.cache.AbstractCacheEntry;import com.caucho.server.cache.AbstractCacheFilterChain;import com.caucho.server.dispatch.BadRequestException;import com.caucho.server.dispatch.InvocationDecoder;import com.caucho.server.session.CookieImpl;import com.caucho.server.session.SessionImpl;import com.caucho.server.session.SessionManager;import com.caucho.server.util.CauchoSystem;import com.caucho.server.webapp.ErrorPageManager;import com.caucho.server.webapp.WebApp;import com.caucho.util.Alarm;import com.caucho.util.CaseInsensitiveIntMap;import com.caucho.util.CharBuffer;import com.caucho.util.HTTPUtil;import com.caucho.util.L10N;import com.caucho.util.QDate;import com.caucho.vfs.ClientDisconnectException;import com.caucho.vfs.FlushBuffer;import com.caucho.vfs.TempBuffer;import com.caucho.vfs.WriteStream;import com.caucho.xml.XmlChar;import javax.servlet.ServletOutputStream;import javax.servlet.ServletResponse;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.io.OutputStream;import java.io.PrintWriter;import java.io.Writer;import java.util.ArrayList;import java.util.HashMap;import java.util.Locale;import java.util.logging.Level;import java.util.logging.Logger;/** * Encapsulates the servlet response, controlling response headers and the * response stream. */abstract public class AbstractHttpResponse implements CauchoResponse {  static final protected Logger log    = Logger.getLogger(AbstractHttpResponse.class.getName());  static final L10N L = new L10N(AbstractHttpResponse.class);  static final HashMap<String,String> _errors;  protected static final CaseInsensitiveIntMap _headerCodes;  protected static final int HEADER_CACHE_CONTROL = 1;  protected static final int HEADER_CONTENT_TYPE = HEADER_CACHE_CONTROL + 1;  protected static final int HEADER_CONTENT_LENGTH = HEADER_CONTENT_TYPE + 1;  protected static final int HEADER_DATE = HEADER_CONTENT_LENGTH + 1;  protected static final int HEADER_SERVER = HEADER_DATE + 1;  protected static final int HEADER_CONNECTION = HEADER_SERVER + 1;  protected CauchoRequest _originalRequest;  protected CauchoRequest _request;  protected int _statusCode;  protected String _statusMessage;  protected String _contentType;  protected String _contentPrefix;  protected String _charEncoding;  protected boolean _hasCharEncoding;    protected final ArrayList<String> _headerKeys = new ArrayList<String>();  protected final ArrayList<String> _headerValues = new ArrayList<String>();    protected final ArrayList<String> _footerKeys = new ArrayList<String>();  protected final ArrayList<String> _footerValues = new ArrayList<String>();  protected final ArrayList<Cookie> _cookiesOut = new ArrayList<Cookie>();  private final AbstractResponseStream _originalResponseStream;    private final ServletOutputStreamImpl _responseOutputStream;  private final ResponseWriter _responsePrintWriter;  private AbstractResponseStream _responseStream;  // the raw output stream.  protected WriteStream _rawWrite;  // any stream that needs flusing before getting the writer.  private FlushBuffer _flushBuffer;  private boolean _isHeaderWritten;  private boolean _isChunked;  protected final QDate _calendar = new QDate(false);  protected final CharBuffer _cb = new CharBuffer();  protected final char [] _headerBuffer = new char[256];  private String _sessionId;  private boolean _hasSessionCookie;  private Locale _locale;  protected boolean _disableHeaders;  protected boolean _disableCaching;  protected long _contentLength;  protected boolean _isClosed;  protected boolean _hasSentLog;    protected boolean _hasWriter;  protected boolean _hasOutputStream;  private AbstractCacheFilterChain _cacheInvocation;  // the cache entry for a match/if-modified-since  private AbstractCacheEntry _matchCacheEntry;  // the new cache for a request getting filled  private AbstractCacheEntry _newCacheEntry;  private OutputStream _cacheStream;  private Writer _cacheWriter;  protected boolean _isNoCache;  private boolean _allowCache;  private boolean _isPrivateCache;  private boolean _hasCacheControl;  protected boolean _isTopCache;  protected boolean _forbidForward;  protected boolean _hasError;  private boolean _isCacheHit;  private final TempBuffer _tempBuffer = TempBuffer.allocate();  protected AbstractHttpResponse()  {    _originalResponseStream = createResponseStream();        _responseOutputStream = new ServletOutputStreamImpl();    _responsePrintWriter = new ResponseWriter();    _responseOutputStream.init(_originalResponseStream);    _responsePrintWriter.init(_originalResponseStream);  }  protected AbstractResponseStream createResponseStream()  {    return new ResponseStream(this);  }  protected AbstractHttpResponse(CauchoRequest request)  {    this();        _request = request;    _originalRequest = request;        _responseOutputStream.init(_originalResponseStream);    _responsePrintWriter.init(_originalResponseStream);  }  /**   * If set true, client disconnect exceptions are no propagated to the   * server code.   */  public boolean isIgnoreClientDisconnect()  {    if (! (_originalRequest instanceof AbstractHttpRequest))      return true;    else {      return ((AbstractHttpRequest) _originalRequest).isIgnoreClientDisconnect();    }  }  /**   * Return true for the top request.   */  public boolean isTop()  {    if (! (_request instanceof AbstractHttpRequest))      return false;    else {      return ((AbstractHttpRequest) _request).isTop();    }  }  /**   * Returns the next response.   */  public ServletResponse getResponse()  {    return null;  }  /**   * Initialize the response for a new request.   *   * @param stream the underlying output stream.   */  public void init(WriteStream stream)  {    _rawWrite = stream;    if (_originalResponseStream instanceof ResponseStream)      ((ResponseStream) _originalResponseStream).init(_rawWrite);  }  /**   * Initialize the response for a new request.   *   * @param request the matching request.   */  public void init(CauchoRequest request)  {    _request = request;    _originalRequest = request;  }  /**   * Returns the corresponding request.   */  public CauchoRequest getRequest()  {    return _request;  }  /**   * Sets the corresponding request.   */  public void setRequest(CauchoRequest req)  {    _request = req;    if (_originalRequest == null)      _originalRequest = req;  }  /**   * Returns the corresponding original   */  public CauchoRequest getOriginalRequest()  {    return _originalRequest;  }  /**   * Closes the request.   */  public void close()    throws IOException  {    finish(true);    // getStream().flush();  }  /**   * Returns true for closed requests.   */  public boolean isClosed()  {    return _isClosed;  }  /**   * Initializes the Response at the beginning of the request.   */  public void start()    throws IOException  {    _statusCode = 200;    _statusMessage = "OK";    _headerKeys.clear();    _headerValues.clear();        _footerKeys.clear();    _footerValues.clear();    _hasSessionCookie = false;    _cookiesOut.clear();    _isHeaderWritten = false;    _isChunked = false;    _charEncoding = null;    _hasCharEncoding = false;    _contentType = null;    _contentPrefix = null;    _locale = null;    if (_originalResponseStream instanceof ResponseStream)      ((ResponseStream) _originalResponseStream).init(_rawWrite);    _flushBuffer = null;    _contentLength = -1;    _disableHeaders = false;    _disableCaching = false;    _isClosed = false;    _hasSentLog = false;    _hasWriter = false;    _hasOutputStream = false;    _cacheInvocation = null;    _matchCacheEntry = null;    _newCacheEntry = null;    _cacheStream = null;    _cacheWriter = null;    _isPrivateCache = false;    _hasCacheControl = false;    _allowCache = true;    _isNoCache = false;    _isTopCache = false;    _isCacheHit = false;    _sessionId = null;    _forbidForward = false;    _originalResponseStream.start();        _responseStream = _originalResponseStream;    _responseOutputStream.init(_responseStream);    _responsePrintWriter.init(_responseStream);  }  /**   * For a HEAD request, the response stream should write no data.   */  void setHead()  {    _originalResponseStream.setHead();  }  /**   * For a HEAD request, the response stream should write no data.   */  protected final boolean isHead()  {    return _originalResponseStream.isHead();  }  /**   * Set true for a cache hit.   */  public void setCacheHit(boolean isHit)  {    _isCacheHit = isHit;  }  /**   * Set true for a cache hit.   */  public boolean isCacheHit()  {    return _isCacheHit;  }  /**   * When set to true, RequestDispatcher.forward() is disallowed on   * this stream.   */  public void setForbidForward(boolean forbid)  {    _forbidForward = forbid;  }  /**   * Returns true if RequestDispatcher.forward() is disallowed on   * this stream.   */  public boolean getForbidForward()  {    return _forbidForward;  }  /**   * Set to true while processing an error.   */  public void setHasError(boolean hasError)  {    _hasError = hasError;  }  /**   * Returns true if we're processing an error.   */  public boolean hasError()  {    return _hasError;  }  /**   * Sets the cache entry so we can use it if the servlet returns   * not_modified response.   *   * @param entry the saved cache entry   */  public void setMatchCacheEntry(AbstractCacheEntry entry)  {    _matchCacheEntry = entry;  }  /**   * Sets the cache invocation to indicate that the response might be   * cacheable.   */  public void setCacheInvocation(AbstractCacheFilterChain cacheInvocation)  {    AbstractCacheFilterChain oldCache = _cacheInvocation;    _cacheInvocation = null;        AbstractCacheEntry oldEntry = _newCacheEntry;    _newCacheEntry = null;    if (oldEntry != null)      oldCache.killCaching(oldEntry);          _cacheInvocation = cacheInvocation;  }  public void setTopCache(boolean isTopCache)  {    _isTopCache = isTopCache;  }  public void setStatus(int code)  {    setStatus(code, null);  }  public void setStatus(int code, String message)  {    if (code < 0)      code = 500;    if (message != null) {    }    else if (code == SC_OK)        message = "OK";        else if (code == SC_NOT_MODIFIED)        message = "Not Modified";        else if (message == null) {      message = (String) _errors.get(String.valueOf(code));      if (message == null)        message = L.l("Internal Server Error");    }    // server/2h0g    if (code != SC_OK && code != SC_NOT_MODIFIED)      killCache();    _statusCode = code;    _statusMessage = message;  }  public int getStatusCode()  {    return _statusCode;  }  public void sendError(int code)    throws IOException  {    sendError(code, null);  }  /**   * Sends an HTTP error to the browser.   *   * @param code the HTTP error code   * @param value a string message   */  public void sendError(int code, String value)    throws IOException  {    if (code == SC_NOT_MODIFIED && _matchCacheEntry != null) {      setStatus(code, value);      if (handleNotModified(_isTopCache))        return;    }        if (isCommitted())      throw new IllegalStateException(L.l("sendError() forbidden after buffer has been committed."));    //_currentWriter = null;    //setStream(_originalStream);    resetBuffer();    if (code != SC_NOT_MODIFIED)      killCache();    /* XXX: if we've already got an error, won't this just mask it?    if (responseStream.isCommitted())      throw new IllegalStateException("response can't sendError() after commit");    */    WebApp app = getRequest().getWebApp();    ErrorPageManager errorManager = null;    if (app != null)      errorManager = app.getErrorPageManager();    setStatus(code, value);    try {      if (code == SC_NOT_MODIFIED || code == SC_NO_CONTENT) {        finish();        return;      }      else if (errorManager != null) {        errorManager.sendError(getOriginalRequest(), this,			       code, _statusMessage);        // _request.killKeepalive();        // close, but don't force a flush        // XXX: finish(false);        finish();        return;      }      setContentType("text/html");      ServletOutputStream s = getOutputStream();      s.println("<html>");      if (! isCommitted()) {        s.print("<head><title>");        s.print(code);        s.print(" ");        s.print(_statusMessage);        s.println("</title></head>");      }      s.println("<body>");      s.print("<h1>");      s.print(code);      s.print(" ");      s.print(_statusMessage);      s.println("</h1>");      if (code == HttpServletResponse.SC_NOT_FOUND) {        s.println(L.l("{0} was not found on this server.",                      HTTPUtil.encodeString(getRequest().getPageURI())));      }      else if (code == HttpServletResponse.SC_SERVICE_UNAVAILABLE) {        s.println(L.l("The server is temporarily unavailable due to maintenance downtime or excessive load."));      }      String version = null;      if (app == null) {      }      else if (app.getServer() != null	       && app.getServer().getServerHeader() != null) {	version = app.getServer().getServerHeader();      }      else if (CauchoSystem.isTesting()) {      }      else	version = com.caucho.Version.FULL_VERSION;          if (version != null) {	s.println("<p /><hr />");	s.println("<small>");		s.println(version);	  	s.println("</small>");      }            s.println("</body></html>");    } catch (Exception e) {      log.log(Level.FINE, e.toString(), e);    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?