
/**
 * Title:        Runtime Client - Server Java Project<p>
 * Description:  This is a client - server application that uses the Java
 * Runtime class to have commands executed on a server.
 *
 * The Server.java program creates 3 classes, Server.class,
 * ServerConnection.class, and Process_Request.class.
 *
 * The Client.java programs creates 3 classes, Client.class, Listener.class, and
 * ClientComm.class.
 *
 * The Server is a multi-threaded server which allows multiple clients to
 * connect and processes all commands by the client in seperate threads.
 *
 * The Client is a simple user input interface which creates a socket connection
 * to the Server and then sends the input command to the Server. It uses the
 * Listener.class, which is a thread, to recieve the output from the server and 
 * print the output to screen.
 *
 * To run, the Server.java file needs to be placed on one system, preferably a
 * UNIX machine. It then needs to be compiled using "javac Server.java" and
 * then started by the following: "java Server [port number] &"
 * The [port number] should be replaced by the port number that the server will
 * use for the socket connection. If none is specified the default of 8000 is used.
 * The "&" is used so that the process runs in the background.
 *
 * The Client.java now needs to be compiled on a seperate system.  After being
 * compiled, to run, type "java Client [server DNS name or IP address] [port]"
 * You will need to replace the [server DNS name ... etc.] with either the DNS
 * name or IP address of the system the Server.class is running on, and [port]
 * should be replaced with the port number that the Server.class is using. You
 * can now type in standard UNIX commands in on the client to be executed. To
 * quit the Client application, type "bye" as the command.
 * <p>
 * Copyright:    Copyright (c) Brian Summers, John Rountree, and Chriss Flynn<p>
 * Company:      none<p>
 * @author Brian Summers, John Rountree, and Chriss Flynn
 * @version 1.0
 */
//package clientserver;

import java.net.*;
import java.io.*;

public class Client {

        public static void main( String[] argv ) {
		int port_number;
	        if ( argv.length < 1 ) {
                    System.out.println("Usage: Client [server] [port]");
                    System.exit(0);
                }
                String server = argv[0];
		if ( argv.length == 1 ) {
			port_number = 8000;
		}
		if ( argv.length == 2 ) {
			port_number = Integer.parseInt(argv[1]);
		}
		else {
			port_number = 8000;
		}

	//Define user input stream
	BufferedReader userin = new BufferedReader(new InputStreamReader(System.in));

	//Create ClientComm object
	ClientComm cc = new ClientComm(server, port_number);
                
	//Create and Start Thread Listener to get output from the server and print it
	Listener getResponse = new Listener(cc.s_socket);
                getResponse.start();

		boolean done = false;
  		String command = null;
		String output = null;

    		while(done == false){

			//get command from user input
			System.out.println("Enter Command: ");
			System.out.flush();
			try {
			    command = userin.readLine();
			} catch ( IOException rl ) {
			    System.out.println("I/O Error: " + rl);
			}

			//Causes the system to wait if the command is null or equal to ""
			//This is a rarely needed loop and thus is inside the if statement
			//So that it is only executed when it is needed
			if ( (command == null) || (command == "") ) {
				while( (command == null) || (command == "") ) {
				}
			} 

			//This does not work properly. It was the main way to exit the program and clean-up after
			//the program.
			if(command == "bye"){
				//sends command to server
				cc.sendCommand(command);

				//kills the Listener Thread
				getResponse.destroy();

				//closes the socket connectio to server
				try {
				  cc.closeConnection();
				} catch ( IOException sc) { 
				System.out.println("Error closing socket to server: " + sc );
				 }
				
				//breaks out of the while loop to exit
				done = true;
			}
			//Passes the command to the server
			else {
			//sends command to server
                               		 cc.sendCommand(command);
                        		}

		}
          }
}


class ClientComm{

	public Socket s_socket;
	private PrintWriter out;


	ClientComm(String server, int port){

		try{
			try {
				//Create socket connection
				s_socket = new Socket(server, port);
			} catch ( UnknownHostException e ) {
		 	 System.out.println("Can not find host: " + server );
			} catch ( IOException e ) {
		  	System.out.println("Error connecting to host: " + server + port );
			}
		


			//Output to Server
			out = new PrintWriter(s_socket.getOutputStream(),true);

		} catch(IOException ioe) {
                       	 System.out.println("Error "+ioe);
               		 }
	}

	//function to output to server
	public void sendCommand(String command){

                	out.println(command);
		out.flush();


	}

	//function to close the connection to server
	public void closeConnection() throws IOException{
		 try {
                		s_socket.close();
		} catch ( IOException s_close ) {
		System.out.println("IOException Error: " + s_close );
		 }
	}

}


class Listener extends Thread {
	private Socket server;
	public BufferedReader in;
	
	public Listener( Socket server_name ) {
    		server = server_name;
  	}

	public void run() {
		try {
			String out_put;
			in = new BufferedReader( new InputStreamReader( server.getInputStream() ) );
			while ( true ) {
				while ((out_put = in.readLine()) != null ) {
				System.out.println( out_put );
				}
			}
		} catch ( IOException e_listen ) {
		System.out.println("I/O Error: " + e_listen );
		}
	}
}

