From aef4a5421908df2511280a9817567030f04ab38d Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Fri, 22 May 2020 19:19:25 -0400
Subject: [PATCH 01/13] Created Initial Files
---
.../ocsf/client/AbstractClient.java | 333 +++++++++++++
.../ocsf/client/AdaptableClient.java | 82 ++++
.../ocsf/client/ObservableClient.java | 181 +++++++
code/simplechat1/ocsf/index.html | 22 +
.../ocsf/server/AbstractServer.java | 459 ++++++++++++++++++
.../ocsf/server/AdaptableServer.java | 129 +++++
.../ocsf/server/ConnectionToClient.java | 270 +++++++++++
.../server/ObservableOriginatorServer.java | 165 +++++++
.../ocsf/server/ObservableServer.java | 309 ++++++++++++
.../ocsf/server/OriginatorMessage.java | 61 +++
10 files changed, 2011 insertions(+)
create mode 100644 code/simplechat1/ocsf/client/AbstractClient.java
create mode 100644 code/simplechat1/ocsf/client/AdaptableClient.java
create mode 100644 code/simplechat1/ocsf/client/ObservableClient.java
create mode 100644 code/simplechat1/ocsf/index.html
create mode 100644 code/simplechat1/ocsf/server/AbstractServer.java
create mode 100644 code/simplechat1/ocsf/server/AdaptableServer.java
create mode 100644 code/simplechat1/ocsf/server/ConnectionToClient.java
create mode 100644 code/simplechat1/ocsf/server/ObservableOriginatorServer.java
create mode 100644 code/simplechat1/ocsf/server/ObservableServer.java
create mode 100644 code/simplechat1/ocsf/server/OriginatorMessage.java
diff --git a/code/simplechat1/ocsf/client/AbstractClient.java b/code/simplechat1/ocsf/client/AbstractClient.java
new file mode 100644
index 0000000..e905636
--- /dev/null
+++ b/code/simplechat1/ocsf/client/AbstractClient.java
@@ -0,0 +1,333 @@
+// 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 ocsf.client;
+
+import java.io.*;
+import java.net.*;
+
+/**
+ * The AbstractClient contains all the methods necessary to set
+ * up the client side of a client-server architecture. When a client is thus
+ * connected to the server, the two programs can then exchange
+ * Object instances.
+ *
+ * Method handleMessageFromServer must be defined by a concrete
+ * subclass. Several other hook methods may also be overriden.
+ *
+ * Several public service methods are provided to application that use this + * framework. + *
+ * Project Name: OCSF (Object Client-Server Framework) + *
+ *
+ * @author Dr. Robert Laganière
+ * @author Dr. Timothy C. Lethbridge
+ * @author François Bél;langer
+ * @author Paul Holden
+ * @version February 2001 (2.12)
+ */
+public abstract class AbstractClient implements Runnable {
+
+ // INSTANCE VARIABLES ***********************************************
+
+ /**
+ * Sockets are used in the operating system as channels of communication
+ * between two processes.
+ *
+ * @see java.net.Socket
+ */
+ private Socket clientSocket;
+
+ /**
+ * The stream to handle data going to the server.
+ */
+ private ObjectOutputStream output;
+
+ /**
+ * The stream to handle data from the server.
+ */
+ private ObjectInputStream input;
+
+ /**
+ * The thread created to read data from the server.
+ */
+ private Thread clientReader;
+
+ /**
+ * Indicates if the thread is ready to stop. Needed so that the loop in the
+ * run method knows when to stop waiting for incoming messages.
+ */
+ private boolean readyToStop = false;
+
+ /**
+ * The server's host name.
+ */
+ private String host;
+
+ /**
+ * The port number.
+ */
+ private int port;
+
+ // CONSTRUCTORS *****************************************************
+
+ /**
+ * Constructs the client.
+ *
+ * @param host
+ * the server's host name.
+ * @param port
+ * the port number.
+ */
+ public AbstractClient(String host, int port) {
+ // Initialize variables
+ this.host = host;
+ this.port = port;
+ }
+
+ // INSTANCE METHODS *************************************************
+
+ /**
+ * Opens the connection with the server. If the connection is already
+ * opened, this call has no effect.
+ *
+ * @exception IOException
+ * if an I/O error occurs when opening.
+ */
+ final public void openConnection() throws IOException {
+ // Do not do anything if the connection is already open
+ if (isConnected())
+ return;
+
+ // Create the sockets and the data streams
+ try {
+ clientSocket = new Socket(host, port);
+ output = new ObjectOutputStream(clientSocket.getOutputStream());
+ input = new ObjectInputStream(clientSocket.getInputStream());
+ } catch (IOException ex)
+ // All three of the above must be closed when there is a failure
+ // to create any of them
+ {
+ try {
+ closeAll();
+ } catch (Exception exc) {
+ }
+
+ throw ex; // Rethrow the exception.
+ }
+
+ clientReader = new Thread(this); // Create the data reader thread
+ readyToStop = false;
+ clientReader.start(); // Start the thread
+ }
+
+ /**
+ * Sends an object to the server. This is the only way that methods should
+ * communicate with the server.
+ *
+ * @param msg
+ * The message to be sent.
+ * @exception IOException
+ * if an I/O error occurs when sending
+ */
+ final public void sendToServer(Object msg) throws IOException {
+ if (clientSocket == null || output == null)
+ throw new SocketException("socket does not exist");
+
+ output.writeObject(msg);
+ }
+
+ /**
+ * Reset the object output stream so we can use the same
+ * buffer repeatedly. This would not normally be used, but is necessary
+ * in some circumstances when Java refuses to send data that it thinks has been sent.
+ */
+ final public void forceResetAfterSend() throws IOException {
+ output.reset();
+ }
+
+ /**
+ * Closes the connection to the server.
+ *
+ * @exception IOException
+ * if an I/O error occurs when closing.
+ */
+ final public void closeConnection() throws IOException {
+ // Prevent the thread from looping any more
+ readyToStop = true;
+
+ try {
+ closeAll();
+ } finally {
+ // Call the hook method
+ connectionClosed();
+ }
+ }
+
+ // ACCESSING METHODS ------------------------------------------------
+
+ /**
+ * @return true if the client is connnected.
+ */
+ final public boolean isConnected() {
+ return clientReader != null && clientReader.isAlive();
+ }
+
+ /**
+ * @return the port number.
+ */
+ final public int getPort() {
+ return port;
+ }
+
+ /**
+ * Sets the server port number for the next connection. The change in port
+ * only takes effect at the time of the next call to openConnection().
+ *
+ * @param port
+ * the port number.
+ */
+ final public void setPort(int port) {
+ this.port = port;
+ }
+
+ /**
+ * @return the host name.
+ */
+ final public String getHost() {
+ return host;
+ }
+
+ /**
+ * Sets the server host for the next connection. The change in host only
+ * takes effect at the time of the next call to openConnection().
+ *
+ * @param host
+ * the host name.
+ */
+ final public void setHost(String host) {
+ this.host = host;
+ }
+
+ /**
+ * returns the client's description.
+ *
+ * @return the client's Inet address.
+ */
+ final public InetAddress getInetAddress() {
+ return clientSocket.getInetAddress();
+ }
+
+ // RUN METHOD -------------------------------------------------------
+
+ /**
+ * Waits for messages from the server. When each arrives, a call is made to
+ * handleMessageFromServer(). Not to be explicitly called.
+ */
+ final public void run() {
+ connectionEstablished();
+
+ // The message from the server
+ Object msg;
+
+ // Loop waiting for data
+
+ try {
+ while (!readyToStop) {
+ // Get data from Server and send it to the handler
+ // The thread waits indefinitely at the following
+ // statement until something is received from the server
+ msg = input.readObject();
+
+ // Concrete subclasses do what they want with the
+ // msg by implementing the following method
+ handleMessageFromServer(msg);
+ }
+ } catch (Exception exception) {
+ if (!readyToStop) {
+ try {
+ closeAll();
+ } catch (Exception ex) {
+ }
+
+ connectionException(exception);
+ }
+ } finally {
+ clientReader = null;
+ }
+ }
+
+ // METHODS DESIGNED TO BE OVERRIDDEN BY CONCRETE SUBCLASSES ---------
+
+ /**
+ * 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() {
+ }
+
+ /**
+ * 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) {
+ }
+
+ /**
+ * Hook method called after a connection has been established. The default
+ * implementation does nothing. It may be overridden by subclasses to do
+ * anything they wish.
+ */
+ protected void connectionEstablished() {
+ }
+
+ /**
+ * Handles a message sent from the server to this client. This MUST be
+ * implemented by subclasses, who should respond to messages.
+ *
+ * @param msg
+ * the message sent.
+ */
+ protected abstract void handleMessageFromServer(Object msg);
+
+ // METHODS TO BE USED FROM WITHIN THE FRAMEWORK ONLY ----------------
+
+ /**
+ * Closes all aspects of the connection to the server.
+ *
+ * @exception IOException
+ * if an I/O error occurs when closing.
+ */
+ private void closeAll() throws IOException {
+ try {
+ // Close the socket
+ if (clientSocket != null)
+ clientSocket.close();
+
+ // Close the output stream
+ if (output != null)
+ output.close();
+
+ // Close the input stream
+ if (input != null)
+ input.close();
+ } finally {
+ // Set the streams and the sockets to NULL no matter what
+ // Doing so allows, but does not require, any finalizers
+ // of these objects to reclaim system resources if and
+ // when they are garbage collected.
+ output = null;
+ input = null;
+ clientSocket = null;
+ }
+ }
+}
+// end of AbstractClient class
\ No newline at end of file
diff --git a/code/simplechat1/ocsf/client/AdaptableClient.java b/code/simplechat1/ocsf/client/AdaptableClient.java
new file mode 100644
index 0000000..143592e
--- /dev/null
+++ b/code/simplechat1/ocsf/client/AdaptableClient.java
@@ -0,0 +1,82 @@
+// This file contains material supporting section 6.13 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.client;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+* The AdaptableClient is a class
+* that extends the AbstractClient in place of
+* the ObservableClient .
+* +* Project Name: OCSF (Object Client-Server Framework)
+*
+* @author Dr. Robert Laganière
+* @version Febuary 2001
+*/
+class AdaptableClient extends AbstractClient
+{
+ //Instance variables **********************************************
+
+ /**
+ * The proxy used to simulate multiple class inheritance.
+ */
+ private ObservableClient client;
+
+// CONSTRUCTORS *****************************************************
+
+ /**
+ * Constructs the client adapter.
+ *
+ * @param host the server's host name.
+ * @param port the port number.
+ */
+ public AdaptableClient(String host, int port, ObservableClient client)
+ {
+ super(host, port);
+ this.client = client;
+ }
+
+// OVERRIDDEN METHODS *************************************************
+
+ /**
+ * Hook method called after the connection has been closed.
+ */
+ final protected void connectionClosed()
+ {
+ client.connectionClosed();
+ }
+
+ /**
+ * Hook method called after an exception
+ * is raised by the client listening thread.
+ *
+ * @param exception the exception raised.
+ */
+ final protected void connectionException(Exception exception)
+ {
+ client.connectionException(exception);
+ }
+
+ /**
+ * Hook method called after a connection has been established.
+ */
+ final protected void connectionEstablished()
+ {
+ client.connectionEstablished();
+ }
+
+ /**
+ * Handles a message sent from the server to this client.
+ *
+ * @param msg the message sent.
+ */
+ final protected void handleMessageFromServer(Object msg)
+ {
+ client.handleMessageFromServer(msg);
+ }
+}
diff --git a/code/simplechat1/ocsf/client/ObservableClient.java b/code/simplechat1/ocsf/client/ObservableClient.java
new file mode 100644
index 0000000..a816488
--- /dev/null
+++ b/code/simplechat1/ocsf/client/ObservableClient.java
@@ -0,0 +1,181 @@
+// This file contains material supporting section 6.13 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.client;
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * This class acts as a subclass of AbstractClient
+ * and is also an Observable class.
+ * Each time a new message is received, observers are notified.
+ *
+ * @author Dr Robert Laganière
+ * @author Dr Timothy C. Lethbridge
+ * @author François Bélange
+ * @version Febuary 2001
+ */
+public class ObservableClient extends Observable
+{
+ // Class variables ***************************************************
+
+ /**
+ * Indicates occurence of a connection exception.
+ */
+ public static final String CONNECTION_EXCEPTION = "#OC:Connection error.";
+
+ /**
+ * Indicates a close of the connection to server.
+ */
+ public static final String CONNECTION_CLOSED = "#OC:Connection closed.";
+
+ /**
+ * Indicates establishment of a connection to server.
+ */
+ public static final String CONNECTION_ESTABLISHED = "#OC:Connection established.";
+
+ //Instance variables **********************************************
+
+ /**
+ * The service instance used to simulate multiple class inheritance.
+ */
+ private AdaptableClient service;
+
+ //Constructor *****************************************************
+
+ public ObservableClient(String host, int port)
+ {
+ service = new AdaptableClient(host, port, this);
+ }
+
+ //Instance methods ************************************************
+
+ /**
+ * Opens the connections with the server.
+ */
+ final public void openConnection() throws IOException
+ {
+ service.openConnection();
+ }
+
+ /**
+ * Closes the connection to the server.
+ */
+ final public void closeConnection() throws IOException
+ {
+ service.closeConnection();
+ }
+
+ /**
+ * Sends an object to the server. This is the only way that
+ * methods should communicate with the server.
+ *
+ * @param msg The message to be sent.
+ */
+ final public void sendToServer(Object msg) throws IOException
+ {
+ service.sendToServer(msg);
+ }
+
+// ACCESSING METHODS ------------------------------------------------
+
+ /**
+ * @used to find out if the client is connnected.
+ */
+ final public boolean isConnected()
+ {
+ return service.isConnected();
+ }
+
+ /**
+ * @return the port number.
+ */
+ final public int getPort()
+ {
+ return service.getPort();
+ }
+
+ /**
+ * Sets the server port number for the next connection.
+ * Only has effect if the client is not currently connected.
+ *
+ * @param port the port number.
+ */
+ final public void setPort(int port)
+ {
+ service.setPort(port);
+ }
+
+ /**
+ * @return the host name.
+ */
+ final public String getHost()
+ {
+ return service.getHost();
+ }
+
+ /**
+ * Sets the server host for the next connection.
+ * Only has effect if the client is not currently connected.
+ *
+ * @param host the host name.
+ */
+ final public void setHost(String host)
+ {
+ service.setHost(host);
+ }
+
+ /**
+ * @return the client's Inet address.
+ */
+ final public InetAddress getInetAddress()
+ {
+ return service.getInetAddress();
+ }
+
+
+ /**
+ * This method is used to handle messages from the server. This method
+ * can be overriden but should always call notifyObservers().
+ *
+ * @param message The message received from the client.
+ */
+ protected void handleMessageFromServer(Object message)
+ {
+ setChanged();
+ notifyObservers(message);
+ }
+
+ /**
+ * Hook method called after the connection has been closed.
+ */
+ protected void connectionClosed()
+ {
+ setChanged();
+ notifyObservers(CONNECTION_CLOSED);
+ }
+
+ /**
+ * Hook method called each time an exception
+ * is raised by the client listening thread.
+ *
+ * @param exception the exception raised.
+ */
+ protected void connectionException(Exception exception)
+ {
+ setChanged();
+ notifyObservers(CONNECTION_EXCEPTION);
+ }
+
+ /**
+ * Hook method called after a connection has been established.
+ */
+ protected void connectionEstablished()
+ {
+ setChanged();
+ notifyObservers(CONNECTION_ESTABLISHED);
+ }
+}
diff --git a/code/simplechat1/ocsf/index.html b/code/simplechat1/ocsf/index.html
new file mode 100644
index 0000000..13025a0
--- /dev/null
+++ b/code/simplechat1/ocsf/index.html
@@ -0,0 +1,22 @@
+
+
To install OCSF, simply compile all the .java files in the client and +server directories.
+ +OCSF is a Framework, so this directory contains no main program. To +learn how it works, consult the book +"Object-Oriented Software Engineering: Practical Software Development +using UML and Java" by Lethbridge and Laganière.
+ +To use OCSF, import the "ocsf.client" or "ocsf.server" package in your +application code. Make sure that the ocsf directory is in your classpath +when you compile your application.
+ + + + + diff --git a/code/simplechat1/ocsf/server/AbstractServer.java b/code/simplechat1/ocsf/server/AbstractServer.java new file mode 100644 index 0000000..0134b22 --- /dev/null +++ b/code/simplechat1/ocsf/server/AbstractServer.java @@ -0,0 +1,459 @@ +// This file contains material supporting section 3.8 of the textbook: +// "Object Oriented Software Engineering" and is issued under the open-source +// license found at www.lloseng.com + +package ocsf.server; + +import java.net.*; +import java.util.*; +import java.io.*; + +/** +* The AbstractServer class maintains a thread that waits
+* for connection attempts from clients. When a connection attempt occurs
+* it creates a new ConnectionToClient instance which
+* runs as a thread. When a client is thus connected to the
+* server, the two programs can then exchange Object
+* instances.
+*
+* Method handleMessageFromClient must be defined by
+* a concrete subclass. Several other hook methods may also be
+* overriden.
+* +* Several public service methods are provided to applications that use +* this framework, and several hook methods are also available
+* +* Project Name: OCSF (Object Client-Server Framework)
+*
+* @author Dr Robert Laganière
+* @author Dr Timothy C. Lethbridge
+* @author François Bélanger
+* @author Paul Holden
+* @version February 2001 (2.12)
+* @see ocsf.server.ConnectionToClient
+*/
+public abstract class AbstractServer implements Runnable
+{
+ // INSTANCE VARIABLES *********************************************
+
+ /**
+ * The server socket: listens for clients who want to connect.
+ */
+ private ServerSocket serverSocket = null;
+
+ /**
+ * The connection listener thread.
+ */
+ private Thread connectionListener;
+
+ /**
+ * The port number
+ */
+ private int port;
+
+ /**
+ * The server timeout while for accepting connections.
+ * After timing out, the server will check to see if a command to
+ * stop the server has been issued; it not it will resume accepting
+ * connections.
+ * Set to half a second by default.
+ */
+ private int timeout = 500;
+
+ /**
+ * The maximum queue length; i.e. the maximum number of clients that
+ * can be waiting to connect.
+ * Set to 10 by default.
+ */
+ private int backlog = 10;
+
+ /**
+ * The thread group associated with client threads. Each member of the
+ * thread group is a
+*
+* Project Name: OCSF (Object Client-Server Framework)
+*
+* @author Dr. Robert Laganière
+* @version Febuary 2001
+*/
+class AdaptableServer extends AbstractServer
+{
+ //Instance variables **********************************************
+
+ /**
+ * The adapter used to simulate multiple class inheritance.
+ */
+ private ObservableServer server;
+
+// CONSTRUCTORS *****************************************************
+
+ /**
+ * Constructs the server adapter.
+ *
+ * @param host the server's host name.
+ * @param port the port number.
+ */
+ public AdaptableServer(int port, ObservableServer server)
+ {
+ super(port);
+ this.server = server;
+ }
+
+// OVERRIDDEN METHODS ---------
+
+ /**
+ * Hook method called each time a new client connection is
+ * accepted.
+ *
+ * @param client the connection connected to the client.
+ */
+ final protected void clientConnected(ConnectionToClient client)
+ {
+ server.clientConnected(client);
+ }
+
+ /**
+ * Hook method called each time a client disconnects.
+ *
+ * @param client the connection with the client.
+ */
+ final protected void clientDisconnected(ConnectionToClient client)
+ {
+ server.clientDisconnected(client);
+ }
+
+ /**
+ * Hook method called each time an exception
+ * is raised in a client thread.
+ *
+ * @param client the client that raised the exception.
+ * @param exception the exception raised.
+ */
+ final protected void clientException(ConnectionToClient client,
+ Throwable exception)
+ {
+ server.clientException(client, exception);
+ }
+
+ /**
+ * Hook method called when the server stops accepting
+ * connections because an exception has been raised.
+ *
+ * @param exception the exception raised.
+ */
+ final protected void listeningException(Throwable exception)
+ {
+ server.listeningException(exception);
+ }
+
+ /**
+ * Hook method called when the server stops accepting
+ * connections.
+ */
+ final protected void serverStopped()
+ {
+ server.serverStopped();
+ }
+
+ /**
+ * Hook method called when the server starts listening for
+ * connections.
+ */
+ final protected void serverStarted()
+ {
+ server.serverStarted();
+ }
+
+ /**
+ * Hook method called when the server is closed.
+ */
+ final protected void serverClosed()
+ {
+ server.serverClosed();
+ }
+
+ /**
+ * Handles a command sent from the client to the server.
+ *
+ * @param msg the message sent.
+ * @param client the connection connected to the client that
+ * sent the message.
+ */
+ final protected void handleMessageFromClient(Object msg,
+ ConnectionToClient client)
+ {
+ server.handleMessageFromClient(msg, client);
+ }
+}
diff --git a/code/simplechat1/ocsf/server/ConnectionToClient.java b/code/simplechat1/ocsf/server/ConnectionToClient.java
new file mode 100644
index 0000000..4394b37
--- /dev/null
+++ b/code/simplechat1/ocsf/server/ConnectionToClient.java
@@ -0,0 +1,270 @@
+// This file contains material supporting section 3.8 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+import java.io.*;
+import java.net.*;
+import java.util.HashMap;
+
+/**
+ * An instance of this class is created by the server when a client connects. It
+ * accepts messages coming from the client and is responsible for sending data
+ * to the client since the socket is private to this class. The AbstractServer
+ * contains a set of instances of this class and is responsible for adding and
+ * deleting them.
+ *
+ * Project Name: OCSF (Object Client-Server Framework)
+ *
+ *
+ * @author Dr Robert Laganière
+ * @author Dr Timothy C. Lethbridge
+ * @author François Bélanger
+ * @author Paul Holden
+ * @version February 2001 (2.12)
+ */
+public class ConnectionToClient extends Thread {
+ // INSTANCE VARIABLES ***********************************************
+
+ /**
+ * A reference to the Server that created this instance.
+ */
+ private AbstractServer server;
+
+ /**
+ * Sockets are used in the operating system as channels of communication
+ * between two processes.
+ *
+ * @see java.net.Socket
+ */
+ private Socket clientSocket;
+
+ /**
+ * Stream used to read from the client.
+ */
+ private ObjectInputStream input;
+
+ /**
+ * Stream used to write to the client.
+ */
+ private ObjectOutputStream output;
+
+ /**
+ * Indicates if the thread is ready to stop. Set to true when closing of the
+ * connection is initiated.
+ */
+ private boolean readyToStop;
+
+ /**
+ * Map to save information about the client such as its login ID. The
+ * initial size of the map is small since it is not expected that concrete
+ * servers will want to store many different types of information about each
+ * client. Used by the setInfo and getInfo methods.
+ */
+ private HashMap savedInfo = new HashMap(10);
+
+ // CONSTRUCTORS *****************************************************
+
+ /**
+ * Constructs a new connection to a client.
+ *
+ * @param group
+ * the thread groupSystem.out.println("Client at "+ client +
+ * "connected"); that contains the connections.
+ * @param clientSocket
+ * contains the client's socket.
+ * @param server
+ * a reference to the server that created this instance
+ * @exception IOException
+ * if an I/O error occur when creating the connection.
+ */
+ ConnectionToClient(ThreadGroup group, Socket clientSocket, AbstractServer server) throws IOException {
+ super(group, (Runnable) null);
+ // Initialize variables
+ this.clientSocket = clientSocket;
+ this.server = server;
+
+ clientSocket.setSoTimeout(0); // make sure timeout is infinite
+
+ // Initialize the objects streams
+ try {
+ input = new ObjectInputStream(clientSocket.getInputStream());
+ output = new ObjectOutputStream(clientSocket.getOutputStream());
+ } catch (IOException ex) {
+ try {
+ closeAll();
+ } catch (Exception exc) {
+ }
+
+ throw ex; // Rethrow the exception.
+ }
+
+ readyToStop = false;
+ start(); // Start the thread waits for data from the socket
+ }
+
+ // INSTANCE METHODS *************************************************
+
+ /**
+ * Sends an object to the client.
+ *
+ * @param msg
+ * the message to be sent.
+ * @exception IOException
+ * if an I/O error occur when sending the message.
+ */
+ final public void sendToClient(Object msg) throws IOException {
+ if (clientSocket == null || output == null)
+ throw new SocketException("socket does not exist");
+
+ output.writeObject(msg);
+ }
+
+ /**
+ * Reset the output stream so we can use the same
+ * buffer repeatedly. This would not normally be used, but is necessary
+ * in some circumstances when Java refuses to send data that it thinks has been sent.
+ */
+ final public void forceResetAfterSend() throws IOException {
+ output.reset();
+ }
+
+ /**
+ * Closes the client. If the connection is already closed, this call has no
+ * effect.
+ *
+ * @exception IOException
+ * if an error occurs when closing the socket.
+ */
+ final public void close() throws IOException {
+ readyToStop = true; // Set the flag that tells the thread to stop
+
+ try {
+ closeAll();
+ } finally {
+ server.clientDisconnected(this);
+ }
+ }
+
+ // ACCESSING METHODS ------------------------------------------------
+
+ /**
+ * Returns the address of the client.
+ *
+ * @return the client's Internet address.
+ */
+ final public InetAddress getInetAddress() {
+ return clientSocket == null ? null : clientSocket.getInetAddress();
+ }
+
+ /**
+ * Returns a string representation of the client.
+ *
+ * @return the client's description.
+ */
+ public String toString() {
+ return clientSocket == null ? null : clientSocket.getInetAddress().getHostName() + " ("
+ + clientSocket.getInetAddress().getHostAddress() + ")";
+ }
+
+ /**
+ * Saves arbitrary information about this client. Designed to be used by
+ * concrete subclasses of AbstractServer. Based on a hash map.
+ *
+ * @param infoType
+ * identifies the type of information
+ * @param info
+ * the information itself.
+ */
+ public void setInfo(String infoType, Object info) {
+ savedInfo.put(infoType, info);
+ }
+
+ /**
+ * Returns information about the client saved using setInfo. Based on a hash
+ * map.
+ *
+ * @param infoType
+ * identifies the type of information
+ */
+ public Object getInfo(String infoType) {
+ return savedInfo.get(infoType);
+ }
+
+ // RUN METHOD -------------------------------------------------------
+
+ /**
+ * Constantly reads the client's input stream. Sends all objects that are
+ * read to the server. Not to be called.
+ */
+ final public void run() {
+ server.clientConnected(this);
+
+ // This loop reads the input stream and responds to messages
+ // from clients
+ try {
+ // The message from the client
+ Object msg;
+
+ while (!readyToStop) {
+ // This block waits until it reads a message from the client
+ // and then sends it for handling by the server
+ msg = input.readObject();
+ server.receiveMessageFromClient(msg, this);
+ }
+ } catch (Exception exception) {
+ if (!readyToStop) {
+ try {
+ closeAll();
+ } catch (Exception ex) {
+ }
+
+ server.clientException(this, exception);
+ }
+ }
+ }
+
+ // METHODS TO BE USED FROM WITHIN THE FRAMEWORK ONLY ----------------
+
+ /**
+ * Closes all connection to the server.
+ *
+ * @exception IOException
+ * if an I/O error occur when closing the connection.
+ */
+ private void closeAll() throws IOException {
+ try {
+ // Close the socket
+ if (clientSocket != null)
+ clientSocket.close();
+
+ // Close the output stream
+ if (output != null)
+ output.close();
+
+ // Close the input stream
+ if (input != null)
+ input.close();
+ } finally {
+ // Set the streams and the sockets to NULL no matter what
+ // Doing so allows, but does not require, any finalizers
+ // of these objects to reclaim system resources if and
+ // when they are garbage collected.
+ output = null;
+ input = null;
+ clientSocket = null;
+ }
+ }
+
+ /**
+ * This method is called by garbage collection.
+ */
+ protected void finalize() {
+ try {
+ closeAll();
+ } catch (IOException e) {
+ }
+ }
+}
+// End of ConnectionToClient class
\ No newline at end of file
diff --git a/code/simplechat1/ocsf/server/ObservableOriginatorServer.java b/code/simplechat1/ocsf/server/ObservableOriginatorServer.java
new file mode 100644
index 0000000..4333694
--- /dev/null
+++ b/code/simplechat1/ocsf/server/ObservableOriginatorServer.java
@@ -0,0 +1,165 @@
+// This file contains material supporting the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+/**
+* The
+*
+* @author Dr Robert Laganière
+* @author Dr Timothy C. Lethbridge
+* @author François Bélanger
+* @author Paul Holden
+* @version February 2001 (2.12)
+* @see ocsf.server.OriginatorMessage
+*/
+public class ObservableOriginatorServer extends ObservableServer
+{
+ // Constructor ******************************************************
+
+ /**
+ * Constructs a new server.
+ *
+ * @param port the port on which to listen.
+ */
+ public ObservableOriginatorServer(int port)
+ {
+ super(port);
+ }
+
+ // Instance methods ************************************************
+
+ /**
+ * This method is used to handle messages coming from the client.
+ * Observers are notfied by receiveing an instance of OriginatorMessage
+ * that contains both the message received and a reference to the
+ * client who sent the message.
+ *
+ * @param message The message received from the client.
+ * @param client The connection to the client.
+ */
+ protected synchronized void handleMessageFromClient
+ (Object message, ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(client, message));
+ }
+
+ /**
+ * Method called each time a new client connection is
+ * accepted. It notifies observers by sending an
+ * To run the SimpleChat, you must first install ocsf, and make sure ocsf is in your classpath (or is a
+subdirectory of simplechat1). Then you must compile the .java files, including those in the
+subdirectories. To run the SimpleChat you must first start a server: "java EchoServer".
+Then you start one or more clients: "java ClientConsole". To run a client
+on a different machine, you enter "java ClientConsole serveraddress", where
+serveraddress is the IP address or host name of the machine where the
+server is runing. Once a client is running, you can type some text; the
+text will be echoed to any other clients that are running. To learn how this code works, consult the book "Object-Oriented Software Engineering:
+Practical Software Development using UML and Java" by Lethbridge and
+Laganière. The book contains many exercises where you will add
+features to SimpleChat. If the server won't start, it might be because the default 'port' number
+of 5555 is already in use. Follow the exercises in the book to improve the
+code and solve this problem.
+ * Method
+ * Several public service methods are provided to application that use this
+ * framework.
+ *
+ * Project Name: OCSF (Object Client-Server Framework)
+ *
+ *
+ * @author Dr. Robert Laganière
+ * @author Dr. Timothy C. Lethbridge
+ * @author François Bél;langer
+ * @author Paul Holden
+ * @version February 2001 (2.12)
+ */
+public abstract class AbstractClient implements Runnable {
+
+ // INSTANCE VARIABLES ***********************************************
+
+ /**
+ * Sockets are used in the operating system as channels of communication
+ * between two processes.
+ *
+ * @see java.net.Socket
+ */
+ private Socket clientSocket;
+
+ /**
+ * The stream to handle data going to the server.
+ */
+ private ObjectOutputStream output;
+
+ /**
+ * The stream to handle data from the server.
+ */
+ private ObjectInputStream input;
+
+ /**
+ * The thread created to read data from the server.
+ */
+ private Thread clientReader;
+
+ /**
+ * Indicates if the thread is ready to stop. Needed so that the loop in the
+ * run method knows when to stop waiting for incoming messages.
+ */
+ private boolean readyToStop = false;
+
+ /**
+ * The server's host name.
+ */
+ private String host;
+
+ /**
+ * The port number.
+ */
+ private int port;
+
+ // CONSTRUCTORS *****************************************************
+
+ /**
+ * Constructs the client.
+ *
+ * @param host
+ * the server's host name.
+ * @param port
+ * the port number.
+ */
+ public AbstractClient(String host, int port) {
+ // Initialize variables
+ this.host = host;
+ this.port = port;
+ }
+
+ // INSTANCE METHODS *************************************************
+
+ /**
+ * Opens the connection with the server. If the connection is already
+ * opened, this call has no effect.
+ *
+ * @exception IOException
+ * if an I/O error occurs when opening.
+ */
+ final public void openConnection() throws IOException {
+ // Do not do anything if the connection is already open
+ if (isConnected())
+ return;
+
+ // Create the sockets and the data streams
+ try {
+ clientSocket = new Socket(host, port);
+ output = new ObjectOutputStream(clientSocket.getOutputStream());
+ input = new ObjectInputStream(clientSocket.getInputStream());
+ } catch (IOException ex)
+ // All three of the above must be closed when there is a failure
+ // to create any of them
+ {
+ try {
+ closeAll();
+ } catch (Exception exc) {
+ }
+
+ throw ex; // Rethrow the exception.
+ }
+
+ clientReader = new Thread(this); // Create the data reader thread
+ readyToStop = false;
+ clientReader.start(); // Start the thread
+ }
+
+ /**
+ * Sends an object to the server. This is the only way that methods should
+ * communicate with the server.
+ *
+ * @param msg
+ * The message to be sent.
+ * @exception IOException
+ * if an I/O error occurs when sending
+ */
+ final public void sendToServer(Object msg) throws IOException {
+ if (clientSocket == null || output == null)
+ throw new SocketException("socket does not exist");
+
+ output.writeObject(msg);
+ }
+
+ /**
+ * Reset the object output stream so we can use the same
+ * buffer repeatedly. This would not normally be used, but is necessary
+ * in some circumstances when Java refuses to send data that it thinks has been sent.
+ */
+ final public void forceResetAfterSend() throws IOException {
+ output.reset();
+ }
+
+ /**
+ * Closes the connection to the server.
+ *
+ * @exception IOException
+ * if an I/O error occurs when closing.
+ */
+ final public void closeConnection() throws IOException {
+ // Prevent the thread from looping any more
+ readyToStop = true;
+
+ try {
+ closeAll();
+ } finally {
+ // Call the hook method
+ connectionClosed();
+ }
+ }
+
+ // ACCESSING METHODS ------------------------------------------------
+
+ /**
+ * @return true if the client is connnected.
+ */
+ final public boolean isConnected() {
+ return clientReader != null && clientReader.isAlive();
+ }
+
+ /**
+ * @return the port number.
+ */
+ final public int getPort() {
+ return port;
+ }
+
+ /**
+ * Sets the server port number for the next connection. The change in port
+ * only takes effect at the time of the next call to openConnection().
+ *
+ * @param port
+ * the port number.
+ */
+ final public void setPort(int port) {
+ this.port = port;
+ }
+
+ /**
+ * @return the host name.
+ */
+ final public String getHost() {
+ return host;
+ }
+
+ /**
+ * Sets the server host for the next connection. The change in host only
+ * takes effect at the time of the next call to openConnection().
+ *
+ * @param host
+ * the host name.
+ */
+ final public void setHost(String host) {
+ this.host = host;
+ }
+
+ /**
+ * returns the client's description.
+ *
+ * @return the client's Inet address.
+ */
+ final public InetAddress getInetAddress() {
+ return clientSocket.getInetAddress();
+ }
+
+ // RUN METHOD -------------------------------------------------------
+
+ /**
+ * Waits for messages from the server. When each arrives, a call is made to
+ *
+*
+* Project Name: OCSF (Object Client-Server Framework)
+*
+* @author Dr. Robert Laganière
+* @version Febuary 2001
+*/
+class AdaptableClient extends AbstractClient
+{
+ //Instance variables **********************************************
+
+ /**
+ * The proxy used to simulate multiple class inheritance.
+ */
+ private ObservableClient client;
+
+// CONSTRUCTORS *****************************************************
+
+ /**
+ * Constructs the client adapter.
+ *
+ * @param host the server's host name.
+ * @param port the port number.
+ */
+ public AdaptableClient(String host, int port, ObservableClient client)
+ {
+ super(host, port);
+ this.client = client;
+ }
+
+// OVERRIDDEN METHODS *************************************************
+
+ /**
+ * Hook method called after the connection has been closed.
+ */
+ final protected void connectionClosed()
+ {
+ client.connectionClosed();
+ }
+
+ /**
+ * Hook method called after an exception
+ * is raised by the client listening thread.
+ *
+ * @param exception the exception raised.
+ */
+ final protected void connectionException(Exception exception)
+ {
+ client.connectionException(exception);
+ }
+
+ /**
+ * Hook method called after a connection has been established.
+ */
+ final protected void connectionEstablished()
+ {
+ client.connectionEstablished();
+ }
+
+ /**
+ * Handles a message sent from the server to this client.
+ *
+ * @param msg the message sent.
+ */
+ final protected void handleMessageFromServer(Object msg)
+ {
+ client.handleMessageFromServer(msg);
+ }
+}
diff --git a/code/simplechat2/ocsf/client/ObservableClient.java b/code/simplechat2/ocsf/client/ObservableClient.java
new file mode 100644
index 0000000..a816488
--- /dev/null
+++ b/code/simplechat2/ocsf/client/ObservableClient.java
@@ -0,0 +1,181 @@
+// This file contains material supporting section 6.13 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.client;
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * This class acts as a subclass of To install OCSF, simply compile all the .java files in the client and
+server directories. OCSF is a Framework, so this directory contains no main program. To
+learn how it works, consult the book
+"Object-Oriented Software Engineering: Practical Software Development
+using UML and Java" by Lethbridge and Laganière. To use OCSF, import the "ocsf.client" or "ocsf.server" package in your
+application code. Make sure that the ocsf directory is in your classpath
+when you compile your application.
+*
+* Method
+*
+* Several public service methods are provided to applications that use
+* this framework, and several hook methods are also available
+*
+* Project Name: OCSF (Object Client-Server Framework)
+*
+* @author Dr Robert Laganière
+* @author Dr Timothy C. Lethbridge
+* @author François Bélanger
+* @author Paul Holden
+* @version February 2001 (2.12)
+* @see ocsf.server.ConnectionToClient
+*/
+public abstract class AbstractServer implements Runnable
+{
+ // INSTANCE VARIABLES *********************************************
+
+ /**
+ * The server socket: listens for clients who want to connect.
+ */
+ private ServerSocket serverSocket = null;
+
+ /**
+ * The connection listener thread.
+ */
+ private Thread connectionListener;
+
+ /**
+ * The port number
+ */
+ private int port;
+
+ /**
+ * The server timeout while for accepting connections.
+ * After timing out, the server will check to see if a command to
+ * stop the server has been issued; it not it will resume accepting
+ * connections.
+ * Set to half a second by default.
+ */
+ private int timeout = 500;
+
+ /**
+ * The maximum queue length; i.e. the maximum number of clients that
+ * can be waiting to connect.
+ * Set to 10 by default.
+ */
+ private int backlog = 10;
+
+ /**
+ * The thread group associated with client threads. Each member of the
+ * thread group is a
+*
+* Project Name: OCSF (Object Client-Server Framework)
+*
+* @author Dr. Robert Laganière
+* @version Febuary 2001
+*/
+class AdaptableServer extends AbstractServer
+{
+ //Instance variables **********************************************
+
+ /**
+ * The adapter used to simulate multiple class inheritance.
+ */
+ private ObservableServer server;
+
+// CONSTRUCTORS *****************************************************
+
+ /**
+ * Constructs the server adapter.
+ *
+ * @param host the server's host name.
+ * @param port the port number.
+ */
+ public AdaptableServer(int port, ObservableServer server)
+ {
+ super(port);
+ this.server = server;
+ }
+
+// OVERRIDDEN METHODS ---------
+
+ /**
+ * Hook method called each time a new client connection is
+ * accepted.
+ *
+ * @param client the connection connected to the client.
+ */
+ final protected void clientConnected(ConnectionToClient client)
+ {
+ server.clientConnected(client);
+ }
+
+ /**
+ * Hook method called each time a client disconnects.
+ *
+ * @param client the connection with the client.
+ */
+ final protected void clientDisconnected(ConnectionToClient client)
+ {
+ server.clientDisconnected(client);
+ }
+
+ /**
+ * Hook method called each time an exception
+ * is raised in a client thread.
+ *
+ * @param client the client that raised the exception.
+ * @param exception the exception raised.
+ */
+ final protected void clientException(ConnectionToClient client,
+ Throwable exception)
+ {
+ server.clientException(client, exception);
+ }
+
+ /**
+ * Hook method called when the server stops accepting
+ * connections because an exception has been raised.
+ *
+ * @param exception the exception raised.
+ */
+ final protected void listeningException(Throwable exception)
+ {
+ server.listeningException(exception);
+ }
+
+ /**
+ * Hook method called when the server stops accepting
+ * connections.
+ */
+ final protected void serverStopped()
+ {
+ server.serverStopped();
+ }
+
+ /**
+ * Hook method called when the server starts listening for
+ * connections.
+ */
+ final protected void serverStarted()
+ {
+ server.serverStarted();
+ }
+
+ /**
+ * Hook method called when the server is closed.
+ */
+ final protected void serverClosed()
+ {
+ server.serverClosed();
+ }
+
+ /**
+ * Handles a command sent from the client to the server.
+ *
+ * @param msg the message sent.
+ * @param client the connection connected to the client that
+ * sent the message.
+ */
+ final protected void handleMessageFromClient(Object msg,
+ ConnectionToClient client)
+ {
+ server.handleMessageFromClient(msg, client);
+ }
+}
diff --git a/code/simplechat2/ocsf/server/ConnectionToClient.java b/code/simplechat2/ocsf/server/ConnectionToClient.java
new file mode 100644
index 0000000..4394b37
--- /dev/null
+++ b/code/simplechat2/ocsf/server/ConnectionToClient.java
@@ -0,0 +1,270 @@
+// This file contains material supporting section 3.8 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+import java.io.*;
+import java.net.*;
+import java.util.HashMap;
+
+/**
+ * An instance of this class is created by the server when a client connects. It
+ * accepts messages coming from the client and is responsible for sending data
+ * to the client since the socket is private to this class. The AbstractServer
+ * contains a set of instances of this class and is responsible for adding and
+ * deleting them.
+ *
+ * Project Name: OCSF (Object Client-Server Framework)
+ *
+ *
+ * @author Dr Robert Laganière
+ * @author Dr Timothy C. Lethbridge
+ * @author François Bélanger
+ * @author Paul Holden
+ * @version February 2001 (2.12)
+ */
+public class ConnectionToClient extends Thread {
+ // INSTANCE VARIABLES ***********************************************
+
+ /**
+ * A reference to the Server that created this instance.
+ */
+ private AbstractServer server;
+
+ /**
+ * Sockets are used in the operating system as channels of communication
+ * between two processes.
+ *
+ * @see java.net.Socket
+ */
+ private Socket clientSocket;
+
+ /**
+ * Stream used to read from the client.
+ */
+ private ObjectInputStream input;
+
+ /**
+ * Stream used to write to the client.
+ */
+ private ObjectOutputStream output;
+
+ /**
+ * Indicates if the thread is ready to stop. Set to true when closing of the
+ * connection is initiated.
+ */
+ private boolean readyToStop;
+
+ /**
+ * Map to save information about the client such as its login ID. The
+ * initial size of the map is small since it is not expected that concrete
+ * servers will want to store many different types of information about each
+ * client. Used by the setInfo and getInfo methods.
+ */
+ private HashMap savedInfo = new HashMap(10);
+
+ // CONSTRUCTORS *****************************************************
+
+ /**
+ * Constructs a new connection to a client.
+ *
+ * @param group
+ * the thread groupSystem.out.println("Client at "+ client +
+ * "connected"); that contains the connections.
+ * @param clientSocket
+ * contains the client's socket.
+ * @param server
+ * a reference to the server that created this instance
+ * @exception IOException
+ * if an I/O error occur when creating the connection.
+ */
+ ConnectionToClient(ThreadGroup group, Socket clientSocket, AbstractServer server) throws IOException {
+ super(group, (Runnable) null);
+ // Initialize variables
+ this.clientSocket = clientSocket;
+ this.server = server;
+
+ clientSocket.setSoTimeout(0); // make sure timeout is infinite
+
+ // Initialize the objects streams
+ try {
+ input = new ObjectInputStream(clientSocket.getInputStream());
+ output = new ObjectOutputStream(clientSocket.getOutputStream());
+ } catch (IOException ex) {
+ try {
+ closeAll();
+ } catch (Exception exc) {
+ }
+
+ throw ex; // Rethrow the exception.
+ }
+
+ readyToStop = false;
+ start(); // Start the thread waits for data from the socket
+ }
+
+ // INSTANCE METHODS *************************************************
+
+ /**
+ * Sends an object to the client.
+ *
+ * @param msg
+ * the message to be sent.
+ * @exception IOException
+ * if an I/O error occur when sending the message.
+ */
+ final public void sendToClient(Object msg) throws IOException {
+ if (clientSocket == null || output == null)
+ throw new SocketException("socket does not exist");
+
+ output.writeObject(msg);
+ }
+
+ /**
+ * Reset the output stream so we can use the same
+ * buffer repeatedly. This would not normally be used, but is necessary
+ * in some circumstances when Java refuses to send data that it thinks has been sent.
+ */
+ final public void forceResetAfterSend() throws IOException {
+ output.reset();
+ }
+
+ /**
+ * Closes the client. If the connection is already closed, this call has no
+ * effect.
+ *
+ * @exception IOException
+ * if an error occurs when closing the socket.
+ */
+ final public void close() throws IOException {
+ readyToStop = true; // Set the flag that tells the thread to stop
+
+ try {
+ closeAll();
+ } finally {
+ server.clientDisconnected(this);
+ }
+ }
+
+ // ACCESSING METHODS ------------------------------------------------
+
+ /**
+ * Returns the address of the client.
+ *
+ * @return the client's Internet address.
+ */
+ final public InetAddress getInetAddress() {
+ return clientSocket == null ? null : clientSocket.getInetAddress();
+ }
+
+ /**
+ * Returns a string representation of the client.
+ *
+ * @return the client's description.
+ */
+ public String toString() {
+ return clientSocket == null ? null : clientSocket.getInetAddress().getHostName() + " ("
+ + clientSocket.getInetAddress().getHostAddress() + ")";
+ }
+
+ /**
+ * Saves arbitrary information about this client. Designed to be used by
+ * concrete subclasses of AbstractServer. Based on a hash map.
+ *
+ * @param infoType
+ * identifies the type of information
+ * @param info
+ * the information itself.
+ */
+ public void setInfo(String infoType, Object info) {
+ savedInfo.put(infoType, info);
+ }
+
+ /**
+ * Returns information about the client saved using setInfo. Based on a hash
+ * map.
+ *
+ * @param infoType
+ * identifies the type of information
+ */
+ public Object getInfo(String infoType) {
+ return savedInfo.get(infoType);
+ }
+
+ // RUN METHOD -------------------------------------------------------
+
+ /**
+ * Constantly reads the client's input stream. Sends all objects that are
+ * read to the server. Not to be called.
+ */
+ final public void run() {
+ server.clientConnected(this);
+
+ // This loop reads the input stream and responds to messages
+ // from clients
+ try {
+ // The message from the client
+ Object msg;
+
+ while (!readyToStop) {
+ // This block waits until it reads a message from the client
+ // and then sends it for handling by the server
+ msg = input.readObject();
+ server.receiveMessageFromClient(msg, this);
+ }
+ } catch (Exception exception) {
+ if (!readyToStop) {
+ try {
+ closeAll();
+ } catch (Exception ex) {
+ }
+
+ server.clientException(this, exception);
+ }
+ }
+ }
+
+ // METHODS TO BE USED FROM WITHIN THE FRAMEWORK ONLY ----------------
+
+ /**
+ * Closes all connection to the server.
+ *
+ * @exception IOException
+ * if an I/O error occur when closing the connection.
+ */
+ private void closeAll() throws IOException {
+ try {
+ // Close the socket
+ if (clientSocket != null)
+ clientSocket.close();
+
+ // Close the output stream
+ if (output != null)
+ output.close();
+
+ // Close the input stream
+ if (input != null)
+ input.close();
+ } finally {
+ // Set the streams and the sockets to NULL no matter what
+ // Doing so allows, but does not require, any finalizers
+ // of these objects to reclaim system resources if and
+ // when they are garbage collected.
+ output = null;
+ input = null;
+ clientSocket = null;
+ }
+ }
+
+ /**
+ * This method is called by garbage collection.
+ */
+ protected void finalize() {
+ try {
+ closeAll();
+ } catch (IOException e) {
+ }
+ }
+}
+// End of ConnectionToClient class
\ No newline at end of file
diff --git a/code/simplechat2/ocsf/server/ObservableOriginatorServer.java b/code/simplechat2/ocsf/server/ObservableOriginatorServer.java
new file mode 100644
index 0000000..4333694
--- /dev/null
+++ b/code/simplechat2/ocsf/server/ObservableOriginatorServer.java
@@ -0,0 +1,165 @@
+// This file contains material supporting the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+/**
+* The
+*
+* @author Dr Robert Laganière
+* @author Dr Timothy C. Lethbridge
+* @author François Bélanger
+* @author Paul Holden
+* @version February 2001 (2.12)
+* @see ocsf.server.OriginatorMessage
+*/
+public class ObservableOriginatorServer extends ObservableServer
+{
+ // Constructor ******************************************************
+
+ /**
+ * Constructs a new server.
+ *
+ * @param port the port on which to listen.
+ */
+ public ObservableOriginatorServer(int port)
+ {
+ super(port);
+ }
+
+ // Instance methods ************************************************
+
+ /**
+ * This method is used to handle messages coming from the client.
+ * Observers are notfied by receiveing an instance of OriginatorMessage
+ * that contains both the message received and a reference to the
+ * client who sent the message.
+ *
+ * @param message The message received from the client.
+ * @param client The connection to the client.
+ */
+ protected synchronized void handleMessageFromClient
+ (Object message, ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(client, message));
+ }
+
+ /**
+ * Method called each time a new client connection is
+ * accepted. It notifies observers by sending an
+ * ConnectionToClient .
+ */
+ private ThreadGroup clientThreadGroup;
+
+ /**
+ * Indicates if the listening thread is ready to stop. Set to
+ * false by default.
+ */
+ private boolean readyToStop = false;
+
+
+// CONSTRUCTOR ******************************************************
+
+ /**
+ * Constructs a new server.
+ *
+ * @param port the port number on which to listen.
+ */
+ public AbstractServer(int port)
+ {
+ this.port = port;
+
+ this.clientThreadGroup =
+ new ThreadGroup("ConnectionToClient threads")
+ {
+ // All uncaught exceptions in connection threads will
+ // be sent to the clientException callback method.
+ public void uncaughtException(
+ Thread thread, Throwable exception)
+ {
+ clientException((ConnectionToClient)thread, exception);
+ }
+ };
+ }
+
+
+// INSTANCE METHODS *************************************************
+
+ /**
+ * Begins the thread that waits for new clients.
+ * If the server is already in listening mode, this
+ * call has no effect.
+ *
+ * @exception IOException if an I/O error occurs
+ * when creating the server socket.
+ */
+ final public void listen() throws IOException
+ {
+ if (!isListening())
+ {
+ if (serverSocket == null)
+ {
+ serverSocket = new ServerSocket(getPort(), backlog);
+ }
+
+ serverSocket.setSoTimeout(timeout);
+ readyToStop = false;
+ connectionListener = new Thread(this);
+ connectionListener.start();
+ }
+ }
+
+ /**
+ * Causes the server to stop accepting new connections.
+ */
+ final public void stopListening()
+ {
+ readyToStop = true;
+ }
+
+ /**
+ * Closes the server socket and the connections with all clients.
+ * Any exception thrown while closing a client is ignored.
+ * If one wishes to catch these exceptions, then clients
+ * should be individually closed before calling this method.
+ * The method also stops listening if this thread is running.
+ * If the server is already closed, this
+ * call has no effect.
+ *
+ * @exception IOException if an I/O error occurs while
+ * closing the server socket.
+ */
+ final synchronized public void close() throws IOException
+ {
+ if (serverSocket == null)
+ return;
+ stopListening();
+ try
+ {
+ serverSocket.close();
+ }
+ finally
+ {
+ // Close the client sockets of the already connected clients
+ Thread[] clientThreadList = getClientConnections();
+ for (int i=0; iConnectionToClient instances.
+ */
+ synchronized final public Thread[] getClientConnections()
+ {
+ Thread[] clientThreadList = new
+ Thread[clientThreadGroup.activeCount()];
+
+ clientThreadGroup.enumerate(clientThreadList);
+
+ return clientThreadList;
+ }
+
+ /**
+ * Counts the number of clients currently connected.
+ *
+ * @return the number of clients currently connected.
+ */
+ final public int getNumberOfClients()
+ {
+ return clientThreadGroup.activeCount();
+ }
+
+ /**
+ * Returns the port number.
+ *
+ * @return the port number.
+ */
+ final public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Sets the port number for the next connection.
+ * The server must be closed and restarted for the port
+ * change to be in effect.
+ *
+ * @param port the port number.
+ */
+ final public void setPort(int port)
+ {
+ this.port = port;
+ }
+
+ /**
+ * Sets the timeout time when accepting connections.
+ * The default is half a second. This means that stopping the
+ * server may take up to timeout duration to actually stop.
+ * The server must be stopped and restarted for the timeout
+ * change to be effective.
+ *
+ * @param timeout the timeout time in ms.
+ */
+ final public void setTimeout(int timeout)
+ {
+ this.timeout = timeout;
+ }
+
+ /**
+ * Sets the maximum number of waiting connections accepted by the
+ * operating system. The default is 20.
+ * The server must be closed and restarted for the backlog
+ * change to be in effect.
+ *
+ * @param backlog the maximum number of connections.
+ */
+ final public void setBacklog(int backlog)
+ {
+ this.backlog = backlog;
+ }
+
+// RUN METHOD -------------------------------------------------------
+
+ /**
+ * Runs the listening thread that allows clients to connect.
+ * Not to be called.
+ */
+ final public void run()
+ {
+ // call the hook method to notify that the server is starting
+ serverStarted();
+
+ try
+ {
+ // Repeatedly waits for a new client connection, accepts it, and
+ // starts a new thread to handle data exchange.
+ while(!readyToStop)
+ {
+ try
+ {
+ // Wait here for new connection attempts, or a timeout
+ Socket clientSocket = serverSocket.accept();
+
+ // When a client is accepted, create a thread to handle
+ // the data exchange, then add it to thread group
+
+ synchronized(this)
+ {
+ ConnectionToClient c = new ConnectionToClient(
+ this.clientThreadGroup, clientSocket, this);
+ }
+ }
+ catch (InterruptedIOException exception)
+ {
+ // This will be thrown when a timeout occurs.
+ // The server will continue to listen if not ready to stop.
+ }
+ }
+
+ // call the hook method to notify that the server has stopped
+ serverStopped();
+ }
+ catch (IOException exception)
+ {
+ if (!readyToStop)
+ {
+ // Closing the socket must have thrown a SocketException
+ listeningException(exception);
+ }
+ else
+ {
+ serverStopped();
+ }
+ }
+ finally
+ {
+ readyToStop = true;
+ connectionListener = null;
+ }
+ }
+
+
+// METHODS DESIGNED TO BE OVERRIDDEN BY CONCRETE SUBCLASSES ---------
+
+ /**
+ * 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) {}
+
+ /**
+ * 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) {}
+
+ /**
+ * 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) {}
+
+ /**
+ * Hook method called when the server stops accepting
+ * connections because an exception has been raised.
+ * The default implementation does nothing.
+ * This method may be overriden by subclasses.
+ *
+ * @param exception the exception raised.
+ */
+ protected void listeningException(Throwable exception) {}
+
+ /**
+ * Hook method called when the server starts listening for
+ * connections. The default implementation does nothing.
+ * The method may be overridden by subclasses.
+ */
+ protected void serverStarted() {}
+
+ /**
+ * Hook method called when the server stops accepting
+ * connections. The default implementation
+ * does nothing. This method may be overriden by subclasses.
+ */
+ protected void serverStopped() {}
+
+ /**
+ * Hook method called when the server is clased.
+ * The default implementation does nothing. This method may be
+ * overriden by subclasses. When the server is closed while still
+ * listening, serverStopped() will also be called.
+ */
+ protected void serverClosed() {}
+
+ /**
+ * Handles a command sent from one client to the server.
+ * This MUST be implemented by subclasses, who should respond to
+ * messages.
+ * This method is called by a synchronized method so it is also
+ * implcitly synchronized.
+ *
+ * @param msg the message sent.
+ * @param client the connection connected to the client that
+ * sent the message.
+ */
+ protected abstract void handleMessageFromClient(
+ Object msg, ConnectionToClient client);
+
+
+// METHODS TO BE USED FROM WITHIN THE FRAMEWORK ONLY ----------------
+
+ /**
+ * Receives a command sent from the client to the server.
+ * Called by the run method of ConnectionToClient
+ * instances that are watching for messages coming from the server
+ * This method is synchronized to ensure that whatever effects it has
+ * do not conflict with work being done by other threads. The method
+ * simply calls the handleMessageFromClient slot method.
+ *
+ * @param msg the message sent.
+ * @param client the connection connected to the client that
+ * sent the message.
+ */
+ final synchronized void receiveMessageFromClient(
+ Object msg, ConnectionToClient client)
+ {
+ this.handleMessageFromClient(msg, client);
+ }
+}
+// End of AbstractServer Class
diff --git a/code/simplechat1/ocsf/server/AdaptableServer.java b/code/simplechat1/ocsf/server/AdaptableServer.java
new file mode 100644
index 0000000..24462d4
--- /dev/null
+++ b/code/simplechat1/ocsf/server/AdaptableServer.java
@@ -0,0 +1,129 @@
+// This file contains material supporting section 6.13 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+* The AdaptableServer is an adapter class
+* that extends the AbstractServer class in place of
+* the AbstractObservableServer . ObservableOriginatorServer is a subclass
+* of ObservableServer that sends
+* OriginatorMessage instances to its observers.
+* This class should be used when the observers need to know
+* the orginator of the messages received. The originator
+* is null when the message sent concerns the server.
+*
+* Project Name: OCSF (Object Client-Server Framework) OriginatorMessage instance
+ * containing a reference to that client and
+ * the message defined by the static variable CLIENT_CONNECTED.
+ *
+ * @param client the connection connected to the client.
+ */
+ protected synchronized void clientConnected(ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(client, CLIENT_CONNECTED));
+ }
+
+ /**
+ * Method called each time a client connection is
+ * disconnected. It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing a reference to that client and
+ * the message defined by the static variable CLIENT_DISCONNECTED.
+ *
+ * @param client the connection connected to the client.
+ */
+ synchronized protected void clientDisconnected(ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(client, CLIENT_DISCONNECTED));
+ }
+
+
+ /**
+ * Method called each time an exception is raised
+ * by a client connection.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing a reference to that client and
+ * the message defined by the static variable CLIENT_EXCEPTION
+ * to which is appended the exception message.
+ *
+ * @param client the client that raised the exception.
+ * @param Throwable the exception thrown.
+ */
+ synchronized protected void clientException(
+ ConnectionToClient client, Throwable exception)
+ {
+ setChanged();
+ notifyObservers(
+ new OriginatorMessage(client,
+ CLIENT_EXCEPTION + exception.getMessage()));
+ }
+
+ /**
+ * Method called each time an exception is raised
+ * while listening.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing the message defined by the static variable LISTENING_EXCEPTION
+ * to which is appended the exception message.
+ * The originator is set to null.
+ *
+ * @param exception the exception raised.
+ */
+ protected synchronized void listeningException(Throwable exception)
+ {
+ setChanged();
+ notifyObservers(
+ new OriginatorMessage(null,
+ LISTENING_EXCEPTION + exception.getMessage()));
+ }
+
+ /**
+ * Method called each time the server is started.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing the message defined by the static variable SERVER_STARTED.
+ * The originator is set to null.
+ */
+ protected synchronized void serverStarted()
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(null, SERVER_STARTED));
+ }
+
+ /**
+ * Method called each time the server is stopped.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing the message defined by the static variable SERVER_STOPPED.
+ * The originator is set to null.
+ */
+ synchronized protected void serverStopped()
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(null, SERVER_STOPPED));
+ }
+
+ /**
+ * Method called each time the server is closed.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing the message defined by the static variable SERVER_CLOSED.
+ * The originator is set to null.
+ */
+ synchronized protected void serverClosed()
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(null, SERVER_CLOSED));
+ }
+}
diff --git a/code/simplechat1/ocsf/server/ObservableServer.java b/code/simplechat1/ocsf/server/ObservableServer.java
new file mode 100644
index 0000000..5b16752
--- /dev/null
+++ b/code/simplechat1/ocsf/server/ObservableServer.java
@@ -0,0 +1,309 @@
+// This file contains material supporting section 6.13 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * This class acts as a subclass of AbstractServer
+ * and is also an Observable class.
+ * This means that when a message is received, all observers
+ * are notified.
+ *
+ * @author François Bélange
+ * @author Dr Timothy C. Lethbridge
+ * @author Dr Robert Laganière
+ * @version August 2000
+ */
+
+public class ObservableServer extends Observable
+{
+ // Class variables ************************************************
+
+ /**
+ * The string sent to the observers when a client has connected.
+ */
+ public static final String CLIENT_CONNECTED= "#OS:Client connected.";
+
+ /**
+ * The string sent to the observers when a client has disconnected.
+ */
+ public static final String CLIENT_DISCONNECTED= "#OS:Client disconnected.";
+
+ /**
+ * The string sent to the observers when an exception occurred with a client.
+ * The error message of that exception will be appended to this string.
+ */
+ public static final String CLIENT_EXCEPTION= "#OS:Client exception.";
+
+ /**
+ * The string sent to the observers when a listening exception occurred.
+ * The error message of that exception will be appended to this string.
+ */
+ public static final String LISTENING_EXCEPTION= "#OS:Listening exception.";
+
+ /**
+ * The string sent to the observers when the server has closed.
+ */
+ public static final String SERVER_CLOSED= "#OS:Server closed.";
+
+ /**
+ * The string sent to the observers when the server has started.
+ */
+ public static final String SERVER_STARTED= "#OS:Server started.";
+
+ /**
+ * The string sent to the observers when the server has stopped.
+ */
+ public static final String SERVER_STOPPED= "#OS:Server stopped.";
+
+
+ //Instance variables **********************************************
+
+ /**
+ * The service used to simulate multiple class inheritance.
+ */
+ private AdaptableServer service;
+
+
+ //Constructor *****************************************************
+
+ /**
+ * Constructs a new server.
+ *
+ * @param port the port on which to listen.
+ */
+ public ObservableServer(int port)
+ {
+ service = new AdaptableServer(port, this);
+ }
+
+ //Instance methods ************************************************
+
+ /**
+ * Begins the thread that waits for new clients
+ */
+ final public void listen() throws IOException
+ {
+ service.listen();
+ }
+
+ /**
+ * Causes the server to stop accepting new connections.
+ */
+ final public void stopListening()
+ {
+ service.stopListening();
+ }
+
+ /**
+ * Closes the server's connections with all clients.
+ */
+ final public void close() throws IOException
+ {
+ service.close();
+ }
+
+ /**
+ * Sends a message to every client connected to the server.
+ *
+ * @param msg The message to be sent
+ */
+ public void sendToAllClients(Object msg)
+ {
+ service.sendToAllClients(msg);
+ }
+
+// ACCESSING METHODS ------------------------------------------------
+
+ /**
+ * Used to find out if the server is accepting new clients.
+ */
+ final public boolean isListening()
+ {
+ return service.isListening();
+ }
+
+ /**
+ * Returns an array of containing the existing
+ * client connections. This can be used by
+ * concrete subclasses to implement messages that do something with
+ * each connection (e.g. kill it, send a message to it etc.)
+ *
+ * @return an array of Thread containing
+ * ConnectionToClient instances.
+ */
+ final public Thread[] getClientConnections()
+ {
+ return service.getClientConnections();
+ }
+
+ /**
+ * @return the number of clients currently connected.
+ */
+ final public int getNumberOfClients()
+ {
+ return service.getNumberOfClients();
+ }
+
+ /**
+ * @return the port number.
+ */
+ final public int getPort()
+ {
+ return service.getPort();
+ }
+
+ /**
+ * Sets the port number for the next connection.
+ * Only has effect if the server is not currently listening.
+ *
+ * @param port the port number.
+ */
+ final public void setPort(int port)
+ {
+ service.setPort(port);
+ }
+
+ /**
+ * Sets the timeout time when accepting connection.
+ * The default is half a second.
+ * The server must be stopped and restarted for the timeout
+ * change be in effect.
+ *
+ * @param timeout the timeout time in ms.
+ */
+ final public void setTimeout(int timeout)
+ {
+ service.setTimeout(timeout);
+ }
+
+ /**
+ * Sets the maximum number of
+ * waiting connections accepted by the operating system.
+ * The default is 20.
+ * The server must be closed and restart for the backlog
+ * change be in effect.
+ *
+ * @param backlog the maximum number of connections.
+ */
+ final public void setBacklog(int backlog)
+ {
+ service.setBacklog(backlog);
+ }
+
+ /**
+ * Hook method called each time a new client connection is
+ * accepted. The method may be overridden by subclasses.
+ *
+ * @param client the connection connected to the client.
+ */
+ protected synchronized void clientConnected(ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(CLIENT_CONNECTED);
+ }
+
+ /**
+ * Hook method called each time a client disconnects.
+ * The method may be overridden by subclasses.
+ *
+ * @param client the connection with the client.
+ */
+ protected synchronized void clientDisconnected(ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(CLIENT_DISCONNECTED);
+ }
+
+ /**
+ * Hook method called each time an exception
+ * is raised in a client thread.
+ * This implementation simply closes the
+ * client connection, ignoring any exception.
+ * The method may be overridden by subclasses.
+ *
+ * @param client the client that raised the exception.
+ * @param exception the exception raised.
+ */
+ protected synchronized void clientException(ConnectionToClient client,
+ Throwable exception)
+ {
+ setChanged();
+ notifyObservers(CLIENT_EXCEPTION);
+ try
+ {
+ client.close();
+ }
+ catch (Exception e) {}
+ }
+
+ /**
+ * This method is called when the server stops accepting
+ * connections because an exception has been raised.
+ * This implementation
+ * simply calls stopListening.
+ * This method may be overriden by subclasses.
+ *
+ * @param exception the exception raised.
+ */
+ protected synchronized void listeningException(Throwable exception)
+ {
+ setChanged();
+ notifyObservers(LISTENING_EXCEPTION);
+ stopListening();
+ }
+
+ /**
+ * This method is called when the server stops accepting
+ * connections for any reason. This method may be overriden by
+ * subclasses.
+ */
+ synchronized protected void serverStopped()
+ {
+ setChanged();
+ notifyObservers(SERVER_STOPPED);
+ }
+
+ /**
+ * This method is called when the server is closed.
+ * This method may be overriden by subclasses.
+ */
+ synchronized protected void serverClosed()
+ {
+ setChanged();
+ notifyObservers(SERVER_CLOSED);
+ }
+
+ /**
+ * This method is called when the server starts listening for
+ * connections. The method may be overridden by subclasses.
+ */
+ protected synchronized void serverStarted()
+ {
+ setChanged();
+ notifyObservers(SERVER_STARTED);
+ }
+
+ /**
+ * This method is used to handle messages coming from the client.
+ * Observers are notfied by receiveing the transmitted message.
+ * Note that, in this implementation, the information concerning
+ * the client that sent the message is lost.
+ * It can be overriden, but is still expected to call notifyObservers().
+ *
+ * @param message The message received from the client.
+ * @param client The connection to the client.
+ * @see ocsf.server.ObservableOriginatorServer
+ */
+ protected synchronized void handleMessageFromClient
+ (Object message, ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(message);
+ }
+}
diff --git a/code/simplechat1/ocsf/server/OriginatorMessage.java b/code/simplechat1/ocsf/server/OriginatorMessage.java
new file mode 100644
index 0000000..a25d2b4
--- /dev/null
+++ b/code/simplechat1/ocsf/server/OriginatorMessage.java
@@ -0,0 +1,61 @@
+// This file contains material supporting the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+/**
+ * A message class used by the Observable layer of the OCSF in order to conserve
+ * information about the originator of a message.
+ *
+ * @author Dr. Robert Laganière
+ * @version July 2001
+ */
+public class OriginatorMessage
+{
+ /**
+ * The connection that originated the message
+ */
+ private ConnectionToClient originator;
+
+ /**
+ * The message.
+ */
+ private Object message;
+
+// Constructor ***************************************************************
+
+ /**
+ * Constructs an instance of an OriginatorMessage
+ *
+ * @param originator The client who created this message
+ * @param message The contents of the message
+ */
+ public OriginatorMessage(ConnectionToClient originator, Object message)
+ {
+ this.originator = originator;
+ this.message = message;
+ }
+
+// Accessor methods *********************************************************
+
+ /**
+ * Returns the originating connection.
+ *
+ * @return The connection from which the message originated.
+ */
+ public ConnectionToClient getOriginator()
+ {
+ return originator;
+ }
+
+ /**
+ * Returns the message's contents.
+ *
+ * @return The content of the message.
+ */
+ public Object getMessage()
+ {
+ return message;
+ }
+}
From 455400b7d9415bcd1bec0ec2be60cb0ca2ce3619 Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Sat, 23 May 2020 01:40:09 -0400
Subject: [PATCH 02/13] Performed Phase-1 Testing
Performed Phase-1 Testing and included the documentation
---
code/simplechat1/TestLogs.txt | 86 +++++++++++++++++++++++++++++++++++
code/simplechat1/Testcase | 0
code/simplechat1/java | 0
3 files changed, 86 insertions(+)
create mode 100644 code/simplechat1/TestLogs.txt
create mode 100644 code/simplechat1/Testcase
create mode 100644 code/simplechat1/java
diff --git a/code/simplechat1/TestLogs.txt b/code/simplechat1/TestLogs.txt
new file mode 100644
index 0000000..2e4bd2b
--- /dev/null
+++ b/code/simplechat1/TestLogs.txt
@@ -0,0 +1,86 @@
+Client 3
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+Testcase 1007!
+> Testcase 1007!
+> Could not send message to server. Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
+
+Client 2
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+Test> Testcase 1007!
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
+
+Client 1
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+Currently on Testcase 1004
+> Currently on Testcase 1004
+Testcase 1005
+> Could not send message to server. Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+This is Testcase 1006
+> This is Testcase 1006
+> Testcase 1007!
+> Could not send message to server. Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+'C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1' is not recognized as an internal or external command,
+operable program or batch file.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>Test> Testcase 1007!
+'Test' is not recognized as an internal or external command,
+operable program or batch file.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+FinFin
+
+
+FIniewfnoewf> FinFin
+>
+>
+Done
+> FIniewfnoewfDone
+d
+> d
+> Final FFFinTestcase 1013, final test
+e
+> Could not send message to server. Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
+
+Server:
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java EchoServer
+Server listening for connections on port 5555
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+Error: Can't setup connection! Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java EchoServer
+Server listening for connections on port 5555
+Message received: Currently on Testcase 1004 from 127.0.0.1 (127.0.0.1)
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java EchoServer
+Server listening for connections on port 5555
+Message received: null from 127.0.0.1 (127.0.0.1)
+Message received: This is Testcase 1006 from 127.0.0.1 (127.0.0.1)
+Message received: Testcase 1007! from 127.0.0.1 (127.0.0.1)
+Message received: null from 127.0.0.1 (127.0.0.1)
+Message received: This message is from my Desktop to my Laptop! from Nev-PC (192.168.2.29)
+Message received: null from Nev-PC (192.168.2.29)
+Message received: FinFin from 127.0.0.1 (127.0.0.1)
+Message received: from 127.0.0.1 (127.0.0.1)
+Message received: from 127.0.0.1 (127.0.0.1)
+Message received: FIniewfnoewfDone from 127.0.0.1 (127.0.0.1)
+Message received: d from 127.0.0.1 (127.0.0.1)
+Message received: Final FFFinTestcase 1013, final test from 127.0.0.1 (127.0.0.1)
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
diff --git a/code/simplechat1/Testcase b/code/simplechat1/Testcase
new file mode 100644
index 0000000..e69de29
diff --git a/code/simplechat1/java b/code/simplechat1/java
new file mode 100644
index 0000000..e69de29
From 189fcb78a71bfd27ca2b8817bdb8b5072a73e839 Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Sat, 23 May 2020 15:39:01 -0400
Subject: [PATCH 03/13] Initial Files Added + Modified Client to Shut Down on
Server Shut Down and use a Specified Port
Started Phase 2 of Simplechat and completed the requirements of 5 a) and b)
---
code/simplechat2/ClientConsole.java | 132 +++++
code/simplechat2/EchoServer.java | 109 +++++
code/simplechat2/client/ChatClient.java | 107 ++++
code/simplechat2/common/ChatIF.java | 22 +
code/simplechat2/index.html | 34 ++
code/simplechat2/java | 0
.../ocsf/client/AbstractClient.java | 333 +++++++++++++
.../ocsf/client/AdaptableClient.java | 82 ++++
.../ocsf/client/ObservableClient.java | 181 +++++++
code/simplechat2/ocsf/index.html | 22 +
.../ocsf/server/AbstractServer.java | 459 ++++++++++++++++++
.../ocsf/server/AdaptableServer.java | 129 +++++
.../ocsf/server/ConnectionToClient.java | 270 +++++++++++
.../server/ObservableOriginatorServer.java | 165 +++++++
.../ocsf/server/ObservableServer.java | 309 ++++++++++++
.../ocsf/server/OriginatorMessage.java | 61 +++
16 files changed, 2415 insertions(+)
create mode 100644 code/simplechat2/ClientConsole.java
create mode 100644 code/simplechat2/EchoServer.java
create mode 100644 code/simplechat2/client/ChatClient.java
create mode 100644 code/simplechat2/common/ChatIF.java
create mode 100644 code/simplechat2/index.html
create mode 100644 code/simplechat2/java
create mode 100644 code/simplechat2/ocsf/client/AbstractClient.java
create mode 100644 code/simplechat2/ocsf/client/AdaptableClient.java
create mode 100644 code/simplechat2/ocsf/client/ObservableClient.java
create mode 100644 code/simplechat2/ocsf/index.html
create mode 100644 code/simplechat2/ocsf/server/AbstractServer.java
create mode 100644 code/simplechat2/ocsf/server/AdaptableServer.java
create mode 100644 code/simplechat2/ocsf/server/ConnectionToClient.java
create mode 100644 code/simplechat2/ocsf/server/ObservableOriginatorServer.java
create mode 100644 code/simplechat2/ocsf/server/ObservableServer.java
create mode 100644 code/simplechat2/ocsf/server/OriginatorMessage.java
diff --git a/code/simplechat2/ClientConsole.java b/code/simplechat2/ClientConsole.java
new file mode 100644
index 0000000..7d7c2b6
--- /dev/null
+++ b/code/simplechat2/ClientConsole.java
@@ -0,0 +1,132 @@
+// 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.*;
+
+/**
+ * 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();
+ 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);
+ }
+
+
+ //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];
+ }
+ catch(ArrayIndexOutOfBoundsException e)
+ {
+ host = "localhost";
+
+ }
+
+ try
+ {
+ port = Integer.parseInt(args[1]);
+ }
+ catch(ArrayIndexOutOfBoundsException e){
+ port = DEFAULT_PORT;
+ }
+
+ ClientConsole chat= new ClientConsole(host, port);
+ chat.accept(); //Wait for console data
+ }
+}
+//End of ConsoleChat class
diff --git a/code/simplechat2/EchoServer.java b/code/simplechat2/EchoServer.java
new file mode 100644
index 0000000..d4f3a1a
--- /dev/null
+++ b/code/simplechat2/EchoServer.java
@@ -0,0 +1,109 @@
+// 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.*;
+
+/**
+ * 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 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.");
+ }
+
+ //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(String[] args)
+ {
+ 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/code/simplechat2/client/ChatClient.java b/code/simplechat2/client/ChatClient.java
new file mode 100644
index 0000000..fb0e0ea
--- /dev/null
+++ b/code/simplechat2/client/ChatClient.java
@@ -0,0 +1,107 @@
+// 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.*;
+
+/**
+ * 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);
+ }
+
+ //Terminates Client when server terminates
+ public void connectionException(Exception Error){
+
+ quit();
+
+ }
+
+ //Displays Message upon client termination
+ public void connectionClosed(){
+ System.out.println("The server has closed");
+ }
+
+}
+//End of ChatClient class
diff --git a/code/simplechat2/common/ChatIF.java b/code/simplechat2/common/ChatIF.java
new file mode 100644
index 0000000..45b04d4
--- /dev/null
+++ b/code/simplechat2/common/ChatIF.java
@@ -0,0 +1,22 @@
+// 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 common;
+
+/**
+ * This interface implements the abstract method used to display
+ * objects onto the client or server UIs.
+ *
+ * @author Dr Robert Laganière
+ * @author Dr Timothy C. Lethbridge
+ * @version July 2000
+ */
+public interface ChatIF
+{
+ /**
+ * Method that when overriden is used to display objects onto
+ * a UI.
+ */
+ public abstract void display(String message);
+}
diff --git a/code/simplechat2/index.html b/code/simplechat2/index.html
new file mode 100644
index 0000000..f88583d
--- /dev/null
+++ b/code/simplechat2/index.html
@@ -0,0 +1,34 @@
+
+ AbstractClient contains all the methods necessary to set
+ * up the client side of a client-server architecture. When a client is thus
+ * connected to the server, the two programs can then exchange
+ * Object instances.
+ * handleMessageFromServer must be defined by a concrete
+ * subclass. Several other hook methods may also be overriden.
+ * handleMessageFromServer(). Not to be explicitly called.
+ */
+ final public void run() {
+ connectionEstablished();
+
+ // The message from the server
+ Object msg;
+
+ // Loop waiting for data
+
+ try {
+ while (!readyToStop) {
+ // Get data from Server and send it to the handler
+ // The thread waits indefinitely at the following
+ // statement until something is received from the server
+ msg = input.readObject();
+
+ // Concrete subclasses do what they want with the
+ // msg by implementing the following method
+ handleMessageFromServer(msg);
+ }
+ } catch (Exception exception) {
+ if (!readyToStop) {
+ try {
+ closeAll();
+ } catch (Exception ex) {
+ }
+
+ connectionException(exception);
+ }
+ } finally {
+ clientReader = null;
+ }
+ }
+
+ // METHODS DESIGNED TO BE OVERRIDDEN BY CONCRETE SUBCLASSES ---------
+
+ /**
+ * 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() {
+ }
+
+ /**
+ * 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) {
+ }
+
+ /**
+ * Hook method called after a connection has been established. The default
+ * implementation does nothing. It may be overridden by subclasses to do
+ * anything they wish.
+ */
+ protected void connectionEstablished() {
+ }
+
+ /**
+ * Handles a message sent from the server to this client. This MUST be
+ * implemented by subclasses, who should respond to messages.
+ *
+ * @param msg
+ * the message sent.
+ */
+ protected abstract void handleMessageFromServer(Object msg);
+
+ // METHODS TO BE USED FROM WITHIN THE FRAMEWORK ONLY ----------------
+
+ /**
+ * Closes all aspects of the connection to the server.
+ *
+ * @exception IOException
+ * if an I/O error occurs when closing.
+ */
+ private void closeAll() throws IOException {
+ try {
+ // Close the socket
+ if (clientSocket != null)
+ clientSocket.close();
+
+ // Close the output stream
+ if (output != null)
+ output.close();
+
+ // Close the input stream
+ if (input != null)
+ input.close();
+ } finally {
+ // Set the streams and the sockets to NULL no matter what
+ // Doing so allows, but does not require, any finalizers
+ // of these objects to reclaim system resources if and
+ // when they are garbage collected.
+ output = null;
+ input = null;
+ clientSocket = null;
+ }
+ }
+}
+// end of AbstractClient class
\ No newline at end of file
diff --git a/code/simplechat2/ocsf/client/AdaptableClient.java b/code/simplechat2/ocsf/client/AdaptableClient.java
new file mode 100644
index 0000000..143592e
--- /dev/null
+++ b/code/simplechat2/ocsf/client/AdaptableClient.java
@@ -0,0 +1,82 @@
+// This file contains material supporting section 6.13 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.client;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+* The AdaptableClient is a class
+* that extends the AbstractClient in place of
+* the ObservableClient .AbstractClient
+ * and is also an Observable class.
+ * Each time a new message is received, observers are notified.
+ *
+ * @author Dr Robert Laganière
+ * @author Dr Timothy C. Lethbridge
+ * @author François Bélange
+ * @version Febuary 2001
+ */
+public class ObservableClient extends Observable
+{
+ // Class variables ***************************************************
+
+ /**
+ * Indicates occurence of a connection exception.
+ */
+ public static final String CONNECTION_EXCEPTION = "#OC:Connection error.";
+
+ /**
+ * Indicates a close of the connection to server.
+ */
+ public static final String CONNECTION_CLOSED = "#OC:Connection closed.";
+
+ /**
+ * Indicates establishment of a connection to server.
+ */
+ public static final String CONNECTION_ESTABLISHED = "#OC:Connection established.";
+
+ //Instance variables **********************************************
+
+ /**
+ * The service instance used to simulate multiple class inheritance.
+ */
+ private AdaptableClient service;
+
+ //Constructor *****************************************************
+
+ public ObservableClient(String host, int port)
+ {
+ service = new AdaptableClient(host, port, this);
+ }
+
+ //Instance methods ************************************************
+
+ /**
+ * Opens the connections with the server.
+ */
+ final public void openConnection() throws IOException
+ {
+ service.openConnection();
+ }
+
+ /**
+ * Closes the connection to the server.
+ */
+ final public void closeConnection() throws IOException
+ {
+ service.closeConnection();
+ }
+
+ /**
+ * Sends an object to the server. This is the only way that
+ * methods should communicate with the server.
+ *
+ * @param msg The message to be sent.
+ */
+ final public void sendToServer(Object msg) throws IOException
+ {
+ service.sendToServer(msg);
+ }
+
+// ACCESSING METHODS ------------------------------------------------
+
+ /**
+ * @used to find out if the client is connnected.
+ */
+ final public boolean isConnected()
+ {
+ return service.isConnected();
+ }
+
+ /**
+ * @return the port number.
+ */
+ final public int getPort()
+ {
+ return service.getPort();
+ }
+
+ /**
+ * Sets the server port number for the next connection.
+ * Only has effect if the client is not currently connected.
+ *
+ * @param port the port number.
+ */
+ final public void setPort(int port)
+ {
+ service.setPort(port);
+ }
+
+ /**
+ * @return the host name.
+ */
+ final public String getHost()
+ {
+ return service.getHost();
+ }
+
+ /**
+ * Sets the server host for the next connection.
+ * Only has effect if the client is not currently connected.
+ *
+ * @param host the host name.
+ */
+ final public void setHost(String host)
+ {
+ service.setHost(host);
+ }
+
+ /**
+ * @return the client's Inet address.
+ */
+ final public InetAddress getInetAddress()
+ {
+ return service.getInetAddress();
+ }
+
+
+ /**
+ * This method is used to handle messages from the server. This method
+ * can be overriden but should always call notifyObservers().
+ *
+ * @param message The message received from the client.
+ */
+ protected void handleMessageFromServer(Object message)
+ {
+ setChanged();
+ notifyObservers(message);
+ }
+
+ /**
+ * Hook method called after the connection has been closed.
+ */
+ protected void connectionClosed()
+ {
+ setChanged();
+ notifyObservers(CONNECTION_CLOSED);
+ }
+
+ /**
+ * Hook method called each time an exception
+ * is raised by the client listening thread.
+ *
+ * @param exception the exception raised.
+ */
+ protected void connectionException(Exception exception)
+ {
+ setChanged();
+ notifyObservers(CONNECTION_EXCEPTION);
+ }
+
+ /**
+ * Hook method called after a connection has been established.
+ */
+ protected void connectionEstablished()
+ {
+ setChanged();
+ notifyObservers(CONNECTION_ESTABLISHED);
+ }
+}
diff --git a/code/simplechat2/ocsf/index.html b/code/simplechat2/ocsf/index.html
new file mode 100644
index 0000000..13025a0
--- /dev/null
+++ b/code/simplechat2/ocsf/index.html
@@ -0,0 +1,22 @@
+
+ AbstractServer class maintains a thread that waits
+* for connection attempts from clients. When a connection attempt occurs
+* it creates a new ConnectionToClient instance which
+* runs as a thread. When a client is thus connected to the
+* server, the two programs can then exchange Object
+* instances. handleMessageFromClient must be defined by
+* a concrete subclass. Several other hook methods may also be
+* overriden. ConnectionToClient .
+ */
+ private ThreadGroup clientThreadGroup;
+
+ /**
+ * Indicates if the listening thread is ready to stop. Set to
+ * false by default.
+ */
+ private boolean readyToStop = false;
+
+
+// CONSTRUCTOR ******************************************************
+
+ /**
+ * Constructs a new server.
+ *
+ * @param port the port number on which to listen.
+ */
+ public AbstractServer(int port)
+ {
+ this.port = port;
+
+ this.clientThreadGroup =
+ new ThreadGroup("ConnectionToClient threads")
+ {
+ // All uncaught exceptions in connection threads will
+ // be sent to the clientException callback method.
+ public void uncaughtException(
+ Thread thread, Throwable exception)
+ {
+ clientException((ConnectionToClient)thread, exception);
+ }
+ };
+ }
+
+
+// INSTANCE METHODS *************************************************
+
+ /**
+ * Begins the thread that waits for new clients.
+ * If the server is already in listening mode, this
+ * call has no effect.
+ *
+ * @exception IOException if an I/O error occurs
+ * when creating the server socket.
+ */
+ final public void listen() throws IOException
+ {
+ if (!isListening())
+ {
+ if (serverSocket == null)
+ {
+ serverSocket = new ServerSocket(getPort(), backlog);
+ }
+
+ serverSocket.setSoTimeout(timeout);
+ readyToStop = false;
+ connectionListener = new Thread(this);
+ connectionListener.start();
+ }
+ }
+
+ /**
+ * Causes the server to stop accepting new connections.
+ */
+ final public void stopListening()
+ {
+ readyToStop = true;
+ }
+
+ /**
+ * Closes the server socket and the connections with all clients.
+ * Any exception thrown while closing a client is ignored.
+ * If one wishes to catch these exceptions, then clients
+ * should be individually closed before calling this method.
+ * The method also stops listening if this thread is running.
+ * If the server is already closed, this
+ * call has no effect.
+ *
+ * @exception IOException if an I/O error occurs while
+ * closing the server socket.
+ */
+ final synchronized public void close() throws IOException
+ {
+ if (serverSocket == null)
+ return;
+ stopListening();
+ try
+ {
+ serverSocket.close();
+ }
+ finally
+ {
+ // Close the client sockets of the already connected clients
+ Thread[] clientThreadList = getClientConnections();
+ for (int i=0; iConnectionToClient instances.
+ */
+ synchronized final public Thread[] getClientConnections()
+ {
+ Thread[] clientThreadList = new
+ Thread[clientThreadGroup.activeCount()];
+
+ clientThreadGroup.enumerate(clientThreadList);
+
+ return clientThreadList;
+ }
+
+ /**
+ * Counts the number of clients currently connected.
+ *
+ * @return the number of clients currently connected.
+ */
+ final public int getNumberOfClients()
+ {
+ return clientThreadGroup.activeCount();
+ }
+
+ /**
+ * Returns the port number.
+ *
+ * @return the port number.
+ */
+ final public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * Sets the port number for the next connection.
+ * The server must be closed and restarted for the port
+ * change to be in effect.
+ *
+ * @param port the port number.
+ */
+ final public void setPort(int port)
+ {
+ this.port = port;
+ }
+
+ /**
+ * Sets the timeout time when accepting connections.
+ * The default is half a second. This means that stopping the
+ * server may take up to timeout duration to actually stop.
+ * The server must be stopped and restarted for the timeout
+ * change to be effective.
+ *
+ * @param timeout the timeout time in ms.
+ */
+ final public void setTimeout(int timeout)
+ {
+ this.timeout = timeout;
+ }
+
+ /**
+ * Sets the maximum number of waiting connections accepted by the
+ * operating system. The default is 20.
+ * The server must be closed and restarted for the backlog
+ * change to be in effect.
+ *
+ * @param backlog the maximum number of connections.
+ */
+ final public void setBacklog(int backlog)
+ {
+ this.backlog = backlog;
+ }
+
+// RUN METHOD -------------------------------------------------------
+
+ /**
+ * Runs the listening thread that allows clients to connect.
+ * Not to be called.
+ */
+ final public void run()
+ {
+ // call the hook method to notify that the server is starting
+ serverStarted();
+
+ try
+ {
+ // Repeatedly waits for a new client connection, accepts it, and
+ // starts a new thread to handle data exchange.
+ while(!readyToStop)
+ {
+ try
+ {
+ // Wait here for new connection attempts, or a timeout
+ Socket clientSocket = serverSocket.accept();
+
+ // When a client is accepted, create a thread to handle
+ // the data exchange, then add it to thread group
+
+ synchronized(this)
+ {
+ ConnectionToClient c = new ConnectionToClient(
+ this.clientThreadGroup, clientSocket, this);
+ }
+ }
+ catch (InterruptedIOException exception)
+ {
+ // This will be thrown when a timeout occurs.
+ // The server will continue to listen if not ready to stop.
+ }
+ }
+
+ // call the hook method to notify that the server has stopped
+ serverStopped();
+ }
+ catch (IOException exception)
+ {
+ if (!readyToStop)
+ {
+ // Closing the socket must have thrown a SocketException
+ listeningException(exception);
+ }
+ else
+ {
+ serverStopped();
+ }
+ }
+ finally
+ {
+ readyToStop = true;
+ connectionListener = null;
+ }
+ }
+
+
+// METHODS DESIGNED TO BE OVERRIDDEN BY CONCRETE SUBCLASSES ---------
+
+ /**
+ * 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) {}
+
+ /**
+ * 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) {}
+
+ /**
+ * 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) {}
+
+ /**
+ * Hook method called when the server stops accepting
+ * connections because an exception has been raised.
+ * The default implementation does nothing.
+ * This method may be overriden by subclasses.
+ *
+ * @param exception the exception raised.
+ */
+ protected void listeningException(Throwable exception) {}
+
+ /**
+ * Hook method called when the server starts listening for
+ * connections. The default implementation does nothing.
+ * The method may be overridden by subclasses.
+ */
+ protected void serverStarted() {}
+
+ /**
+ * Hook method called when the server stops accepting
+ * connections. The default implementation
+ * does nothing. This method may be overriden by subclasses.
+ */
+ protected void serverStopped() {}
+
+ /**
+ * Hook method called when the server is clased.
+ * The default implementation does nothing. This method may be
+ * overriden by subclasses. When the server is closed while still
+ * listening, serverStopped() will also be called.
+ */
+ protected void serverClosed() {}
+
+ /**
+ * Handles a command sent from one client to the server.
+ * This MUST be implemented by subclasses, who should respond to
+ * messages.
+ * This method is called by a synchronized method so it is also
+ * implcitly synchronized.
+ *
+ * @param msg the message sent.
+ * @param client the connection connected to the client that
+ * sent the message.
+ */
+ protected abstract void handleMessageFromClient(
+ Object msg, ConnectionToClient client);
+
+
+// METHODS TO BE USED FROM WITHIN THE FRAMEWORK ONLY ----------------
+
+ /**
+ * Receives a command sent from the client to the server.
+ * Called by the run method of ConnectionToClient
+ * instances that are watching for messages coming from the server
+ * This method is synchronized to ensure that whatever effects it has
+ * do not conflict with work being done by other threads. The method
+ * simply calls the handleMessageFromClient slot method.
+ *
+ * @param msg the message sent.
+ * @param client the connection connected to the client that
+ * sent the message.
+ */
+ final synchronized void receiveMessageFromClient(
+ Object msg, ConnectionToClient client)
+ {
+ this.handleMessageFromClient(msg, client);
+ }
+}
+// End of AbstractServer Class
diff --git a/code/simplechat2/ocsf/server/AdaptableServer.java b/code/simplechat2/ocsf/server/AdaptableServer.java
new file mode 100644
index 0000000..24462d4
--- /dev/null
+++ b/code/simplechat2/ocsf/server/AdaptableServer.java
@@ -0,0 +1,129 @@
+// This file contains material supporting section 6.13 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+* The AdaptableServer is an adapter class
+* that extends the AbstractServer class in place of
+* the AbstractObservableServer . ObservableOriginatorServer is a subclass
+* of ObservableServer that sends
+* OriginatorMessage instances to its observers.
+* This class should be used when the observers need to know
+* the orginator of the messages received. The originator
+* is null when the message sent concerns the server.
+*
+* Project Name: OCSF (Object Client-Server Framework) OriginatorMessage instance
+ * containing a reference to that client and
+ * the message defined by the static variable CLIENT_CONNECTED.
+ *
+ * @param client the connection connected to the client.
+ */
+ protected synchronized void clientConnected(ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(client, CLIENT_CONNECTED));
+ }
+
+ /**
+ * Method called each time a client connection is
+ * disconnected. It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing a reference to that client and
+ * the message defined by the static variable CLIENT_DISCONNECTED.
+ *
+ * @param client the connection connected to the client.
+ */
+ synchronized protected void clientDisconnected(ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(client, CLIENT_DISCONNECTED));
+ }
+
+
+ /**
+ * Method called each time an exception is raised
+ * by a client connection.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing a reference to that client and
+ * the message defined by the static variable CLIENT_EXCEPTION
+ * to which is appended the exception message.
+ *
+ * @param client the client that raised the exception.
+ * @param Throwable the exception thrown.
+ */
+ synchronized protected void clientException(
+ ConnectionToClient client, Throwable exception)
+ {
+ setChanged();
+ notifyObservers(
+ new OriginatorMessage(client,
+ CLIENT_EXCEPTION + exception.getMessage()));
+ }
+
+ /**
+ * Method called each time an exception is raised
+ * while listening.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing the message defined by the static variable LISTENING_EXCEPTION
+ * to which is appended the exception message.
+ * The originator is set to null.
+ *
+ * @param exception the exception raised.
+ */
+ protected synchronized void listeningException(Throwable exception)
+ {
+ setChanged();
+ notifyObservers(
+ new OriginatorMessage(null,
+ LISTENING_EXCEPTION + exception.getMessage()));
+ }
+
+ /**
+ * Method called each time the server is started.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing the message defined by the static variable SERVER_STARTED.
+ * The originator is set to null.
+ */
+ protected synchronized void serverStarted()
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(null, SERVER_STARTED));
+ }
+
+ /**
+ * Method called each time the server is stopped.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing the message defined by the static variable SERVER_STOPPED.
+ * The originator is set to null.
+ */
+ synchronized protected void serverStopped()
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(null, SERVER_STOPPED));
+ }
+
+ /**
+ * Method called each time the server is closed.
+ * It notifies observers by sending an
+ * OriginatorMessage instance
+ * containing the message defined by the static variable SERVER_CLOSED.
+ * The originator is set to null.
+ */
+ synchronized protected void serverClosed()
+ {
+ setChanged();
+ notifyObservers(new OriginatorMessage(null, SERVER_CLOSED));
+ }
+}
diff --git a/code/simplechat2/ocsf/server/ObservableServer.java b/code/simplechat2/ocsf/server/ObservableServer.java
new file mode 100644
index 0000000..5b16752
--- /dev/null
+++ b/code/simplechat2/ocsf/server/ObservableServer.java
@@ -0,0 +1,309 @@
+// This file contains material supporting section 6.13 of the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * This class acts as a subclass of AbstractServer
+ * and is also an Observable class.
+ * This means that when a message is received, all observers
+ * are notified.
+ *
+ * @author François Bélange
+ * @author Dr Timothy C. Lethbridge
+ * @author Dr Robert Laganière
+ * @version August 2000
+ */
+
+public class ObservableServer extends Observable
+{
+ // Class variables ************************************************
+
+ /**
+ * The string sent to the observers when a client has connected.
+ */
+ public static final String CLIENT_CONNECTED= "#OS:Client connected.";
+
+ /**
+ * The string sent to the observers when a client has disconnected.
+ */
+ public static final String CLIENT_DISCONNECTED= "#OS:Client disconnected.";
+
+ /**
+ * The string sent to the observers when an exception occurred with a client.
+ * The error message of that exception will be appended to this string.
+ */
+ public static final String CLIENT_EXCEPTION= "#OS:Client exception.";
+
+ /**
+ * The string sent to the observers when a listening exception occurred.
+ * The error message of that exception will be appended to this string.
+ */
+ public static final String LISTENING_EXCEPTION= "#OS:Listening exception.";
+
+ /**
+ * The string sent to the observers when the server has closed.
+ */
+ public static final String SERVER_CLOSED= "#OS:Server closed.";
+
+ /**
+ * The string sent to the observers when the server has started.
+ */
+ public static final String SERVER_STARTED= "#OS:Server started.";
+
+ /**
+ * The string sent to the observers when the server has stopped.
+ */
+ public static final String SERVER_STOPPED= "#OS:Server stopped.";
+
+
+ //Instance variables **********************************************
+
+ /**
+ * The service used to simulate multiple class inheritance.
+ */
+ private AdaptableServer service;
+
+
+ //Constructor *****************************************************
+
+ /**
+ * Constructs a new server.
+ *
+ * @param port the port on which to listen.
+ */
+ public ObservableServer(int port)
+ {
+ service = new AdaptableServer(port, this);
+ }
+
+ //Instance methods ************************************************
+
+ /**
+ * Begins the thread that waits for new clients
+ */
+ final public void listen() throws IOException
+ {
+ service.listen();
+ }
+
+ /**
+ * Causes the server to stop accepting new connections.
+ */
+ final public void stopListening()
+ {
+ service.stopListening();
+ }
+
+ /**
+ * Closes the server's connections with all clients.
+ */
+ final public void close() throws IOException
+ {
+ service.close();
+ }
+
+ /**
+ * Sends a message to every client connected to the server.
+ *
+ * @param msg The message to be sent
+ */
+ public void sendToAllClients(Object msg)
+ {
+ service.sendToAllClients(msg);
+ }
+
+// ACCESSING METHODS ------------------------------------------------
+
+ /**
+ * Used to find out if the server is accepting new clients.
+ */
+ final public boolean isListening()
+ {
+ return service.isListening();
+ }
+
+ /**
+ * Returns an array of containing the existing
+ * client connections. This can be used by
+ * concrete subclasses to implement messages that do something with
+ * each connection (e.g. kill it, send a message to it etc.)
+ *
+ * @return an array of Thread containing
+ * ConnectionToClient instances.
+ */
+ final public Thread[] getClientConnections()
+ {
+ return service.getClientConnections();
+ }
+
+ /**
+ * @return the number of clients currently connected.
+ */
+ final public int getNumberOfClients()
+ {
+ return service.getNumberOfClients();
+ }
+
+ /**
+ * @return the port number.
+ */
+ final public int getPort()
+ {
+ return service.getPort();
+ }
+
+ /**
+ * Sets the port number for the next connection.
+ * Only has effect if the server is not currently listening.
+ *
+ * @param port the port number.
+ */
+ final public void setPort(int port)
+ {
+ service.setPort(port);
+ }
+
+ /**
+ * Sets the timeout time when accepting connection.
+ * The default is half a second.
+ * The server must be stopped and restarted for the timeout
+ * change be in effect.
+ *
+ * @param timeout the timeout time in ms.
+ */
+ final public void setTimeout(int timeout)
+ {
+ service.setTimeout(timeout);
+ }
+
+ /**
+ * Sets the maximum number of
+ * waiting connections accepted by the operating system.
+ * The default is 20.
+ * The server must be closed and restart for the backlog
+ * change be in effect.
+ *
+ * @param backlog the maximum number of connections.
+ */
+ final public void setBacklog(int backlog)
+ {
+ service.setBacklog(backlog);
+ }
+
+ /**
+ * Hook method called each time a new client connection is
+ * accepted. The method may be overridden by subclasses.
+ *
+ * @param client the connection connected to the client.
+ */
+ protected synchronized void clientConnected(ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(CLIENT_CONNECTED);
+ }
+
+ /**
+ * Hook method called each time a client disconnects.
+ * The method may be overridden by subclasses.
+ *
+ * @param client the connection with the client.
+ */
+ protected synchronized void clientDisconnected(ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(CLIENT_DISCONNECTED);
+ }
+
+ /**
+ * Hook method called each time an exception
+ * is raised in a client thread.
+ * This implementation simply closes the
+ * client connection, ignoring any exception.
+ * The method may be overridden by subclasses.
+ *
+ * @param client the client that raised the exception.
+ * @param exception the exception raised.
+ */
+ protected synchronized void clientException(ConnectionToClient client,
+ Throwable exception)
+ {
+ setChanged();
+ notifyObservers(CLIENT_EXCEPTION);
+ try
+ {
+ client.close();
+ }
+ catch (Exception e) {}
+ }
+
+ /**
+ * This method is called when the server stops accepting
+ * connections because an exception has been raised.
+ * This implementation
+ * simply calls stopListening.
+ * This method may be overriden by subclasses.
+ *
+ * @param exception the exception raised.
+ */
+ protected synchronized void listeningException(Throwable exception)
+ {
+ setChanged();
+ notifyObservers(LISTENING_EXCEPTION);
+ stopListening();
+ }
+
+ /**
+ * This method is called when the server stops accepting
+ * connections for any reason. This method may be overriden by
+ * subclasses.
+ */
+ synchronized protected void serverStopped()
+ {
+ setChanged();
+ notifyObservers(SERVER_STOPPED);
+ }
+
+ /**
+ * This method is called when the server is closed.
+ * This method may be overriden by subclasses.
+ */
+ synchronized protected void serverClosed()
+ {
+ setChanged();
+ notifyObservers(SERVER_CLOSED);
+ }
+
+ /**
+ * This method is called when the server starts listening for
+ * connections. The method may be overridden by subclasses.
+ */
+ protected synchronized void serverStarted()
+ {
+ setChanged();
+ notifyObservers(SERVER_STARTED);
+ }
+
+ /**
+ * This method is used to handle messages coming from the client.
+ * Observers are notfied by receiveing the transmitted message.
+ * Note that, in this implementation, the information concerning
+ * the client that sent the message is lost.
+ * It can be overriden, but is still expected to call notifyObservers().
+ *
+ * @param message The message received from the client.
+ * @param client The connection to the client.
+ * @see ocsf.server.ObservableOriginatorServer
+ */
+ protected synchronized void handleMessageFromClient
+ (Object message, ConnectionToClient client)
+ {
+ setChanged();
+ notifyObservers(message);
+ }
+}
diff --git a/code/simplechat2/ocsf/server/OriginatorMessage.java b/code/simplechat2/ocsf/server/OriginatorMessage.java
new file mode 100644
index 0000000..a25d2b4
--- /dev/null
+++ b/code/simplechat2/ocsf/server/OriginatorMessage.java
@@ -0,0 +1,61 @@
+// This file contains material supporting the textbook:
+// "Object Oriented Software Engineering" and is issued under the open-source
+// license found at www.lloseng.com
+
+package ocsf.server;
+
+/**
+ * A message class used by the Observable layer of the OCSF in order to conserve
+ * information about the originator of a message.
+ *
+ * @author Dr. Robert Laganière
+ * @version July 2001
+ */
+public class OriginatorMessage
+{
+ /**
+ * The connection that originated the message
+ */
+ private ConnectionToClient originator;
+
+ /**
+ * The message.
+ */
+ private Object message;
+
+// Constructor ***************************************************************
+
+ /**
+ * Constructs an instance of an OriginatorMessage
+ *
+ * @param originator The client who created this message
+ * @param message The contents of the message
+ */
+ public OriginatorMessage(ConnectionToClient originator, Object message)
+ {
+ this.originator = originator;
+ this.message = message;
+ }
+
+// Accessor methods *********************************************************
+
+ /**
+ * Returns the originating connection.
+ *
+ * @return The connection from which the message originated.
+ */
+ public ConnectionToClient getOriginator()
+ {
+ return originator;
+ }
+
+ /**
+ * Returns the message's contents.
+ *
+ * @return The content of the message.
+ */
+ public Object getMessage()
+ {
+ return message;
+ }
+}
From bda6e28e0c38b19f23df1264d87ebbf7e6e35ae0 Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Sat, 23 May 2020 15:46:30 -0400
Subject: [PATCH 04/13] Implemented clientConnected and clientDisconnected
Fulfilled the requirements of 5 c)
---
code/simplechat2/EchoServer.java | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/code/simplechat2/EchoServer.java b/code/simplechat2/EchoServer.java
index d4f3a1a..8b58f39 100644
--- a/code/simplechat2/EchoServer.java
+++ b/code/simplechat2/EchoServer.java
@@ -71,6 +71,18 @@ protected void serverStopped()
System.out.println
("Server has stopped listening for connections.");
}
+
+ //Displays a message to all clients when a new client connects
+ public void clientConnected(ConnectionToClient client){
+ String message = client + " has connected!";
+ sendToAllClients(message);
+ }
+
+ //Displays a message to all clients when a client disconnects
+ public void clientDisconnected(ConnectionToClient client){
+ String message = client + "has disconnected";
+ sendToAllClients(message);
+ }
//Class methods ***************************************************
From 1deaffb4a7a304eeb42a834c8397c2f07f0983fb Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Sat, 23 May 2020 16:39:51 -0400
Subject: [PATCH 05/13] Implemented Client Commands
Satisfied 6 a) of the assignment
---
code/simplechat2/client/ChatClient.java | 107 ++++++++++++++++++++++--
1 file changed, 98 insertions(+), 9 deletions(-)
diff --git a/code/simplechat2/client/ChatClient.java b/code/simplechat2/client/ChatClient.java
index fb0e0ea..5065727 100644
--- a/code/simplechat2/client/ChatClient.java
+++ b/code/simplechat2/client/ChatClient.java
@@ -66,16 +66,104 @@ public void handleMessageFromServer(Object msg)
*/
public void handleMessageFromClientUI(String message)
{
- try
- {
- sendToServer(message);
+
+ char commandKey = "#".charAt(0);
+
+ if(message != null && message.charAt(0) == commandKey){
+
+ parseClientCommand(message);
+
}
- catch(IOException e)
- {
- clientUI.display
- ("Could not send message to server. Terminating client.");
- quit();
+ else{
+
+ try
+ {
+ sendToServer(message);
+ }
+ catch(IOException e)
+ {
+ clientUI.display
+ ("Could not send message to server. Terminating client.");
+ quit();
+ }
}
+ }
+
+ private void parseClientCommand(String message){
+
+ String[] messageList = message.split(" ");
+
+ switch(messageList[0]){
+ case "#quit":
+ quit();
+ break;
+
+ case "#logoff":
+ if(!isConnected()){
+ System.out.println("Error: Client Not Connected to a Server");
+ }
+ else{
+ try{
+ closeConnection();
+ }
+ catch(IOException e){
+ System.out.println(e.toString());
+ }
+ }
+ break;
+
+ case "#sethost":
+ if(!isConnected()){
+ setHost(messageList[1]);
+ }
+ else{
+ System.out.println("Error: Cannot Change Host While Connected to a Server");
+ }
+ break;
+
+ case "#setport":
+
+ if(!isConnected()){
+ setPort(Integer.parseInt(messageList[1]));
+ }
+ else{
+ System.out.println("Error: Cannot Change Port While Connected to a Server");
+ }
+
+ break;
+
+ case "#login":
+
+ if(!isConnected()){
+ try{
+ openConnection();
+ }
+ catch(IOException e){
+ System.out.println(e.toString());
+ }
+ }
+ else{
+ System.out.println("Error: Cannot login with an open connection");
+ }
+
+ break;
+
+ case "#gethost":
+ System.out.println("Host: " + this.getHost());
+ break;
+
+ case "#getport":
+ System.out.println("Port: " + this.getPort());
+ break;
+
+ default:
+ System.out.println("Error: Command Not Recognized");
+
+ }
+
+
+
+
}
/**
@@ -94,13 +182,14 @@ public void quit()
//Terminates Client when server terminates
public void connectionException(Exception Error){
+ System.out.println("The server has closed");
quit();
}
//Displays Message upon client termination
public void connectionClosed(){
- System.out.println("The server has closed");
+
}
}
From 10b5b29dbc843a97cd477639d2d8fb771e67ea95 Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Fri, 29 May 2020 04:16:47 -0400
Subject: [PATCH 06/13] Added Server-Side Chat Functionality
Completed 6 b)
---
code/simplechat2/EchoServer.java | 29 ++--------
code/simplechat2/ServerConsole.java | 82 +++++++++++++++++++++++++++++
2 files changed, 86 insertions(+), 25 deletions(-)
create mode 100644 code/simplechat2/ServerConsole.java
diff --git a/code/simplechat2/EchoServer.java b/code/simplechat2/EchoServer.java
index 8b58f39..5b497c0 100644
--- a/code/simplechat2/EchoServer.java
+++ b/code/simplechat2/EchoServer.java
@@ -3,6 +3,7 @@
// license found at www.lloseng.com
import java.io.*;
+import common.*;
import ocsf.server.*;
/**
@@ -23,6 +24,7 @@ public class EchoServer extends AbstractServer
* The default port to listen on.
*/
final public static int DEFAULT_PORT = 5555;
+ ChatIF serverChat;
//Constructors ****************************************************
@@ -31,9 +33,10 @@ public class EchoServer extends AbstractServer
*
* @param port The port number to connect on.
*/
- public EchoServer(int port)
+ public EchoServer(int port, ChatIF serverChat)
{
super(port);
+ this.serverChat = serverChat;
}
@@ -93,29 +96,5 @@ public void clientDisconnected(ConnectionToClient client){
* @param args[0] The port number to listen on. Defaults to 5555
* if no argument is entered.
*/
- public static void main(String[] args)
- {
- 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/code/simplechat2/ServerConsole.java b/code/simplechat2/ServerConsole.java
new file mode 100644
index 0000000..e16789a
--- /dev/null
+++ b/code/simplechat2/ServerConsole.java
@@ -0,0 +1,82 @@
+import java.io.*;
+import common.ChatIF;
+
+public class ServerConsole implements ChatIF {
+
+ //Instance Variables
+ EchoServer server;
+ int port;
+
+
+ //Constructors
+
+ public ServerConsole(int port){
+
+ this.port = port;
+
+ try{
+ server = new EchoServer(port, this);
+ server.listen();
+ }
+ catch(IOException e){
+ System.out.println("Error: Cannot setup server");
+ System.exit(1);
+ }
+
+ }
+
+ //Instance Methods
+
+ public void display(String message){
+ System.out.println(message);
+ }
+
+ public void accept()
+ {
+ try
+ {
+ BufferedReader fromServer =
+ new BufferedReader(new InputStreamReader(System.in));
+ String message;
+
+ while (true)
+ {
+ message = fromServer.readLine();
+ message = "SERVER MSG> " + message;
+ display(message);
+ server.sendToAllClients(message);
+ }
+ }
+ catch (Exception ex)
+ {
+ System.out.println("Unexpected error while reading from server!");
+ }
+ }
+
+
+ //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 DEFAULT_PORT = 5555; //Default 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
+ }
+
+ ServerConsole chat = new ServerConsole(port);
+ chat.accept(); //Wait for server data
+ }
+ }
+
From f812a5e13e7a691ca02bd609923bee07127e4260 Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Fri, 29 May 2020 05:36:31 -0400
Subject: [PATCH 07/13] Implemented Server Side Commands
Completed 7 c) and changed the implementation of 7 b) to be more efficient and closer reflect the client solution
---
code/simplechat2/EchoServer.java | 87 +++++++++++++++++++++++++++++
code/simplechat2/ServerConsole.java | 6 +-
2 files changed, 89 insertions(+), 4 deletions(-)
diff --git a/code/simplechat2/EchoServer.java b/code/simplechat2/EchoServer.java
index 5b497c0..d6d1976 100644
--- a/code/simplechat2/EchoServer.java
+++ b/code/simplechat2/EchoServer.java
@@ -25,6 +25,7 @@ public class EchoServer extends AbstractServer
*/
final public static int DEFAULT_PORT = 5555;
ChatIF serverChat;
+ boolean isClosed;
//Constructors ****************************************************
@@ -37,6 +38,7 @@ public EchoServer(int port, ChatIF serverChat)
{
super(port);
this.serverChat = serverChat;
+ isClosed = false;
}
@@ -63,6 +65,7 @@ protected void serverStarted()
{
System.out.println
("Server listening for connections on port " + getPort());
+ isClosed = false;
}
/**
@@ -86,6 +89,90 @@ public void clientDisconnected(ConnectionToClient client){
String message = client + "has disconnected";
sendToAllClients(message);
}
+
+ public void handleMessageFromServerUI(String message){
+
+ char commandKey = "#".charAt(0);
+
+ if(message != null && message.charAt(0) == commandKey){
+
+ parseServerCommand(message);
+
+ }
+ else{
+ message = "SERVER MSG> " + message;
+ System.out.println(message);
+ sendToAllClients(message);
+ }
+ }
+
+ private void parseServerCommand(String command){
+
+ String[] commandList = command.split(" ");
+
+ switch(commandList[0]){
+
+ case "#quit":
+ System.exit(0);
+ break;
+
+ case "#close":
+ try{
+ close();
+ }
+ catch(IOException e){
+ System.out.println("Error: Unknown IOException");
+ }
+ break;
+
+ case "#setport":
+
+ if(isClosed){
+
+ try{
+ setPort(Integer.parseInt(commandList[1]));
+ }
+ catch(IndexOutOfBoundsException e){
+ System.out.println("Error: Port Not Specified");
+ }
+ catch(NumberFormatException ex){
+ System.out.println("Error: Port Must be a Number");
+ }
+
+ }
+ else{
+ System.out.println("Error: Server Not Closed");
+ }
+
+ break;
+
+ case "#getport":
+ System.out.println("Port: " + getPort());
+ break;
+
+ case "#start":
+ try{
+ listen();
+ }
+ catch(IOException e){
+ System.out.println("Error: Unknown IOException");
+ }
+ break;
+
+ case "#stop":
+ stopListening();
+ break;
+
+ default:
+ System.out.println("Error: Command not Recognized");
+
+ }
+
+ }
+
+ public void serverClosed(){
+ isClosed = true;
+ }
//Class methods ***************************************************
diff --git a/code/simplechat2/ServerConsole.java b/code/simplechat2/ServerConsole.java
index e16789a..645cd8d 100644
--- a/code/simplechat2/ServerConsole.java
+++ b/code/simplechat2/ServerConsole.java
@@ -40,11 +40,9 @@ public void accept()
String message;
while (true)
- {
+ {
message = fromServer.readLine();
- message = "SERVER MSG> " + message;
- display(message);
- server.sendToAllClients(message);
+ server.handleMessageFromServerUI(message);
}
}
catch (Exception ex)
From 144dff1645709646f14311775469b4ee916a1707 Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Fri, 29 May 2020 05:49:06 -0400
Subject: [PATCH 08/13] LoginID added
Completed 7 a) and b)
---
code/simplechat2/ClientConsole.java | 20 +++++++++++++++-----
code/simplechat2/client/ChatClient.java | 6 +++++-
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/code/simplechat2/ClientConsole.java b/code/simplechat2/ClientConsole.java
index 7d7c2b6..5dd5ec1 100644
--- a/code/simplechat2/ClientConsole.java
+++ b/code/simplechat2/ClientConsole.java
@@ -41,11 +41,11 @@ public class ClientConsole implements ChatIF
* @param host The host to connect to.
* @param port The port to connect on.
*/
- public ClientConsole(String host, int port)
+ public ClientConsole(String host, int port, String loginID)
{
try
{
- client= new ChatClient(host, port, this);
+ client= new ChatClient(loginID, host, port, this);
}
catch(IOException exception)
{
@@ -106,10 +106,20 @@ public static void main(String[] args)
{
String host = "";
int port = 0; //The port number
+ String loginID = "";
try
{
- host = args[0];
+ loginID = args[0];
+ }
+ catch(ArrayIndexOutOfBoundsException e){
+ System.out.println("Error: No Login ID Provided");
+ System.exit(0);
+ }
+
+ try
+ {
+ host = args[1];
}
catch(ArrayIndexOutOfBoundsException e)
{
@@ -119,13 +129,13 @@ public static void main(String[] args)
try
{
- port = Integer.parseInt(args[1]);
+ port = Integer.parseInt(args[2]);
}
catch(ArrayIndexOutOfBoundsException e){
port = DEFAULT_PORT;
}
- ClientConsole chat= new ClientConsole(host, port);
+ ClientConsole chat= new ClientConsole(host, port, loginID);
chat.accept(); //Wait for console data
}
}
diff --git a/code/simplechat2/client/ChatClient.java b/code/simplechat2/client/ChatClient.java
index 5065727..8e255e1 100644
--- a/code/simplechat2/client/ChatClient.java
+++ b/code/simplechat2/client/ChatClient.java
@@ -26,6 +26,7 @@ public class ChatClient extends AbstractClient
* the display method in the client.
*/
ChatIF clientUI;
+ public String loginID;
//Constructors ****************************************************
@@ -38,12 +39,14 @@ public class ChatClient extends AbstractClient
* @param clientUI The interface type variable.
*/
- public ChatClient(String host, int port, ChatIF clientUI)
+ public ChatClient(String loginID, String host, int port, ChatIF clientUI)
throws IOException
{
super(host, port); //Call the superclass constructor
this.clientUI = clientUI;
+ this.loginID = loginID;
openConnection();
+ sendToServer("#login " + loginID);
}
@@ -137,6 +140,7 @@ private void parseClientCommand(String message){
if(!isConnected()){
try{
openConnection();
+ sendToServer("#login " + loginID);
}
catch(IOException e){
System.out.println(e.toString());
From 9d42aa75917dc8a750f44e2e98bd03effb19b2ab Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Fri, 29 May 2020 06:26:39 -0400
Subject: [PATCH 09/13] Implemented LoginID on the Server-Side
Completed 7 c)
---
code/simplechat2/EchoServer.java | 44 +++++++++++++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/code/simplechat2/EchoServer.java b/code/simplechat2/EchoServer.java
index d6d1976..704455c 100644
--- a/code/simplechat2/EchoServer.java
+++ b/code/simplechat2/EchoServer.java
@@ -3,6 +3,8 @@
// license found at www.lloseng.com
import java.io.*;
+import java.sql.Connection;
+
import common.*;
import ocsf.server.*;
@@ -54,7 +56,47 @@ public EchoServer(int port, ChatIF serverChat)
(Object msg, ConnectionToClient client)
{
System.out.println("Message received: " + msg + " from " + client);
- this.sendToAllClients(msg);
+
+ char commandKey = "#".charAt(0);
+ String msgString = msg.toString();
+
+ if(msg!= null && msgString.charAt(0) == commandKey){
+ handleClientLogin(msgString, client);
+ }
+ else{
+ msg = client.getInfo("loginID") + ": " + msg;
+ this.sendToAllClients(msg);
+ }
+ }
+
+ private void handleClientLogin(String msg, ConnectionToClient client){
+
+ String[] loginList = msg.split(" ");
+
+ switch(loginList[0]){
+ case "#login":
+ if(client.getInfo("loginID") == null){
+ client.setInfo("loginID", loginList[1]);
+ }
+ else{
+ System.out.println("Error: Client Already Logged In");
+
+ try{
+ client.sendToClient("Error: Client Already Logged In");
+ client.close();
+ }
+ catch(IOException e){
+ System.out.println("Error: IOException Thrown on Client Invalid Login");
+ }
+
+ }
+ break;
+
+ default:
+ System.out.println("Error: Unknown Client-Sent Command");
+ }
+
+
}
/**
From c98bf941aab82191de55b0c00935a3eb4a4f7f2b Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Fri, 29 May 2020 12:07:33 -0400
Subject: [PATCH 10/13] Made some changes to fix testcases
---
code/simplechat2/ClientConsole.java | 18 ++++-------
code/simplechat2/EchoServer.java | 40 ++++++++++++++++++++-----
code/simplechat2/ServerConsole.java | 10 +++++--
code/simplechat2/client/ChatClient.java | 16 ++++++----
4 files changed, 56 insertions(+), 28 deletions(-)
diff --git a/code/simplechat2/ClientConsole.java b/code/simplechat2/ClientConsole.java
index 5dd5ec1..3188c39 100644
--- a/code/simplechat2/ClientConsole.java
+++ b/code/simplechat2/ClientConsole.java
@@ -43,16 +43,9 @@ public class ClientConsole implements ChatIF
*/
public ClientConsole(String host, int port, String loginID)
{
- try
- {
- client= new ChatClient(loginID, host, port, this);
- }
- catch(IOException exception)
- {
- System.out.println("Error: Can't setup connection!"
- + " Terminating client.");
- System.exit(1);
- }
+
+ client= new ChatClient(loginID, host, port, this);
+
}
@@ -78,8 +71,7 @@ public void accept()
}
catch (Exception ex)
{
- System.out.println
- ("Unexpected error while reading from console!");
+ // System.out.println("Unexpected error while reading from console!");
}
}
@@ -113,7 +105,7 @@ public static void main(String[] args)
loginID = args[0];
}
catch(ArrayIndexOutOfBoundsException e){
- System.out.println("Error: No Login ID Provided");
+ System.out.println("ERROR - No login ID specified. Connection aborted.");
System.exit(0);
}
diff --git a/code/simplechat2/EchoServer.java b/code/simplechat2/EchoServer.java
index 704455c..c5b6c35 100644
--- a/code/simplechat2/EchoServer.java
+++ b/code/simplechat2/EchoServer.java
@@ -55,7 +55,7 @@ public EchoServer(int port, ChatIF serverChat)
public void handleMessageFromClient
(Object msg, ConnectionToClient client)
{
- System.out.println("Message received: " + msg + " from " + client);
+ System.out.println("Message received: " + msg + " from " + client.getInfo("loginID"));
char commandKey = "#".charAt(0);
String msgString = msg.toString();
@@ -64,7 +64,7 @@ public EchoServer(int port, ChatIF serverChat)
handleClientLogin(msgString, client);
}
else{
- msg = client.getInfo("loginID") + ": " + msg;
+ msg = client.getInfo("loginID") + "> " + msg;
this.sendToAllClients(msg);
}
}
@@ -77,6 +77,10 @@ private void handleClientLogin(String msg, ConnectionToClient client){
case "#login":
if(client.getInfo("loginID") == null){
client.setInfo("loginID", loginList[1]);
+
+ String message = client.getInfo("loginID") + " has logged on.";
+ System.out.println(message);
+ sendToAllClients(message);
}
else{
System.out.println("Error: Client Already Logged In");
@@ -119,16 +123,17 @@ protected void serverStopped()
System.out.println
("Server has stopped listening for connections.");
}
-
- //Displays a message to all clients when a new client connects
+
public void clientConnected(ConnectionToClient client){
- String message = client + " has connected!";
- sendToAllClients(message);
+
+ System.out.println("A new client is attempting to connect to the server.");
+
}
//Displays a message to all clients when a client disconnects
public void clientDisconnected(ConnectionToClient client){
- String message = client + "has disconnected";
+ String message = client.getInfo("loginID") + " has disconnected";
+ System.out.println(message);
sendToAllClients(message);
}
@@ -160,6 +165,7 @@ private void parseServerCommand(String command){
case "#close":
try{
+ sendToAllClients("SERVER SHUTTING DOWN! DISCONNECTING!");
close();
}
catch(IOException e){
@@ -203,6 +209,7 @@ private void parseServerCommand(String command){
case "#stop":
stopListening();
+ sendToAllClients("WARNING - The server has stopped listening for connections");
break;
default:
@@ -225,5 +232,24 @@ public void serverClosed(){
* @param args[0] The port number to listen on. Defaults to 5555
* if no argument is entered.
*/
+
+ public static void main(String[] args)
+ {
+ int DEFAULT_PORT = 5555; //Default 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
+ }
+
+ ServerConsole chat = new ServerConsole(port);
+ chat.accept(); //Wait for client data
+ }
+
}
//End of EchoServer class
diff --git a/code/simplechat2/ServerConsole.java b/code/simplechat2/ServerConsole.java
index 645cd8d..9bd71b0 100644
--- a/code/simplechat2/ServerConsole.java
+++ b/code/simplechat2/ServerConsole.java
@@ -59,11 +59,12 @@ public void accept()
*
* @param args[0] The host to connect to.
*/
+
public static void main(String[] args)
{
int DEFAULT_PORT = 5555; //Default Port
int port = 0; //Port to listen on
-
+
try
{
port = Integer.parseInt(args[0]); //Get port from command line
@@ -72,9 +73,12 @@ public static void main(String[] args)
{
port = DEFAULT_PORT; //Set port to 5555
}
-
+
ServerConsole chat = new ServerConsole(port);
- chat.accept(); //Wait for server data
+ chat.accept(); //Wait for client data
}
+
}
+
+
diff --git a/code/simplechat2/client/ChatClient.java b/code/simplechat2/client/ChatClient.java
index 8e255e1..ca8f8dd 100644
--- a/code/simplechat2/client/ChatClient.java
+++ b/code/simplechat2/client/ChatClient.java
@@ -39,14 +39,19 @@ public class ChatClient extends AbstractClient
* @param clientUI The interface type variable.
*/
- public ChatClient(String loginID, String host, int port, ChatIF clientUI)
- throws IOException
+ public ChatClient(String loginID, String host, int port, ChatIF clientUI)
{
super(host, port); //Call the superclass constructor
this.clientUI = clientUI;
this.loginID = loginID;
+
+ try{
openConnection();
sendToServer("#login " + loginID);
+ }
+ catch(IOException e){
+ System.out.println("Cannot open connection. Awaiting command.");
+ }
}
@@ -118,6 +123,7 @@ private void parseClientCommand(String message){
case "#sethost":
if(!isConnected()){
setHost(messageList[1]);
+ System.out.println("Host set to: " + getHost() + ".");
}
else{
System.out.println("Error: Cannot Change Host While Connected to a Server");
@@ -128,6 +134,7 @@ private void parseClientCommand(String message){
if(!isConnected()){
setPort(Integer.parseInt(messageList[1]));
+ System.out.println("Port set to: " + getPort() + ".");
}
else{
System.out.println("Error: Cannot Change Port While Connected to a Server");
@@ -186,14 +193,13 @@ public void quit()
//Terminates Client when server terminates
public void connectionException(Exception Error){
- System.out.println("The server has closed");
- quit();
+ System.out.println("Abnormal termination of connection.");
}
//Displays Message upon client termination
public void connectionClosed(){
-
+ System.out.println("Connection Closed.");
}
}
From 52f1efe7ede4d8d1534ae6f370536dfe87bd7ed4 Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Fri, 29 May 2020 13:21:37 -0400
Subject: [PATCH 11/13] Temp Push, Troubleshooting Issues
---
code/simplechat2/EchoServer.java | 3 ++-
code/simplechat2/client/ChatClient.java | 4 ----
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/code/simplechat2/EchoServer.java b/code/simplechat2/EchoServer.java
index c5b6c35..36c16fe 100644
--- a/code/simplechat2/EchoServer.java
+++ b/code/simplechat2/EchoServer.java
@@ -83,7 +83,6 @@ private void handleClientLogin(String msg, ConnectionToClient client){
sendToAllClients(message);
}
else{
- System.out.println("Error: Client Already Logged In");
try{
client.sendToClient("Error: Client Already Logged In");
@@ -137,6 +136,7 @@ public void clientDisconnected(ConnectionToClient client){
sendToAllClients(message);
}
+
public void handleMessageFromServerUI(String message){
char commandKey = "#".charAt(0);
@@ -179,6 +179,7 @@ private void parseServerCommand(String command){
try{
setPort(Integer.parseInt(commandList[1]));
+ System.out.println("Port Set to: " + getPort());
}
catch(IndexOutOfBoundsException e){
System.out.println("Error: Port Not Specified");
diff --git a/code/simplechat2/client/ChatClient.java b/code/simplechat2/client/ChatClient.java
index ca8f8dd..1ac8ac9 100644
--- a/code/simplechat2/client/ChatClient.java
+++ b/code/simplechat2/client/ChatClient.java
@@ -171,10 +171,6 @@ private void parseClientCommand(String message){
System.out.println("Error: Command Not Recognized");
}
-
-
-
-
}
/**
From 88293d18f363ba976eedf7407da7b21497025f92 Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Fri, 29 May 2020 13:45:36 -0400
Subject: [PATCH 12/13] Fixed Disconnect Messages
---
code/simplechat2/EchoServer.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/simplechat2/EchoServer.java b/code/simplechat2/EchoServer.java
index 36c16fe..294b425 100644
--- a/code/simplechat2/EchoServer.java
+++ b/code/simplechat2/EchoServer.java
@@ -130,7 +130,7 @@ public void clientConnected(ConnectionToClient client){
}
//Displays a message to all clients when a client disconnects
- public void clientDisconnected(ConnectionToClient client){
+ public void clientException(ConnectionToClient client, Throwable e){
String message = client.getInfo("loginID") + " has disconnected";
System.out.println(message);
sendToAllClients(message);
From 0cc834483055affc0b56463b64632bca84491008 Mon Sep 17 00:00:00 2001
From: jksza042 <55514862+jksza042@users.noreply.github.com>
Date: Fri, 29 May 2020 13:55:06 -0400
Subject: [PATCH 13/13] Added Final Test Logs
---
.../simplechat2/TestCases - Phase 1 and 2.txt | 428 ++++++++++++++++++
1 file changed, 428 insertions(+)
create mode 100644 code/simplechat2/TestCases - Phase 1 and 2.txt
diff --git a/code/simplechat2/TestCases - Phase 1 and 2.txt b/code/simplechat2/TestCases - Phase 1 and 2.txt
new file mode 100644
index 0000000..805393e
--- /dev/null
+++ b/code/simplechat2/TestCases - Phase 1 and 2.txt
@@ -0,0 +1,428 @@
+Name: Jacob Kszan
+Student Number: 300132837
+Email: jksza042@uottawa.ca
+
+PHASE 1 TESTING (Sorry if it's a bit unorganized, phase 2 is better)
+
+Client 3
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+Testcase 1007!
+> Testcase 1007!
+> Could not send message to server. Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
+
+Client 2
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+Test> Testcase 1007!
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
+
+Client 1
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+Currently on Testcase 1004
+> Currently on Testcase 1004
+Testcase 1005
+> Could not send message to server. Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+This is Testcase 1006
+> This is Testcase 1006
+> Testcase 1007!
+> Could not send message to server. Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+'C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1' is not recognized as an internal or external command,
+operable program or batch file.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>Test> Testcase 1007!
+'Test' is not recognized as an internal or external command,
+operable program or batch file.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+FinFin
+
+
+FIniewfnoewf> FinFin
+>
+>
+Done
+> FIniewfnoewfDone
+d
+> d
+> Final FFFinTestcase 1013, final test
+e
+> Could not send message to server. Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
+
+Server:
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java EchoServer
+Server listening for connections on port 5555
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java ClientConsole
+Error: Can't setup connection! Terminating client.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java EchoServer
+Server listening for connections on port 5555
+Message received: Currently on Testcase 1004 from 127.0.0.1 (127.0.0.1)
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>java EchoServer
+Server listening for connections on port 5555
+Message received: null from 127.0.0.1 (127.0.0.1)
+Message received: This is Testcase 1006 from 127.0.0.1 (127.0.0.1)
+Message received: Testcase 1007! from 127.0.0.1 (127.0.0.1)
+Message received: null from 127.0.0.1 (127.0.0.1)
+Message received: This message is from my Desktop to my Laptop! from Nev-PC (192.168.2.29)
+Message received: null from Nev-PC (192.168.2.29)
+Message received: FinFin from 127.0.0.1 (127.0.0.1)
+Message received: from 127.0.0.1 (127.0.0.1)
+Message received: from 127.0.0.1 (127.0.0.1)
+Message received: FIniewfnoewfDone from 127.0.0.1 (127.0.0.1)
+Message received: d from 127.0.0.1 (127.0.0.1)
+Message received: Final FFFinTestcase 1013, final test from 127.0.0.1 (127.0.0.1)
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat1>
+
+
+
+-------------------------------------------------------------------------------------------------------------------------------
+
+PHASE 2 TESTING
+
+Testcase 2001:
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+
+Testcase 2002:
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole
+ERROR - No login ID specified. Connection aborted.
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>
+
+Testcase 2003:
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Testcase2003
+Cannot open connection. Awaiting command.
+
+Testcase 2004:
+
+Client -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Testcase2004
+> Testcase2004 has logged on.
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login Testcase2004 from null
+Testcase2004 has logged on.
+
+Testcase 2005:
+
+Client -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Testcase2004
+> Testcase2004 has logged on.
+This is Testcase 2005!
+> Testcase2004> This is Testcase 2005!
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login Testcase2004 from null
+Testcase2004 has logged on.
+Message received: This is Testcase 2005! from Testcase2004
+
+Testcase 2006:
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login YipOne from null
+YipOne has logged on.
+A new client is attempting to connect to the server.
+Message received: #login YipTwo from null
+YipTwo has logged on.
+Message received: YipTwo here! from YipTwo
+Message received: YipOne Here! from YipOne
+YipServer also present
+SERVER MSG> YipServer also present
+
+Client 1 -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole YipOne
+> YipOne has logged on.
+> YipTwo has logged on.
+> YipTwo> YipTwo here!
+YipOne Here!
+> YipOne> YipOne Here!
+> SERVER MSG> YipServer also present
+
+Client 2 -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole YipTwo
+> YipTwo has logged on.
+YipTwo here!
+> YipTwo> YipTwo here!
+> YipOne> YipOne Here!
+> SERVER MSG> YipServer also present
+
+Testcase 2007:
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+#quit
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>
+
+Testcase 2008:
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login First from null
+First has logged on.
+#stop
+Server has stopped listening for connections.
+Message received: Still here from First
+#start
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login Second from null
+Second has logged on.
+
+Client 1 -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole First
+> First has logged on.
+> WARNING - The server has stopped listening for connections
+Still here
+> First> Still here
+> Second has logged on.
+
+Client 2 -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Second
+> Second has logged on.
+
+Testcase 2009:
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login Connector from null
+Connector has logged on.
+#stop
+Server has stopped listening for connections.
+#close
+Connector has disconnected
+
+Client -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Connector
+> Connector has logged on.
+> WARNING - The server has stopped listening for connections
+> SERVER SHUTTING DOWN! DISCONNECTING!
+Abnormal termination of connection.
+
+
+
+Testcase 2009 (There are two Testcase 2009):
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login One from null
+One has logged on.
+#close
+Server has stopped listening for connections.
+One has disconnected
+#start
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login Two from null
+Two has logged on.
+
+Client -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole One
+> One has logged on.
+> SERVER SHUTTING DOWN! DISCONNECTING!
+Abnormal termination of connection.
+#quit
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Two
+> Two has logged on.
+
+
+
+Testcase 2010:
+
+Client -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Test
+Cannot open connection. Awaiting command.
+#quit
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>
+
+
+
+Testcase 2011:
+
+Client -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Yipper
+> Yipper has logged on.
+#logoff
+Connection Closed.
+
+Testcase 2012:
+
+Client -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Testcase
+Cannot open connection. Awaiting command.
+#sethost newhost
+Host set to: newhost.
+#setport 1234
+Port set to: 1234.
+
+Testcase 2013:
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ServerConsole 1234
+Server listening for connections on port 1234
+
+Testcase 2014:
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ServerConsole 1234
+Server listening for connections on port 1234
+A new client is attempting to connect to the server.
+Message received: #login Tester from null
+Tester has logged on.
+
+Client -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Tester localhost 1234
+> Tester has logged on.
+
+Testcase 2015:
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login Desktop from null
+Desktop has logged on.
+A new client is attempting to connect to the server.
+Message received: #login Laptop from null
+Laptop has logged on.
+Message received: Laptop here! from Laptop
+Message received: Desktop here! from Desktop
+#close
+Server has stopped listening for connections.
+Laptop has disconnected
+Desktop has disconnected
+#setport 1234
+Port Set to: 1234
+#start
+Server listening for connections on port 1234
+A new client is attempting to connect to the server.
+Message received: #login Desktop from null
+Desktop has logged on.
+Message received: Desktop Back! from Desktop
+A new client is attempting to connect to the server.
+Message received: #login Laptop from null
+Laptop has logged on.
+Message received: Laptop back! from Laptop
+
+Client 1 -
+
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Laptop
+> Laptop has logged on.
+Laptop here!
+> Laptop> Laptop here!
+> Desktop> Desktop here!
+> SERVER SHUTTING DOWN! DISCONNECTING!
+Abnormal termination of connection.
+#setport 1234
+Port set to: 1234.
+#login Laptop
+> Laptop has logged on.
+Laptop back!
+> Laptop> Laptop back!
+
+Client 2 -
+
+C:\Users\Nev\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole Deskto
+p JKTOP
+> Desktop has logged on.
+> Laptop has logged on.
+> Laptop> Laptop here!
+Desktop here!
+> Desktop> Desktop here!
+> SERVER SHUTTING DOWN! DISCONNECTING!
+> Laptop has disconnected
+Abnormal termination of connection.
+#setport 1234
+Port set to: 1234.
+#login Desktop
+> Desktop has logged on.
+Desktop Back!
+> Desktop> Desktop Back!
+> Laptop has logged on.
+> Laptop> Laptop back!
+
+Testcase 2016:
+
+Server -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java EchoServer
+Server listening for connections on port 5555
+A new client is attempting to connect to the server.
+Message received: #login UserOne from null
+UserOne has logged on.
+A new client is attempting to connect to the server.
+Message received: #login UserTwo from null
+UserTwo has logged on.
+A new client is attempting to connect to the server.
+Message received: #login UserThree from null
+UserThree has logged on.
+UserOne has disconnected
+UserTwo has disconnected
+
+Client 1 -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole UserOne
+> UserOne has logged on.
+> UserTwo has logged on.
+> UserThree has logged on.
+#quit
+Connection Closed.
+
+Client 2 -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole UserTwo
+> UserTwo has logged on.
+> UserThree has logged on.
+> UserOne has disconnected
+#logoff
+Connection Closed.
+
+
+Client 3 -
+C:\Users\Nevada\Documents\GitHub\Lloseng\code\simplechat2>java ClientConsole UserThree
+> UserThree has logged on.
+> UserOne has disconnected
+> UserTwo has disconnected
+
+
+
+I do not have the computers and operating systems to do some of the tests, so some are omitted
+
+
+
+