Merge pull request #109 from informatik-ag-ngl/f/invalid_login
Reacting to HandshakeRejectionEvents
This commit is contained in:
commit
cd590448cc
2
pom.xml
2
pom.xml
@ -28,7 +28,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.informatik-ag-ngl</groupId>
|
<groupId>com.github.informatik-ag-ngl</groupId>
|
||||||
<artifactId>envoy-common</artifactId>
|
<artifactId>envoy-common</artifactId>
|
||||||
<version>develop-SNAPSHOT</version>
|
<version>v0.2-alpha</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package envoy.client;
|
package envoy.client.data;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -6,7 +6,6 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.prefs.Preferences;
|
import java.util.prefs.Preferences;
|
||||||
|
|
||||||
import envoy.client.data.Config;
|
|
||||||
import envoy.client.ui.Color;
|
import envoy.client.ui.Color;
|
||||||
import envoy.client.ui.Theme;
|
import envoy.client.ui.Theme;
|
||||||
import envoy.util.SerializationUtils;
|
import envoy.util.SerializationUtils;
|
@ -1,4 +1,4 @@
|
|||||||
package envoy.client;
|
package envoy.client.data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
@ -0,0 +1,18 @@
|
|||||||
|
package envoy.client.event;
|
||||||
|
|
||||||
|
import envoy.event.Event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This {@link Event} indicates that a handshake was completed successfully.
|
||||||
|
*
|
||||||
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
* File: <strong>HandshakeSuccessfulEvent.java</strong><br>
|
||||||
|
* Created: <strong>8 Feb 2020</strong><br>
|
||||||
|
*
|
||||||
|
* @author Leon Hofmeister
|
||||||
|
* @since Envoy v0.3-alpha
|
||||||
|
*/
|
||||||
|
public class HandshakeSuccessfulEvent extends Event.Valueless {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -157972384126278855L;
|
||||||
|
}
|
@ -42,6 +42,7 @@ public class Client implements Closeable {
|
|||||||
// Asynchronously initialized during handshake
|
// Asynchronously initialized during handshake
|
||||||
private volatile User sender;
|
private volatile User sender;
|
||||||
private volatile Contacts contacts;
|
private volatile Contacts contacts;
|
||||||
|
private volatile boolean rejected;
|
||||||
|
|
||||||
// Configuration and logging
|
// Configuration and logging
|
||||||
private static final Config config = Config.getInstance();
|
private static final Config config = Config.getInstance();
|
||||||
@ -54,16 +55,19 @@ public class Client implements Closeable {
|
|||||||
* an exception is thrown.
|
* an exception is thrown.
|
||||||
*
|
*
|
||||||
* @param credentials the login credentials of the user
|
* @param credentials the login credentials of the user
|
||||||
* @param localDb the local database used to persist the current
|
|
||||||
* {@link IdGenerator}
|
|
||||||
* @param receivedMessageCache a message cache containing all unread messages
|
* @param receivedMessageCache a message cache containing all unread messages
|
||||||
* from the server that can be relayed after
|
* from the server that can be relayed after
|
||||||
* initialization
|
* initialization
|
||||||
* @throws Exception if the online mode could not be entered or the request
|
* @throws TimeLimitExceededException if the server could not be reached
|
||||||
* failed for some other reason
|
* @throws IOException if the login credentials could not be
|
||||||
* @since Envoy v0.2-alpha
|
* written
|
||||||
|
* @throws InterruptedException if the current thread is interrupted while
|
||||||
|
* waiting for the handshake response
|
||||||
*/
|
*/
|
||||||
public void onlineInit(LoginCredentials credentials, LocalDb localDb, Cache<Message> receivedMessageCache) throws Exception {
|
public void performHandshake(LoginCredentials credentials, Cache<Message> receivedMessageCache)
|
||||||
|
throws TimeLimitExceededException, IOException, InterruptedException {
|
||||||
|
if (online) throw new IllegalStateException("Handshake has already been performed successfully");
|
||||||
|
|
||||||
// Establish TCP connection
|
// Establish TCP connection
|
||||||
logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
|
logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
|
||||||
socket = new Socket(config.getServer(), config.getPort());
|
socket = new Socket(config.getServer(), config.getPort());
|
||||||
@ -76,6 +80,9 @@ public class Client implements Closeable {
|
|||||||
receiver.registerProcessor(User.class, sender -> { logger.info("Acquired user object " + sender); this.sender = sender; });
|
receiver.registerProcessor(User.class, sender -> { logger.info("Acquired user object " + sender); this.sender = sender; });
|
||||||
receiver.registerProcessor(Contacts.class, contacts -> { logger.info("Acquired contacts object " + contacts); this.contacts = contacts; });
|
receiver.registerProcessor(Contacts.class, contacts -> { logger.info("Acquired contacts object " + contacts); this.contacts = contacts; });
|
||||||
receiver.registerProcessor(Message.class, receivedMessageCache);
|
receiver.registerProcessor(Message.class, receivedMessageCache);
|
||||||
|
receiver.registerProcessor(HandshakeRejectionEvent.class, evt -> { rejected = true; EventBus.getInstance().dispatch(evt); });
|
||||||
|
|
||||||
|
rejected = false;
|
||||||
|
|
||||||
// Start receiver
|
// Start receiver
|
||||||
new Thread(receiver).start();
|
new Thread(receiver).start();
|
||||||
@ -87,6 +94,15 @@ public class Client implements Closeable {
|
|||||||
// Wait for a maximum of five seconds to acquire the sender object
|
// Wait for a maximum of five seconds to acquire the sender object
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
while (sender == null || contacts == null) {
|
while (sender == null || contacts == null) {
|
||||||
|
|
||||||
|
// Quit immediately after handshake rejection
|
||||||
|
// This method can then be called again
|
||||||
|
if (rejected) {
|
||||||
|
socket.close();
|
||||||
|
receiver.removeAllProcessors();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (System.currentTimeMillis() - start > 5000) throw new TimeLimitExceededException("Did not log in after 5 seconds");
|
if (System.currentTimeMillis() - start > 5000) throw new TimeLimitExceededException("Did not log in after 5 seconds");
|
||||||
Thread.sleep(500);
|
Thread.sleep(500);
|
||||||
}
|
}
|
||||||
@ -96,8 +112,23 @@ public class Client implements Closeable {
|
|||||||
|
|
||||||
// Remove user creation processor
|
// Remove user creation processor
|
||||||
receiver.removeAllProcessors();
|
receiver.removeAllProcessors();
|
||||||
|
}
|
||||||
|
|
||||||
// Register processors for message and status handling
|
/**
|
||||||
|
* Initializes the {@link Receiver} used to process data sent from the server to
|
||||||
|
* this client.
|
||||||
|
*
|
||||||
|
* @param localDb the local database used to persist the current
|
||||||
|
* {@link IdGenerator}
|
||||||
|
* @param receivedMessageCache a message cache containing all unread messages
|
||||||
|
* from the server that can be relayed after
|
||||||
|
* initialization
|
||||||
|
* @throws IOException if no {@link IdGenerator} is present and none could be
|
||||||
|
* requested from the server
|
||||||
|
* @since Envoy v0.2-alpha
|
||||||
|
*/
|
||||||
|
public void initReceiver(LocalDb localDb, Cache<Message> receivedMessageCache) throws IOException {
|
||||||
|
checkOnline();
|
||||||
|
|
||||||
// Process incoming messages
|
// Process incoming messages
|
||||||
final ReceivedMessageProcessor receivedMessageProcessor = new ReceivedMessageProcessor();
|
final ReceivedMessageProcessor receivedMessageProcessor = new ReceivedMessageProcessor();
|
||||||
|
@ -51,7 +51,7 @@ public class Receiver implements Runnable {
|
|||||||
|
|
||||||
try (ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(objBytes))) {
|
try (ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(objBytes))) {
|
||||||
Object obj = oin.readObject();
|
Object obj = oin.readObject();
|
||||||
logger.finest("Received object " + obj);
|
logger.info("Received object " + obj);
|
||||||
|
|
||||||
// Get appropriate processor
|
// Get appropriate processor
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -12,9 +12,9 @@ import javax.swing.border.EmptyBorder;
|
|||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
|
||||||
import envoy.client.data.Chat;
|
import envoy.client.data.Chat;
|
||||||
import envoy.client.data.LocalDb;
|
import envoy.client.data.LocalDb;
|
||||||
|
import envoy.client.data.Settings;
|
||||||
import envoy.client.event.MessageCreationEvent;
|
import envoy.client.event.MessageCreationEvent;
|
||||||
import envoy.client.event.ThemeChangeEvent;
|
import envoy.client.event.ThemeChangeEvent;
|
||||||
import envoy.client.net.Client;
|
import envoy.client.net.Client;
|
||||||
|
@ -6,7 +6,7 @@ import java.awt.Font;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
import envoy.client.data.Settings;
|
||||||
import envoy.client.event.SendEvent;
|
import envoy.client.event.SendEvent;
|
||||||
import envoy.client.ui.list.ComponentList;
|
import envoy.client.ui.list.ComponentList;
|
||||||
import envoy.client.ui.list.ComponentListCellRenderer;
|
import envoy.client.ui.list.ComponentListCellRenderer;
|
||||||
|
@ -2,40 +2,52 @@ package envoy.client.ui;
|
|||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ItemEvent;
|
import java.awt.event.ItemEvent;
|
||||||
import java.awt.event.ItemListener;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.naming.TimeLimitExceededException;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
import envoy.client.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.LoginCredentials;
|
||||||
|
import envoy.data.Message;
|
||||||
|
import envoy.data.User;
|
||||||
|
import envoy.event.EventBus;
|
||||||
|
import envoy.event.HandshakeRejectionEvent;
|
||||||
|
import envoy.exception.EnvoyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>envoy-client</strong><br>
|
* Project: <strong>envoy-client</strong><br>
|
||||||
* File: <strong>LoginDialog.java</strong><br>
|
* File: <strong>LoginDialog.java</strong><br>
|
||||||
* Created: <strong>01.01.2020</strong><br>
|
* Created: <strong>01.01.2020</strong><br>
|
||||||
*
|
*
|
||||||
* @author Kai S. K. Engelbart
|
* @author Kai S. K. Engelbart
|
||||||
* @author Maximilian Käfer
|
* @author Maximilian Käfer
|
||||||
* @since Envoy v0.3-alpha
|
* @since Envoy v0.3-alpha
|
||||||
*/
|
*/
|
||||||
public class LoginDialog extends JDialog {
|
public class LoginDialog extends JDialog {
|
||||||
|
|
||||||
private final JPanel contentPanel;
|
private JPanel contentPanel;
|
||||||
private JTextField textField;
|
private JTextField textField;
|
||||||
private JPasswordField passwordField;
|
private JPasswordField passwordField;
|
||||||
private JPasswordField repeatPasswordField;
|
private JPasswordField repeatPasswordField;
|
||||||
|
|
||||||
private JLabel lblUserName;
|
private JLabel lblUserName;
|
||||||
private JLabel lblPassword;
|
private JLabel lblPassword;
|
||||||
private JLabel lblRepeatPassword;
|
private JLabel lblRepeatPassword;
|
||||||
|
private JLabel errorMessage;
|
||||||
|
|
||||||
private GridBagConstraints gbc_lblRepeatPassword;
|
private GridBagConstraints gbc_lblRepeatPassword;
|
||||||
private GridBagConstraints gbc_repeatPasswordField;
|
private GridBagConstraints gbc_repeatPasswordField;
|
||||||
|
private GridBagConstraints gbc_errorMessage;
|
||||||
|
|
||||||
private JPanel buttonPane;
|
private JPanel buttonPane;
|
||||||
private JTextPane registerText;
|
private JTextPane registerText;
|
||||||
private JCheckBox registerCheckBox;
|
private JCheckBox registerCheckBox;
|
||||||
private PrimaryButton okButton;
|
private PrimaryButton okButton;
|
||||||
@ -43,15 +55,101 @@ public class LoginDialog extends JDialog {
|
|||||||
|
|
||||||
private LoginCredentials credentials;
|
private LoginCredentials credentials;
|
||||||
|
|
||||||
private static final long serialVersionUID = 352021600833907468L;
|
private final Client client;
|
||||||
|
private final LocalDb localDb;
|
||||||
|
private final Cache<Message> 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.
|
* 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
|
* @since Envoy v0.3-alpha
|
||||||
*/
|
*/
|
||||||
public LoginDialog() {
|
public LoginDialog(Client client, LocalDb localDb, Cache<Message> 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 -> { clearPasswordFields(); errorMessage.setVisible(true); errorMessage.setText(evt.get()); });
|
||||||
|
|
||||||
|
// 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 | 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);
|
setSize(338, 123);
|
||||||
setLocationRelativeTo(null);
|
setLocationRelativeTo(null);
|
||||||
|
setResizable(false);
|
||||||
getContentPane().setLayout(new BorderLayout());
|
getContentPane().setLayout(new BorderLayout());
|
||||||
contentPanel = new JPanel();
|
contentPanel = new JPanel();
|
||||||
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
|
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
@ -62,137 +160,121 @@ public class LoginDialog extends JDialog {
|
|||||||
gbl_contentPanel.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
|
gbl_contentPanel.columnWeights = new double[] { 0.0, 1.0, Double.MIN_VALUE };
|
||||||
gbl_contentPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
|
gbl_contentPanel.rowWeights = new double[] { 0.0, 0.0, Double.MIN_VALUE };
|
||||||
contentPanel.setLayout(gbl_contentPanel);
|
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();
|
|
||||||
repeatPasswordField.setBorder(null);
|
|
||||||
gbc_repeatPasswordField = new GridBagConstraints();
|
|
||||||
gbc_repeatPasswordField.fill = GridBagConstraints.HORIZONTAL;
|
|
||||||
gbc_repeatPasswordField.gridx = 1;
|
|
||||||
gbc_repeatPasswordField.gridy = 2;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
buttonPane = new JPanel();
|
|
||||||
|
|
||||||
registerText = new JTextPane();
|
lblUserName = new JLabel("Username:");
|
||||||
registerText.setEditable(false);
|
GridBagConstraints gbc_lblUserName = new GridBagConstraints();
|
||||||
registerText.setText("Register?");
|
gbc_lblUserName.anchor = GridBagConstraints.EAST;
|
||||||
registerText.setFont(new Font("Arial", Font.BOLD, 12));
|
gbc_lblUserName.insets = new Insets(0, 0, 5, 5);
|
||||||
registerText.setAlignmentX(LEFT_ALIGNMENT);
|
gbc_lblUserName.gridx = 0;
|
||||||
buttonPane.add(registerText);
|
gbc_lblUserName.gridy = 0;
|
||||||
|
contentPanel.add(lblUserName, gbc_lblUserName);
|
||||||
|
|
||||||
registerCheckBox = new JCheckBox();
|
textField = new JTextField();
|
||||||
registerCheckBox.setAlignmentX(LEFT_ALIGNMENT);
|
textField.setBorder(null);
|
||||||
registerCheckBox.addItemListener(new ItemListener() {
|
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);
|
||||||
|
|
||||||
@Override
|
lblPassword = new JLabel("Password:");
|
||||||
public void itemStateChanged(ItemEvent e) {
|
GridBagConstraints gbc_lblPassword = new GridBagConstraints();
|
||||||
switch (e.getStateChange()) {
|
gbc_lblPassword.anchor = GridBagConstraints.EAST;
|
||||||
case ItemEvent.SELECTED:
|
gbc_lblPassword.insets = new Insets(0, 0, 0, 5);
|
||||||
contentPanel.add(lblRepeatPassword, gbc_lblRepeatPassword);
|
gbc_lblPassword.gridx = 0;
|
||||||
contentPanel.add(repeatPasswordField, gbc_repeatPasswordField);
|
gbc_lblPassword.gridy = 1;
|
||||||
setSize(338, 148);
|
contentPanel.add(lblPassword, gbc_lblPassword);
|
||||||
contentPanel.revalidate();
|
|
||||||
contentPanel.repaint();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ItemEvent.DESELECTED:
|
passwordField = new JPasswordField();
|
||||||
if (repeatPasswordField.getParent() == contentPanel) {
|
passwordField.setBorder(null);
|
||||||
contentPanel.remove(lblRepeatPassword);
|
GridBagConstraints gbc_passwordField = new GridBagConstraints();
|
||||||
contentPanel.remove(repeatPasswordField);
|
gbc_passwordField.fill = GridBagConstraints.HORIZONTAL;
|
||||||
setSize(338, 123);
|
gbc_passwordField.gridx = 1;
|
||||||
contentPanel.revalidate();
|
gbc_passwordField.gridy = 1;
|
||||||
contentPanel.repaint();
|
contentPanel.add(passwordField, gbc_passwordField);
|
||||||
}
|
|
||||||
break;
|
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;
|
||||||
|
|
||||||
|
errorMessage = new JLabel();
|
||||||
|
gbc_errorMessage = new GridBagConstraints();
|
||||||
|
gbc_errorMessage.gridx = 1;
|
||||||
|
gbc_errorMessage.gridy = 3;
|
||||||
|
gbc_errorMessage.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
gbc_errorMessage.insets = new Insets(5, 5, 5, 5);
|
||||||
|
errorMessage.setForeground(Color.RED);
|
||||||
|
errorMessage.setVisible(false);
|
||||||
|
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);
|
||||||
|
|
||||||
|
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, 173);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ItemEvent.DESELECTED:
|
||||||
|
if (repeatPasswordField.getParent() == contentPanel) {
|
||||||
|
contentPanel.remove(lblRepeatPassword);
|
||||||
|
contentPanel.remove(repeatPasswordField);
|
||||||
|
setSize(338, 148);
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
});
|
}
|
||||||
buttonPane.add(registerCheckBox);
|
contentPanel.revalidate();
|
||||||
|
contentPanel.repaint();
|
||||||
|
});
|
||||||
|
buttonPane.add(registerCheckBox);
|
||||||
|
|
||||||
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
|
||||||
getContentPane().add(buttonPane, BorderLayout.SOUTH);
|
getContentPane().add(buttonPane, BorderLayout.SOUTH);
|
||||||
{
|
okButton = new PrimaryButton("OK");
|
||||||
okButton = new PrimaryButton("OK");
|
okButton.setActionCommand("OK");
|
||||||
okButton.addActionListener((evt) -> {
|
buttonPane.add(okButton);
|
||||||
try {
|
getRootPane().setDefaultButton(okButton);
|
||||||
if (registerCheckBox.isSelected()) {
|
|
||||||
if (Arrays.equals(passwordField.getPassword(), repeatPasswordField.getPassword())) {
|
cancelButton = new PrimaryButton("Cancel");
|
||||||
credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), true);
|
cancelButton.setActionCommand("Cancel");
|
||||||
dispose();
|
buttonPane.add(cancelButton);
|
||||||
} else {
|
|
||||||
JOptionPane.showMessageDialog(this, "The repeated password is unequal to the origional password!");
|
|
||||||
passwordField.setText(null);
|
|
||||||
repeatPasswordField.setText(null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
credentials = new LoginCredentials(textField.getText(), passwordField.getPassword(), false);
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
okButton.setActionCommand("OK");
|
|
||||||
buttonPane.add(okButton);
|
|
||||||
getRootPane().setDefaultButton(okButton);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
cancelButton = new PrimaryButton("Cancel");
|
|
||||||
cancelButton.addActionListener((evt) -> dispose());
|
|
||||||
cancelButton.setActionCommand("Cancel");
|
|
||||||
buttonPane.add(cancelButton);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setTheme();
|
setTheme();
|
||||||
|
|
||||||
setModal(true);
|
setModalityType(Dialog.DEFAULT_MODALITY_TYPE);
|
||||||
setVisible(true);
|
|
||||||
|
EventBus.getInstance().register(HandshakeSuccessfulEvent.class, evt -> dispose());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the text stored in the password fields.
|
||||||
|
*
|
||||||
|
* @since Envoy v0.3-alpha
|
||||||
|
*/
|
||||||
|
private void clearPasswordFields() {
|
||||||
|
passwordField.setText(null);
|
||||||
|
repeatPasswordField.setText(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTheme() {
|
private void setTheme() {
|
||||||
@ -238,11 +320,4 @@ public class LoginDialog extends JDialog {
|
|||||||
cancelButton.setBackground(theme.getInteractableBackgroundColor());
|
cancelButton.setBackground(theme.getInteractableBackgroundColor());
|
||||||
cancelButton.setForeground(theme.getInteractableForegroundColor());
|
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; }
|
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ import java.text.SimpleDateFormat;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
import envoy.client.data.Settings;
|
||||||
import envoy.client.ui.list.ComponentList;
|
import envoy.client.ui.list.ComponentList;
|
||||||
import envoy.client.ui.list.ComponentListCellRenderer;
|
import envoy.client.ui.list.ComponentListCellRenderer;
|
||||||
import envoy.data.Message;
|
import envoy.data.Message;
|
||||||
|
@ -12,7 +12,7 @@ import javax.swing.JComponent;
|
|||||||
import javax.swing.JScrollBar;
|
import javax.swing.JScrollBar;
|
||||||
import javax.swing.plaf.basic.BasicScrollBarUI;
|
import javax.swing.plaf.basic.BasicScrollBarUI;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
import envoy.client.data.Settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project: <strong>envoy-client</strong><br>
|
* Project: <strong>envoy-client</strong><br>
|
||||||
|
@ -5,8 +5,8 @@ import java.awt.Graphics;
|
|||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
import envoy.client.data.Settings;
|
||||||
import envoy.client.SettingsItem;
|
import envoy.client.data.SettingsItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component can be used to toggle between two options. This will change
|
* This component can be used to toggle between two options. This will change
|
||||||
|
@ -11,14 +11,11 @@ import javax.swing.JFrame;
|
|||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
|
||||||
import envoy.client.data.*;
|
import envoy.client.data.*;
|
||||||
import envoy.client.net.Client;
|
import envoy.client.net.Client;
|
||||||
import envoy.client.net.WriteProxy;
|
import envoy.client.net.WriteProxy;
|
||||||
import envoy.client.util.EnvoyLog;
|
import envoy.client.util.EnvoyLog;
|
||||||
import envoy.data.LoginCredentials;
|
|
||||||
import envoy.data.Message;
|
import envoy.data.Message;
|
||||||
import envoy.data.User;
|
|
||||||
import envoy.exception.EnvoyException;
|
import envoy.exception.EnvoyException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,7 +60,7 @@ public class Startup {
|
|||||||
if (args.length > 0) config.load(args);
|
if (args.length > 0) config.load(args);
|
||||||
|
|
||||||
// Check if all mandatory configuration values have been initialized
|
// Check if all mandatory configuration values have been initialized
|
||||||
if (!config.isInitialized()) throw new EnvoyException("Server or port are not defined");
|
if (!config.isInitialized()) throw new EnvoyException("Configuration is not fully initialized");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
JOptionPane
|
JOptionPane
|
||||||
.showMessageDialog(null, "Error loading configuration values:\n" + e.toString(), "Configuration error", JOptionPane.ERROR_MESSAGE);
|
.showMessageDialog(null, "Error loading configuration values:\n" + e.toString(), "Configuration error", JOptionPane.ERROR_MESSAGE);
|
||||||
@ -75,14 +72,6 @@ public class Startup {
|
|||||||
EnvoyLog.setFileLevelBarrier(config.getFileLevelBarrier());
|
EnvoyLog.setFileLevelBarrier(config.getFileLevelBarrier());
|
||||||
EnvoyLog.setConsoleLevelBarrier(config.getConsoleLevelBarrier());
|
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 aborted by the user. Exiting...");
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the local database
|
// Initialize the local database
|
||||||
LocalDb localDb;
|
LocalDb localDb;
|
||||||
if (config.isIgnoreLocalDB()) {
|
if (config.isIgnoreLocalDB()) {
|
||||||
@ -96,40 +85,18 @@ public class Startup {
|
|||||||
} catch (IOException e3) {
|
} catch (IOException e3) {
|
||||||
logger.log(Level.SEVERE, "Could not initialize local database", e3);
|
logger.log(Level.SEVERE, "Could not initialize local database", e3);
|
||||||
JOptionPane
|
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);
|
System.exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> chatWindow.setVisible(true));
|
// Initialize client and unread message cache
|
||||||
|
|
||||||
// Acquire the client user (with ID) either from the server or from the local
|
|
||||||
// database, which triggers offline mode
|
|
||||||
Client client = new Client();
|
Client client = new Client();
|
||||||
Cache<Message> cache = new Cache<>();
|
Cache<Message> cache = new Cache<>();
|
||||||
try {
|
|
||||||
// Try entering online mode first
|
// Try to connect to the server
|
||||||
localDb.loadIdGenerator();
|
new LoginDialog(client, localDb, cache);
|
||||||
client.onlineInit(credentials, localDb, cache);
|
SwingUtilities.invokeLater(() -> chatWindow.setVisible(true));
|
||||||
} 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.getName());
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set client user in local database
|
// Set client user in local database
|
||||||
localDb.setUser(client.getSender());
|
localDb.setUser(client.getSender());
|
||||||
|
@ -7,7 +7,7 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.ListCellRenderer;
|
import javax.swing.ListCellRenderer;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
import envoy.client.data.Settings;
|
||||||
import envoy.data.User;
|
import envoy.data.User;
|
||||||
import envoy.data.User.UserStatus;
|
import envoy.data.User.UserStatus;
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ import java.util.logging.Logger;
|
|||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JTextPane;
|
import javax.swing.JTextPane;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
import envoy.client.data.Settings;
|
||||||
import envoy.client.SettingsItem;
|
import envoy.client.data.SettingsItem;
|
||||||
import envoy.client.ui.Theme;
|
import envoy.client.ui.Theme;
|
||||||
import envoy.client.util.EnvoyLog;
|
import envoy.client.util.EnvoyLog;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import javax.swing.JDialog;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTextPane;
|
import javax.swing.JTextPane;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
import envoy.client.data.Settings;
|
||||||
import envoy.client.ui.PrimaryButton;
|
import envoy.client.ui.PrimaryButton;
|
||||||
import envoy.client.ui.PrimaryTextArea;
|
import envoy.client.ui.PrimaryTextArea;
|
||||||
import envoy.client.ui.Theme;
|
import envoy.client.ui.Theme;
|
||||||
|
@ -9,7 +9,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
import envoy.client.data.Settings;
|
||||||
import envoy.client.event.ThemeChangeEvent;
|
import envoy.client.event.ThemeChangeEvent;
|
||||||
import envoy.client.ui.PrimaryButton;
|
import envoy.client.ui.PrimaryButton;
|
||||||
import envoy.client.ui.Theme;
|
import envoy.client.ui.Theme;
|
||||||
|
@ -9,7 +9,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import envoy.client.Settings;
|
import envoy.client.data.Settings;
|
||||||
import envoy.client.event.ThemeChangeEvent;
|
import envoy.client.event.ThemeChangeEvent;
|
||||||
import envoy.client.ui.Color;
|
import envoy.client.ui.Color;
|
||||||
import envoy.client.ui.Theme;
|
import envoy.client.ui.Theme;
|
||||||
|
Reference in New Issue
Block a user