// WebConnection.java

import java.io.*;
import java.net.*;
import java.util.*;

/** A class to handle a connection to the Internet.
 */
public class WebConnection 
{
    private Socket socket;
    private InputStream webis;
    private OutputStream webos;
    private InetAddress ia;
    private int port;
    private Date releasedAt;

     /** A class to handle the addresses of the connections.
     *  Basically just a pair of InetAddress and port number.
     */
    public class Address {
        /** The internet address of this Address. */
        public InetAddress ia;
        /** The port number were connected to. */
        public int port;

        /** Create a new Address with given InetAddress and port 
         * @param ia the InetAddress this Address is connected to.
         * @param port the port number this Address is connected to.
	 */
        public Address (InetAddress ia, int port) {
            this.ia = ia;
            this.port = port;
        }
        
        /** Get the hash code for this object.
         * @return the hash code.
         */
        public int hashCode () {
            String s = ia.toString () + ":" + port;
            return s.hashCode ();
        }
        
        /** Compare this objcet agains another object.
         * @param o the Object to compare against.
         * @return true if the other Object is an Address connected to 
         *  the same InetAddress and port, false otherwise.
         */
        public boolean equals (Object o) {
            if (o instanceof Address) {
                Address a = (Address)o;
                return (port == a.port && ia.equals (a.ia));
            }
            return false;
        }
    }
    
    //Do nothing constructor
    public WebConnection () {
    }

     // Get a WebConnection for the given header.
    public WebConnection getConnection (HTTPHeader header) throws IOException { 
        String error = null;
        try {
            WebConnection wc = null;
            String requri = header.getRequestURI ();
            URL url = new URL (requri);
            InetAddress ia = Proxy.getInetAddress (url);
            int port = url.getPort () > 0 ? url.getPort () : 80;
            port = Proxy.getConnectPort (port);
            Address a = new Address (ia, port);
	    wc = new WebConnection (ia, port);
	    return wc;

        } catch (UnknownHostException e) {
	    System.out.println("Could not find the host: '" + e + "':\n" + header);
	} catch (MalformedURLException e) {
	    System.out.println("Bad URI in request: '" + e + "':\n" + header); 
	} catch (IllegalArgumentException e) {
	    System.out.println("Bad port number in request: '" + e + "':\n" + header);
	}
	throw new IOException ("Could not connect to host: " + error);
    }

    /** Create a new WebConnection to the given InetAddress and port.
     * @param InetAddress the computer to connect to.
     * @param port the port number to connect to.
     */
    public WebConnection (InetAddress ia, int port) throws IOException {
	this.ia = ia; 
	this.port = port;
	try {
	    socket = new Socket (ia, port);	
	    socket.setSoTimeout (5*60*1000);        // 5 min should be enough
	    webos = socket.getOutputStream();
	    webis = socket.getInputStream();
	} catch (IOException e) {
	    throw new IOException ("Could not connect to the site: " + ia + ":" + port);
	}
    }

    /** Close the connection.
     */
    public void close () {
	try {
	    webos.close ();
	    webis.close ();
	    socket.close ();
	} catch (IOException e) {
	}
    }
    
    /** Get the InetAddress that this WebConnection is connected to.
     * @return the InetAddress.
     */
    public InetAddress getInetAddress () {
	return ia;
    }
    
    /** Get the port number this WebConnection is connected to.
     * @return the port number.
     */
    public int getPort () {
	return port;
    }

    /** Mark this WebConnection as released at current time.
     */
    public void setReleased () {
	setReleased (new Date ());
    }

    /** Mark this WebConnection as released at given time.
     * @param d the time that this WebConnection is released.
     */
    public void setReleased (Date d) {
	releasedAt = d;
    }
    
    /** Get the time that this WebConnection was released.
     */
    public Date getReleasedAt () {
	return releasedAt;
    }

    /** Get the InputStream.
     * @return an HTTPInputStream.
     */
    public InputStream getInputStream () {
	return webis;
    }
    
    /** Get the OutputStream of this WebConnection.
     * @return an HTTPOutputStream.
     */
    public OutputStream getOutputStream () {
	return webos;
    }
}







