diff --git a/src/main/java/envoy/client/Client.java b/src/main/java/envoy/client/Client.java
index 6a4b754..a037e8c 100644
--- a/src/main/java/envoy/client/Client.java
+++ b/src/main/java/envoy/client/Client.java
@@ -1,7 +1,5 @@
package envoy.client;
-import java.io.IOException;
-import java.io.InputStream;
import java.net.Socket;
import java.util.Map;
import java.util.logging.Logger;
@@ -9,6 +7,7 @@ import java.util.logging.Logger;
import envoy.client.util.EnvoyLog;
import envoy.data.LoginCredentials;
import envoy.data.User;
+import envoy.exception.EnvoyException;
import envoy.util.SerializationUtils;
/**
@@ -23,10 +22,11 @@ import envoy.util.SerializationUtils;
*/
public class Client {
- private Socket socket;
- private Config config = Config.getInstance();
- private User sender, recipient;
- private boolean online;
+ private Socket socket;
+ private Config config = Config.getInstance();
+ private volatile User sender;
+ private User recipient;
+ private boolean online;
private static final Logger logger = EnvoyLog.getLogger(Client.class.getSimpleName());
@@ -34,11 +34,11 @@ public class Client {
* Enters the online mode by acquiring a user ID from the server.
*
* @param credentials the login credentials of the user
- * @throws IOException if the online mode could not be entered or the request
- * failed for some other reason
+ * @throws Exception if the online mode could not be entered or the request
+ * failed for some other reason
* @since Envoy v0.2-alpha
*/
- public void onlineInit(LoginCredentials credentials) throws IOException {
+ public void onlineInit(LoginCredentials credentials) throws Exception {
logger.info(String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
socket = new Socket(config.getServer(), config.getPort());
logger.info("Successfully connected to server.");
@@ -47,14 +47,20 @@ public class Client {
logger.finest("Sending login credentials...");
SerializationUtils.writeBytesWithLength(credentials, socket.getOutputStream());
- // Read response (user object)
- InputStream in = socket.getInputStream();
+ // Create message receiver
+ Receiver receiver = new Receiver(socket.getInputStream());
- // Read object
- try {
- sender = SerializationUtils.read(in, User.class);
- } catch (ClassNotFoundException e) {
- throw new IOException(e);
+ // Register user creation processor
+ receiver.registerProcessor(User.class, sender -> { logger.info("Acquired user object " + sender); this.sender = sender; });
+
+ // Start receiver
+ new Thread(receiver).start();
+
+ // Wait for a maximum of five seconds to acquire the sender object
+ long start = System.currentTimeMillis();
+ while (sender == null) {
+ if (System.currentTimeMillis() - start > 5000) throw new EnvoyException("Did not log in after 5 seconds");
+ Thread.sleep(500);
}
online = true;
diff --git a/src/main/java/envoy/client/ObjectProcessor.java b/src/main/java/envoy/client/ObjectProcessor.java
new file mode 100644
index 0000000..b0aed2d
--- /dev/null
+++ b/src/main/java/envoy/client/ObjectProcessor.java
@@ -0,0 +1,15 @@
+package envoy.client;
+
+
+/**
+ * Project: envoy-client
+ * File: ObjectProcessor.java
+ * Created: 30.12.2019
+ *
+ * @author Kai S. K. Engelbart
+ * @since Envoy v0.3-alpha
+ */
+public interface ObjectProcessor {
+
+ void process(T input);
+}
\ No newline at end of file
diff --git a/src/main/java/envoy/client/Receiver.java b/src/main/java/envoy/client/Receiver.java
new file mode 100644
index 0000000..64a4655
--- /dev/null
+++ b/src/main/java/envoy/client/Receiver.java
@@ -0,0 +1,50 @@
+package envoy.client;
+
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import envoy.client.util.EnvoyLog;
+
+/**
+ * Project: envoy-client
+ * File: Receiver.java
+ * Created: 30.12.2019
+ *
+ * @author Kai S. K. Engelbart
+ * @since Envoy v0.3-alpha
+ */
+public class Receiver implements Runnable {
+
+ private InputStream in;
+ private Map, ObjectProcessor>> processors = new HashMap<>();
+
+ private static final Logger logger = EnvoyLog.getLogger(Receiver.class.getSimpleName());
+
+ public Receiver(InputStream in) { this.in = in; }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void run() {
+ try (ObjectInputStream oin = new ObjectInputStream(in)) {
+ while (true) {
+ Object obj = oin.readObject();
+ logger.finest("Received object " + obj);
+
+ // Get appropriate processor
+ ObjectProcessor processor = processors.get(obj.getClass());
+ if (processor == null)
+ logger.severe(String.format("The received object has the class %s for which no processor is defined.", obj.getClass()));
+ else
+ processor.process(obj);
+ }
+ } catch(Exception e) {
+ logger.log(Level.SEVERE, "Error on receiver thread", e);
+ }
+ }
+
+ public void registerProcessor(Class processorClass, ObjectProcessor processor) { processors.put(processorClass, processor); }
+}
\ 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 2faaa1a..1a2c96e 100644
--- a/src/main/java/envoy/client/ui/Startup.java
+++ b/src/main/java/envoy/client/ui/Startup.java
@@ -101,6 +101,7 @@ public class Startup {
client.onlineInit(new LoginCredentials(userName, pass.toCharArray()));
} catch (Exception e1) {
logger.warning("Could not connect to server. Trying offline mode...");
+ e1.printStackTrace();
try {
// Try entering offline mode
localDB.loadUsers();