httpstream.java

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

JAVA
868
字号
/* * 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.vfs;import com.caucho.util.Alarm;import com.caucho.util.CharBuffer;import com.caucho.util.Log;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocketFactory;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ConnectException;import java.net.Socket;import java.net.SocketException;import java.util.HashMap;import java.util.Iterator;import java.util.logging.Level;import java.util.logging.Logger;/** * Underlying stream handling HTTP requests. */class HttpStream extends StreamImpl {  private static final Logger log = Log.open(HttpStream.class);  // reserved headers that should not be passed to the HTTP server  private static HashMap<String,String> _reserved;  private static final Object LOCK = new Object();    // Saved keepalive stream for a new request.  private static HttpStream _savedStream;  // Time the stream was saved  private static long _saveTime;    private long _socketTimeout = 30000L;  private boolean _isSSL;  private Socket _s;  private InputStream _is;  private OutputStream _os;  private ReadStream _rs;  private WriteStream _ws;  // The server's host name  private String _host;  // The server's port  private int _port;  private String _virtualHost;  // the method  private String _method;  // true for a HEAD stream  private boolean _isHead;  // true for a POST stream  private boolean _isPost;  // buffer containing the POST data  private MemoryStream _tempStream;  // true if keepalive is allowed  private boolean _isKeepalive = true;  // true after the request has been sent  private boolean _didGet;  // content length from the returned response  private int _contentLength;  // true if the response was chunked  private boolean _isChunked;  // length of the current chunk, -1 on eof  private int _chunkLength;  // the request is done  private boolean _isRequestDone;  private HashMap<String,Object> _attributes;  // Used to read unread bytes on recycle.  private byte []_tempBuffer;  /**   * Create a new HTTP stream.   */  private HttpStream(Path path, String host, int port, Socket s)    throws IOException  {    _s = s;    _host = host;    _port = port;        _is = _s.getInputStream();    _os = _s.getOutputStream();    _ws = VfsStream.openWrite(_os);    _rs = VfsStream.openRead(_is, _ws);    _attributes = new HashMap<String,Object>();    init(path);  }  /**   * Opens a new HTTP stream for reading, i.e. a GET request.   *   * @param path the URL for the stream   *   * @return the opened stream   */  static HttpStreamWrapper openRead(HttpPath path) throws IOException  {    HttpStream stream = createStream(path);    stream._isPost = false;    return new HttpStreamWrapper(stream);  }  /**   * Opens a new HTTP stream for reading and writing, i.e. a POST request.   *   * @param path the URL for the stream   *   * @return the opened stream   */  static HttpStreamWrapper openReadWrite(HttpPath path) throws IOException  {    HttpStream stream = createStream(path);    stream._isPost = true;    return new HttpStreamWrapper(stream);  }  /**   * Creates a new HTTP stream.  If there is a saved connection to   * the same host, use it.   *   * @param path the URL for the stream   *   * @return the opened stream   */  static private HttpStream createStream(HttpPath path) throws IOException  {    String host = path.getHost();    int port = path.getPort();    HttpStream stream = null;    long streamTime = 0;    synchronized (LOCK) {      if (_savedStream != null          && host.equals(_savedStream.getHost())          && port == _savedStream.getPort()) {        stream = _savedStream;        streamTime = _saveTime;        _savedStream = null;      }    }    if (stream == null) {    }    // if the stream is still valid, use it    else if (Alarm.getCurrentTime() < streamTime + 5000) {      stream.init(path);      return stream;    }    // if the stream has timed out, close it    else {      try {        stream._isKeepalive = false;        stream.close();      } catch (IOException e) {        log.log(Level.FINE, e.toString(), e);      }    }    Socket s;    try {      s = new Socket(host, port);            if (path instanceof HttpsPath) {        SSLContext context = SSLContext.getInstance("TLS");	javax.net.ssl.TrustManager tm =	  new javax.net.ssl.X509TrustManager() {	    public java.security.cert.X509Certificate[]	      getAcceptedIssuers() {	      return null;	    }	    public void checkClientTrusted(					   java.security.cert.X509Certificate[] cert, String foo) {	    }	    public void checkServerTrusted(					   java.security.cert.X509Certificate[] cert, String foo) {	    }	  };              context.init(null, new javax.net.ssl.TrustManager[] { tm }, null);        SSLSocketFactory factory = context.getSocketFactory();        s = factory.createSocket(s, host, port, true);      }    } catch (ConnectException e) {      throw new ConnectException(path.getURL() + ": " + e.getMessage());    } catch (Exception e) {      throw new ConnectException(path.getURL() + ": " + e.toString());    }    int socketTimeout = 300 * 1000;    try {      s.setSoTimeout(socketTimeout);    } catch (Exception e) {    }              return new HttpStream(path, host, port, s);  }  /**   * Initializes the stream for the next request.   */  private void init(Path path)  {    _contentLength = -1;    _isChunked = false;    _isRequestDone = false;    _didGet = false;    _isPost = false;    _isHead = false;    _method = null;    _attributes.clear();        setPath(path);    if (path instanceof HttpPath)      _virtualHost = ((HttpPath) path).getVirtualHost();  }  /**   * Set if this should be an SSL connection.   */  public void setSSL(boolean isSSL)  {    _isSSL = isSSL;  }  /**   * Set if this should be an SSL connection.   */  public boolean isSSL()  {    return _isSSL;  }  /**   * Sets the method   */  public void setMethod(String method)  {    _method = method;  }  /**   * Sets true if we're only interested in the head.   */  public void setHead(boolean isHead)  {    _isHead = isHead;  }  /**   * Returns the stream's host.   */  public String getHost()  {    return _host;  }  /**   * Returns the stream's port.   */  public int getPort()  {    return _port;  }    /**   * Returns a header from the response returned from the HTTP server.   *   * @param name name of the header   * @return the header value.   */  public Object getAttribute(String name)    throws IOException  {    if (! _didGet)      getConnInput();        return _attributes.get(name.toLowerCase());  }  /**   * Returns an iterator of the returned header names.   */  public Iterator getAttributeNames()    throws IOException  {    if (! _didGet)      getConnInput();    return _attributes.keySet().iterator();  }  /**   * Sets a header for the request.   */  public void setAttribute(String name, Object value)  {    if (name.equals("method"))      setMethod((String) value);    else if (name.equals("socket-timeout")) {      if (value instanceof Integer) {        int socketTimeout = ((Integer) value).intValue();        if (socketTimeout > 0) {          try {            if (_s != null)              _s.setSoTimeout(socketTimeout);          } catch (Exception e) {          }        }      }    }    else {      Object oldValue = _attributes.put(name.toLowerCase(), value);      if (oldValue instanceof String[]) {	String []old = (String []) oldValue;	String []newValue = new String[old.length + 1];	System.arraycopy(old, 0, newValue, 0, old.length);	newValue[old.length] = String.valueOf(value);	_attributes.put(name.toLowerCase(), newValue);      }      else if (oldValue != null) {	String []newValue = new String[] { String.valueOf(oldValue),					   String.valueOf(value) };	_attributes.put(name.toLowerCase(), newValue);      }    }  }  /**   * Remove a header for the request.   */  public void removeAttribute(String name)  {    _attributes.remove(name.toLowerCase());  }  /**   * Sets the timeout.   */  public void setSocketTimeout(long timeout)    throws SocketException  {    if (_s != null)      _s.setSoTimeout((int) timeout);  }  /**   * The stream is always writable (?)   */  public boolean canWrite()  {    return true;  }  /**   * Writes a buffer to the underlying stream.   *   * @param buffer the byte array to write.   * @param offset the offset into the byte array.   * @param length the number of bytes to write.   * @param isEnd true when the write is flushing a close.   */  public void write(byte []buf, int offset, int length, boolean isEnd)    throws IOException  {    if (! _isPost)      return;    if (_tempStream == null)      _tempStream = new MemoryStream();    _tempStream.write(buf, offset, length, isEnd);  }  /**   * The stream is readable.   */  public boolean canRead()  {    return true;  }

⌨️ 快捷键说明

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