// HttpURLConnection.java - Subclass of communications links using
//			Hypertext Transfer Protocol.

/* Copyright (C) 1999, 2000  Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

package java.net;

import java.io.*;

/**
 * @author Warren Levy <warrenl@cygnus.com>
 * @date March 29, 1999.
 */

/**
 * 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.
 */

public abstract class HttpURLConnection extends URLConnection
{
  /* HTTP Success Response Codes */
  public static final int HTTP_OK		= 200;
  public static final int HTTP_CREATED		= 201;
  public static final int HTTP_ACCEPTED 	= 202;
  public static final int HTTP_NOT_AUTHORITATIVE = 203;
  public static final int HTTP_NO_CONTENT	= 204;
  public static final int HTTP_RESET		= 205;
  public static final int HTTP_PARTIAL		= 206;

  /* HTTP Redirection Response Codes */
  public static final int HTTP_MULT_CHOICE	= 300;
  public static final int HTTP_MOVED_PERM	= 301;
  public static final int HTTP_MOVED_TEMP	= 302;
  public static final int HTTP_SEE_OTHER	= 303;
  public static final int HTTP_NOT_MODIFIED	= 304;
  public static final int HTTP_USE_PROXY	= 305;

  /* HTTP Client Error Response Codes */
  public static final int HTTP_BAD_REQUEST	= 400;
  public static final int HTTP_UNAUTHORIZED	= 401;
  public static final int HTTP_PAYMENT_REQUIRED	= 402;
  public static final int HTTP_FORBIDDEN	= 403;
  public static final int HTTP_NOT_FOUND	= 404;
  public static final int HTTP_BAD_METHOD	= 405;
  public static final int HTTP_NOT_ACCEPTABLE	= 406;
  public static final int HTTP_PROXY_AUTH	= 407;
  public static final int HTTP_CLIENT_TIMEOUT	= 408;
  public static final int HTTP_CONFLICT		= 409;
  public static final int HTTP_GONE		= 410;
  public static final int HTTP_LENGTH_REQUIRED	= 411;
  public static final int HTTP_PRECON_FAILED	= 412;
  public static final int HTTP_ENTITY_TOO_LARGE	= 413;
  public static final int HTTP_REQ_TOO_LONG	= 414;
  public static final int HTTP_UNSUPPORTED_TYPE	= 415;

  /* HTTP Server Error Response Codes */
  public static final int HTTP_SERVER_ERROR	= 500;
  public static final int HTTP_INTERNAL_ERROR	= 501;
  public static final int HTTP_BAD_GATEWAY	= 502;
  public static final int HTTP_UNAVAILABLE	= 503;
  public static final int HTTP_GATEWAY_TIMEOUT	= 504;
  public static final int HTTP_VERSION		= 505;

  static boolean followRedirects = true;

  protected String method = "GET";
  protected int responseCode = -1;
  protected String responseMessage;
  protected boolean instanceFollowRedirects = followRedirects;

  private boolean gotResponseVals = false;

  protected HttpURLConnection(URL url)
  {
    super(url);
  }

  public abstract void disconnect();

  public abstract boolean usingProxy();

  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;
  }

  public static boolean getFollowRedirects()
  {
    return followRedirects;
  }

  public void setRequestMethod(String method) throws ProtocolException
  {
    if (connected)
      throw new ProtocolException("Already connected");

    if (method.equals("GET") || method.equals("POST") ||
	method.equals("HEAD") || method.equals("OPTIONS") ||
	method.equals("PUT") || method.equals("DELETE") ||
	method.equals("TRACE"))
      this.method = method;
    else
      throw new ProtocolException("Invalid HTTP request method");
  }

  public String getRequestMethod()
  {
    return method;
  }

  public int getResponseCode() throws IOException
  {
    if (!gotResponseVals)
      getResponseVals();
    return responseCode;
  }

  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;
    // 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;
      }
  }

  // TODO12: public Permission getPermission() throws IOException
  // {
  // }

  // TODO12: public InputStream getErrorStream()
  // {
  // }
}
