abstracthttpresponse.java

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

JAVA
2,408
字号
    _request.killKeepalive();    // close, but don't force a flush    finish();  }  /**   * Sends a redirect to the browser.  If the URL is relative, it gets   * combined with the current url.   *   * @param url the possibly relative url to send to the browser   */  public void sendRedirect(String url)    throws IOException  {    if (url == null)      throw new NullPointerException();        if (_originalResponseStream.isCommitted())      throw new IllegalStateException(L.l("Can't sendRedirect() after data has committed to the client."));    _responseStream.clearBuffer();    _originalResponseStream.clearBuffer();        _responseStream = _originalResponseStream;    resetBuffer();        setStatus(SC_MOVED_TEMPORARILY);    String path = getAbsolutePath(url);    CharBuffer cb = new CharBuffer();    for (int i = 0; i < path.length(); i++) {      char ch = path.charAt(i);      if (ch == '<')	cb.append("%3c");      else if (ch < 0x80)	cb.append(ch);      else if (_charEncoding == null) {	addHex(cb, ch);      }      else if (ch < 0x800) {	int d1 = 0xc0 + ((ch >> 6) & 0x1f);	int d2 = 0x80 + (ch & 0x3f);	addHex(cb, d1);	addHex(cb, d2);      }      else if (ch < 0x8000) {	int d1 = 0xe0 + ((ch >> 12) & 0xf);	int d2 = 0x80 + ((ch >> 6) & 0x3f);	int d3 = 0x80 + (ch & 0x3f);	addHex(cb, d1);	addHex(cb, d2);	addHex(cb, d3);      }    }    path = cb.toString();        setHeader("Location", path);    setHeader("Content-Type", "text/html");    // The data is required for some WAP devices that can't handle an    // empty response.    ServletOutputStream out = getOutputStream();    out.println("The URL has moved <a href=\"" + path + "\">here</a>");    // closeConnection();        if (_request instanceof AbstractHttpRequest) {      AbstractHttpRequest request = (AbstractHttpRequest) _request;      request.saveSession(); // #503    }    close();  }  private void addHex(CharBuffer cb, int hex)  {    int d1 = (hex >> 4) & 0xf;    int d2 = (hex) & 0xf;        cb.append('%');    cb.append(d1 < 10 ? (char) (d1 + '0') : (char) (d1 - 10 + 'a'));    cb.append(d2 < 10 ? (char) (d2 + '0') : (char) (d2 - 10 + 'a'));  }  /**   * Switch to raw socket mode.   */  public void switchToRaw()    throws IOException  {    throw new UnsupportedOperationException(L.l("raw mode is not supported in this configuration"));  }  /**   * Switch to raw socket mode.   */  public WriteStream getRawOutput()    throws IOException  {    throw new UnsupportedOperationException(L.l("raw mode is not supported in this configuration"));  }  /**   * Returns the absolute path for a given relative path.   *   * @param path the possibly relative url to send to the browser   */  private String getAbsolutePath(String path)  {    int slash = path.indexOf('/');        int len = path.length();    for (int i = 0; i < len; i++) {      char ch = path.charAt(i);      if (ch == ':')        return path;      else if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')        continue;      else        break;    }    WebApp app = getRequest().getWebApp();    String hostPrefix = null;    String host = _request.getHeader("Host");    String serverName = app.getHostName();    if (serverName == null || serverName.equals(""))      serverName = _request.getServerName();    int port = _request.getServerPort();    if (hostPrefix != null && ! hostPrefix.equals("")) {    }    else if (serverName.startsWith("http:")	     || serverName.startsWith("https:"))      hostPrefix = serverName;    else if (host != null) {      hostPrefix = _request.getScheme() + "://" + host;    }    else {      hostPrefix = _request.getScheme() + "://" + serverName;            if (serverName.indexOf(':') < 0	  && port != 0 && port != 80 && port != 443)        hostPrefix += ":" + port;    }    if (slash == 0)      return hostPrefix + path;    String uri = _request.getRequestURI();    String queryString = null;    int p = path.indexOf('?');    if (p > 0) {      queryString = path.substring(p + 1);      path = path.substring(0, p);    }        p = uri.lastIndexOf('/');    if (p >= 0)      path = uri.substring(0, p + 1) + path;    try {      if (queryString != null)        return hostPrefix + InvocationDecoder.normalizeUri(path) + '?' + queryString;      else        return hostPrefix + InvocationDecoder.normalizeUri(path);    } catch (IOException e) {      throw new RuntimeException(e);    }  }  /**   * Returns true if the response already contains the named header.   *   * @param name name of the header to test.   */  public boolean containsHeader(String name)  {    for (int i = 0; i < _headerKeys.size(); i++) {      String oldKey = _headerKeys.get(i);       if (oldKey.equalsIgnoreCase(name)) 	return true;    }    if (name.equalsIgnoreCase("content-type"))      return _contentType != null;        if (name.equalsIgnoreCase("content-length"))      return _contentLength >= 0;     return false;  }  /**   * Returns the value of an already set output header.   *   * @param name name of the header to get.   */  public String getHeader(String name)  {    ArrayList<String> keys = _headerKeys;        int headerSize = keys.size();    for (int i = 0; i < headerSize; i++) {      String oldKey = (String) keys.get(i);       if (oldKey.equalsIgnoreCase(name)) 	return (String) _headerValues.get(i);    }    if (name.equalsIgnoreCase("content-type"))      return _contentType;     if (name.equalsIgnoreCase("content-length"))      return _contentLength >= 0 ? String.valueOf(_contentLength) : null;     return null;  }  /**   * Sets a header, replacing an already-existing header.   *   * @param key the header key to set.   * @param value the header value to set.   */  public void setHeader(String key, String value)  {    if (_disableHeaders)      return;    else if (value == null)      throw new NullPointerException();    if (setSpecial(key, value))      return;    int i = 0;    boolean hasHeader = false;    ArrayList<String> keys = _headerKeys;    ArrayList<String> values = _headerValues;        for (i = keys.size() - 1; i >= 0; i--) {      String oldKey = keys.get(i);      if (oldKey.equalsIgnoreCase(key)) {	if (hasHeader) {	  keys.remove(i);	  values.remove(i);	}	else {	  hasHeader = true;	  values.set(i, value);	}      }    }    if (! hasHeader) {      keys.add(key);      values.add(value);    }  }  /**   * Adds a new header.  If an old header with that name exists,   * both headers are output.   *   * @param key the header key.   * @param value the header value.   */  public void addHeader(String key, String value)  {    if (_disableHeaders)      return;    if (setSpecial(key, value))      return;    _headerKeys.add(key);    _headerValues.add(value);  }  /**   * Special processing for a special value.   */  protected boolean setSpecial(String key, String value)  {    int length = key.length();    if (256 <= length)      return false;        key.getChars(0, length, _headerBuffer, 0);    switch (_headerCodes.get(_headerBuffer, length)) {    case HEADER_CACHE_CONTROL:      if (value.startsWith("max-age")) {      }      else if (value.equals("x-anonymous")) {      }      else	_hasCacheControl = true;      return false;	    case HEADER_CONNECTION:      if ("close".equalsIgnoreCase(value))	_request.killKeepalive();      return true;	    case HEADER_CONTENT_TYPE:      setContentType(value);      return true;	    case HEADER_CONTENT_LENGTH:      _contentLength = Long.parseLong(value);      return true;	    case HEADER_DATE:      return true;	    case HEADER_SERVER:      return false;    default:      return false;    }  }    public void removeHeader(String key)  {    if (_disableHeaders)      return;        ArrayList<String> keys = _headerKeys;    ArrayList<String> values = _headerValues;        for (int i = keys.size() - 1; i >= 0; i--) {      String oldKey = keys.get(i);      if (oldKey.equalsIgnoreCase(key)) {        keys.remove(i);        values.remove(i);        return;      }    }  }  /**   * Convenience for setting an integer header.  An old header with the   * same name will be replaced.   *   * @param name the header name.   * @param value an integer to be converted to a string for the header.   */  public void setIntHeader(String name, int value)  {    _cb.clear();    _cb.append(value);    setHeader(name, _cb.toString());  }  /**   * Convenience for adding an integer header.  If an old header already   * exists, both will be sent to the browser.   *   * @param key the header name.   * @param value an integer to be converted to a string for the header.   */  public void addIntHeader(String key, int value)  {    _cb.clear();    _cb.append(value);    addHeader(key, _cb.toString());  }  /**   * Convenience for setting a date header.  An old header with the   * same name will be replaced.   *   * @param name the header name.   * @param value an time in milliseconds to be converted to a date string.   */  public void setDateHeader(String name, long value)  {    _calendar.setGMTTime(value);    setHeader(name, _calendar.printDate());  }  /**   * Convenience for adding a date header.  If an old header with the   * same name exists, both will be displayed.   *   * @param key the header name.   * @param value an time in milliseconds to be converted to a date string.   */  public void addDateHeader(String key, long value)  {    _calendar.setGMTTime(value);    addHeader(key, _calendar.printDate());  }  /**   * Sets the content length of the result.  In general, Resin will handle   * the content length, but for things like long downloads adding the   * length will give a valuable hint to the browser.   *   * @param length the length of the content.   */  public void setContentLength(int length)  {    _contentLength = length;  }  /**   * Returns the value of the content-length header.   */  public long getContentLengthHeader()  {    return _contentLength;  }  /**   * Sets the browser content type.  If the value contains a charset,   * the output encoding will be changed to match.   *   * <p>For example, to set the output encoding to use UTF-8 instead of   * the default ISO-8859-1 (Latin-1), use the following:   * <code><pre>   * setContentType("text/html; charset=UTF-8");   * </pre></code>   */  public void setContentType(String value)  {    if (isCommitted())      return;    if (_disableHeaders || value == null) {      _contentType = null;      return;    }    else if (value == "text/html" || value.equals("text/html")) {      _contentType = "text/html";      return;    }        _contentType = value;        int length = value.length();    int i;    int ch;    for (i = 0;	 i < length && value.charAt(i) != ';'	   && ! Character.isWhitespace(value.charAt(i));	 i++) {    }    if (i < length)      _contentPrefix = _contentType.substring(0, i);    else      _contentPrefix = _contentType;    while ((i = value.indexOf(';', i)) > 0) {      int semicolon = i;      for (i++; i < length && XmlChar.isWhitespace(value.charAt(i)); i++) {      }      int j;      for (j = i + 1;           j < length && ! XmlChar.isWhitespace((ch = value.charAt(j))) &&             ch != '=';           j++) {      }            if (length <= j)	break;      else if ((ch = value.charAt(i)) != 'c' && ch != 'C') {      }      else if (value.substring(i, j).equalsIgnoreCase("charset")) {	for (; j < length && XmlChar.isWhitespace(value.charAt(j)); j++) {	}        if (length <= j || value.charAt(j) != '=')          continue;        	for (j++; j < length && XmlChar.isWhitespace(value.charAt(j)); j++) {	}        String encoding;        if (j < length && value.charAt(j) == '"') {          int k = ++j;                    for (; j < length && value.charAt(j) != '"'; j++) {          }          encoding = value.substring(k, j);        }        else {          int k = j;          for (k = j;               j < length && ! XmlChar.isWhitespace(ch = value.charAt(j)) && ch != ';';               j++) {          }          encoding = value.substring(k, j);        }	int tail = value.indexOf(';', semicolon + 1);	StringBuilder sb = new StringBuilder();	sb.append(value, 0, semicolon);	if (tail > 0)	  sb.append(value, tail, value.length());		_contentType = sb.toString();	if (! _hasWriter) {	  _hasCharEncoding = true;	  _charEncoding = encoding;	}	break;      }      else	i = j;    }    // XXX: conflict with servlet exception throwing order?    try {      _responseStream.setEncoding(_charEncoding);    } catch (Exception e) {      log.log(Level.WARNING, e.toString(), e);    }  }  /**   * Gets the content type.   */  public String getContentType()  {    if (_contentType == null)      return null;    String charEncoding = getCharacterEncoding();    if (charEncoding != null)      return _contentType + "; charset=" + charEncoding;    else      return _contentType;  }  /**   * Gets the character encoding.   */  public String getCharacterEncoding()  {    if (_charEncoding != null)      return _charEncoding;    WebApp app = _request.getWebApp();    String encoding = null;        if (app != null)      encoding = app.getCharacterEncoding();    if (encoding != null)      return encoding;    else      return "iso-8859-1";  }  /**   * Sets the character encoding.   */  public void setCharacterEncoding(String encoding)  {    if (isCommitted())      return;    if (_hasWriter)      return;    _hasCharEncoding = true;    if (encoding == null        || encoding.equals("ISO-8859-1")        || encoding.equals("")) {

⌨️ 快捷键说明

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