/*
 *  Kholoud Khateeb, Craig Ward
 *  CMSI 698, Internet Technologies
 *  Homework Assignment 2, February 27, 2003
 */
import java.net.Socket;
import java.util.Date;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;

/**
 * Modified CapitalizeServer. This version does not use an inner class to run
 * the service thread; nor does it use a ServerSocket directly. This version
 * subclasses an abstract server class that handles the ServerSocket accept()
 * method and defines two methods that must be implemented in the subclass:
 *
 * spawn(Socket socket) -- Receive the socket returned by the accept
 * run() -- The required method for the Thread to run.
 */
public class CapitalizeServer extends GenericThreadedServer {

    private int clientNumber = 0;
    private Socket socket;

    public static void main(String[] args) throws Exception {  
        System.out.println("The capititalization server is running.");
	CapitalizeServer capitalizer;
	try {
	    capitalizer = new CapitalizeServer(9898);
	    capitalizer.listen();
	} catch (IOException ioe) {
	    System.out.println("server error: " + ioe);
	    System.exit(1);
	}
    }

    /**
     * Create the Object that will listen for requests and call the spawn()
     * method.
     */
    public CapitalizeServer(int port) throws IOException
    {
	super(port);
    }

    /**
     * Create an instance of the server for a particular client.
     */
    public CapitalizeServer(Socket socket, int clientNumber)
    {
	this.socket = socket;
	this.clientNumber = clientNumber;
    }

    /**
     * Create a new thread using the socket we're handed and using the client
     * counter.
     */
    public void spawn(Socket socket)
    {
	new Thread(new CapitalizeServer(socket, ++clientNumber)).start();
    }

    /**
     * Services this thread's client by first sending the
     * client a welcome message then repeatedly reading strings
     * and sending back the capitalized version of the string.
     */
    public void run() 
    {  
	try {  

            log("New connection with client# " + clientNumber
		+ " at " + socket);
	    // Decorate the streams so we can send characters
	    // and not just bytes.  Ensure output is flushed
	    // after every newline.
	    BufferedReader in = 
	    	new BufferedReader(
			new InputStreamReader(socket.getInputStream()));
	    PrintWriter out = 
		new PrintWriter(socket.getOutputStream(), true);

	    // Send a welcome message to the client.
	    out.println("Hello, you are client #" + clientNumber + ".");
	    out.println("Enter a line with only a period to quit\n");
      
	    // Get messages from the client, line by line; return them
	    // capitalized
	    while (true) {
		String input = in.readLine();
		if (input == null || input.equals(".")) {
		    break;
		}
		out.println(input.toUpperCase());
	    }
	} catch (IOException e) {
	    log("Error handling client# " + clientNumber + ": " + e);
	} finally {
	    try {
		socket.close();
	    } catch (IOException e) {
		log("Couldn't close a socket, what's going on?");
	    }
	    log("Connection with client# " + clientNumber + " closed");
	}
    } 

    /**
     * Logs a simple message.  In this case we just write the
     * message to the server applications standard output.
     */
    private void log(String message) 
    {
	System.out.println(message);
    }
}

