diff --git a/src/fr/univ/lyon1/client/Client.java b/src/fr/univ/lyon1/client/Client.java index 791a586..fd58b95 100644 --- a/src/fr/univ/lyon1/client/Client.java +++ b/src/fr/univ/lyon1/client/Client.java @@ -49,9 +49,13 @@ public class Client { this.port = port; this.username = username; this.password = password; + System.out.println("Init SSL..."); socket = initSSL(); + System.out.println("Set output stream..."); out = new ObjectOutputStream(socket.getOutputStream()); + System.out.println("Get In..."); getIn(); + System.out.println("Client ok"); } /** @@ -61,9 +65,7 @@ public class Client { */ private Socket initSSL() throws IOException { SSLContext ctx = ChatSSL.getSSLContext(); - SocketFactory factory = ctx.getSocketFactory(); - Socket connection = factory.createSocket(address, port); ((SSLSocket) connection).setEnabledProtocols(new String[] {ChatSSL.tlsVersion}); SSLParameters sslParams = new SSLParameters(); @@ -234,7 +236,7 @@ public class Client { Thread clientSendThread = new Thread(new ClientSend(this, out, socket)); clientSendThread.start(); - Thread clientReceiveThread = new Thread(new ClientReceive(this, socket)); + Thread clientReceiveThread = new Thread(new ClientReceive(this)); clientReceiveThread.start(); started = true; diff --git a/src/fr/univ/lyon1/client/ClientReceive.java b/src/fr/univ/lyon1/client/ClientReceive.java index 0124fb2..d82da06 100644 --- a/src/fr/univ/lyon1/client/ClientReceive.java +++ b/src/fr/univ/lyon1/client/ClientReceive.java @@ -2,7 +2,6 @@ package fr.univ.lyon1.client; import java.io.IOException; import java.io.ObjectInputStream; -import java.net.Socket; import java.net.SocketException; /** @@ -10,17 +9,13 @@ import java.net.SocketException; */ public class ClientReceive implements Runnable { private final Client client; - private ObjectInputStream in; - private final Socket socket; /** * Create a receiver manager from a client and a socket * @param client the client - * @param socket the client socket to the server */ - public ClientReceive(Client client, Socket socket) { + public ClientReceive(Client client) { this.client = client; - this.socket = socket; } /** @@ -28,6 +23,8 @@ public class ClientReceive implements Runnable { */ @Override public void run() { + ObjectInputStream in; + try { in = client.getIn(); } catch (IOException e) { @@ -37,6 +34,7 @@ public class ClientReceive implements Runnable { while(true) { Object data; + try { data = in.readObject(); } catch (ClassNotFoundException|IOException e) { @@ -44,13 +42,16 @@ public class ClientReceive implements Runnable { System.err.println("Connexion closed"); break; } + System.err.println("Fail to read object !"); e.printStackTrace(); + try { - Thread.sleep(1000); + Thread.currentThread().join(1000); } catch (InterruptedException ex) { break; } + continue; } diff --git a/src/fr/univ/lyon1/common/ServerConfiguration.java b/src/fr/univ/lyon1/common/ServerConfiguration.java index 7ff6a51..9737196 100644 --- a/src/fr/univ/lyon1/common/ServerConfiguration.java +++ b/src/fr/univ/lyon1/common/ServerConfiguration.java @@ -12,7 +12,7 @@ import java.util.Properties; * The client server configuration * ToDo should be in gui and not in common ? */ -public record ServerConfiguration(@NotNull String address, int port) { +public record ServerConfiguration(@NotNull String address, int port, @NotNull String pseudo, @NotNull String password) { @NotNull private static final File file = new File("connection.properties"); @@ -20,10 +20,14 @@ public record ServerConfiguration(@NotNull String address, int port) { * Create a configuration * @param address the server address * @param port the server port + * @param pseudo the username + * @param password the user password */ - public ServerConfiguration(@NotNull String address, int port) { + public ServerConfiguration(@NotNull String address, int port, @NotNull String pseudo, @NotNull String password) { this.address = address; this.port = port; + this.pseudo = pseudo; + this.password = password; } /** @@ -40,7 +44,7 @@ public record ServerConfiguration(@NotNull String address, int port) { @NotNull final Properties properties = new Properties(); properties.load(new FileReader(file)); - return new ServerConfiguration(properties.getProperty("address"), Integer.parseInt(properties.getProperty("port"))); + return new ServerConfiguration(properties.getProperty("address"), Integer.parseInt(properties.getProperty("port")), properties.getProperty("pseudo"), properties.getProperty("password")); } /** @@ -51,6 +55,8 @@ public record ServerConfiguration(@NotNull String address, int port) { @NotNull final Properties properties = new Properties(); properties.setProperty("address", this.address); properties.setProperty("port", String.valueOf(this.port)); + properties.setProperty("pseudo", this.pseudo); + properties.setProperty("password", this.password); properties.store(new FileWriter(file), "Information needed to connect to the server"); } @@ -69,4 +75,12 @@ public record ServerConfiguration(@NotNull String address, int port) { public int getPort() { return port; } + + public String getPseudo() { + return pseudo; + } + + public String getPassword() { + return password; + } } diff --git a/src/fr/univ/lyon1/gui/ClientGUI.java b/src/fr/univ/lyon1/gui/ClientGUI.java deleted file mode 100644 index a41ef37..0000000 --- a/src/fr/univ/lyon1/gui/ClientGUI.java +++ /dev/null @@ -1,39 +0,0 @@ -package fr.univ.lyon1.gui; - -import fr.univ.lyon1.client.Client; -import fr.univ.lyon1.client.ClientReceive; -import fr.univ.lyon1.common.Message; -import fr.univ.lyon1.common.command.CommandType; -import fr.univ.lyon1.gui.handlers.MainHandler; -import fr.univ.lyon1.common.command.Command; - -import java.io.IOException; -import java.util.List; - -public class ClientGUI extends Client { - private final MainHandler gui; - - public ClientGUI(MainHandler handler, String address, int port) throws IOException { - super(address, port, null, null); - this.gui = handler; - } - - @Override - protected void commandMessage(Command cmd) { - gui.receiveMessage(cmd.getArgs().get(0).toString()); - } - - @Override - public void run() throws IOException { - if (started) - return; - - Thread clientReceiveThread = new Thread(new ClientReceive(this, super.socket)); - clientReceiveThread.start(); - - out.writeObject(new Command(CommandType.login, List.of("test", "test"))); // ToDo: Setup login - out.flush(); - - started = true; - } -} diff --git a/src/fr/univ/lyon1/gui/ClientPanel.java b/src/fr/univ/lyon1/gui/ClientPanel.java deleted file mode 100644 index 701de6b..0000000 --- a/src/fr/univ/lyon1/gui/ClientPanel.java +++ /dev/null @@ -1,86 +0,0 @@ -package fr.univ.lyon1.gui; - -import fr.univ.lyon1.gui.handlers.MainHandler; -import javafx.application.Platform; -import javafx.event.ActionEvent; -import javafx.scene.Parent; -import javafx.scene.control.Button; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.TextArea; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; -import javafx.scene.text.Text; -import javafx.scene.text.TextFlow; - -public class ClientPanel extends Parent { - private final TextArea textToSend = new TextArea(); - private final TextFlow receivedText = new TextFlow(); - private final MainHandler gui; - - public ClientPanel(MainHandler gui) { - this.gui = gui; - ScrollPane scrollReceivedText = new ScrollPane(); - scrollReceivedText.setLayoutX(20); - scrollReceivedText.setLayoutY(20); - scrollReceivedText.setPrefWidth(400); - scrollReceivedText.setPrefHeight(350); - scrollReceivedText.setContent(receivedText); - scrollReceivedText.vvalueProperty().bind(receivedText.heightProperty()); - this.getChildren().add(scrollReceivedText); - - Button sendBtn = new Button(); - sendBtn.setPrefWidth(80); - - int btnMargin = 20; - - textToSend.setLayoutX(scrollReceivedText.getLayoutX()); - textToSend.setLayoutY(scrollReceivedText.getLayoutY() + scrollReceivedText.getPrefHeight() + 20); - textToSend.setPrefWidth(400- sendBtn.getPrefWidth()-btnMargin); - textToSend.setPrefHeight(100); - this.getChildren().add(textToSend); - textToSend.setOnKeyPressed(this::textToSendKeyPressed); - - sendBtn.setText("Send"); - sendBtn.setLayoutX(textToSend.getLayoutX() + textToSend.getPrefWidth() + btnMargin); - sendBtn.setLayoutY(textToSend.getLayoutY()); - sendBtn.setPrefWidth(80); - sendBtn.setPrefHeight(40); - sendBtn.setVisible(true); - this.getChildren().add(sendBtn); - sendBtn.setOnAction(this::sendBtnAction); - - Button clearBtn = new Button(); - clearBtn.setText("Clear"); - clearBtn.setLayoutX(sendBtn.getLayoutX()); - clearBtn.setPrefWidth(sendBtn.getPrefWidth()); - clearBtn.setPrefHeight(sendBtn.getPrefHeight()); - clearBtn.setLayoutY(textToSend.getLayoutY() + textToSend.getPrefHeight() - clearBtn.getPrefHeight()); - clearBtn.setVisible(true); - this.getChildren().add(clearBtn); - clearBtn.setOnAction(this::clearBtnAction); - } - - private void send() { - String msg = textToSend.getText(); - gui.sendMessage(msg); - textToSend.clear(); - addMessage(msg); - } - - private void sendBtnAction(ActionEvent e) { - send(); - } - - private void textToSendKeyPressed(KeyEvent e) { - if (e.getCode() == KeyCode.ENTER) - send(); - } - - private void clearBtnAction(ActionEvent e) { - textToSend.clear(); - } - - public void addMessage(String message) { - Platform.runLater(() -> receivedText.getChildren().add(new Text(message+"\n"))); - } -} diff --git a/src/fr/univ/lyon1/gui/Dialog.java b/src/fr/univ/lyon1/gui/Dialog.java new file mode 100644 index 0000000..b0b0613 --- /dev/null +++ b/src/fr/univ/lyon1/gui/Dialog.java @@ -0,0 +1,45 @@ +package fr.univ.lyon1.gui; + +import javafx.scene.control.Alert; +import org.jetbrains.annotations.NotNull; + +public class Dialog { + /** + * Show an error alert dialog for user interface + * @param title Title of the alert + * @param description Description of the alert + */ + public static void showErrorDialog(String title, String description) { + @NotNull + final Alert alert = new Alert(Alert.AlertType.WARNING); + extracted(title, description, alert); + } + + /** + * Show a success alert dialog for user interface + * @param title Title of the alert + * @param description Description of the alert + */ + public static void showSuccessDialog(String title, String description) { + System.out.println("Create success dialog..."); + @NotNull + final Alert alert = new Alert(Alert.AlertType.INFORMATION); + System.out.println("Extracting..."); + extracted(title, description, alert); + } + + /** + * Method used to avoid duplication code + * @param title Title of the alert + * @param description Description of the alert + * @param alert Alert interface + */ + private static void extracted(String title, String description, @NotNull Alert alert) { + System.out.println("Set title"); + alert.setTitle(title); + System.out.println("Set description"); + alert.setContentText(description); + System.out.println("Show"); + alert.show(); + } +} diff --git a/src/fr/univ/lyon1/gui/MainGui.java b/src/fr/univ/lyon1/gui/MainGui.java index 36281f9..27320e7 100644 --- a/src/fr/univ/lyon1/gui/MainGui.java +++ b/src/fr/univ/lyon1/gui/MainGui.java @@ -1,6 +1,6 @@ package fr.univ.lyon1.gui; -import fr.univ.lyon1.gui.handlers.MainHandler; +import fr.univ.lyon1.gui.handlers.ApplicationHandler; import fr.univ.lyon1.gui.handlers.ServerConfigurationHandler; import javafx.application.Application; import javafx.application.Platform; @@ -12,8 +12,10 @@ public class MainGui extends Application { @Override public void start(Stage stage) { try { - new MainHandler().launch(stage); + new ApplicationHandler().launch(stage); } catch (IOException e) { + System.out.println(e.getMessage()); + // Launch server configuration try { new ServerConfigurationHandler().launch(stage); diff --git a/src/fr/univ/lyon1/gui/controller/ApplicationController.java b/src/fr/univ/lyon1/gui/controller/ApplicationController.java new file mode 100644 index 0000000..58f61c9 --- /dev/null +++ b/src/fr/univ/lyon1/gui/controller/ApplicationController.java @@ -0,0 +1,266 @@ +package fr.univ.lyon1.gui.controller; + +import fr.univ.lyon1.common.Channel; +import fr.univ.lyon1.common.ChatSSL; +import fr.univ.lyon1.common.Message; +import fr.univ.lyon1.common.ServerConfiguration; +import fr.univ.lyon1.common.command.Command; +import fr.univ.lyon1.common.command.CommandType; +import fr.univ.lyon1.common.exception.ChatException; +import fr.univ.lyon1.common.exception.LoginInvalid; +import fr.univ.lyon1.common.exception.UnknownCommand; +import fr.univ.lyon1.gui.handlers.ServerConfigurationHandler; +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.scene.control.TextArea; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.text.Text; +import javafx.scene.text.TextFlow; +import javafx.stage.Stage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Controller used by interface resources/message_gui.fxml + */ +public class ApplicationController { + @NotNull + private final List channels = new ArrayList<>(); + @Nullable + private Channel currentChannel = null; + + private boolean isRunning = true; + @NotNull + private final Socket socket; + @NotNull + private final ObjectOutputStream objectOutputStream; + @NotNull + private final ObjectInputStream objectInputStream; + + @FXML + public TextArea textSendArea; + @FXML + public TextFlow textReceiveArea; + @FXML + public VBox vboxChannelsList; + + public ApplicationController() throws IOException { + System.out.println("Loading configuration..."); + @NotNull + final ServerConfiguration serverConfiguration = ServerConfiguration.load(); + + // Init secure socket + System.out.println("Init socket..."); + this.socket = this.initSSLSocket(serverConfiguration.getAddress(), serverConfiguration.getPort()); + this.objectOutputStream = new ObjectOutputStream(this.socket.getOutputStream()); + this.objectInputStream = new ObjectInputStream(this.socket.getInputStream()); + + // Main thread when server send object + @NotNull + final Thread receiveObjectThread = new Thread(() -> { + while (this.isRunning) { + try { + @Nullable + final Object object = this.objectInputStream.readObject(); + + if (object != null) { + if (object instanceof Command command) { + switch (command.getType()) { + // If client receive login type message + case login -> { + // Request all list of users + this.sendObject(new Command(CommandType.list, null)); + // TODO: List all channels available + // Join a channel + this.sendObject(new Command(CommandType.join, List.of("general"))); + } + + // If client receive a message type + case message -> { + @NotNull + final Message message = (Message) command.getArgs().get(0); + System.out.println("Message received : " + message.toString()); + + // If same channel + if (this.currentChannel != null && message.getChannel().getUUID().equals(this.currentChannel.getUUID())) { + Platform.runLater(() -> this.textReceiveArea.getChildren().add(new Text("@" + message.getSender().getUsername() + ": " + message.getContent()))); + } + } + + // If client receive all users + case list -> System.out.println("Connected users : " + Arrays.toString(command.getArgs().toArray())); + + // If client receive a join type message + case join -> { + @NotNull + final Channel channel = (Channel) command.getArgs().get(0); + boolean ifChannelExists = this.channels.stream().anyMatch(fChannel -> fChannel.getName().equalsIgnoreCase(channel.getName())); + System.out.println("Channel exists : " + ifChannelExists); + this.currentChannel = channel; + this.channels.add(channel); + System.out.println("Successfully connected to : " + this.currentChannel.toString()); + + if (!ifChannelExists) { + @NotNull + final Text text = new Text("- #" + channel.getName()); + text.setFill(Color.RED); + + text.setOnMousePressed(event -> { + System.out.println("Selected channel : #" + channel.getName()); + + try { + this.sendObject(new Command(CommandType.join, List.of(channel.getName()))); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + Platform.runLater(() -> this.vboxChannelsList.getChildren().add(text)); + } else { + this.vboxChannelsList.getChildren().stream().filter(node -> node instanceof Text).forEach(txt -> ((Text) txt).setFill(Color.BLACK)); + + @NotNull + final Text text = (Text) this.vboxChannelsList.getChildren().stream().filter(node -> node instanceof Text txt && txt.getText().equalsIgnoreCase("- #" + channel.getName())).toList().get(0); + text.setFill(Color.RED); + } + } + } + } else if (object instanceof LoginInvalid) { + Platform.runLater(() -> { + try { + this.closeSocket(); + + @NotNull + final Stage stage = (Stage) this.vboxChannelsList.getScene().getWindow(); + new ServerConfigurationHandler().launch(stage); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } else if (object instanceof ChatException chatException) { + System.out.println("?"); + chatException.printStackTrace(); + } else { + this.sendObject(new UnknownCommand()); + } + } else { + try { + this.closeSocket(); + } catch (IOException ex) { + System.out.println("Can not close connection"); + ex.printStackTrace(); + } + } + } catch (IOException | ClassNotFoundException e) { + if (e instanceof SocketException) { + try { + this.closeSocket(); + } catch (IOException ex) { + System.out.println("Can not close connection"); + ex.printStackTrace(); + } + } + } + } + }); + receiveObjectThread.start(); + + // Login the user with the server configuration + System.out.println("Login..."); + this.sendObject(new Command(CommandType.login, List.of(serverConfiguration.getPseudo(), serverConfiguration.getPassword()))); + } + + /** + * Close properly the socket + */ + private void closeSocket() throws IOException { + this.isRunning = false; + this.objectOutputStream.close(); + this.objectInputStream.close(); + this.socket.close(); + } + + /** + * Init the secure socket with SSL + * @param address Address of the server + * @param port Port of the server + * @return Secure socket + */ + @NotNull + private Socket initSSLSocket(@NotNull String address, int port) throws IOException { + SSLContext ctx = ChatSSL.getSSLContext(); + SocketFactory factory = ctx.getSocketFactory(); + Socket connection = factory.createSocket(address, port); + ((SSLSocket) connection).setEnabledProtocols(new String[] {ChatSSL.tlsVersion}); + SSLParameters sslParams = new SSLParameters(); + sslParams.setEndpointIdentificationAlgorithm("HTTPS"); + ((SSLSocket) connection).setSSLParameters(sslParams); + return connection; + } + + /** + * Send object to the server + * @param object Object to send + */ + private void sendObject(@NotNull Object object) throws IOException { + this.objectOutputStream.writeObject(object); + this.objectOutputStream.flush(); + } + + /** + * Event when a key is pressed on the text area message + * @param keyEvent Key event + */ + public void keyPressedOnTextSendArea(KeyEvent keyEvent) { + // If the key pressed is enter, send the current message + if (keyEvent.getCode() == KeyCode.ENTER) + this.send(); + } + + /** + * Send the current message to server + */ + public void send() { + // Get current message + @NotNull + final String textToSend = this.textSendArea.getText(); + // Clear the textarea content + this.clear(); + // Add the message to the current client + System.out.print(">> Send : " + textToSend); + Platform.runLater(() -> this.textReceiveArea.getChildren().add(new Text("*>> " + textToSend))); + + if (this.currentChannel != null) { + try { + // Send the message to the server + this.sendObject(new Command(CommandType.message, List.of(new Message(textToSend, this.currentChannel)))); + } catch (IOException e) { + System.out.println("Can not send message to server : " + e.getMessage()); + e.printStackTrace(); + } + } + } + + /** + * Clear the current textarea message + */ + public void clear() { + this.textSendArea.setText(""); + } +} \ No newline at end of file diff --git a/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java b/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java index 2016191..c5d6824 100644 --- a/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java +++ b/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java @@ -1,7 +1,8 @@ package fr.univ.lyon1.gui.controller; import fr.univ.lyon1.common.ServerConfiguration; -import fr.univ.lyon1.gui.handlers.MainHandler; +import fr.univ.lyon1.gui.Dialog; +import fr.univ.lyon1.gui.handlers.ApplicationHandler; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.TextField; @@ -11,16 +12,23 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.net.Socket; +/** + * Controller used by interface resources/connect_gui.fxml + */ public class ConnectGuiController { @FXML public TextField addressTextField; @FXML public TextField portTextField; @FXML + public TextField pseudoTextField; + @FXML + public TextField passwordTextField; + @FXML public Button connectButton; /** - * Called by submit button in resources/connect_gui.fxml + * Called by connect button */ public void connect() { this.connectButton.setDisable(true); @@ -29,43 +37,62 @@ public class ConnectGuiController { final String address = this.addressTextField.getText(); @NotNull final String port = this.portTextField.getText(); + @NotNull + final String pseudo = this.pseudoTextField.getText(); + @NotNull + final String password = this.passwordTextField.getText(); - System.out.println("Checking if port is valid..."); - // Check if the port is a number and if it's an available port - if (this.isNumber(port) && this.isAvailablePort(Integer.parseInt(port))) { - final int iPort = Integer.parseInt(port); - System.out.println("Port valid, next step..."); - System.out.println("Checking if connection is available..."); + System.out.println("Checking if all text fields is not empty"); + // If all fields is not empty + if (!address.isEmpty() && !port.isEmpty() && !pseudo.isEmpty() && !password.isEmpty()) { + System.out.println("Checking if port is valid..."); + // Check if the port is a number and if it's an available port + if (this.isNumber(port) && this.isAvailablePort(Integer.parseInt(port))) { + final int iPort = Integer.parseInt(port); + System.out.println("Port valid, next step..."); + System.out.println("Checking if connection is available..."); - // Check if the connection is available - if (this.isAccessible(address, iPort)) { - System.out.println("Connection available, saving file..."); + // Check if the connection is available + if (this.isAccessible(address, iPort)) { + System.out.println("Connection available, saving file..."); - try { - // Save server configuration - new ServerConfiguration(address, iPort).save(); - Dialog.showSuccessDialog("Connecté", "Vous êtes bien connecté au serveur"); - System.out.println("File saved, next step..."); + try { + // Save server configuration + new ServerConfiguration(address, iPort, pseudo, password).save(); + Dialog.showSuccessDialog("Connecté", "Vous êtes bien connecté au serveur"); + System.out.println("File saved, next step..."); - @NotNull - final Stage stage = (Stage) this.connectButton.getScene().getWindow(); - new MainHandler().launch(stage); - } catch (IOException e) { - Dialog.showErrorDialog("Erreur", "Impossible de sauvegarder les informations de connexion au serveur"); + // Change scene for the main application + @NotNull + final Stage stage = (Stage) this.connectButton.getScene().getWindow(); + new ApplicationHandler().launch(stage); + } catch (IOException e) { + System.out.println(e.getMessage()); + + Dialog.showErrorDialog("Erreur", "Impossible de sauvegarder les informations de connexion au serveur"); + this.connectButton.setDisable(false); + System.out.println("Failed to save file, error: " + e.getMessage()); + } + } else { + System.out.println("Connection not available"); + Dialog.showErrorDialog("Erreur de connexion", "Impossible de se connecter au serveur, veuillez vérifier les informations saisies"); this.connectButton.setDisable(false); - System.out.println("Failed to save file, error: " + e.getMessage()); } } else { - System.out.println("Connection not available"); - Dialog.showErrorDialog("Erreur de connexion", "Impossible de se connecter au serveur, veuillez vérifier les informations saisies"); + Dialog.showErrorDialog("Erreur", "Veuillez saisir un numéro de port valide"); this.connectButton.setDisable(false); } } else { - Dialog.showErrorDialog("Erreur", "Veuillez saisir un numéro de port valide"); + Dialog.showErrorDialog("Erreur", "Veuillez renseigner tout les champs"); this.connectButton.setDisable(false); } } + /** + * Check if a string is a number + * @param text String to check + * @return Is number + */ private boolean isNumber(String text) { try { Integer.parseInt(text); @@ -75,17 +102,30 @@ public class ConnectGuiController { } } + /** + * Check if a port is in correct range of ports + * @param port Port to check + * @return If port is available + */ private boolean isAvailablePort(int port) { return !(port < 0 || port > 0xFFFF); } + /** + * Check if an address with port is available through a socket + * @param address Address of the server + * @param port Port used by the server + * @return If socket has successfully connected to the server + */ private boolean isAccessible(String address, int port) { try { @NotNull final Socket socket = new Socket(address, port); socket.setSoTimeout(5 * 1000); + boolean connected = socket.isConnected(); + socket.close(); - return true; + return connected; } catch (IOException exception) { return false; } diff --git a/src/fr/univ/lyon1/gui/controller/Dialog.java b/src/fr/univ/lyon1/gui/controller/Dialog.java deleted file mode 100644 index 6623ab8..0000000 --- a/src/fr/univ/lyon1/gui/controller/Dialog.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.univ.lyon1.gui.controller; - -import javafx.scene.control.Alert; -import org.jetbrains.annotations.NotNull; - -public class Dialog { - public static void showErrorDialog(String title, String description) { - @NotNull - final Alert alert = new Alert(Alert.AlertType.WARNING); - extracted(title, description, alert); - } - - public static void showSuccessDialog(String title, String description) { - @NotNull - final Alert alert = new Alert(Alert.AlertType.INFORMATION); - extracted(title, description, alert); - } - - private static void extracted(String title, String description, @NotNull Alert alert) { - alert.setTitle(title); - alert.setContentText(description); - alert.show(); - } -} diff --git a/src/fr/univ/lyon1/gui/handlers/ApplicationHandler.java b/src/fr/univ/lyon1/gui/handlers/ApplicationHandler.java new file mode 100644 index 0000000..173d929 --- /dev/null +++ b/src/fr/univ/lyon1/gui/handlers/ApplicationHandler.java @@ -0,0 +1,18 @@ +package fr.univ.lyon1.gui.handlers; + +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.stage.Stage; + +import java.io.IOException; + +public class ApplicationHandler implements Handler { + @Override + public void launch(Stage stage) throws IOException { + FXMLLoader fxmlLoader = new FXMLLoader(ClassLoader.getSystemClassLoader().getResource("message_gui.fxml")); + Scene scene = new Scene(fxmlLoader.load(), 600, 400); + stage.setTitle("Chat client"); + stage.setScene(scene); + stage.show(); + } +} diff --git a/src/fr/univ/lyon1/gui/handlers/MainHandler.java b/src/fr/univ/lyon1/gui/handlers/MainHandler.java deleted file mode 100644 index be9a06f..0000000 --- a/src/fr/univ/lyon1/gui/handlers/MainHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package fr.univ.lyon1.gui.handlers; - -import fr.univ.lyon1.common.ServerConfiguration; -import fr.univ.lyon1.gui.ClientGUI; -import fr.univ.lyon1.gui.ClientPanel; -import javafx.scene.Group; -import javafx.scene.Scene; -import javafx.stage.Stage; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; - -public class MainHandler implements Handler { - private ClientPanel clientPanel; - @Nullable - private ClientGUI client; - - @Override - public void launch(Stage stage) throws IOException { - @NotNull - final ServerConfiguration serverConfiguration = ServerConfiguration.load(); - this.client = new ClientGUI(this, serverConfiguration.getAddress(), serverConfiguration.getPort()); - - stage.setTitle("Chat client"); - stage.setWidth(440); - - this.clientPanel = new ClientPanel(this); - Group root = new Group(); - root.getChildren().add(this.clientPanel); - Scene scene = new Scene(root, 600, 500); - - stage.setScene(scene); - stage.show(); - - if (this.client != null) { - this.client.run(); - } - } - - public void sendMessage(String msg) { - if (client != null) { - client.sendMessage(msg); - } - } - - public void receiveMessage(String msg) { - clientPanel.addMessage(msg); - } -} diff --git a/src/fr/univ/lyon1/gui/handlers/ServerConfigurationHandler.java b/src/fr/univ/lyon1/gui/handlers/ServerConfigurationHandler.java index 5c4211d..bc70d2c 100644 --- a/src/fr/univ/lyon1/gui/handlers/ServerConfigurationHandler.java +++ b/src/fr/univ/lyon1/gui/handlers/ServerConfigurationHandler.java @@ -10,7 +10,7 @@ public class ServerConfigurationHandler implements Handler { @Override public void launch(Stage stage) throws IOException { FXMLLoader fxmlLoader = new FXMLLoader(ClassLoader.getSystemClassLoader().getResource("connect_gui.fxml")); - Scene scene = new Scene(fxmlLoader.load(), 320, 240); + Scene scene = new Scene(fxmlLoader.load(), 640, 480); stage.setTitle("Configuration du serveur"); stage.setScene(scene); stage.show(); diff --git a/src/fr/univ/lyon1/server/ConnectedClient.java b/src/fr/univ/lyon1/server/ConnectedClient.java index f6082b7..65c5ef2 100644 --- a/src/fr/univ/lyon1/server/ConnectedClient.java +++ b/src/fr/univ/lyon1/server/ConnectedClient.java @@ -180,7 +180,8 @@ public class ConnectedClient implements Runnable { actionCommand((Command) data); else throw new UnknownCommand(); - } catch (ChatException e) { + } catch (IOException | ChatException e) { + System.out.println("Error server " + e.getLocalizedMessage()); out.writeObject(e); out.flush(); } diff --git a/src/main/resources/connect_gui.fxml b/src/main/resources/connect_gui.fxml index b574c85..8fe0383 100644 --- a/src/main/resources/connect_gui.fxml +++ b/src/main/resources/connect_gui.fxml @@ -5,34 +5,47 @@ - + - + - - + + - diff --git a/src/main/resources/message_gui.fxml b/src/main/resources/message_gui.fxml new file mode 100644 index 0000000..feaee24 --- /dev/null +++ b/src/main/resources/message_gui.fxml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + +