mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			577 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			577 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Java
		
	
	
	
// HttpURLConnection.java - Subclass of communications links using
 | 
						|
//			Hypertext Transfer Protocol.
 | 
						|
 | 
						|
/* Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath 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, or (at your option)
 | 
						|
any later version.
 | 
						|
 
 | 
						|
GNU Classpath 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.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 | 
						|
02111-1307 USA. 
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
package java.net;
 | 
						|
 | 
						|
import java.io.*;
 | 
						|
import java.security.Permission;
 | 
						|
 | 
						|
/*
 | 
						|
 * Written using on-line Java Platform 1.2 API Specification, as well
 | 
						|
 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
 | 
						|
 * Status:  Believed complete and correct.
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 * This class provides a common abstract implementation for those 
 | 
						|
 * URL connection classes that will connect using the HTTP protocol.
 | 
						|
 * In addition to the functionality provided by the URLConnection
 | 
						|
 * class, it defines constants for HTTP return code values and
 | 
						|
 * methods for setting the HTTP request method and determining whether
 | 
						|
 * or not to follow redirects. 
 | 
						|
 *
 | 
						|
 * @since 1.1
 | 
						|
 *
 | 
						|
 * @author Warren Levy (warrenl@cygnus.com)
 | 
						|
 * @author Aaron M. Renn (arenn@urbanophile.com)
 | 
						|
 */
 | 
						|
public abstract class HttpURLConnection extends URLConnection
 | 
						|
{
 | 
						|
  /* HTTP Success Response Codes */
 | 
						|
 | 
						|
  /**
 | 
						|
   * Indicates that the client may continue with its request.  This value
 | 
						|
   * is specified as part of RFC 2068 but was not included in Sun's JDK, so
 | 
						|
   * beware of using this value
 | 
						|
   */
 | 
						|
  static final int HTTP_CONTINUE = 100;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * Indicates the request succeeded.
 | 
						|
   */
 | 
						|
  public static final int HTTP_OK		= 200;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The requested resource has been created.
 | 
						|
   */
 | 
						|
  public static final int HTTP_CREATED		= 201;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The request has been accepted for processing but has not completed.
 | 
						|
   * There is no guarantee that the requested action will actually ever
 | 
						|
   * be completed succesfully, but everything is ok so far.
 | 
						|
   */
 | 
						|
  public static final int HTTP_ACCEPTED 	= 202;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The meta-information returned in the header is not the actual data
 | 
						|
   * from the original server, but may be from a local or other copy. 
 | 
						|
   * Normally this still indicates a successful completion.
 | 
						|
   */
 | 
						|
  public static final int HTTP_NOT_AUTHORITATIVE = 203;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The server performed the request, but there is no data to send
 | 
						|
   * back.  This indicates that the user's display should not be changed.
 | 
						|
   */
 | 
						|
  public static final int HTTP_NO_CONTENT	= 204;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The server performed the request, but there is no data to sent back,
 | 
						|
   * however, the user's display should be "reset" to clear out any form
 | 
						|
   * fields entered.
 | 
						|
   */
 | 
						|
  public static final int HTTP_RESET		= 205;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The server completed the partial GET request for the resource.
 | 
						|
   */
 | 
						|
  public static final int HTTP_PARTIAL		= 206;
 | 
						|
 | 
						|
 | 
						|
  /* HTTP Redirection Response Codes */
 | 
						|
 | 
						|
  /**
 | 
						|
   * There is a list of choices available for the requested resource.
 | 
						|
   */
 | 
						|
  public static final int HTTP_MULT_CHOICE = 300;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The resource has been permanently moved to a new location.
 | 
						|
   */
 | 
						|
  public static final int HTTP_MOVED_PERM = 301;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The resource requested has been temporarily moved to a new location.
 | 
						|
   */
 | 
						|
  public static final int HTTP_MOVED_TEMP = 302;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The response to the request issued is available at another location.
 | 
						|
   */
 | 
						|
  public static final int HTTP_SEE_OTHER = 303;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The document has not been modified since the criteria specified in
 | 
						|
   * a conditional GET.
 | 
						|
   */
 | 
						|
  public static final int HTTP_NOT_MODIFIED = 304;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The requested resource needs to be accessed through a proxy.
 | 
						|
   */
 | 
						|
  public static final int HTTP_USE_PROXY = 305;
 | 
						|
  
 | 
						|
  
 | 
						|
  /* HTTP Client Error Response Codes */
 | 
						|
 | 
						|
  /**
 | 
						|
   * The request was misformed or could not be understood.
 | 
						|
   */
 | 
						|
  public static final int HTTP_BAD_REQUEST = 400;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The request made requires user authorization.  Try again with
 | 
						|
   * a correct authentication header.
 | 
						|
   */
 | 
						|
  public static final int HTTP_UNAUTHORIZED = 401;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * Code reserved for future use - I hope way in the future.
 | 
						|
   */
 | 
						|
  public static final int HTTP_PAYMENT_REQUIRED = 402;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * There is no permission to access the requested resource.
 | 
						|
   */
 | 
						|
  public static final int HTTP_FORBIDDEN = 403;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The requested resource was not found.
 | 
						|
   */
 | 
						|
  public static final int HTTP_NOT_FOUND = 404;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The specified request method is not allowed for this resource.
 | 
						|
   */
 | 
						|
  public static final int HTTP_BAD_METHOD = 405;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * Based on the input headers sent, the resource returned in response
 | 
						|
   * to the request would not be acceptable to the client.
 | 
						|
   */
 | 
						|
  public static final int HTTP_NOT_ACCEPTABLE = 406;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The client must authenticate with a proxy prior to attempting this
 | 
						|
   * request.
 | 
						|
   */
 | 
						|
  public static final int HTTP_PROXY_AUTH = 407;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The request timed out.
 | 
						|
   */
 | 
						|
  public static final int HTTP_CLIENT_TIMEOUT = 408;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * There is a conflict between the current state of the resource and the
 | 
						|
   * requested action.
 | 
						|
   */
 | 
						|
  public static final int HTTP_CONFLICT = 409;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The requested resource is no longer available.  This ususally indicates
 | 
						|
   * a permanent condition.
 | 
						|
   */
 | 
						|
  public static final int HTTP_GONE = 410;
 | 
						|
 | 
						|
  /**
 | 
						|
   * A Content-Length header is required for this request, but was not
 | 
						|
   * supplied.
 | 
						|
   */
 | 
						|
  public static final int HTTP_LENGTH_REQUIRED = 411;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * A client specified pre-condition was not met on the server.
 | 
						|
   */
 | 
						|
  public static final int HTTP_PRECON_FAILED = 412;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The request sent was too large for the server to handle.
 | 
						|
   */
 | 
						|
  public static final int HTTP_ENTITY_TOO_LARGE = 413;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The name of the resource specified was too long.
 | 
						|
   */
 | 
						|
  public static final int HTTP_REQ_TOO_LONG = 414;
 | 
						|
  
 | 
						|
  /**
 | 
						|
   * The request is in a format not supported by the requested resource.
 | 
						|
   */
 | 
						|
  public static final int HTTP_UNSUPPORTED_TYPE = 415;
 | 
						|
 | 
						|
 | 
						|
  /* HTTP Server Error Response Codes */
 | 
						|
 | 
						|
  /**
 | 
						|
   * This error code indicates that some sort of server error occurred.
 | 
						|
   */
 | 
						|
  public static final int HTTP_SERVER_ERROR    = 500;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The server encountered an unexpected error (such as a CGI script crash)
 | 
						|
   * that prevents the request from being fulfilled.
 | 
						|
   */
 | 
						|
  public static final int HTTP_INTERNAL_ERROR   = 500;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The server does not support the requested functionality.  
 | 
						|
   * @since 1.3
 | 
						|
   */
 | 
						|
  public static final int HTTP_NOT_IMPLEMENTED = 501;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The proxy encountered a bad response from the server it was proxy-ing for
 | 
						|
   */
 | 
						|
  public static final int HTTP_BAD_GATEWAY = 502;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The HTTP service is not availalble, such as because it is overloaded
 | 
						|
   * and does not want additional requests.
 | 
						|
   */
 | 
						|
  public static final int HTTP_UNAVAILABLE = 503;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The proxy timed out getting a reply from the remote server it was
 | 
						|
   * proxy-ing for.
 | 
						|
   */
 | 
						|
  public static final int HTTP_GATEWAY_TIMEOUT = 504;
 | 
						|
 | 
						|
  /**
 | 
						|
   * This server does not support the protocol version requested.
 | 
						|
   */
 | 
						|
  public static final int HTTP_VERSION = 505;
 | 
						|
 | 
						|
  // Non-HTTP response static variables
 | 
						|
 | 
						|
  /**
 | 
						|
   * Flag to indicate whether or not redirects should be automatically
 | 
						|
   * followed by default.
 | 
						|
   */
 | 
						|
  private static boolean followRedirects = true;
 | 
						|
 | 
						|
  /**
 | 
						|
   * This is a list of valid request methods, separated by "|" characters.
 | 
						|
   */
 | 
						|
  private static String valid_methods
 | 
						|
      = "|GET|POST|HEAD|OPTIONS|PUT|DELETE|TRACE|";
 | 
						|
 | 
						|
  // Instance Variables
 | 
						|
 | 
						|
  /**
 | 
						|
   * The requested method in use for this connection. Default is GET.
 | 
						|
   */
 | 
						|
  protected String method = "GET";
 | 
						|
 | 
						|
  /**
 | 
						|
   * The response code received from the server
 | 
						|
   */
 | 
						|
  protected int responseCode = -1;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The response message string received from the server.
 | 
						|
   */
 | 
						|
  protected String responseMessage = null;
 | 
						|
 | 
						|
  /**
 | 
						|
   * If this instance should follow redirect requests.
 | 
						|
   */
 | 
						|
  protected boolean instanceFollowRedirects = followRedirects;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Whether we alreadt got a valid response code for this connection.
 | 
						|
   * Used by <code>getResponceCode()</code> and
 | 
						|
   * <code>getResponseMessage()</code>.
 | 
						|
   */
 | 
						|
  private boolean gotResponseVals = false;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Create an HttpURLConnection for the specified URL
 | 
						|
   *
 | 
						|
   * @param url The URL to create this connection for.
 | 
						|
   */
 | 
						|
  protected HttpURLConnection(URL url)
 | 
						|
  {
 | 
						|
    super(url);
 | 
						|
  }
 | 
						|
  
 | 
						|
  /**   
 | 
						|
   * Closes the connection to the server.
 | 
						|
   */
 | 
						|
  public abstract void disconnect();
 | 
						|
 | 
						|
  /** 
 | 
						|
   * Returns a boolean indicating whether or not this connection is going
 | 
						|
   * through a proxy
 | 
						|
   * 
 | 
						|
   * @return true if through a proxy, false otherwise
 | 
						|
   */
 | 
						|
  public abstract boolean usingProxy();
 | 
						|
 | 
						|
  /**
 | 
						|
   * Sets whether HTTP redirects (requests with response code 3xx) should be
 | 
						|
   * automatically followed by this class. True by default
 | 
						|
   *
 | 
						|
   * @param set true if redirects should be followed, false otherwis.
 | 
						|
   *
 | 
						|
   * @exception SecurityException If a security manager exists and its
 | 
						|
   * checkSetFactory method doesn't allow the operation
 | 
						|
   */
 | 
						|
  public static void setFollowRedirects(boolean set)
 | 
						|
  {
 | 
						|
    // Throw an exception if an extant security mgr precludes
 | 
						|
    // setting the factory.
 | 
						|
    SecurityManager s = System.getSecurityManager();
 | 
						|
    if (s != null)
 | 
						|
      s.checkSetFactory();
 | 
						|
 | 
						|
    followRedirects = set;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns a boolean indicating whether or not HTTP redirects will 
 | 
						|
   * automatically be followed or not.
 | 
						|
   *
 | 
						|
   * @return true if redirects will be followed, false otherwise
 | 
						|
   */
 | 
						|
  public static boolean getFollowRedirects()
 | 
						|
  {
 | 
						|
    return followRedirects;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the value of this HttpURLConnection's instanceFollowRedirects
 | 
						|
   * field
 | 
						|
   */
 | 
						|
  public boolean getInstanceFollowRedirects ()
 | 
						|
  {
 | 
						|
    return instanceFollowRedirects;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Sets the value of this HttpURLConnection's instanceFollowRedirects field
 | 
						|
   */
 | 
						|
  public void setInstanceFollowRedirects (boolean follow)
 | 
						|
  {
 | 
						|
    instanceFollowRedirects = follow;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Set the method for the URL request, one of:
 | 
						|
   * GET POST HEAD OPTIONS PUT DELETE TRACE are legal
 | 
						|
   *
 | 
						|
   * @exception ProtocolException If the method cannot be reset or if the
 | 
						|
   * requested method isn't valid for HTTP
 | 
						|
   */
 | 
						|
  public void setRequestMethod(String method) throws ProtocolException
 | 
						|
  {
 | 
						|
    if (connected)
 | 
						|
      throw new ProtocolException("Already connected");
 | 
						|
 | 
						|
    method = method.toUpperCase();
 | 
						|
    if (valid_methods.indexOf("|" + method + "|") != -1)
 | 
						|
      this.method = method;
 | 
						|
    else
 | 
						|
      throw new ProtocolException("Invalid HTTP request method: " + method);
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * The request method currently in use for this connection.
 | 
						|
   *
 | 
						|
   * @return The request method
 | 
						|
   */
 | 
						|
  public String getRequestMethod()
 | 
						|
  {
 | 
						|
    return method;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Gets the status code from an HTTP response message, or -1 if
 | 
						|
   * the response code could not be determined.
 | 
						|
   * Note that all valid response codes have class variables
 | 
						|
   * defined for them in this class.
 | 
						|
   *
 | 
						|
   * @return The response code
 | 
						|
   *
 | 
						|
   * @exception IOException If an error occurs
 | 
						|
   */
 | 
						|
  public int getResponseCode() throws IOException
 | 
						|
  {
 | 
						|
    if (!gotResponseVals)
 | 
						|
      getResponseVals();
 | 
						|
    return responseCode;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Gets the HTTP response message, if any, returned along with the
 | 
						|
   * response code from a server. Null if no response message was set
 | 
						|
   * or an error occured while connecting.
 | 
						|
   *
 | 
						|
   * @return The response message
 | 
						|
   *
 | 
						|
   * @exception IOException If an error occurs
 | 
						|
   */
 | 
						|
  public String getResponseMessage() throws IOException
 | 
						|
  {
 | 
						|
    if (!gotResponseVals)
 | 
						|
      getResponseVals();
 | 
						|
    return responseMessage;
 | 
						|
  }
 | 
						|
 | 
						|
  private void getResponseVals() throws IOException
 | 
						|
  {
 | 
						|
    // getHeaderField() will connect for us, but do it here first in
 | 
						|
    // order to pick up IOExceptions.
 | 
						|
    if (!connected)
 | 
						|
      connect();
 | 
						|
      
 | 
						|
    gotResponseVals = true;
 | 
						|
 | 
						|
    // If responseCode not yet explicitly set by subclass
 | 
						|
    if (responseCode == -1)
 | 
						|
      {
 | 
						|
	// Response is the first header received from the connection.
 | 
						|
	String respField = getHeaderField(0);
 | 
						|
	
 | 
						|
	if (respField == null || ! respField.startsWith("HTTP/"))
 | 
						|
	  {
 | 
						|
	    // Set to default values on failure.
 | 
						|
	    responseCode = -1;
 | 
						|
	    responseMessage = null;
 | 
						|
	    return;
 | 
						|
	  }
 | 
						|
 | 
						|
	int firstSpc, nextSpc;
 | 
						|
	firstSpc = respField.indexOf(' ');
 | 
						|
	nextSpc = respField.indexOf(' ', firstSpc + 1);
 | 
						|
	responseMessage = respField.substring(nextSpc + 1);
 | 
						|
	String codeStr = respField.substring(firstSpc + 1, nextSpc);
 | 
						|
	try
 | 
						|
	  {
 | 
						|
	    responseCode = Integer.parseInt(codeStr);
 | 
						|
	  }
 | 
						|
	catch (NumberFormatException e)
 | 
						|
	  {
 | 
						|
	    // Set to default values on failure.
 | 
						|
	    responseCode = -1;
 | 
						|
	    responseMessage = null;
 | 
						|
	  }
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns a permission object representing the permission necessary to make
 | 
						|
   * the connection represented by this object
 | 
						|
   *
 | 
						|
   * @exception IOException If an error occurs
 | 
						|
   */
 | 
						|
  public Permission getPermission() throws IOException
 | 
						|
  {
 | 
						|
    URL url = getURL();
 | 
						|
    String host = url.getHost();
 | 
						|
    int port = url.getPort();
 | 
						|
    if (port == -1)
 | 
						|
      port = 80;
 | 
						|
    
 | 
						|
    host = host + ":" + port;
 | 
						|
    
 | 
						|
    return new SocketPermission(host, "connect");
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * This method allows the caller to retrieve any data that might have
 | 
						|
   * been sent despite the fact that an error occurred.  For example, the
 | 
						|
   * HTML page sent along with a 404 File Not Found error.  If the socket
 | 
						|
   * is not connected, or if no error occurred or no data was returned,
 | 
						|
   * this method returns <code>null</code>.
 | 
						|
   *
 | 
						|
   * @return An <code>InputStream</code> for reading error data.
 | 
						|
   */
 | 
						|
  public InputStream getErrorStream ()
 | 
						|
  {
 | 
						|
    if (!connected)
 | 
						|
      return(null);
 | 
						|
    
 | 
						|
    int code;
 | 
						|
    try 
 | 
						|
      {
 | 
						|
	code = getResponseCode();
 | 
						|
      }
 | 
						|
    catch(IOException e)
 | 
						|
      {
 | 
						|
	code = -1;
 | 
						|
      }
 | 
						|
    
 | 
						|
    if (code == -1)
 | 
						|
      return(null);
 | 
						|
    
 | 
						|
    if (((code/100) != 4) || ((code/100) != 5))
 | 
						|
      return(null); 
 | 
						|
    
 | 
						|
    try
 | 
						|
      {
 | 
						|
	PushbackInputStream pbis = new PushbackInputStream(getInputStream());
 | 
						|
	
 | 
						|
	int i = pbis.read();
 | 
						|
	if (i == -1)
 | 
						|
	  return(null);
 | 
						|
	
 | 
						|
	pbis.unread(i);
 | 
						|
	return(pbis);
 | 
						|
      }
 | 
						|
    catch(IOException e)
 | 
						|
      {
 | 
						|
	return(null);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the value of the named field parsed as date
 | 
						|
   */
 | 
						|
  public long getHeaderFieldDate (String key, long value)
 | 
						|
  {
 | 
						|
    // FIXME: implement this correctly
 | 
						|
    // http://www.w3.org/Protocols/HTTP-NG/ng-notes.txt
 | 
						|
    
 | 
						|
    return super.getHeaderFieldDate (key, value);
 | 
						|
  }
 | 
						|
}
 |