/*
 * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import sun.net.www.MessageHeader;

/**
 * This class encapsulates a HTTP request received and a response to be
 * generated in one transaction. It provides methods for examaining the
 * request from the client, and for building and sending a reply.
 */

public class HttpTransaction {

    String command;
    URI requesturi;
    HttpServer.Server server;
    MessageHeader reqheaders, reqtrailers;
    String reqbody;
    byte[] rspbody;
    MessageHeader rspheaders, rsptrailers;
    SelectionKey  key;
    int rspbodylen;
    boolean rspchunked;

    HttpTransaction (HttpServer.Server server, String command,
                        URI requesturi, MessageHeader headers,
                        String body, MessageHeader trailers, SelectionKey  key) {
        this.command = command;
        this.requesturi = requesturi;
        this.reqheaders = headers;
        this.reqbody = body;
        this.reqtrailers = trailers;
        this.key = key;
        this.server = server;
    }

    /**
     * Get the value of a request header whose name is specified by the
     * String argument.
     *
     * @param key the name of the request header
     * @return the value of the header or null if it does not exist
     */
    public String getRequestHeader (String key) {
        return reqheaders.findValue (key);
    }

    /**
     * Get the value of a response header whose name is specified by the
     * String argument.
     *
     * @param key the name of the response header
     * @return the value of the header or null if it does not exist
     */
    public String getResponseHeader (String key) {
        return rspheaders.findValue (key);
    }

    /**
     * Get the request URI
     *
     * @return the request URI
     */
    public URI getRequestURI () {
        return requesturi;
    }

    public String toString () {
        StringBuffer buf = new StringBuffer();
        buf.append ("Request from: ").append (key.channel().toString()).append("\r\n");
        buf.append ("Command: ").append (command).append("\r\n");
        buf.append ("Request URI: ").append (requesturi).append("\r\n");
        buf.append ("Headers: ").append("\r\n");
        buf.append (reqheaders.toString()).append("\r\n");
        buf.append ("Body: ").append (reqbody).append("\r\n");
        buf.append ("---------Response-------\r\n");
        buf.append ("Headers: ").append("\r\n");
        if (rspheaders != null) {
            buf.append (rspheaders.toString()).append("\r\n");
        }
        String rbody = rspbody == null? "": new String (rspbody);
        buf.append ("Body: ").append (rbody).append("\r\n");
        return new String (buf);
    }

    /**
     * Get the value of a request trailer whose name is specified by
     * the String argument.
     *
     * @param key the name of the request trailer
     * @return the value of the trailer or null if it does not exist
     */
    public String getRequestTrailer (String key) {
        return reqtrailers.findValue (key);
    }

    /**
     * Add a response header to the response. Multiple calls with the same
     * key value result in multiple header lines with the same key identifier
     * @param key the name of the request header to add
     * @param val the value of the header
     */
    public void addResponseHeader (String key, String val) {
        if (rspheaders == null)
            rspheaders = new MessageHeader ();
        rspheaders.add (key, val);
    }

    /**
     * Set a response header. Searches for first header with named key
     * and replaces its value with val
     * @param key the name of the request header to add
     * @param val the value of the header
     */
    public void setResponseHeader (String key, String val) {
        if (rspheaders == null)
            rspheaders = new MessageHeader ();
        rspheaders.set (key, val);
    }

    /**
     * Add a response trailer to the response. Multiple calls with the same
     * key value result in multiple trailer lines with the same key identifier
     * @param key the name of the request trailer to add
     * @param val the value of the trailer
     */
    public void addResponseTrailer (String key, String val) {
        if (rsptrailers == null)
            rsptrailers = new MessageHeader ();
        rsptrailers.add (key, val);
    }

    /**
     * Get the request method
     *
     * @return the request method
     */
    public String getRequestMethod (){
        return command;
    }

    /**
     * Perform an orderly close of the TCP connection associated with this
     * request. This method guarantees that any response already sent will
     * not be reset (by this end). The implementation does a shutdownOutput()
     * of the TCP connection and for a period of time consumes and discards
     * data received on the reading side of the connection. This happens
     * in the background. After the period has expired the
     * connection is completely closed.
     */

    public void orderlyClose () {
        try {
            server.orderlyCloseChannel (key);
        } catch (IOException e) {
            System.out.println (e);
        }
    }

    /**
     * Do an immediate abortive close of the TCP connection associated
     * with this request.
     */
    public void abortiveClose () {
        try {
            server.abortiveCloseChannel(key);
        } catch (IOException e) {
            System.out.println (e);
        }
    }

    /**
     * Get the SocketChannel associated with this request
     *
     * @return the socket channel
     */
    public SocketChannel channel() {
        return (SocketChannel) key.channel();
    }

    /**
     * Get the request entity body associated with this request
     * as a single String.
     *
     * @return the entity body in one String
     */
    public String getRequestEntityBody (){
        return reqbody;
    }

    /**
     * Set the entity response body with the given string
     * The content length is set to the length of the string
     * @param body the string to send in the response
     */
    public void setResponseEntityBody (String body){
        rspbody = body.getBytes();
        rspbodylen = body.length();
        rspchunked = false;
        addResponseHeader ("Content-length", Integer.toString (rspbodylen));
    }
    /**
     * Set the entity response body with the given byte[]
     * The content length is set to the gven length
     * @param body the string to send in the response
     */
    public void setResponseEntityBody (byte[] body, int len){
        rspbody = body;
        rspbodylen = len;
        rspchunked = false;
        addResponseHeader ("Content-length", Integer.toString (rspbodylen));
    }


    /**
     * Set the entity response body by reading the given inputstream
     *
     * @param is the inputstream from which to read the body
     */
    public void setResponseEntityBody (InputStream is) throws IOException {
        byte[] buf = new byte [2048];
        byte[] total = new byte [2048];
        int total_len = 2048;
        int c, len=0;
        while ((c=is.read (buf)) != -1) {
            if (len+c > total_len) {
                byte[] total1 = new byte [total_len * 2];
                System.arraycopy (total, 0, total1, 0, len);
                total = total1;
                total_len = total_len * 2;
            }
            System.arraycopy (buf, 0, total, len, c);
            len += c;
        }
        setResponseEntityBody (total, len);
    }

    /* chunked */

    /**
     * Set the entity response body with the given array of strings
     * The content encoding is set to "chunked" and each array element
     * is sent as one chunk.
     * @param body the array of string chunks to send in the response
     */
    public void setResponseEntityBody (String[] body) {
        StringBuffer buf = new StringBuffer ();
        int len = 0;
        for (int i=0; i<body.length; i++) {
            String chunklen = Integer.toHexString (body[i].length());
            len += body[i].length();
            buf.append (chunklen).append ("\r\n");
            buf.append (body[i]).append ("\r\n");
        }
        buf.append ("0\r\n");
        rspbody = new String (buf).getBytes();
        rspbodylen = rspbody.length;
        rspchunked = true;
        addResponseHeader ("Transfer-encoding", "chunked");
    }

    /**
     * Send the response with the current set of response parameters
     * but using the response code and string tag line as specified
     * @param rCode the response code to send
     * @param rTag the response string to send with the response code
     */
    public void sendResponse (int rCode, String rTag) throws IOException {
        OutputStream os = new HttpServer.NioOutputStream(channel());
        PrintStream ps = new PrintStream (os);
        ps.print ("HTTP/1.1 " + rCode + " " + rTag + "\r\n");
        if (rspheaders != null) {
            rspheaders.print (ps);
        } else {
            ps.print ("\r\n");
        }
        ps.flush ();
        if (rspbody != null) {
            os.write (rspbody, 0, rspbodylen);
            os.flush();
        }
        if (rsptrailers != null) {
            rsptrailers.print (ps);
        } else if (rspchunked) {
            ps.print ("\r\n");
        }
        ps.flush();
    }

    /* sends one byte less than intended */

    public void sendPartialResponse (int rCode, String rTag)throws IOException {
        OutputStream os = new HttpServer.NioOutputStream(channel());
        PrintStream ps = new PrintStream (os);
        ps.print ("HTTP/1.1 " + rCode + " " + rTag + "\r\n");
        ps.flush();
        if (rspbody != null) {
            os.write (rspbody, 0, rspbodylen-1);
            os.flush();
        }
        if (rsptrailers != null) {
            rsptrailers.print (ps);
        }
        ps.flush();
    }
}
