diff --git a/src/main/java/envoy/client/net/Receiver.java b/src/main/java/envoy/client/net/Receiver.java
index 25e7153..d8a0d45 100644
--- a/src/main/java/envoy/client/net/Receiver.java
+++ b/src/main/java/envoy/client/net/Receiver.java
@@ -51,7 +51,7 @@ public class Receiver implements Runnable {
try (ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(objBytes))) {
Object obj = oin.readObject();
- logger.finest("Received object " + obj);
+ logger.info("Received object " + obj);
// Get appropriate processor
@SuppressWarnings("rawtypes")
diff --git a/src/main/java/envoy/client/ui/LoginDialog.java b/src/main/java/envoy/client/ui/LoginDialog.java
index d9e4750..bdac73a 100644
--- a/src/main/java/envoy/client/ui/LoginDialog.java
+++ b/src/main/java/envoy/client/ui/LoginDialog.java
@@ -2,17 +2,25 @@ package envoy.client.ui;
import java.awt.*;
import java.awt.event.ItemEvent;
+import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.logging.Logger;
+import javax.naming.TimeLimitExceededException;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
-import envoy.client.data.Settings;
+import envoy.client.data.*;
import envoy.client.event.HandshakeSuccessfulEvent;
+import envoy.client.net.Client;
+import envoy.client.util.EnvoyLog;
import envoy.data.LoginCredentials;
+import envoy.data.Message;
+import envoy.data.User;
import envoy.event.EventBus;
import envoy.event.HandshakeRejectionEvent;
+import envoy.exception.EnvoyException;
/**
* Project: envoy-client
@@ -25,7 +33,7 @@ import envoy.event.HandshakeRejectionEvent;
*/
public class LoginDialog extends JDialog {
- private final JPanel contentPanel;
+ private JPanel contentPanel;
private JTextField textField;
private JPasswordField passwordField;
private JPasswordField repeatPasswordField;
@@ -47,14 +55,111 @@ public class LoginDialog extends JDialog {
private LoginCredentials credentials;
- private static final long serialVersionUID = 352021600833907468L;
+ private final Client client;
+ private final LocalDb localDb;
+ private final Cache receivedMessageCache;
+
+ private static final Config config = Config.getInstance();
+ private static final Logger logger = EnvoyLog.getLogger(LoginDialog.class.getSimpleName());
+ private static final long serialVersionUID = 352021600833907468L;
/**
* Displays a dialog enabling the user to enter their user name and password.
*
+ * @param client the client used to perform the handshake
+ * @param localDb the local database in which data is persisted
+ * @param receivedMessageCache the cache that stored messages received during
+ * the handshake
* @since Envoy v0.3-alpha
*/
- public LoginDialog() {
+ public LoginDialog(Client client, LocalDb localDb, Cache receivedMessageCache) {
+ this.client = client;
+ this.localDb = localDb;
+ this.receivedMessageCache = receivedMessageCache;
+
+ // Prepare handshake
+ localDb.loadIdGenerator();
+
+ initUi();
+
+ okButton.addActionListener((evt) -> {
+ try {
+ if (registerCheckBox.isSelected()) {
+ // Check password equality
+ if (Arrays.equals(passwordField.getPassword(), repeatPasswordField.getPassword()))
+ credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), true);
+ else {
+ JOptionPane.showMessageDialog(this, "The repeated password is not the origional password!");
+ clearPasswordFields();
+ }
+ } else credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), false);
+ performHandshake();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ });
+
+ // Listen to handshake rejections
+ EventBus.getInstance().register(HandshakeRejectionEvent.class, evt -> {
+ for (Component c : contentPanel.getComponents())
+ if (c == errorMessage) contentPanel.remove(errorMessage);
+ clearPasswordFields();
+ errorMessage = new JLabel(evt.get());
+ gbc_errorMessage = new GridBagConstraints();
+ gbc_errorMessage.gridx = 2;
+ gbc_errorMessage.gridy = 0;
+ gbc_errorMessage.fill = GridBagConstraints.HORIZONTAL;
+ gbc_errorMessage.insets = new Insets(5, 5, 5, 5);
+ contentPanel.add(errorMessage, gbc_errorMessage);
+ contentPanel.revalidate();
+ contentPanel.repaint();
+ });
+
+ // Exit the application when the dialog is cancelled
+ cancelButton.addActionListener(evt -> { logger.info("The login process has been cancelled. Exiting..."); System.exit(0); });
+
+ // Log in directly if configured
+ if (config.hasLoginCredentials()) {
+ credentials = config.getLoginCredentials();
+ performHandshake();
+ return;
+ }
+
+ setVisible(true);
+ }
+
+ private void performHandshake() {
+ try {
+ client.performHandshake(credentials, receivedMessageCache);
+ if (client.isOnline()) {
+ client.initReceiver(localDb, receivedMessageCache);
+ dispose();
+ }
+ } catch (IOException | InterruptedException e) {
+ e.printStackTrace();
+ } catch (TimeLimitExceededException e) {
+ logger.warning("Could not connect to server. Trying offline mode...");
+ e.printStackTrace();
+ try {
+ // Try entering offline mode
+ localDb.loadUsers();
+ User clientUser = localDb.getUsers().get(credentials.getIdentifier());
+ if (clientUser == null) throw new EnvoyException("Could not enter offline mode: user name unknown");
+ client.setSender(clientUser);
+ JOptionPane.showMessageDialog(null,
+ "A connection to the server could not be established. Starting in offline mode.\n" + e,
+ "Connection error",
+ JOptionPane.WARNING_MESSAGE);
+ dispose();
+ } catch (Exception e1) {
+ JOptionPane.showMessageDialog(null, e1, "Client error", JOptionPane.ERROR_MESSAGE);
+ System.exit(1);
+ return;
+ }
+ }
+ }
+
+ private void initUi() {
setSize(338, 123);
setLocationRelativeTo(null);
getContentPane().setLayout(new BorderLayout());
@@ -67,150 +172,109 @@ public class LoginDialog extends JDialog {
gbl_contentPanel.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
gbl_contentPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
contentPanel.setLayout(gbl_contentPanel);
- {
- lblUserName = new JLabel("Username:");
- GridBagConstraints gbc_lblUserName = new GridBagConstraints();
- gbc_lblUserName.anchor = GridBagConstraints.EAST;
- gbc_lblUserName.insets = new Insets(0, 0, 5, 5);
- gbc_lblUserName.gridx = 0;
- gbc_lblUserName.gridy = 0;
- contentPanel.add(lblUserName, gbc_lblUserName);
- }
- {
- textField = new JTextField();
- textField.setBorder(null);
- GridBagConstraints gbc_textField = new GridBagConstraints();
- gbc_textField.insets = new Insets(0, 0, 5, 0);
- gbc_textField.fill = GridBagConstraints.HORIZONTAL;
- gbc_textField.gridx = 1;
- gbc_textField.gridy = 0;
- contentPanel.add(textField, gbc_textField);
- textField.setColumns(10);
- }
- {
- lblPassword = new JLabel("Password:");
- GridBagConstraints gbc_lblPassword = new GridBagConstraints();
- gbc_lblPassword.anchor = GridBagConstraints.EAST;
- gbc_lblPassword.insets = new Insets(0, 0, 0, 5);
- gbc_lblPassword.gridx = 0;
- gbc_lblPassword.gridy = 1;
- contentPanel.add(lblPassword, gbc_lblPassword);
- }
- {
- passwordField = new JPasswordField();
- passwordField.setBorder(null);
- GridBagConstraints gbc_passwordField = new GridBagConstraints();
- gbc_passwordField.fill = GridBagConstraints.HORIZONTAL;
- gbc_passwordField.gridx = 1;
- gbc_passwordField.gridy = 1;
- contentPanel.add(passwordField, gbc_passwordField);
- }
- {
- lblRepeatPassword = new JLabel("Repeat Password:");
- gbc_lblRepeatPassword = new GridBagConstraints();
- gbc_lblRepeatPassword.anchor = GridBagConstraints.EAST;
- gbc_lblRepeatPassword.insets = new Insets(0, 0, 0, 5);
- gbc_lblRepeatPassword.gridx = 0;
- gbc_lblRepeatPassword.gridy = 2;
- }
- {
- repeatPasswordField = new JPasswordField();
- gbc_repeatPasswordField = new GridBagConstraints();
- gbc_repeatPasswordField.fill = GridBagConstraints.HORIZONTAL;
- gbc_repeatPasswordField.gridx = 1;
- gbc_repeatPasswordField.gridy = 2;
- }
- {
- EventBus.getInstance().register(HandshakeRejectionEvent.class, evt -> {
- contentPanel.remove(errorMessage);
- clearPasswordFields();
- // TODO delete - only for testing purposes
- System.out.println("Caught HandshakeRejectionEvent with reason" + evt.get());
- errorMessage = new JLabel(evt.get());
- gbc_errorMessage = new GridBagConstraints();
- gbc_errorMessage.gridx = 2;
- gbc_errorMessage.gridy = 0;
- gbc_errorMessage.fill = GridBagConstraints.HORIZONTAL;
- gbc_errorMessage.insets = new Insets(5, 5, 5, 5);
- contentPanel.add(errorMessage, gbc_errorMessage);
- });
- }
- {
- buttonPane = new JPanel();
- registerText = new JTextPane();
- registerText.setEditable(false);
- registerText.setText("Register?");
- registerText.setFont(new Font("Arial", Font.BOLD, 12));
- registerText.setAlignmentX(LEFT_ALIGNMENT);
- buttonPane.add(registerText);
+ lblUserName = new JLabel("Username:");
+ GridBagConstraints gbc_lblUserName = new GridBagConstraints();
+ gbc_lblUserName.anchor = GridBagConstraints.EAST;
+ gbc_lblUserName.insets = new Insets(0, 0, 5, 5);
+ gbc_lblUserName.gridx = 0;
+ gbc_lblUserName.gridy = 0;
+ contentPanel.add(lblUserName, gbc_lblUserName);
- registerCheckBox = new JCheckBox();
- registerCheckBox.setAlignmentX(LEFT_ALIGNMENT);
- registerCheckBox.addItemListener(e -> {
- switch (e.getStateChange()) {
- case ItemEvent.SELECTED:
- contentPanel.add(lblRepeatPassword, gbc_lblRepeatPassword);
- contentPanel.add(repeatPasswordField, gbc_repeatPasswordField);
- setSize(338, 148);
- break;
+ textField = new JTextField();
+ textField.setBorder(null);
+ GridBagConstraints gbc_textField = new GridBagConstraints();
+ gbc_textField.insets = new Insets(0, 0, 5, 0);
+ gbc_textField.fill = GridBagConstraints.HORIZONTAL;
+ gbc_textField.gridx = 1;
+ gbc_textField.gridy = 0;
+ contentPanel.add(textField, gbc_textField);
+ textField.setColumns(10);
- case ItemEvent.DESELECTED:
- if (repeatPasswordField.getParent() == contentPanel) {
- contentPanel.remove(lblRepeatPassword);
- contentPanel.remove(repeatPasswordField);
- setSize(338, 123);
- }
- break;
- }
- contentPanel.revalidate();
- contentPanel.repaint();
- });
- buttonPane.add(registerCheckBox);
+ lblPassword = new JLabel("Password:");
+ GridBagConstraints gbc_lblPassword = new GridBagConstraints();
+ gbc_lblPassword.anchor = GridBagConstraints.EAST;
+ gbc_lblPassword.insets = new Insets(0, 0, 0, 5);
+ gbc_lblPassword.gridx = 0;
+ gbc_lblPassword.gridy = 1;
+ contentPanel.add(lblPassword, gbc_lblPassword);
- buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
- getContentPane().add(buttonPane, BorderLayout.SOUTH);
- {
- okButton = new PrimaryButton("OK");
- okButton.addActionListener((evt) -> {
- try {
- if (registerCheckBox.isSelected()) {
- // password checking
- if (Arrays.equals(passwordField.getPassword(), repeatPasswordField.getPassword()))
- credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), true);
- else {
- JOptionPane.showMessageDialog(this, "The repeated password is not the origional password!");
- clearPasswordFields();
- }
- } else credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), false);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
+ passwordField = new JPasswordField();
+ passwordField.setBorder(null);
+ GridBagConstraints gbc_passwordField = new GridBagConstraints();
+ gbc_passwordField.fill = GridBagConstraints.HORIZONTAL;
+ gbc_passwordField.gridx = 1;
+ gbc_passwordField.gridy = 1;
+ contentPanel.add(passwordField, gbc_passwordField);
+
+ lblRepeatPassword = new JLabel("Repeat Password:");
+ gbc_lblRepeatPassword = new GridBagConstraints();
+ gbc_lblRepeatPassword.anchor = GridBagConstraints.EAST;
+ gbc_lblRepeatPassword.insets = new Insets(0, 0, 0, 5);
+ gbc_lblRepeatPassword.gridx = 0;
+ gbc_lblRepeatPassword.gridy = 2;
+
+ repeatPasswordField = new JPasswordField();
+ gbc_repeatPasswordField = new GridBagConstraints();
+ gbc_repeatPasswordField.fill = GridBagConstraints.HORIZONTAL;
+ gbc_repeatPasswordField.gridx = 1;
+ gbc_repeatPasswordField.gridy = 2;
+
+ buttonPane = new JPanel();
+
+ registerText = new JTextPane();
+ registerText.setEditable(false);
+ registerText.setText("Register?");
+ registerText.setFont(new Font("Arial", Font.BOLD, 12));
+ registerText.setAlignmentX(LEFT_ALIGNMENT);
+ buttonPane.add(registerText);
+
+ registerCheckBox = new JCheckBox();
+ registerCheckBox.setAlignmentX(LEFT_ALIGNMENT);
+ registerCheckBox.addItemListener(e -> {
+ switch (e.getStateChange()) {
+ case ItemEvent.SELECTED:
+ contentPanel.add(lblRepeatPassword, gbc_lblRepeatPassword);
+ contentPanel.add(repeatPasswordField, gbc_repeatPasswordField);
+ setSize(338, 148);
+ break;
+
+ case ItemEvent.DESELECTED:
+ if (repeatPasswordField.getParent() == contentPanel) {
+ contentPanel.remove(lblRepeatPassword);
+ contentPanel.remove(repeatPasswordField);
+ setSize(338, 123);
}
- });
- okButton.setActionCommand("OK");
- buttonPane.add(okButton);
- getRootPane().setDefaultButton(okButton);
+ break;
}
- {
- cancelButton = new PrimaryButton("Cancel");
- cancelButton.addActionListener((evt) -> dispose());
- cancelButton.setActionCommand("Cancel");
- buttonPane.add(cancelButton);
- }
- }
+ contentPanel.revalidate();
+ contentPanel.repaint();
+ });
+ buttonPane.add(registerCheckBox);
+
+ buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ getContentPane().add(buttonPane, BorderLayout.SOUTH);
+ okButton = new PrimaryButton("OK");
+ okButton.setActionCommand("OK");
+ buttonPane.add(okButton);
+ getRootPane().setDefaultButton(okButton);
+
+ cancelButton = new PrimaryButton("Cancel");
+ cancelButton.setActionCommand("Cancel");
+ buttonPane.add(cancelButton);
setTheme();
- setModal(true);
- setVisible(true);
+ setModalityType(Dialog.DEFAULT_MODALITY_TYPE);
+
EventBus.getInstance().register(HandshakeSuccessfulEvent.class, evt -> dispose());
}
/**
- * Resets the text stored in the passwort fields.
+ * Resets the text stored in the password fields.
*
* @since Envoy v0.3-alpha
*/
- public void clearPasswordFields() {
+ private void clearPasswordFields() {
passwordField.setText(null);
repeatPasswordField.setText(null);
}
@@ -258,11 +322,4 @@ public class LoginDialog extends JDialog {
cancelButton.setBackground(theme.getInteractableBackgroundColor());
cancelButton.setForeground(theme.getInteractableForegroundColor());
}
-
- /**
- * @return the {@link LoginCredentials} entered by the user, or {@code null} if
- * the dialog has been cancelled
- * @since Envoy v0.3-alpha
- */
- public LoginCredentials getCredentials() { return credentials; }
}
\ No newline at end of file
diff --git a/src/main/java/envoy/client/ui/Startup.java b/src/main/java/envoy/client/ui/Startup.java
index f31cfa3..a684326 100644
--- a/src/main/java/envoy/client/ui/Startup.java
+++ b/src/main/java/envoy/client/ui/Startup.java
@@ -15,9 +15,7 @@ import envoy.client.data.*;
import envoy.client.net.Client;
import envoy.client.net.WriteProxy;
import envoy.client.util.EnvoyLog;
-import envoy.data.LoginCredentials;
import envoy.data.Message;
-import envoy.data.User;
import envoy.exception.EnvoyException;
/**
@@ -74,14 +72,6 @@ public class Startup {
EnvoyLog.setFileLevelBarrier(config.getFileLevelBarrier());
EnvoyLog.setConsoleLevelBarrier(config.getConsoleLevelBarrier());
- // Acquire login credentials
- LoginCredentials credentials = config.hasLoginCredentials() ? config.getLoginCredentials() : new LoginDialog().getCredentials();
-
- if (credentials == null) {
- logger.info("The login process has been cancelled. Exiting...");
- System.exit(0);
- }
-
// Initialize the local database
LocalDb localDb;
if (config.isIgnoreLocalDB()) {
@@ -95,45 +85,23 @@ public class Startup {
} catch (IOException e3) {
logger.log(Level.SEVERE, "Could not initialize local database", e3);
JOptionPane
- .showMessageDialog(null, "Could not initialize local database!\n" + e3.toString(), "Local database error", JOptionPane.ERROR_MESSAGE);
+ .showMessageDialog(null, "Could not initialize local database!\n" + e3, "Local database error", JOptionPane.ERROR_MESSAGE);
System.exit(1);
return;
}
- SwingUtilities.invokeLater(() -> chatWindow.setVisible(true));
-
- // Acquire the client user (with ID) either from the server or from the local
- // database, which triggers offline mode
+ // Initialize client and unread message cache
Client client = new Client();
Cache cache = new Cache<>();
- try {
- // Try entering online mode first
- localDb.loadIdGenerator();
- client.performHandshake(credentials, cache);
- client.initReceiver(localDb, cache);
- } catch (Exception e1) {
- logger.warning("Could not connect to server. Trying offline mode...");
- e1.printStackTrace();
- try {
- // Try entering offline mode
- localDb.loadUsers();
- User clientUser = localDb.getUsers().get(credentials.getIdentifier());
- if (clientUser == null) throw new EnvoyException("Could not enter offline mode: user name unknown");
- client.setSender(clientUser);
- JOptionPane.showMessageDialog(null,
- "A connection to the server could not be established. Starting in offline mode.\n" + e1,
- "Connection error",
- JOptionPane.WARNING_MESSAGE);
- } catch (Exception e2) {
- JOptionPane.showMessageDialog(null, e2.toString(), "Client error", JOptionPane.ERROR_MESSAGE);
- System.exit(1);
- return;
- }
- }
+
+ // Try to connect to the server
+ new LoginDialog(client, localDb, cache);
+ SwingUtilities.invokeLater(() -> chatWindow.setVisible(true));
// Set client user in local database
localDb.setUser(client.getSender());
+
// Initialize chats in local database
try {
localDb.initializeUserStorage();