package client_server;

/**
 * The Simple Web Server opens a port and gets a new ServerSocket.  When a web page client
 * opens a socket on the same port, it accepts the connection and spawns a thread to 
 * handle it.  The thread parses the URL string, sending the parameters for processing in
 * the Response class.  It then gets a new instance of the class (given by the URL string)
 * that is to process the request.  It then invokes that class's process method.
**/
import java.io.*;
import java.net.*;
import java.util.*;

public class WebServer
{
	public static void main (String [] args)
	{
		try
		{
			// Set the port that the server will listen on.
			Scanner keyboard = new Scanner (System.in);
			int port = 8080; // The default port.
			System.out.print ("Port: ");
			String portStr = keyboard.nextLine ();
			if (! portStr.equals ("")) 
				port = Integer.parseInt (portStr); // Use a different port.
			
			int count = 1; // Track the number of clients.
			ServerSocket serverSocket = new ServerSocket (port);
			while (true)
			{
				Socket clientSocket = serverSocket.accept (); // Respond to the client.
				System.out.println ("Client " + count + " starting:");
				new Server (clientSocket).start ();
				count ++;
			}
		} catch (IOException e) {System.out.println ("IO Exception");}
		catch (NumberFormatException e) {System.out.println ("Number error");}
	} //main
} // SimpleServer

/**
 * The Server class is a thread.  It reads the URL string from the client's socket.
 * It then gets a StringTokenizer for it and uses the tokenizer to parse the string.
 * The first two tokens in the string are the method (get or post) and the name of
 * the class that is to process the request.  The remainder of the tokens are sent
 * to the Request class for further processing.  The process method in the processor
 * class is then started.
**/

class Server extends Thread
{
	WebRequestProcessor processor;
	Socket clientSocket;
	
	public Server (Socket clientSocket) {this.clientSocket = clientSocket;}
	
	public void run ()
	{
		String urlString, method, processName;
		try
		{
			// Get the URL string and tokenize it.
			InputStream inStream = clientSocket.getInputStream ();
			BufferedReader in = new BufferedReader (new InputStreamReader 
				(clientSocket.getInputStream ()));
			OutputStream outStream = clientSocket.getOutputStream ();
			PrintWriter writer = new PrintWriter(new OutputStreamWriter(outStream),true);
			urlString = in.readLine();
			System.out.println (urlString);
			StringTokenizer tokenizer = new StringTokenizer(urlString, "/?&= ");
			
			// Get the first two tokens and send the rest of the tokens to the Request class.
			method = tokenizer.nextToken();
			System.out.println (method);
			processName = tokenizer.nextToken();
			System.out.println (processName);
			
			// Set up the Request and Response clases.
			Request request = new Request (tokenizer, method);
			Response response = new Response (outStream);
			
			// Start the processing.	
			System.out.println ("Processing: " + processName);
			processor = (WebRequestProcessor) Class.forName (processName).newInstance ();
			processor.process (request, response);
			clientSocket.close (); // Close the client's socket.
		} catch (IOException e) {System.out.println ("Processing Exception");}
		catch (ClassNotFoundException ce) {System.out.println("Class not found");}
		catch (InstantiationException ie) {System.out.println ("Instantiation exception");}
		catch (IllegalAccessException ie) {System.out.println ("Illegal Access Exception");}
		System.out.println("Client at "+ clientSocket.getInetAddress() + " disconnected");
	} // run
} // class Server




