From 5689f5053c8c9039d2933f458a0f8939116960e7 Mon Sep 17 00:00:00 2001 From: Hai HoDac <hhodac@student.unimelb.edu.au> Date: Thu, 24 Oct 2019 20:34:16 +1100 Subject: [PATCH] Merged with Isaac's code Add color to text --- src/GUI/ApplicationMain.java | 99 +++++++++++++++++++++---- src/GUI/ChatScreen.java | 7 +- src/GUI/StartScreen.java | 70 ++++++++++++++++-- src/client/Client.java | 117 +++++++++++++++++++++--------- src/client/ClientUpdate.java | 6 ++ src/remote/IClientController.java | 4 +- src/remote/IClientUpdate.java | 2 +- src/server/ClientController.java | 34 ++++++--- 8 files changed, 271 insertions(+), 68 deletions(-) diff --git a/src/GUI/ApplicationMain.java b/src/GUI/ApplicationMain.java index 25d25f4..2e6823a 100644 --- a/src/GUI/ApplicationMain.java +++ b/src/GUI/ApplicationMain.java @@ -9,6 +9,7 @@ import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.rmi.RemoteException; import java.util.ArrayList; +import java.util.Random; public class ApplicationMain extends JPanel { private Client client; @@ -24,6 +25,33 @@ public class ApplicationMain extends JPanel { return frame; } + public int showManagerQuitMessage() { + int answer = JOptionPane.showConfirmDialog(null, + "Do you want to terminate the application for all the users?", + "Close the application", JOptionPane.YES_NO_CANCEL_OPTION); + return answer; + } + + public int showNextManagerMessage() { + int answer = JOptionPane.showConfirmDialog(null, + "Before leaving, do you want to choose the next manager manually?", + "Close the application", JOptionPane.YES_NO_CANCEL_OPTION); + return answer; + } + + public String showAssignManagerMessage() { + int numUsers = client.getChatScreen().getKickUserComboBox().getItemCount(); + String[] userOptions = new String[numUsers]; + for (int i = 0; i < numUsers; i++) { + userOptions[i] = client.getChatScreen().getKickUserComboBox().getItemAt(i).toString(); + } + String input = (String) JOptionPane.showInputDialog(null, "Choose the next manager", + "Assign a new manager before leaving", JOptionPane.QUESTION_MESSAGE, null, + userOptions, // Array of choices + userOptions[0]); // Initial choice + return input; + } + public ApplicationMain(Client client) { this.client = client; this.chatScreen = new ChatScreen(client); @@ -82,24 +110,52 @@ public class ApplicationMain extends JPanel { @Override public void windowClosing(WindowEvent arg0) { - int reply = JOptionPane.showConfirmDialog(null, - "Are you sure you want to quit the session?", - "Shut down session", JOptionPane.YES_NO_OPTION); - - if( reply == JOptionPane.YES_OPTION ) - { - try - { - client.getClientController().quit(client.getUserName()); + + try { + if (client.getUserName().equals(client.getClientController().getAdmin())) { + + int terminateAppAnswer = showManagerQuitMessage(); + // If the manager terminates the application + if (terminateAppAnswer == 0) { + client.getClientController().kickAll(client.getUserName()); + exitApplication(); + } + else if (terminateAppAnswer == 1) { + int answer = showNextManagerMessage(); + // If the manager wants to assign the next manager manually + if (answer == 0) { + String newManager = showAssignManagerMessage(); + client.getClientController().assignAdmin(client.getUserName(), newManager); + client.getClientController().quit(client.getUserName()); + exitApplication(); + } + // If the manager wants to assign the next manager by random choice + if (answer == 1) { + int numUsers = client.getChatScreen().getKickUserComboBox().getItemCount(); + Random random = new Random(); + int randomUserIndex = random.nextInt(numUsers); + String newManager = client.getChatScreen().getKickUserComboBox().getItemAt(randomUserIndex).toString(); + client.getClientController().assignAdmin(client.getUserName(), newManager); + client.getClientController().quit(client.getUserName()); + exitApplication(); + } + } + } - catch (RemoteException e) - { - StartScreen.showErrorMessage("Error in quitting the server"); - //e.printStackTrace(); + else { + int reply = JOptionPane.showConfirmDialog(null, + "Are you sure you want to quit the session?", + "Shut down session", JOptionPane.YES_NO_OPTION); + if( reply == 0 ) + { + client.getClientController().quit(client.getUserName()); + exitApplication(); + } } - - System.exit(0); + } catch (RemoteException e) { + e.printStackTrace(); } + } }); @@ -108,6 +164,19 @@ public class ApplicationMain extends JPanel { frame.setResizable(false); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public void exitApplication(){ + System.out.println("I am in exit application"); + frame.setVisible(false); + frame.dispose(); + client.setVisibleStartScreen(); + } + + public void setVisible() { frame.setVisible(true); + chatScreen.setUserName(client.getUserName()); } } diff --git a/src/GUI/ChatScreen.java b/src/GUI/ChatScreen.java index 1c70a5f..6e86ccf 100644 --- a/src/GUI/ChatScreen.java +++ b/src/GUI/ChatScreen.java @@ -11,10 +11,10 @@ import java.rmi.RemoteException; public class ChatScreen { public JPanel panel2; + public JPanel othersPanel; private JButton sendButton; - private JPanel othersPanel; private JComboBox sendMessageToComboBox; private JTextArea chatDisplayBox; private JComboBox kickUserComboBox; @@ -53,6 +53,11 @@ public class ChatScreen { this.yourNameDisplay.setText(userName); } + public void setManagerName(String manager) + { + this.managersNameDisplay.setText(manager); + } + public JButton getSendButton() { return sendButton; } diff --git a/src/GUI/StartScreen.java b/src/GUI/StartScreen.java index 9494617..6b6a4b5 100644 --- a/src/GUI/StartScreen.java +++ b/src/GUI/StartScreen.java @@ -4,21 +4,29 @@ import client.Client; import javax.imageio.ImageIO; import javax.swing.*; +import java.awt.event.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; + public class StartScreen { private JTextPane information; private JPanel panel1; private JTextField usernameField; private JButton joinButton; + + private JTextField textField2; + private boolean kickedOut; + private boolean appTerminated; + private JTextField serverField; private JTextField textField3; private JPasswordField passwordField; + JFrame frame; private Client client; @@ -28,11 +36,6 @@ public class StartScreen { this.client = client; } -// public static void main(String[] args) { -// new StartScreen().go(); -// } - - ActionListener actionListener = new ActionListener() { public void actionPerformed(ActionEvent e) @@ -49,9 +52,17 @@ public class StartScreen { { frame.setVisible(false); frame.dispose(); - client.startApplication(); + if (client.getApplicationMain().getFrame() == null) { + client.startApplication(); + } + else { + client.clearChat(); + client.clearDrawingArea(); + client.setVisibleApplication(); + } + } - else if( connectionStatus == 2 ) + else if( connectionStatus == 2 || connectionStatus == 6 ) { showErrorMessage("Duplicate usernameField: Please enter a new usernameField"); } @@ -63,6 +74,12 @@ public class StartScreen { { showErrorMessage("Incorrect Password"); } + else if( connectionStatus == 5 ) + { + frame.setVisible(false); + frame.dispose(); + client.setVisibleApplication(); + } else { showErrorMessage("Unknown Connection Status"); @@ -72,6 +89,8 @@ public class StartScreen { }; + + public static void showErrorMessage(String message) { JOptionPane.showMessageDialog(null, @@ -91,6 +110,42 @@ public class StartScreen { //frame.getContentPane().add(new JPanelWithBackground("sample.jpeg")); frame.setVisible(true); + + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowOpened(WindowEvent e) { + if (isAppTerminated()){ + showKickAllMessage(); + setAppTerminated(false); + } + } + }); + } + + public void setVisible(){ + frame.setVisible(true); + } + + public void setKickedOut(boolean kickedOut) { + this.kickedOut = kickedOut; + } + + public void setAppTerminated(boolean appTerminated) { + this.appTerminated = appTerminated; + } + + public boolean isKickedOut() { + return kickedOut; + } + + public boolean isAppTerminated() { + return appTerminated; + } + + public void showKickAllMessage() { + JOptionPane.showMessageDialog(null, + "The manager terminated the application", "Application terminated", + JOptionPane.ERROR_MESSAGE); } // public class JPanelWithBackground extends JPanel @@ -113,4 +168,5 @@ public class StartScreen { // g.drawImage(backgroundImage, 0, 0, this); // } // } + } diff --git a/src/client/Client.java b/src/client/Client.java index 7397f62..a241d33 100644 --- a/src/client/Client.java +++ b/src/client/Client.java @@ -20,6 +20,7 @@ public class Client private final String DEFAULT_SERVER_ADDRESS = "localhost"; private final EncryptionUpdate encryptionUpdate; + private String defaultUserName; private String userName; private String serverAddress; @@ -40,6 +41,11 @@ public class Client return this.userName; } + public String getDefaultUserName() + { + return this.defaultUserName; + } + public void setUserName(String userName) { this.userName = userName; @@ -56,7 +62,6 @@ public class Client } - public ApplicationMain getApplicationMain() { return applicationMain; } public ChatScreen getChatScreen() { @@ -75,10 +80,14 @@ public class Client public IDrawingController getDrawingController() { return drawingController; } + public StartScreen getStartScreen() { + return startScreen; + } + public Client(String username) throws RemoteException, NoSuchProviderException, NoSuchAlgorithmException { - this.userName = username; + this.defaultUserName = username; this.clientUpdate = new ClientUpdate(this); this.chatUpdate = new ChatUpdate(this); this.drawingUpdate = new DrawingUpdate(this); @@ -107,6 +116,10 @@ public class Client startScreen.go(); } + public void setVisibleStartScreen(){ + startScreen.setVisible(); + } + public void startApplication() { @@ -114,59 +127,97 @@ public class Client applicationMain.getChatScreen().setManagerToolsVisibility(); } + public void setVisibleApplication(){ + applicationMain.setVisible(); + } + // return = 1 -> connected successfully // return = 2 -> duplicate username // return = 3 -> error in locating the server // return = 4 -> incorrect password entered + // return = 5 -> re-connected successfully + // return = 6 -> duplicate username when re-connecting public int connect(String userName, String serverAddress, String password) { - if( !userName.trim().isEmpty() ) + try { - setUserName(userName); - } - userName = getUserName(); + if (userName.trim().isEmpty()) { + userName = getDefaultUserName(); + } + if (serverAddress.trim().isEmpty()) { + serverAddress = DEFAULT_SERVER_ADDRESS; + } + // If the client wants to reconnect to the same server using the same username + if (registryServer != null && getUserName().equals(userName) + && getServerAddress().equals(serverAddress) + && getApplicationMain().getFrame() != null) { - if( serverAddress.trim().isEmpty() ) - { - serverAddress = DEFAULT_SERVER_ADDRESS; - setServerAddress(serverAddress); - } - setServerAddress(serverAddress); + System.out.println("Server address:" + getServerAddress()); + System.out.println("User name:" + getUserName()); + System.out.println("Password: " + password); - try - { - System.out.println("Server address: " + serverAddress); - registryServer = LocateRegistry.getRegistry(serverAddress); + if( clientController.checkPassword(password) ) + { + if (clientController.join(getUserName(), this.chatUpdate, this.clientUpdate, this.drawingUpdate, this.encryptionUpdate)) + { + System.out.println("Connected to server"); + return 5; + } + else + { + return 6; + } + } + else + { + return 4; + } + } + // New connection + else { + setUserName(userName); + setServerAddress(serverAddress); + System.out.println("Server address:" + serverAddress); - chatController = (IChatController) registryServer.lookup("ChatController"); - clientController = (IClientController) registryServer.lookup("ClientController"); - drawingController = (IDrawingController) registryServer.lookup("DrawingController"); + registryServer = LocateRegistry.getRegistry(serverAddress); + chatController = (IChatController) registryServer.lookup("ChatController"); + clientController = (IClientController) registryServer.lookup("ClientController"); + drawingController = (IDrawingController) registryServer.lookup("DrawingController"); - System.out.println("User name: " + userName); - System.out.println("Password: " + password); + System.out.println("User name:" + getUserName()); + System.out.println("Password: " + password); - if( clientController.checkPassword(password) ) - { - if( clientController.join(userName, this.chatUpdate, this.clientUpdate, this.drawingUpdate, this.encryptionUpdate) ) + if( clientController.checkPassword(password) ) { - System.out.println("Connected to server"); - - return 1; + if (clientController.join(getUserName(), this.chatUpdate, this.clientUpdate, this.drawingUpdate, this.encryptionUpdate)) + { + System.out.println("Connected to server"); + return 1; + } + else + { + return 2; + } } else { - return 2; + return 4; } - } - else - { - return 4; + } } catch (Exception e) { - //e.printStackTrace(); return 3; } } + + public void clearChat() { + getApplicationMain().getChatScreen().getChatDisplayBox().setText(""); + } + + public void clearDrawingArea() { + getApplicationMain().getPaintGUI().getDrawingArea().clear(); + } + } \ No newline at end of file diff --git a/src/client/ClientUpdate.java b/src/client/ClientUpdate.java index 5bcea9a..860a34b 100644 --- a/src/client/ClientUpdate.java +++ b/src/client/ClientUpdate.java @@ -60,6 +60,9 @@ public class ClientUpdate extends UnicastRemoteObject implements IClientUpdate, { kickUserBox.addItem(s); } + else { + client.getApplicationMain().getChatScreen().setManagerName(s); + } } @@ -85,6 +88,9 @@ public class ClientUpdate extends UnicastRemoteObject implements IClientUpdate, case ASSIGNADMIN: client.getChatScreen().getChatDisplayBox().append(toClient + " is the new manager.\n"); break; + case KICKALL: + client.getStartScreen().setAppTerminated(true); + client.getApplicationMain().exitApplication(); } } } diff --git a/src/remote/IClientController.java b/src/remote/IClientController.java index 07f8125..a8b583f 100644 --- a/src/remote/IClientController.java +++ b/src/remote/IClientController.java @@ -5,7 +5,7 @@ import java.rmi.RemoteException; public interface IClientController extends Remote { - enum Action {KICKOUT, ASSIGNADMIN}; + enum Action {KICKOUT, ASSIGNADMIN, KICKALL}; boolean join(String username, IChatUpdate clientChat, IClientUpdate clientUpdate, IDrawingUpdate clientDrawing, IEncryptionUpdate encryptionUpdate) throws RemoteException; @@ -17,6 +17,8 @@ public interface IClientController extends Remote boolean broadcastManagerMessage(String toClient, Action action) throws RemoteException; + void kickAll(String manager) throws RemoteException; + String getAdmin() throws RemoteException; boolean checkPassword(String password) throws RemoteException; diff --git a/src/remote/IClientUpdate.java b/src/remote/IClientUpdate.java index 1d4dea6..3788bd2 100644 --- a/src/remote/IClientUpdate.java +++ b/src/remote/IClientUpdate.java @@ -6,7 +6,7 @@ import java.rmi.RemoteException; public interface IClientUpdate extends Remote, Serializable { - enum Action {KICKOUT, ASSIGNADMIN}; + enum Action {KICKOUT, ASSIGNADMIN, KICKALL}; boolean updateUserList(String[] users) throws RemoteException; void terminateChat() throws RemoteException; void notifyManagerActions(String toClient, Action action) throws RemoteException; diff --git a/src/server/ClientController.java b/src/server/ClientController.java index 2d40ff1..6ff46e6 100644 --- a/src/server/ClientController.java +++ b/src/server/ClientController.java @@ -19,6 +19,7 @@ public class ClientController extends UnicastRemoteObject implements IClientCont @Override public boolean join(String username, IChatUpdate clientChat, IClientUpdate clientUpdate, IDrawingUpdate clientDrawing, IEncryptionUpdate encryptionUpdate) throws RemoteException { + System.out.println("I am in join"); if( getUserIndex(username) < 0 ) { // user with same username is not connected @@ -55,13 +56,11 @@ public class ClientController extends UnicastRemoteObject implements IClientCont if( userIndex >= 0 ) { server.users.remove(userIndex); - - server.chatController.broadcastMessageUserLogout(username); - - broadcastUserList(); + if (!server.users.isEmpty()) { + server.chatController.broadcastMessageUserLogout(username); + broadcastUserList(); + } } - - //printUserList(); } // for debuggins purposes @@ -108,11 +107,8 @@ public class ClientController extends UnicastRemoteObject implements IClientCont { server.users.get(userIndex).getIClientUpdate().terminateChat(); } - finally - { - System.out.print(server.users); + finally { server.users.remove(userIndex); - System.out.print(server.users); broadcastUserList(); broadcastManagerMessage(kickedUser, Action.KICKOUT); } @@ -205,6 +201,24 @@ public class ClientController extends UnicastRemoteObject implements IClientCont } @Override + public void kickAll (String manager) throws RemoteException { + + int adminIndex = getUserIndex(manager); + IClientUpdate client; + String toClient; + + if (server.users.get(adminIndex).isAdmin()) { + for (User u : server.users) { + client = u.getIClientUpdate(); + toClient = u.getUserName(); + client.notifyManagerActions(toClient, remote.IClientUpdate.Action.KICKALL); + } + server.users.clear(); + } else { + System.out.println("You are not the manager"); + } + } + public boolean checkPassword(String password) { if( server.users.size() == 0 ) -- GitLab