diff --git a/ChatClient.java b/ChatClient.java new file mode 100644 index 0000000..ea28d5f --- /dev/null +++ b/ChatClient.java @@ -0,0 +1,210 @@ +// This file contains material supporting section 3.7 of the textbook: +// "Object Oriented Software Engineering" and is issued under the open-source +// license found at www.lloseng.com + +package client; + +import ocsf.client.*; +import common.*; +import java.io.*; +import java.util.Arrays; +import java.util.List; + +/** + * This class overrides some of the methods defined in the abstract + * superclass in order to give more functionality to the client. + * + * @author Dr Timothy C. Lethbridge + * @author Dr Robert Laganiè + * @author François Bélanger + * @version July 2000 + */ +public class ChatClient extends AbstractClient +{ + //Instance variables ********************************************** + + /** + * The interface type variable. It allows the implementation of + * the display method in the client. + */ + ChatIF clientUI; + + + //Constructors **************************************************** + + /** + * Constructs an instance of the chat client. + * + * @param host The server to connect to. + * @param port The port number to connect on. + * @param clientUI The interface type variable. + */ + + public ChatClient(String host, int port, ChatIF clientUI) + throws IOException + { + super(host, port); //Call the superclass constructor + this.clientUI = clientUI; + openConnection(); + } + + + //Instance methods ************************************************ + + /** + * This method handles all data that comes in from the server. + * + * @param msg The message from the server. + */ + public void handleMessageFromServer(Object msg) + { + clientUI.display(msg.toString()); + } + + /** + * This method handles all data coming from the UI + * + * @param message The message from the UI. + */ + public void handleMessageFromClientUI(String message) + { + try + { + sendToServer(message); + } + catch(IOException e) + { + clientUI.display + ("Could not send message to server. Terminating client."); + quit(); + } + } + + /** + * This method terminates the client. + */ + public void quit() + { + try + { + closeConnection(); + } + catch(IOException e) {} + System.exit(0); + } + + /** + * Hook method called after the connection has been closed. The default + * implementation does nothing. The method may be overriden by subclasses to + * perform special processing such as cleaning up and terminating, or + * attempting to reconnect. + */ + protected void connectionClosed() { + System.out.println("SYSTEM ::: Connection to the Server Terminated"); + } + + /** + * Hook method called each time an exception is thrown by the client's + * thread that is waiting for messages from the server. The method may be + * overridden by subclasses. + * + * @param exception + * the exception raised. + */ + protected void connectionException(Exception exception) { + System.out.println("SYSTEM ::: Server Shutdown"); + quit(); + } + + /** + * This method contains all the client commands. + * Every commands begin with '#'. + * + * @param command word that needs to be actioned. + */ + public void clientCommand(String message){ + + //Make the message received into an array (necessary for setHost/setPort) + String[] messageArray = message.split(" "); + String[] commandArray = new String[]{"#quit","#login","#logoff","#gethost","#sethost","#getport","#setport"}; + + //If the command isn't in the 'known' list, give error message and command list. + if (!Arrays.asList(commandArray).contains(messageArray[0])){ + System.out.println("The command line you entered is 'INVALID', here is a list of all current commands."); + System.out.println("#quit // #login // #logoff // #gethost // #sethost // #getport // #setport"); + } + + switch(messageArray[0]) { + case "#quit": + quit(); + + case "#login": + //what happens in #login + if (isConnected()){ + System.out.println("SYSTEM ::: The client is already connected"); + return; + } + else { + try + { + openConnection(); + System.out.println("SYSTEM ::: Client connected"); + } + catch (IOException ex){System.out.println("SYSTEM ::: Failed to connect to Server");} + return; + } + + case "#logoff": + try + { + System.out.println("SYSTEM ::: Shutting down client"); + closeConnection(); + return; + } + catch(IOException e) {} + return; + + case "#gethost": + System.out.println("SYSTEM ::: The Host name is: " + getHost()); + return; + + case "#sethost": + + try + { + setHost(messageArray[1]); + System.out.println("SYSTEM ::: The new Host has been set to: " + getHost()); + } catch (Exception ex2) + { + System.out.println("SYSTEM ::: Array Out of Bound: Please try again with the new Host name."); + } return; + + case "#getport": + + try + { + System.out.println("SYSTEM ::: The current Port is: " + getPort()); + } + + catch (Exception a) + { + System.out.println("SYSTEM ::: There was an error in the getPort attempt"); + } + return; + + case "#setport": + + try { + int newPort = Integer.parseInt(messageArray[1]); + + setPort(newPort); + System.out.println("SYSTEM ::: The new Port has been set to: " + getPort()); + } catch (Exception ex2) + { + System.out.println("SYSTEM ::: Array Out-of-Bound or your Port was not a valid Integer between 1 and 65535."); + } return; + } + } + +} +//End of ChatClient class diff --git a/ClientConsole.java b/ClientConsole.java new file mode 100644 index 0000000..c2af2ea --- /dev/null +++ b/ClientConsole.java @@ -0,0 +1,177 @@ +// This file contains material supporting section 3.7 of the textbook: +// "Object Oriented Software Engineering" and is issued under the open-source +// license found at www.lloseng.com + +import java.io.*; +import client.*; +import common.*; +import java.util.Arrays; +import java.util.List; + +/** + * This class constructs the UI for a chat client. It implements the + * chat interface in order to activate the display() method. + * Warning: Some of the code here is cloned in ServerConsole + * + * @author François Bélanger + * @author Dr Timothy C. Lethbridge + * @author Dr Robert Laganière + * @version July 2000 + */ +public class ClientConsole implements ChatIF +{ + //Class variables ************************************************* + + /** + * The default port to connect on. + */ + final public static int DEFAULT_PORT = 5555; + + //Instance variables ********************************************** + + /** + * The instance of the client that created this ConsoleChat. + */ + ChatClient client; + + + //Constructors **************************************************** + + /** + * Constructs an instance of the ClientConsole UI. + * + * @param host The host to connect to. + * @param port The port to connect on. + */ + public ClientConsole(String host, int port) + { + try + { + client= new ChatClient(host, port, this); + } + catch(IOException exception) + { + System.out.println("Error: Can't setup connection!" + + " Terminating client."); + System.exit(1); + } + } + + + //Instance methods ************************************************ + + /** + * This method waits for input from the console. Once it is + * received, it sends it to the client's message handler. + */ + public void accept() + { + try + { + BufferedReader fromConsole = + new BufferedReader(new InputStreamReader(System.in)); + String message; + + while (true) + { + message = fromConsole.readLine(); + + + //This is where I decide what to do with the code. + + if ( message.charAt(0) == '#' ){ + client.clientCommand(message);} + + else {client.handleMessageFromClientUI(message);} + + } + } + catch (Exception ex) + { + System.out.println + ("Unexpected error while reading from console!"); + } + } + + /** + * This method overrides the method in the ChatIF interface. It + * displays a message onto the screen. + * + * @param message The string to be displayed. + */ + public void display(String message) + { + System.out.println("> " + message); + } + + /** + * Hook method called after the connection has been closed. The default + * implementation does nothing. The method may be overriden by subclasses to + * perform special processing such as cleaning up and terminating, or + * attempting to reconnect. + */ + protected void connectionClosed() { + System.out.println("The server has shutdown."); + } + + /** + * Hook method called each time an exception is thrown by the client's + * thread that is waiting for messages from the server. The method may be + * overridden by subclasses. + * + * @param exception + * the exception raised. + */ + protected void connectionException(Exception exception) { + connectionClosed(); + } + + + //Class methods *************************************************** + + /** + * This method is responsible for the creation of the Client UI. + * + * @param args[0] The host to connect to. + */ + public static void main(String[] args) + { + String host = ""; + int port = 0; //The port number + + try + { + host = args[0]; + port = Integer.parseInt(args[1]); + } + catch(ArrayIndexOutOfBoundsException e) + { + port = DEFAULT_PORT; + + try + { + host = args[0]; + } + catch(ArrayIndexOutOfBoundsException f) + { + host = "localhost"; + } + } + + if (args.length == 0) + { + System.out.println("Host Name: " + host + " (default)"); + } + else { System.out.println("Host Name: " + host);} + + if (port == DEFAULT_PORT) + { + System.out.println("Port Number: " + port + " (default)"); + } + else {System.out.println("Port Number: " + port);} + + ClientConsole chat= new ClientConsole(host, port); + chat.accept(); //Wait for console data + } +} +//End of ConsoleChat class diff --git a/EchoServer.java b/EchoServer.java new file mode 100644 index 0000000..94fc4ab --- /dev/null +++ b/EchoServer.java @@ -0,0 +1,239 @@ +// This file contains material supporting section 3.7 of the textbook: +// "Object Oriented Software Engineering" and is issued under the open-source +// license found at www.lloseng.com + +import java.io.*; +import ocsf.server.*; +import java.util.Arrays; +import java.util.List; + +/** + * This class overrides some of the methods in the abstract + * superclass in order to give more functionality to the server. + * + * @author Dr Timothy C. Lethbridge + * @author Dr Robert Laganière + * @author François Bélanger + * @author Paul Holden + * @version July 2000 + */ +public class EchoServer extends AbstractServer +{ + //Class variables ************************************************* + + /** + * The default port to listen on. + */ + final public static int DEFAULT_PORT = 5555; + + //Constructors **************************************************** + + /** + * Constructs an instance of the echo server. + * + * @param port The port number to connect on. + */ + public EchoServer(int port) + { + super(port); + } + + + //Instance methods ************************************************ + + /** + * This method handles all data coming from the ServerConsole + * + * @param message The message from the ServerConsole. + */ + public void handleMessageFromServerConsole(String message) + { + this.sendToAllClients(message); + System.out.println(message); + } + + /** + * This method handles any messages received from the client. + * + * @param msg The message received from the client. + * @param client The connection from which the message originated. + */ + public void handleMessageFromClient + (Object msg, ConnectionToClient client) + { + System.out.println("Message received: " + msg + " from " + client); + this.sendToAllClients(msg); + } + + /** + * This method overrides the one in the superclass. Called + * when the server starts listening for connections. + */ + protected void serverStarted() + { + System.out.println + ("Server listening for connections on port " + getPort()); + } + + /** + * This method overrides the one in the superclass. Called + * when the server stops listening for connections. + */ + protected void serverStopped() + { + System.out.println + ("Server has stopped listening for connections."); + } + + /** + * Hook method called each time a new client connection is + * accepted. The default implementation does nothing. + * @param client the connection connected to the client. + */ + protected void clientConnected(ConnectionToClient client) + { + System.out.println("SYSTEM ::: A new client connected ::: " + client); + } + + /** + * Hook method called each time a client disconnects. + * The default implementation does nothing. The method + * may be overridden by subclasses but should remains synchronized. + * + * @param client the connection with the client. + */ + synchronized protected void clientDisconnected(ConnectionToClient client) + { + System.out.println("SYSTEM ::: A client disconnected"); + } + + /** + * Hook method called each time an exception is thrown in a + * ConnectionToClient thread. + * The method may be overridden by subclasses but should remains + * synchronized. + * + * @param client the client that raised the exception. + * @param Throwable the exception thrown. + */ + synchronized protected void clientException( + ConnectionToClient client, Throwable exception) + { + clientDisconnected(client); + } + + /** + * This method contains all the server commands. + * Every commands begin with '#'. + * + * @param command word that needs to be actioned. + */ + public void serverCommand(String message){ + + //Make the message received into an array (necessary for setHost/setPort) + String[] messageArray = message.split(" "); + String[] commandArray = new String[]{"#quit","#start","#stop","#close","#getport","#setport"}; + + //If the command isn't in the 'known' list, give error message and command list. + if (!Arrays.asList(commandArray).contains(messageArray[2])){ + System.out.println("The command line you entered is 'INVALID', here is a list of all current commands."); + System.out.println("#quit // #start // #stop // #close // #getport // #setport"); + } + + switch(messageArray[2]) { + case "#quit": //not done + try + { + close(); + } + catch(IOException e) {System.out.println("exception");} + System.exit(0); + break; + + case "#start"://finished + //what happens in #start + if (!isListening()) + { + try + { + listen(); + } + catch (IOException e) {} + } break; + + case "#stop"://completed + this.stopListening(); + break; + + case "#close"://completed + System.out.println("SYSTEM ::: Server closed - Disconnect all current Client and Stop Listening for new Client"); + try + { + this.stopListening(); + this.close(); + } + catch(IOException e) {} + break; + + case "#getport"://completed + + try + { + System.out.println("SYSTEM ::: The current Port is: " + getPort()); + } + + catch (Exception a) + { + System.out.println("SYSTEM ::: There was an error in the getPort attempt"); + } + break; + + case "#setport": //completed + + try { + int newPort = Integer.parseInt(messageArray[3]); + + setPort(newPort); + System.out.println("SYSTEM ::: The new Port has been set to: " + getPort()); + } catch (Exception ex2) + { + System.out.println("SYSTEM ::: Array Out-of-Bound or your Port was not a valid Integer between 1 and 65535."); + } break; + } + } + + //Class methods *************************************************** + + /** + * This method is responsible for the creation of + * the server instance (there is no UI in this phase). + * + * @param args[0] The port number to listen on. Defaults to 5555 + * if no argument is entered. + */ + public static void main(int port) + { + //int port = 0; //Port to listen on + + // try + // { + // port = Integer.parseInt(args[0]); //Get port from command line + // } + // catch(Throwable t) + // { + // port = DEFAULT_PORT; //Set port to 5555 + // } + + //EchoServer sv = new EchoServer(port); + + // try + // { + // sv.listen(); //Start listening for connections + // } + // catch (Exception ex) + // { + // System.out.println("ERROR - Could not listen for clients!"); + // } + } +} +//End of EchoServer class diff --git a/ServerConsole.java b/ServerConsole.java new file mode 100644 index 0000000..3927d41 --- /dev/null +++ b/ServerConsole.java @@ -0,0 +1,171 @@ +// This file contains material supporting section 3.7 of the textbook: +// "Object Oriented Software Engineering" and is issued under the open-source +// license found at www.lloseng.com + +import java.io.*; +import client.*; +import common.*; +import java.util.Arrays; +import java.util.List; + +/** + * This class constructs the UI for a chat client. It implements the + * chat interface in order to activate the display() method. + * Warning: Some of the code here is cloned in ServerConsole + * + * @author François Bélanger + * @author Dr Timothy C. Lethbridge + * @author Dr Robert Laganière + * @version July 2000 + */ +public class ServerConsole implements ChatIF +{ + //Class variables ************************************************* + + /** + * The default port to connect on. + */ + final public static int DEFAULT_PORT = 5555; + + //Instance variables ********************************************** + + /** + * The instance of the client that created this ConsoleChat. + */ + ChatClient client; + + /** + * The instance of EchoServer for this Console. + */ + static EchoServer echo; + + //Constructors **************************************************** + + /** + * Constructs an instance of the ClientConsole UI. + * + * @param host The host to connect to. + * @param port The port to connect on. + */ + public ServerConsole(int port) + { + try + { + echo = new EchoServer(port); + } + catch(Exception e) + { + System.out.println("SYSTEM ::: Could not setup server"); + System.exit(1); + } + } + + + //Instance methods ************************************************ + + /** + * This method waits for input from the console. Once it is + * received, it sends it to the client's message handler. + */ + public void accept() + { + try + { + BufferedReader fromConsole = + new BufferedReader(new InputStreamReader(System.in)); + String message; + + while (true) + { + message = fromConsole.readLine(); + message = "SERVER MSG> " + message; + + + //This is where I decide what to do with the code. + + if ( message.charAt(12) == '#' ){ + echo.serverCommand(message);} + + else {echo.handleMessageFromServerConsole(message);} + + } + } + catch (Exception ex) + { + System.out.println + ("Unexpected error while reading from console!"); + } + } + + /** + * This method overrides the method in the ChatIF interface. It + * displays a message onto the screen. + * + * @param message The string to be displayed. + */ + public void display(String message) + { + System.out.println("> " + message); + } + + /** + * Hook method called after the connection has been closed. The default + * implementation does nothing. The method may be overriden by subclasses to + * perform special processing such as cleaning up and terminating, or + * attempting to reconnect. + */ + protected void connectionClosed() { + System.out.println("The server has shutdown."); + } + + /** + * Hook method called each time an exception is thrown by the client's + * thread that is waiting for messages from the server. The method may be + * overridden by subclasses. + * + * @param exception + * the exception raised. + */ + protected void connectionException(Exception exception) { + connectionClosed(); + } + + + //Class methods *************************************************** + + /** + * This method is responsible for the creation of the Client UI. + * + * @param args[0] The host to connect to. + */ + public static void main(String[] args) + { + int port = 0; //The port number + + try + { + port = Integer.parseInt(args[0]); + } + catch(ArrayIndexOutOfBoundsException e) + { + port = DEFAULT_PORT; + } + + + + + ServerConsole chat= new ServerConsole(port); + + try + { + echo.listen(); //Start listening for connections + } + catch (Exception ex) + { + System.out.println("ERROR - Could not listen for clients!"); + } + + chat.accept(); //Wait for console data + } +} +//End of ConsoleChat class