diff --git a/src/main/java/envoy/server/LoginCredentialProcessor.java b/src/main/java/envoy/server/LoginCredentialProcessor.java new file mode 100644 index 0000000..f208a3e --- /dev/null +++ b/src/main/java/envoy/server/LoginCredentialProcessor.java @@ -0,0 +1,29 @@ +package envoy.server; + +import envoy.data.LoginCredentials; +import envoy.data.User; + +/** + * This {@link ObjectProcessor} handles {@link LoginCredentials}.
+ *
+ * Project: envoy-server-standalone
+ * File: LoginCredentialProcessor.java
+ * Created: 30.12.2019
+ * + * @author Kai S. K. Engelbart + * @since Envoy Server Standalone v0.1-alpha + */ +public class LoginCredentialProcessor implements ObjectProcessor { + + // TODO: Acquire user IDs from database + private static long currentUserId = 1; + + @Override + public Class getInputClass() { return LoginCredentials.class; } + + @Override + public User process(LoginCredentials input) { + System.out.println("Received login credentials " + input); + return new User(currentUserId++, input.getName()); + } +} diff --git a/src/main/java/envoy/server/MessageProcessor.java b/src/main/java/envoy/server/MessageProcessor.java new file mode 100644 index 0000000..ea52c55 --- /dev/null +++ b/src/main/java/envoy/server/MessageProcessor.java @@ -0,0 +1,22 @@ +package envoy.server; + +import envoy.data.Message; + +/** + * This {@link ObjectProcessor} handles incoming {@link Message}s.
+ *
+ * Project: envoy-server-standalone
+ * File: MessageProcessor.java
+ * Created: 30.12.2019
+ * + * @author Kai S. K. Engelbart + * @since Envoy Server Standalone v0.1-alpha + */ +public class MessageProcessor implements ObjectProcessor { + + @Override + public Class getInputClass() { return Message.class; } + + @Override + public Void process(Message input) { return null; } +} diff --git a/src/main/java/envoy/server/ObjectMessageProcessor.java b/src/main/java/envoy/server/ObjectMessageProcessor.java index 77a086b..53e53da 100644 --- a/src/main/java/envoy/server/ObjectMessageProcessor.java +++ b/src/main/java/envoy/server/ObjectMessageProcessor.java @@ -1,29 +1,65 @@ package envoy.server; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Set; import com.jenkov.nioserver.IMessageProcessor; import com.jenkov.nioserver.Message; import com.jenkov.nioserver.WriteProxy; /** + * Handles incoming objects.
+ *
* Project: envoy-server-standalone
* File: ObjectMessageProcessor.java
* Created: 28.12.2019
- * + * * @author Kai S. K. Engelbart * @since Envoy Server Standalone v0.1-alpha */ public class ObjectMessageProcessor implements IMessageProcessor { + private final Set> processors; + + /** + * The constructor to set the {@link ObjectProcessor}s. + * + * @param processors the {@link ObjectProcessor} to set + * @since Envoy Server Standalone v0.1-alpha + */ + public ObjectMessageProcessor(Set> processors) { this.processors = processors; } + + @SuppressWarnings("unchecked") @Override public void process(Message message, WriteProxy writeProxy) { try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(message.sharedArray, message.offset + 4, message.length - 4))) { Object obj = in.readObject(); - // TODO: Process pipeline System.out.println("Read object: " + obj.toString()); + + // Process object + processors.stream().filter(p -> p.getInputClass().isInstance(obj)).forEach((@SuppressWarnings("rawtypes") ObjectProcessor p) -> { + Object responseObj = p.process(p.getInputClass().cast(obj)); + if (responseObj != null) { + // Create message targeted at the client + Message response = writeProxy.getMessage(); + response.socketId = message.socketId; + + // Serialize object to byte array + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ObjectOutputStream oout = new ObjectOutputStream(baos)) { + oout.writeObject(responseObj); + } catch (IOException e) { + e.printStackTrace(); + } + byte[] objBytes = baos.toByteArray(); + response.writeToMessage(objBytes); + writeProxy.enqueue(response); + } + }); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } diff --git a/src/main/java/envoy/server/ObjectMessageReader.java b/src/main/java/envoy/server/ObjectMessageReader.java index 9a20c7f..f0fa73a 100644 --- a/src/main/java/envoy/server/ObjectMessageReader.java +++ b/src/main/java/envoy/server/ObjectMessageReader.java @@ -11,10 +11,12 @@ import com.jenkov.nioserver.MessageBuffer; import com.jenkov.nioserver.Socket; /** + * This {@link IMessageReader} decodes serialized Java objects.
+ *
* Project: envoy-server-standalone
* File: ObjectMessageReader.java
* Created: 28.12.2019
- * + * * @author Kai S. K. Engelbart * @since Envoy Server Standalone v0.1-alpha */ @@ -24,6 +26,14 @@ public class ObjectMessageReader implements IMessageReader { private Message nextMessage; private MessageBuffer messageBuffer; + private int fromByteArray(byte[] bytes, int offset) { + return ((bytes[offset] & 0xFF) << 24) | ((bytes[offset + 1] & 0xFF) << 16) | ((bytes[offset + 2] & 0xFF) << 8) + | ((bytes[offset + 3] & 0xFF) << 0); + } + + @Override + public List getMessages() { return completeMessages; } + @Override public void init(MessageBuffer messageBuffer) { this.messageBuffer = messageBuffer; @@ -55,12 +65,4 @@ public class ObjectMessageReader implements IMessageReader { buffer.clear(); } - - private int fromByteArray(byte[] bytes, int offset) { - return ((bytes[offset] & 0xFF) << 24) | ((bytes[offset + 1] & 0xFF) << 16) | ((bytes[offset + 2] & 0xFF) << 8) - | ((bytes[offset + 3] & 0xFF) << 0); - } - - @Override - public List getMessages() { return completeMessages; } } \ No newline at end of file diff --git a/src/main/java/envoy/server/ObjectProcessor.java b/src/main/java/envoy/server/ObjectProcessor.java new file mode 100644 index 0000000..44c07e1 --- /dev/null +++ b/src/main/java/envoy/server/ObjectProcessor.java @@ -0,0 +1,30 @@ +package envoy.server; + +/** + * This interface defines methods for processing objects of a specific + * type incoming from a client.
+ *
+ * Project: envoy-server-standalone
+ * File: ObjectProcessor.java
+ * Created: 30.12.2019
+ * + * @author Kai S. K. Engelbart + * @param type of the request object + * @param type of the response object + * @since Envoy Server Standalone v0.1-alpha + */ +public interface ObjectProcessor { + + /** + * @return the Class of the request object + * @since Envoy Server Standalone v0.1-alpha + */ + Class getInputClass(); + + /** + * @param input the request object + * @return the response object + * @since Envoy Server Standalone v0.1-alpha + */ + U process(T input); +} \ No newline at end of file diff --git a/src/main/java/envoy/server/Startup.java b/src/main/java/envoy/server/Startup.java index 1c0932b..58a8366 100644 --- a/src/main/java/envoy/server/Startup.java +++ b/src/main/java/envoy/server/Startup.java @@ -1,21 +1,35 @@ package envoy.server; import java.io.IOException; +import java.util.HashSet; +import java.util.Set; import com.jenkov.nioserver.Server; /** + * Starts the server.
+ *
* Project: envoy-server-standalone
* File: Startup.java
* Created: 24.12.2019
- * + * * @author Kai S. K. Engelbart * @since Envoy Server Standalone v0.1-alpha */ public class Startup { + /** + * Starts the server. + * + * @param args the run configuration. Currently unused. + * @throws IOException if the server crashes + * @since Envoy Server Standalone v0.1-alpha + */ public static void main(String[] args) throws IOException { - Server server = new Server(8080, () -> new ObjectMessageReader(), new ObjectMessageProcessor()); + Set> processors = new HashSet<>(); + processors.add(new LoginCredentialProcessor()); + processors.add(new MessageProcessor()); + Server server = new Server(8080, () -> new ObjectMessageReader(), new ObjectMessageProcessor(processors)); server.start(); } } \ No newline at end of file