// HttpNgClientFactory.java
// $Id: HttpNgClientFactory.java,v 1.1 1997/11/21 00:49:09 veillard Exp $
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.httpng;

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

import javastubs.iluhttp.*;
import w3c.www.http.*;
import w3c.jigsaw.http.*;

/**
 * The HttpNgReply serves to convert a Jigsaw Reply to an
 * HTTP-NG Response
 */

class HttpNgReply {
    /**
     * What are the Headers in HTTP that will be reused by HTTP-NG
     * Responses.
     */
    public static final int httpNgNbHeader = 50;
    public static int ngHeader[];
    public static String ngHeaderName[];
    private static int ngHeaderNo = 0;

    static void addHeader(String header) {
	ngHeaderName[ngHeaderNo++] = header;
    }
    static {
        ngHeader = new int[httpNgNbHeader];
        ngHeaderName = new String[httpNgNbHeader];

	/* From HttpMessage */
        addHeader("Cache-Control");
        addHeader("Connection");
        addHeader("Proxy-Connection");
        addHeader("Date");
        addHeader("Pragma");
        addHeader("Transfer-Encoding");
        addHeader("Upgrade");
        addHeader("Via");
        addHeader("Protocol");
        addHeader("Protocol-Request");
        addHeader("Protocol-Query");
        addHeader("Protocol-Info");
        addHeader("Set-Cookie");
        addHeader("Cookie");

	/* From HttpEntityMessage */
	addHeader("Allow");
	addHeader("Content-Length");
	addHeader("Content-Base");
	addHeader("Content-Encoding");
	addHeader("Content-Language");
	addHeader("Content-Location");
	addHeader("Content-Md5");
	addHeader("Content-Range");
	addHeader("Content-Type");
	addHeader("Etag");
	addHeader("Expires");
	addHeader("Last-Modified");

	/* From HttpReplyMessage */
	addHeader("Accept-Ranges");
	addHeader("Age");
	addHeader("Location");
	addHeader("Proxy-Authenticate");
	addHeader("Public");
	addHeader("Retry-After");
	addHeader("Server");
	addHeader("Vary");
	addHeader("Warning");
	addHeader("WWW-authenticate");
    }

    /**
     * This create an HTTP-Ng Response from a Jigsaw Reply.
     * @param reply the Jigsaw internal Reply to a Request
     * @return a Response containing the appropriate Headers and body.
     */
    static javastubs.iluhttp.Response buildResponse(Reply reply) {
	int index = 0;
	int ngHeaderNumber[] = new int[ngHeaderNo];
	String ngHeaderValues[] = new String[ngHeaderNo];
	HeaderValue hValue;
	int nbHeaders = 0;
	int contentLenght;

	/*
	 * Ask for all the fields we are interested in.
	 */
	contentLenght = reply.getContentLength();
	for (index = 0; index < ngHeaderNo; index++) {
	    hValue = reply.getHeaderValue(ngHeaderName[index]);
	    if (hValue != null) {
		ngHeaderNumber[nbHeaders] = index;
		ngHeaderValues[nbHeaders] = hValue.toExternalForm();
		// System.out.println(ngHeaderName[index] + ": " +
		//                   ngHeaderValues[nbHeaders]);

		nbHeaders++;
	    }
	}

	/*
	 * Build the Headers.
	 */
        javastubs.iluhttp.Response rep = new javastubs.iluhttp.Response();
	javastubs.iluhttp.Header hdrs[] = 
	            new javastubs.iluhttp.Header[nbHeaders];

        for (index = 0; index < nbHeaders; index++) {
	    hdrs[index] = new Header();
	    hdrs[index].name = ngHeaderName[ngHeaderNumber[index]];
	    hdrs[index].value = ngHeaderValues[index];
	}

        /*
	 * Get the body as a byte[] if possible !!!!
	 */
	byte body[];
	if (contentLenght < 0) {
	    System.out.println("No Content-Length, sending garbage !");
	    String result = "Coucou";
	    body = result.getBytes();
	} else {
	    InputStream is = reply.openStream();
	    if ( is == null ) {
	        System.out.println("reply.openStream() failed !");
		String result = "Error cannot open stream !";
		body = result.getBytes();
	    } else {
	        if (contentLenght >= 100000)
		    System.out.println("Content-Length = " + contentLenght);

		/*
		 * Read the body from the Input Stream in body[].
		 */
		body = new byte[contentLenght];
		int got = 0 ;
		int written = 0;
		try {
		    while ((got = is.read(body, written,
					  body.length - written)) > 0) {
			written += got ;
		    }
		} catch (java.io.IOException ex) {
		    System.out.println("Got exception when reading input !");
		}
            }
	}

	/*
	 * Build the response
	 */
	rep.status = StatusCode.from_int(reply.getStatus());
	rep.headers = hdrs;
	rep.body = body;

	return(rep);
    }
}

/**
 * The HttpNgClientFactory makes the interface between the ILU
 * implementation providing incoming requests and the Jigsaw
 * server part expecting HTTPRequest objects for processing.
 */

public class HttpNgClientFactory
  implements ClientFactory, javastubs.iluhttp.Resource {
    private httpd server;

    public static javastubs.iluhttp.Response buildResponse(Reply reply) {
	int index = 0;
        Enumeration headerList = reply.enumerateHeaderDescriptions(false);
        javastubs.iluhttp.Response rep = new javastubs.iluhttp.Response();
	javastubs.iluhttp.Header hdrs[] = new javastubs.iluhttp.Header[50];
	byte body[];
	String result = "Hello World";

        /*
        for (; headerList.hasMoreElements() ;) {
	    Header[index] = new Header();
	    System.out.println(e.nextElement());
	} */
        body = result.getBytes();
	rep.status = StatusCode.from_int(StatusCode._OK);
	rep.headers = hdrs;
	rep.body = body;

	hdrs[0] =  new Header();
	hdrs[0].name = "Date";
	hdrs[0].value = "Thu, 20 Nov 1997 00:48:57 GMT";
	hdrs[1] =  new Header();
	hdrs[1].name = "Content-Type";
	hdrs[1].value = "text/html";
	hdrs[2] =  new Header();
	hdrs[2].name = "Server";
	hdrs[2].value = "Apache/1.2.4";

	return(rep);
    }

    /********************************************************************
     *									*
     *		Implementation of the ClientFactory interfaces		*
     *									*
     ********************************************************************/
    /**
     * Shutdown this client factory.
     * @param force If <strong>true</strong>, force the shutdown, and stop
     * all operations in progress.
     */

    public void shutdown(boolean force) {
        System.out.println("HttpNgClientFactory.shutdown(" + force + ")");
    }

    /**
     * Handle the given, new connection.
     * @param socket The newly accepted connection.
     */

    public void handleConnection(Socket socket) {
        System.out.println("HttpNgClientFactory.handleConnection(" + socket + ")");
    }

    /**
     * Initialize that client factory.
     * Initialize this new client factory, and create the <em>server 
     * socket</em> (ie the socket that will be used to accept new connections.
     * @param server The httpd instance to be used as the context for
     * this client factory.
     */
     
    public void initialize(w3c.jigsaw.http.httpd server) {
        System.out.println("HttpNgClientFactory.initialize(" + server + ")");
    }

    /**
     * Create the server socket for this client factory.
     * This method is always called <em>after</em> the initialize method
     * of the client factory is done.
     * @return A server socket instance. 
     * @exception IOException If some IO error occurs while creating the
     * server socket.
     */

    public ServerSocket createServerSocket() 
	throws IOException {
        System.out.println("HttpNgClientFactory.createServerSocket()");
	return(null);
    }

    /********************************************************************
     *									*
     *		Implementation of the ClientFactory interfaces		*
     *									*
     ********************************************************************/
    /**
     * Serving an HTTP request GET .
     * @param Request the request parameters
     * @return a Response object
     */
    public javastubs.iluhttp.Response GET(javastubs.iluhttp.Request request)
        throws xerox.ilu.IluSystemException {
	Reply rep = null;

        // System.out.println("HttpNgClientFactory.GET(" + request + ")");

	/*
	 * Transform the incoming HTTP-NG request to a Jigsaw one
	 */
	w3c.jigsaw.http.Request req = HttpNgRequest.create(server, request);

	/*
	 * Perform the request
	 */
	try {
	    rep = server.perform(req);
        } catch (w3c.jigsaw.http.HTTPException ex) {
	    System.out.println("Caught HTTPException:" + ex.getMessage());
	    ex.printStackTrace();
	} catch (w3c.jigsaw.http.ClientException ex) {
	    System.out.println("Caught ClientException:" + ex.getMessage());
	    ex.printStackTrace();
	} catch (Exception ex) {
	    System.out.println("Caught Exception:" + ex.getMessage());
	    ex.printStackTrace();
	}

	/*
	 * Transform the reply to an HTTP-NH Response
	 */
        return(HttpNgReply.buildResponse(rep));
    }

    /**
     * Serving an HTTP request HEAD .
     * @param Request the request parameters
     * @return a Response object
     */
    public javastubs.iluhttp.Response HEAD(javastubs.iluhttp.Request request)
        throws xerox.ilu.IluSystemException {
        System.out.println("HttpNgClientFactory.HEAD(" + request + ")");
        return(null);
    }

    /**
     * Serving an HTTP request POST .
     * @param Request the request parameters
     * @return a Response object
     */
    public javastubs.iluhttp.Response POST(javastubs.iluhttp.Request request)
        throws xerox.ilu.IluSystemException {
        System.out.println("HttpNgClientFactory.POST(" + request + ")");
        return(null);
    }

    /**
     * Initializer
     * @param daemon : the HttpNg httpd for this ClientFactory
     * @returns a properly initialized ClientFactory
     */
    public HttpNgClientFactory(httpd daemon) {
        server = daemon;
	System.out.println("Creating an HttpNgClientFactory");
    }
}
