From 998fc3a91eb050d1b0e28fde95646ef13dd14fcf Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Fri, 3 Jan 2020 16:40:43 +0200 Subject: [PATCH 1/7] Moved classes related to java-nio-server to envoy.server.net package. --- src/main/java/envoy/server/Startup.java | 3 +++ .../server/{ => net}/ObjectMessageProcessor.java | 4 +++- .../envoy/server/{ => net}/ObjectMessageReader.java | 12 ++++++------ 3 files changed, 12 insertions(+), 7 deletions(-) rename src/main/java/envoy/server/{ => net}/ObjectMessageProcessor.java (97%) rename src/main/java/envoy/server/{ => net}/ObjectMessageReader.java (98%) diff --git a/src/main/java/envoy/server/Startup.java b/src/main/java/envoy/server/Startup.java index 58a8366..dd295a4 100644 --- a/src/main/java/envoy/server/Startup.java +++ b/src/main/java/envoy/server/Startup.java @@ -6,6 +6,9 @@ import java.util.Set; import com.jenkov.nioserver.Server; +import envoy.server.net.ObjectMessageProcessor; +import envoy.server.net.ObjectMessageReader; + /** * Starts the server.
*
diff --git a/src/main/java/envoy/server/ObjectMessageProcessor.java b/src/main/java/envoy/server/net/ObjectMessageProcessor.java similarity index 97% rename from src/main/java/envoy/server/ObjectMessageProcessor.java rename to src/main/java/envoy/server/net/ObjectMessageProcessor.java index 53e53da..6f652d9 100644 --- a/src/main/java/envoy/server/ObjectMessageProcessor.java +++ b/src/main/java/envoy/server/net/ObjectMessageProcessor.java @@ -1,4 +1,4 @@ -package envoy.server; +package envoy.server.net; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -11,6 +11,8 @@ import com.jenkov.nioserver.IMessageProcessor; import com.jenkov.nioserver.Message; import com.jenkov.nioserver.WriteProxy; +import envoy.server.ObjectProcessor; + /** * Handles incoming objects.
*
diff --git a/src/main/java/envoy/server/ObjectMessageReader.java b/src/main/java/envoy/server/net/ObjectMessageReader.java similarity index 98% rename from src/main/java/envoy/server/ObjectMessageReader.java rename to src/main/java/envoy/server/net/ObjectMessageReader.java index f0fa73a..b477734 100644 --- a/src/main/java/envoy/server/ObjectMessageReader.java +++ b/src/main/java/envoy/server/net/ObjectMessageReader.java @@ -1,4 +1,4 @@ -package envoy.server; +package envoy.server.net; import java.io.IOException; import java.nio.ByteBuffer; @@ -26,11 +26,6 @@ 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; } @@ -65,4 +60,9 @@ 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); + } } \ No newline at end of file From c42bdffbd7d02c13df41e0ecefaa6f8b2342c789 Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Fri, 3 Jan 2020 18:11:38 +0200 Subject: [PATCH 2/7] Added ConnectionManager, propagating socketId to processors --- .../java/envoy/server/ConnectionManager.java | 79 +++++++++++++++++++ .../server/LoginCredentialProcessor.java | 8 +- .../java/envoy/server/MessageProcessor.java | 12 ++- .../java/envoy/server/ObjectProcessor.java | 5 +- src/main/java/envoy/server/Startup.java | 2 + .../server/net/ObjectMessageProcessor.java | 8 +- 6 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 src/main/java/envoy/server/ConnectionManager.java diff --git a/src/main/java/envoy/server/ConnectionManager.java b/src/main/java/envoy/server/ConnectionManager.java new file mode 100644 index 0000000..ac4b0c0 --- /dev/null +++ b/src/main/java/envoy/server/ConnectionManager.java @@ -0,0 +1,79 @@ +package envoy.server; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.jenkov.nioserver.ISocketIdListener; + +/** + * Project: envoy-server-standalone
+ * File: ConnectionManager.java
+ * Created: 03.01.2020
+ * + * @author Kai S. K. Engelbart + * @since Envoy Server Standalone v0.1-alpha + */ +public class ConnectionManager implements ISocketIdListener { + + /** + * Contains all socket IDs that have not yet performed a handshake / acquired + * their corresponding user ID. + * + * @since Envoy Server Standalone v0.1-alpha + */ + private Set pendingSockets = new HashSet<>(); + + /** + * Contains all socket IDs that have acquired a user ID as keys to these IDs. + * + * @since Envoy Server Standalone v0.1-alpha + */ + private Map sockets = new HashMap<>(); + + private static ConnectionManager connectionManager = new ConnectionManager(); + + private ConnectionManager() {} + + /** + * @return a singleton instance of this object + * @since Envoy Server Standalone v0.1-alpha + */ + public static ConnectionManager getInstance() { return connectionManager; } + + @Override + public void socketCancelled(long socketId) { + if (!pendingSockets.remove(socketId)) + sockets.entrySet().stream().filter(e -> e.getValue() == socketId).forEach(e -> sockets.remove(e.getValue())); + } + + @Override + public void socketRegistered(long socketId) { pendingSockets.add(socketId); } + + /** + * Associates a socket ID with a user ID. + * + * @param socketId the socket ID + * @param userId the user ID + * @since Envoy Server Standalone v0.1-alpha + */ + public void registerUser(long socketId, long userId) { + sockets.put(socketId, userId); + pendingSockets.remove(socketId); + } + + /** + * @param userId the ID of the user registered at the a socket + * @return the ID of the socket + * @since Envoy Server Standalone v0.1-alpha + */ + public long getSocketId(long userId) { return sockets.get(userId); } + + /** + * @param userId the ID of the user to check for + * @return {@code true} if the user is online + * @since Envoy Server Standalone v0.1-alpha + */ + public boolean isOnline(long userId) { return sockets.containsKey(userId); } +} diff --git a/src/main/java/envoy/server/LoginCredentialProcessor.java b/src/main/java/envoy/server/LoginCredentialProcessor.java index f208a3e..0a84edf 100644 --- a/src/main/java/envoy/server/LoginCredentialProcessor.java +++ b/src/main/java/envoy/server/LoginCredentialProcessor.java @@ -22,8 +22,10 @@ public class LoginCredentialProcessor implements ObjectProcessor getInputClass() { return LoginCredentials.class; } @Override - public User process(LoginCredentials input) { - System.out.println("Received login credentials " + input); - return new User(currentUserId++, input.getName()); + public User process(LoginCredentials input, long socketId) { + System.out.println(String.format("Received login credentials %s from socket ID %d", input, socketId)); + User user = new User(currentUserId++, input.getName()); + ConnectionManager.getInstance().registerUser(socketId, user.getId()); + return user; } } diff --git a/src/main/java/envoy/server/MessageProcessor.java b/src/main/java/envoy/server/MessageProcessor.java index ea52c55..8d80e53 100644 --- a/src/main/java/envoy/server/MessageProcessor.java +++ b/src/main/java/envoy/server/MessageProcessor.java @@ -18,5 +18,15 @@ public class MessageProcessor implements ObjectProcessor { public Class getInputClass() { return Message.class; } @Override - public Void process(Message input) { return null; } + public Void process(Message message, long socketId) { + + // TODO: Send message to recipient if online + ConnectionManager connectionManager = ConnectionManager.getInstance(); + if (connectionManager.isOnline(message.getRecipientId())) { + + } + + // TODO: Add message to database + return null; + } } diff --git a/src/main/java/envoy/server/ObjectProcessor.java b/src/main/java/envoy/server/ObjectProcessor.java index 44c07e1..07c0480 100644 --- a/src/main/java/envoy/server/ObjectProcessor.java +++ b/src/main/java/envoy/server/ObjectProcessor.java @@ -22,9 +22,10 @@ public interface ObjectProcessor { Class getInputClass(); /** - * @param input the request object + * @param input the request object + * @param socketId the ID of the socket from which the object was received * @return the response object * @since Envoy Server Standalone v0.1-alpha */ - U process(T input); + U process(T input, long socketId); } \ 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 dd295a4..b616946 100644 --- a/src/main/java/envoy/server/Startup.java +++ b/src/main/java/envoy/server/Startup.java @@ -32,7 +32,9 @@ public class Startup { Set> processors = new HashSet<>(); processors.add(new LoginCredentialProcessor()); processors.add(new MessageProcessor()); + Server server = new Server(8080, () -> new ObjectMessageReader(), new ObjectMessageProcessor(processors)); server.start(); + server.getSocketProcessor().registerSocketIdListener(ConnectionManager.getInstance()); } } \ No newline at end of file diff --git a/src/main/java/envoy/server/net/ObjectMessageProcessor.java b/src/main/java/envoy/server/net/ObjectMessageProcessor.java index 6f652d9..1bf707f 100644 --- a/src/main/java/envoy/server/net/ObjectMessageProcessor.java +++ b/src/main/java/envoy/server/net/ObjectMessageProcessor.java @@ -25,7 +25,7 @@ import envoy.server.ObjectProcessor; */ public class ObjectMessageProcessor implements IMessageProcessor { - private final Set> processors; + private final Set> processors; /** * The constructor to set the {@link ObjectProcessor}s. @@ -33,7 +33,9 @@ public class ObjectMessageProcessor implements IMessageProcessor { * @param processors the {@link ObjectProcessor} to set * @since Envoy Server Standalone v0.1-alpha */ - public ObjectMessageProcessor(Set> processors) { this.processors = processors; } + public ObjectMessageProcessor(Set> processors) { + this.processors = processors; + } @SuppressWarnings("unchecked") @Override @@ -44,7 +46,7 @@ public class ObjectMessageProcessor implements IMessageProcessor { // Process object processors.stream().filter(p -> p.getInputClass().isInstance(obj)).forEach((@SuppressWarnings("rawtypes") ObjectProcessor p) -> { - Object responseObj = p.process(p.getInputClass().cast(obj)); + Object responseObj = p.process(p.getInputClass().cast(obj), message.socketId); if (responseObj != null) { // Create message targeted at the client Message response = writeProxy.getMessage(); From 242593472ed4869eb29aeb49c1a9accae323d945 Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Mon, 6 Jan 2020 14:58:28 +0200 Subject: [PATCH 3/7] Added writing capabilities to ObjectProcessor, completed db integration At this moment the client is not able to receive to objects sent consecutively. This will be worked on in a future commit and should be fixed before merging this branch into develop. --- pom.xml | 5 +++ .../server/LoginCredentialProcessor.java | 21 ++++++++++-- .../java/envoy/server/MessageProcessor.java | 6 ++-- .../java/envoy/server/ObjectProcessor.java | 11 +++--- src/main/java/envoy/server/data/Message.java | 20 +++++++++-- src/main/java/envoy/server/data/User.java | 6 +++- .../server/net/ObjectMessageProcessor.java | 32 ++++++----------- .../envoy/server/net/ObjectWriteProxy.java | 34 +++++++++++++++++++ src/main/resources/META-INF/persistence.xml | 29 ++++++++++++++++ 9 files changed, 128 insertions(+), 36 deletions(-) create mode 100644 src/main/java/envoy/server/net/ObjectWriteProxy.java create mode 100644 src/main/resources/META-INF/persistence.xml diff --git a/pom.xml b/pom.xml index 5b81ded..48a6be0 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,11 @@ hibernate-core 5.4.10.Final + + org.postgresql + postgresql + 42.2.9 + diff --git a/src/main/java/envoy/server/LoginCredentialProcessor.java b/src/main/java/envoy/server/LoginCredentialProcessor.java index 0a84edf..89261cf 100644 --- a/src/main/java/envoy/server/LoginCredentialProcessor.java +++ b/src/main/java/envoy/server/LoginCredentialProcessor.java @@ -1,7 +1,12 @@ package envoy.server; +import java.io.IOException; +import java.util.ArrayList; + +import envoy.data.Contacts; import envoy.data.LoginCredentials; import envoy.data.User; +import envoy.server.net.ObjectWriteProxy; /** * This {@link ObjectProcessor} handles {@link LoginCredentials}.
@@ -13,7 +18,7 @@ import envoy.data.User; * @author Kai S. K. Engelbart * @since Envoy Server Standalone v0.1-alpha */ -public class LoginCredentialProcessor implements ObjectProcessor { +public class LoginCredentialProcessor implements ObjectProcessor { // TODO: Acquire user IDs from database private static long currentUserId = 1; @@ -22,10 +27,20 @@ public class LoginCredentialProcessor implements ObjectProcessor getInputClass() { return LoginCredentials.class; } @Override - public User process(LoginCredentials input, long socketId) { + public void process(LoginCredentials input, long socketId, ObjectWriteProxy writeProxy) throws IOException { System.out.println(String.format("Received login credentials %s from socket ID %d", input, socketId)); + + // Create user User user = new User(currentUserId++, input.getName()); ConnectionManager.getInstance().registerUser(socketId, user.getId()); - return user; + + // Create contacts + Contacts contacts = new Contacts(user.getId(), new ArrayList<>()); + + // Complete handshake + System.out.println("Sending user..."); + writeProxy.write(socketId, user); + System.out.println("Sending contacts..."); + writeProxy.write(socketId, contacts); } } diff --git a/src/main/java/envoy/server/MessageProcessor.java b/src/main/java/envoy/server/MessageProcessor.java index 8d80e53..3e2f139 100644 --- a/src/main/java/envoy/server/MessageProcessor.java +++ b/src/main/java/envoy/server/MessageProcessor.java @@ -1,6 +1,7 @@ package envoy.server; import envoy.data.Message; +import envoy.server.net.ObjectWriteProxy; /** * This {@link ObjectProcessor} handles incoming {@link Message}s.
@@ -12,13 +13,13 @@ import envoy.data.Message; * @author Kai S. K. Engelbart * @since Envoy Server Standalone v0.1-alpha */ -public class MessageProcessor implements ObjectProcessor { +public class MessageProcessor implements ObjectProcessor { @Override public Class getInputClass() { return Message.class; } @Override - public Void process(Message message, long socketId) { + public void process(Message message, long socketId, ObjectWriteProxy writeProxy) { // TODO: Send message to recipient if online ConnectionManager connectionManager = ConnectionManager.getInstance(); @@ -27,6 +28,5 @@ public class MessageProcessor implements ObjectProcessor { } // TODO: Add message to database - return null; } } diff --git a/src/main/java/envoy/server/ObjectProcessor.java b/src/main/java/envoy/server/ObjectProcessor.java index 07c0480..0221fc0 100644 --- a/src/main/java/envoy/server/ObjectProcessor.java +++ b/src/main/java/envoy/server/ObjectProcessor.java @@ -1,5 +1,9 @@ package envoy.server; +import java.io.IOException; + +import envoy.server.net.ObjectWriteProxy; + /** * This interface defines methods for processing objects of a specific * type incoming from a client.
@@ -10,13 +14,12 @@ package envoy.server; * * @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 { +public interface ObjectProcessor { /** - * @return the Class of the request object + * @return the class of the request object * @since Envoy Server Standalone v0.1-alpha */ Class getInputClass(); @@ -27,5 +30,5 @@ public interface ObjectProcessor { * @return the response object * @since Envoy Server Standalone v0.1-alpha */ - U process(T input, long socketId); + void process(T input, long socketId, ObjectWriteProxy writeProxy) throws IOException; } \ No newline at end of file diff --git a/src/main/java/envoy/server/data/Message.java b/src/main/java/envoy/server/data/Message.java index 19e25a6..af7f612 100644 --- a/src/main/java/envoy/server/data/Message.java +++ b/src/main/java/envoy/server/data/Message.java @@ -4,6 +4,7 @@ import java.util.Date; import javax.persistence.Entity; import javax.persistence.Id; +import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; @@ -28,8 +29,12 @@ import envoy.data.MessageBuilder; @Entity @Table(name = "messages") @NamedQueries( - { @NamedQuery(query = "SELECT m FROM Message m WHERE m.recipient =:recipient AND m.state = 1", name = "getUnreadMessages"), @NamedQuery( - query = "SELECT m FROM Message m WHERE m.sender =:sender AND m.state = :state", + { @NamedQuery( + query = "SELECT m FROM Message m WHERE m.recipient =:recipient AND m.status = envoy.data.Message$MessageStatus.SENT", + name = "getUnreadMessages" + ), + @NamedQuery( + query = "SELECT m FROM Message m WHERE m.sender =:sender AND m.status = :status", name = "find read messages"//TODO do we need this namedQuery? ), @NamedQuery(query = "SELECT m FROM Message m WHERE m.id = :messageId", name = "get message") }//TODO do we need this namedQuery? ) @@ -37,13 +42,22 @@ public class Message { @Id private long id; - private User sender, recipient; + + @ManyToOne + private User sender; + + @ManyToOne + private User recipient; + @Temporal(TemporalType.TIMESTAMP) private Date creationDate; + @Temporal(TemporalType.TIMESTAMP) private Date receivedDate; + @Temporal(TemporalType.TIMESTAMP) private Date readDate; + private envoy.data.Message.MessageStatus status; private String text; private byte[] attachment; diff --git a/src/main/java/envoy/server/data/User.java b/src/main/java/envoy/server/data/User.java index e0de15f..40e25c7 100644 --- a/src/main/java/envoy/server/data/User.java +++ b/src/main/java/envoy/server/data/User.java @@ -3,6 +3,7 @@ package envoy.server.data; import java.util.Date; import java.util.List; +import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; @@ -27,7 +28,7 @@ import javax.persistence.TemporalType; */ @Entity @Table(name = "users") -@NamedQuery(query = "SELECT u FROM DBUser u WHERE u.id = :id", name = "getUserById") +@NamedQuery(query = "SELECT u FROM User u WHERE u.id = :id", name = "getUserById") public class User { @Id @@ -35,9 +36,12 @@ public class User { private long id; private String name; private byte[] passwordHash; + @Temporal(TemporalType.TIMESTAMP) private Date lastSeen; private envoy.data.User.UserStatus status; + + @ElementCollection private List contacts; /** diff --git a/src/main/java/envoy/server/net/ObjectMessageProcessor.java b/src/main/java/envoy/server/net/ObjectMessageProcessor.java index 1bf707f..47dae57 100644 --- a/src/main/java/envoy/server/net/ObjectMessageProcessor.java +++ b/src/main/java/envoy/server/net/ObjectMessageProcessor.java @@ -1,10 +1,8 @@ package envoy.server.net; 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; @@ -25,7 +23,7 @@ import envoy.server.ObjectProcessor; */ public class ObjectMessageProcessor implements IMessageProcessor { - private final Set> processors; + private final Set> processors; /** * The constructor to set the {@link ObjectProcessor}s. @@ -33,9 +31,7 @@ public class ObjectMessageProcessor implements IMessageProcessor { * @param processors the {@link ObjectProcessor} to set * @since Envoy Server Standalone v0.1-alpha */ - public ObjectMessageProcessor(Set> processors) { - this.processors = processors; - } + public ObjectMessageProcessor(Set> processors) { this.processors = processors; } @SuppressWarnings("unchecked") @Override @@ -45,25 +41,17 @@ public class ObjectMessageProcessor implements IMessageProcessor { 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), message.socketId); - 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); + processors.stream() + .filter(p -> p.getInputClass().isInstance(obj)) + .forEach((@SuppressWarnings( + "rawtypes" + ) ObjectProcessor p) -> { + try { + p.process(p.getInputClass().cast(obj), message.socketId, new ObjectWriteProxy(writeProxy)); } 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/net/ObjectWriteProxy.java b/src/main/java/envoy/server/net/ObjectWriteProxy.java new file mode 100644 index 0000000..b1dc337 --- /dev/null +++ b/src/main/java/envoy/server/net/ObjectWriteProxy.java @@ -0,0 +1,34 @@ +package envoy.server.net; + +import java.io.IOException; + +import com.jenkov.nioserver.Message; +import com.jenkov.nioserver.WriteProxy; + +import envoy.util.SerializationUtils; + +/** + * Project: envoy-server-standalone
+ * File: ObjectWriteProxy.java
+ * Created: 04.01.2020
+ * + * @author Kai S. K. Engelbart + * @since Envoy Server Standalone v0.1-alpha + */ +public class ObjectWriteProxy { + + private final WriteProxy writeProxy; + + public ObjectWriteProxy(WriteProxy writeProxy) { this.writeProxy = writeProxy; } + + public void write(long recipientSocketId, Object obj) throws IOException { + // Create message targeted at the client + Message response = writeProxy.getMessage(); + response.socketId = recipientSocketId; + + // Serialize object to byte array + byte[] objBytes = SerializationUtils.writeToByteArray(obj); + response.writeToMessage(objBytes); + writeProxy.enqueue(response); + } +} diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..4d937c9 --- /dev/null +++ b/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From d40194b10d94cce62695e9a1bace529e258f8fe3 Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Mon, 6 Jan 2020 17:40:19 +0100 Subject: [PATCH 4/7] LV-encoding messages, added JPA validation. --- .classpath | 16 +++++----------- .project | 11 +++++++++++ .settings/org.eclipse.jdt.core.prefs | 3 +++ .settings/org.eclipse.jpt.core.prefs | 3 +++ ...lipse.wst.common.project.facet.core.prefs.xml | 7 +++++++ ...org.eclipse.wst.common.project.facet.core.xml | 5 +++++ src/main/java/envoy/server/Startup.java | 4 ++-- .../envoy/server/net/ObjectMessageReader.java | 14 ++++---------- .../java/envoy/server/net/ObjectWriteProxy.java | 7 ++++++- 9 files changed, 46 insertions(+), 24 deletions(-) create mode 100644 .settings/org.eclipse.jpt.core.prefs create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.prefs.xml create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.xml diff --git a/.classpath b/.classpath index 2a83b68..047eee0 100644 --- a/.classpath +++ b/.classpath @@ -6,11 +6,6 @@ - - - - - @@ -18,12 +13,6 @@ - - - - - - @@ -35,5 +24,10 @@ + + + + + diff --git a/.project b/.project index 45a395e..fdd0c87 100644 --- a/.project +++ b/.project @@ -5,11 +5,21 @@ + + org.eclipse.wst.common.project.facet.core.builder + + + org.eclipse.jdt.core.javabuilder + + org.eclipse.wst.validation.validationbuilder + + + org.eclipse.m2e.core.maven2Builder @@ -19,5 +29,6 @@ org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 2f5cc74..cac0df4 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,10 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore org.eclipse.jdt.core.compiler.release=disabled diff --git a/.settings/org.eclipse.jpt.core.prefs b/.settings/org.eclipse.jpt.core.prefs new file mode 100644 index 0000000..7ff3376 --- /dev/null +++ b/.settings/org.eclipse.jpt.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +org.eclipse.jpt.core.platform=generic2_1 +org.eclipse.jpt.jpa.core.discoverAnnotatedClasses=true diff --git a/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml new file mode 100644 index 0000000..7961132 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.prefs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..90f3be6 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/java/envoy/server/Startup.java b/src/main/java/envoy/server/Startup.java index b616946..58931ff 100644 --- a/src/main/java/envoy/server/Startup.java +++ b/src/main/java/envoy/server/Startup.java @@ -29,10 +29,10 @@ public class Startup { * @since Envoy Server Standalone v0.1-alpha */ public static void main(String[] args) throws IOException { - Set> processors = new HashSet<>(); + Set> processors = new HashSet<>(); processors.add(new LoginCredentialProcessor()); processors.add(new MessageProcessor()); - + // new PersistenceManager(); Server server = new Server(8080, () -> new ObjectMessageReader(), new ObjectMessageProcessor(processors)); server.start(); server.getSocketProcessor().registerSocketIdListener(ConnectionManager.getInstance()); diff --git a/src/main/java/envoy/server/net/ObjectMessageReader.java b/src/main/java/envoy/server/net/ObjectMessageReader.java index b477734..51fa3df 100644 --- a/src/main/java/envoy/server/net/ObjectMessageReader.java +++ b/src/main/java/envoy/server/net/ObjectMessageReader.java @@ -5,10 +5,9 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import com.jenkov.nioserver.IMessageReader; -import com.jenkov.nioserver.Message; -import com.jenkov.nioserver.MessageBuffer; -import com.jenkov.nioserver.Socket; +import com.jenkov.nioserver.*; + +import envoy.util.SerializationUtils; /** * This {@link IMessageReader} decodes serialized Java objects.
@@ -49,7 +48,7 @@ public class ObjectMessageReader implements IMessageReader { // Get message length if (nextMessage.length - nextMessage.offset < 4) return; - int length = fromByteArray(nextMessage.sharedArray, nextMessage.offset) + 4; + int length = SerializationUtils.bytesToInt(nextMessage.sharedArray, nextMessage.offset) + 4; if (nextMessage.length - nextMessage.offset >= length) { Message message = messageBuffer.getMessage(); @@ -60,9 +59,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); - } } \ No newline at end of file diff --git a/src/main/java/envoy/server/net/ObjectWriteProxy.java b/src/main/java/envoy/server/net/ObjectWriteProxy.java index b1dc337..bd6baf4 100644 --- a/src/main/java/envoy/server/net/ObjectWriteProxy.java +++ b/src/main/java/envoy/server/net/ObjectWriteProxy.java @@ -11,7 +11,7 @@ import envoy.util.SerializationUtils; * Project: envoy-server-standalone
* File: ObjectWriteProxy.java
* Created: 04.01.2020
- * + * * @author Kai S. K. Engelbart * @since Envoy Server Standalone v0.1-alpha */ @@ -28,6 +28,11 @@ public class ObjectWriteProxy { // Serialize object to byte array byte[] objBytes = SerializationUtils.writeToByteArray(obj); + + // Acquire object length in bytes + byte[] objLen = SerializationUtils.intToBytes(objBytes.length); + + response.writeToMessage(objLen); response.writeToMessage(objBytes); writeProxy.enqueue(response); } From 786150ec0cadbbb36c6a14234d8c89a46cadea4e Mon Sep 17 00:00:00 2001 From: delvh Date: Sat, 11 Jan 2020 09:42:02 +0100 Subject: [PATCH 5/7] configured JPA validation --- .settings/org.eclipse.jpt.core.prefs | 2 +- .settings/org.hibernate.eclipse.console.prefs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .settings/org.hibernate.eclipse.console.prefs diff --git a/.settings/org.eclipse.jpt.core.prefs b/.settings/org.eclipse.jpt.core.prefs index 7ff3376..8aa2bb2 100644 --- a/.settings/org.eclipse.jpt.core.prefs +++ b/.settings/org.eclipse.jpt.core.prefs @@ -1,3 +1,3 @@ eclipse.preferences.version=1 -org.eclipse.jpt.core.platform=generic2_1 +org.eclipse.jpt.core.platform=hibernate2_1 org.eclipse.jpt.jpa.core.discoverAnnotatedClasses=true diff --git a/.settings/org.hibernate.eclipse.console.prefs b/.settings/org.hibernate.eclipse.console.prefs new file mode 100644 index 0000000..a6ccf3c --- /dev/null +++ b/.settings/org.hibernate.eclipse.console.prefs @@ -0,0 +1,3 @@ +default.configuration=envoy-server-standalone +eclipse.preferences.version=1 +hibernate3.enabled=true From 135ca4a86f82cc5f98fb90a444946af417d6e20c Mon Sep 17 00:00:00 2001 From: CyB3RC0nN0R Date: Sat, 11 Jan 2020 11:43:31 +0100 Subject: [PATCH 6/7] Replaces local dependencies with jitpack.io dependencies --- .classpath | 6 ++++++ pom.xml | 15 +++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.classpath b/.classpath index 047eee0..b468bc4 100644 --- a/.classpath +++ b/.classpath @@ -29,5 +29,11 @@
+ + + + + + diff --git a/pom.xml b/pom.xml index 48a6be0..c0ed70b 100644 --- a/pom.xml +++ b/pom.xml @@ -17,16 +17,23 @@ 1.8 + + + jitpack.io + https://jitpack.io + + + - informatik-ag-ngl + com.github.informatik-ag-ngl envoy-common - 0.2-alpha + develop-SNAPSHOT - informatik-ag-ngl + com.github.informatik-ag-ngl java-nio-server - 0.0.1-SNAPSHOT + master-SNAPSHOT org.hibernate From fb4ecaed4e92992d8c9c2440bf2af4b740131caf Mon Sep 17 00:00:00 2001 From: delvh Date: Sat, 11 Jan 2020 18:28:48 +0100 Subject: [PATCH 7/7] Added EventProcessor and methods to handle MessageStatus changes additionally cleaned up whole project, fixed some Javadoc errors and added a few database and connection options. Sorry for the huge commit, there was almost no time inbetween where a commit would have been possible, as to solve every problem, a new problem arose. However, as of now, f/message_handling should be ready to be merged into develop, besides that it could not be tested yet. --- .settings/org.eclipse.jdt.core.prefs | 4 + .../java/envoy/server/ConnectionManager.java | 16 ++-- .../java/envoy/server/MessageProcessor.java | 32 -------- .../java/envoy/server/ObjectProcessor.java | 7 +- src/main/java/envoy/server/Startup.java | 4 + src/main/java/envoy/server/data/Message.java | 29 ++++--- src/main/java/envoy/server/data/User.java | 34 +++++++- .../server/database/PersistenceManager.java | 28 ++++++- .../server/net/ObjectMessageProcessor.java | 18 ++--- .../envoy/server/net/ObjectWriteProxy.java | 14 ++++ .../server/processors/EventProcessor.java | 77 +++++++++++++++++++ .../LoginCredentialProcessor.java | 17 +++- .../server/processors/MessageProcessor.java | 47 +++++++++++ 13 files changed, 255 insertions(+), 72 deletions(-) delete mode 100644 src/main/java/envoy/server/MessageProcessor.java create mode 100644 src/main/java/envoy/server/processors/EventProcessor.java rename src/main/java/envoy/server/{ => processors}/LoginCredentialProcessor.java (66%) create mode 100644 src/main/java/envoy/server/processors/MessageProcessor.java diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index cac0df4..db24ee7 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,11 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled org.eclipse.jdt.core.compiler.problem.enumIdentifier=error diff --git a/src/main/java/envoy/server/ConnectionManager.java b/src/main/java/envoy/server/ConnectionManager.java index ac4b0c0..0ae8fcc 100644 --- a/src/main/java/envoy/server/ConnectionManager.java +++ b/src/main/java/envoy/server/ConnectionManager.java @@ -11,7 +11,7 @@ import com.jenkov.nioserver.ISocketIdListener; * Project: envoy-server-standalone
* File: ConnectionManager.java
* Created: 03.01.2020
- * + * * @author Kai S. K. Engelbart * @since Envoy Server Standalone v0.1-alpha */ @@ -20,14 +20,14 @@ public class ConnectionManager implements ISocketIdListener { /** * Contains all socket IDs that have not yet performed a handshake / acquired * their corresponding user ID. - * + * * @since Envoy Server Standalone v0.1-alpha */ private Set pendingSockets = new HashSet<>(); /** * Contains all socket IDs that have acquired a user ID as keys to these IDs. - * + * * @since Envoy Server Standalone v0.1-alpha */ private Map sockets = new HashMap<>(); @@ -53,14 +53,14 @@ public class ConnectionManager implements ISocketIdListener { /** * Associates a socket ID with a user ID. - * - * @param socketId the socket ID + * * @param userId the user ID + * @param socketId the socket ID * @since Envoy Server Standalone v0.1-alpha */ - public void registerUser(long socketId, long userId) { - sockets.put(socketId, userId); - pendingSockets.remove(socketId); + public void registerUser(long userId, long socketId) { + sockets.put(userId, socketId); + pendingSockets.remove(userId); } /** diff --git a/src/main/java/envoy/server/MessageProcessor.java b/src/main/java/envoy/server/MessageProcessor.java deleted file mode 100644 index 3e2f139..0000000 --- a/src/main/java/envoy/server/MessageProcessor.java +++ /dev/null @@ -1,32 +0,0 @@ -package envoy.server; - -import envoy.data.Message; -import envoy.server.net.ObjectWriteProxy; - -/** - * 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 message, long socketId, ObjectWriteProxy writeProxy) { - - // TODO: Send message to recipient if online - ConnectionManager connectionManager = ConnectionManager.getInstance(); - if (connectionManager.isOnline(message.getRecipientId())) { - - } - - // TODO: Add message to database - } -} diff --git a/src/main/java/envoy/server/ObjectProcessor.java b/src/main/java/envoy/server/ObjectProcessor.java index 0221fc0..6828598 100644 --- a/src/main/java/envoy/server/ObjectProcessor.java +++ b/src/main/java/envoy/server/ObjectProcessor.java @@ -25,9 +25,10 @@ public interface ObjectProcessor { Class getInputClass(); /** - * @param input the request object - * @param socketId the ID of the socket from which the object was received - * @return the response object + * @param input the request object + * @param socketId the ID of the socket from which the object was received + * @param writeProxy the object that allows writing to a client + * @throws IOException if something went wrong during processing * @since Envoy Server Standalone v0.1-alpha */ void process(T input, long socketId, ObjectWriteProxy writeProxy) throws IOException; diff --git a/src/main/java/envoy/server/Startup.java b/src/main/java/envoy/server/Startup.java index 58931ff..e2edb6a 100644 --- a/src/main/java/envoy/server/Startup.java +++ b/src/main/java/envoy/server/Startup.java @@ -8,6 +8,9 @@ import com.jenkov.nioserver.Server; import envoy.server.net.ObjectMessageProcessor; import envoy.server.net.ObjectMessageReader; +import envoy.server.processors.EventProcessor; +import envoy.server.processors.LoginCredentialProcessor; +import envoy.server.processors.MessageProcessor; /** * Starts the server.
@@ -32,6 +35,7 @@ public class Startup { Set> processors = new HashSet<>(); processors.add(new LoginCredentialProcessor()); processors.add(new MessageProcessor()); + processors.add(new EventProcessor()); // new PersistenceManager(); Server server = new Server(8080, () -> new ObjectMessageReader(), new ObjectMessageProcessor(processors)); server.start(); diff --git a/src/main/java/envoy/server/data/Message.java b/src/main/java/envoy/server/data/Message.java index af7f612..575da6a 100644 --- a/src/main/java/envoy/server/data/Message.java +++ b/src/main/java/envoy/server/data/Message.java @@ -12,6 +12,7 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; import envoy.data.MessageBuilder; +import envoy.server.database.PersistenceManager; /** * This class serves as a way to let Hibernate communicate with the server @@ -32,16 +33,15 @@ import envoy.data.MessageBuilder; { @NamedQuery( query = "SELECT m FROM Message m WHERE m.recipient =:recipient AND m.status = envoy.data.Message$MessageStatus.SENT", name = "getUnreadMessages" - ), - @NamedQuery( - query = "SELECT m FROM Message m WHERE m.sender =:sender AND m.status = :status", - name = "find read messages"//TODO do we need this namedQuery? - ), @NamedQuery(query = "SELECT m FROM Message m WHERE m.id = :messageId", name = "get message") }//TODO do we need this namedQuery? + ), @NamedQuery( + query = "SELECT m FROM Message m WHERE m.sender =:sender AND m.status = :status", + name = "find read messages"// TODO do we need this namedQuery? + ), @NamedQuery(query = "SELECT m FROM Message m WHERE m.id = :messageId", name = "getMessageById") } ) public class Message { @Id - private long id; + private long id; @ManyToOne private User sender; @@ -50,13 +50,13 @@ public class Message { private User recipient; @Temporal(TemporalType.TIMESTAMP) - private Date creationDate; + private Date creationDate; @Temporal(TemporalType.TIMESTAMP) - private Date receivedDate; + private Date receivedDate; @Temporal(TemporalType.TIMESTAMP) - private Date readDate; + private Date readDate; private envoy.data.Message.MessageStatus status; private String text; @@ -76,9 +76,14 @@ public class Message { * @since Envoy Server Standalone v0.1-alpha */ public Message(envoy.data.Message message) { - id = message.getId(); - status = message.getStatus(); - text = message.getText(); + PersistenceManager persMan = PersistenceManager.getPersistenceManager(); + id = message.getId(); + status = message.getStatus(); + text = message.getText(); + creationDate = message.getCreationDate(); + sender = persMan.getUserById(message.getSenderId()); + recipient = persMan.getUserById(message.getRecipientId()); + // attachment = message.getAttachment().toByteArray();DOES NOT WORK YET } /** diff --git a/src/main/java/envoy/server/data/User.java b/src/main/java/envoy/server/data/User.java index 40e25c7..5f4e28e 100644 --- a/src/main/java/envoy/server/data/User.java +++ b/src/main/java/envoy/server/data/User.java @@ -33,16 +33,42 @@ public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private long id; - private String name; - private byte[] passwordHash; + private long id; + private String name; + private byte[] passwordHash; @Temporal(TemporalType.TIMESTAMP) private Date lastSeen; private envoy.data.User.UserStatus status; @ElementCollection - private List contacts; + private List contacts; + + /** + * Creates an instance of @link{User}. + * Solely used for JPA/ Hibernate + * + * @since Envoy Server Standalone v0.1-alpha + */ + public User() {} + + /** + * Creates an instance of @link{User}. + * + * @param user the {@link envoy.data.User} to convert + * @since Envoy Server Standalone v0.1-alpha + */ + public User(envoy.data.User user) { + id = user.getId(); + name = user.getName(); + status = user.getStatus(); + } + + /** + * @return a database {@link User} converted into an {@link envoy.data.User} + * @since Envoy Server Standalone v0.1-alpha + */ + public envoy.data.User toCommonUser() { return new envoy.data.User(this.id, this.name); } /** * @return the id of a {link envoy.data.User} diff --git a/src/main/java/envoy/server/database/PersistenceManager.java b/src/main/java/envoy/server/database/PersistenceManager.java index e7c2dc8..fb38a9e 100644 --- a/src/main/java/envoy/server/database/PersistenceManager.java +++ b/src/main/java/envoy/server/database/PersistenceManager.java @@ -20,6 +20,21 @@ import envoy.server.data.User; */ public class PersistenceManager { + private static final PersistenceManager persistenceManager = new PersistenceManager(); + + /** + * Creates the singleton instance of the @link{PersistenceManager}. + * + * @since Envoy Server Standalone v0.1-alpha + */ + private PersistenceManager() {} + + /** + * @return the {@link PersistenceManager} singleton + * @since Envoy Server Standalone v0.1-alpha + */ + public static PersistenceManager getPersistenceManager() { return persistenceManager; } + private EntityManager entityManager = Persistence.createEntityManagerFactory("envoy").createEntityManager(); /** @@ -55,7 +70,7 @@ public class PersistenceManager { public void updateMessage(Message message) { entityManager.unwrap(Session.class).merge(message); } /** - * Searches for a user with a specific id. + * Searches for a {@link User} with a specific id. * * @param id - the id to search for * @return the user with the specified id @@ -63,6 +78,17 @@ public class PersistenceManager { */ public User getUserById(long id) { return (User) entityManager.createNamedQuery("getUserById").setParameter("id", id).getSingleResult(); } + /** + * Searches for a {@link Message} with a specific id. + * + * @param id - the id to search for + * @return the message with the specified id + * @since Envoy Server Standalone v0.1-alpha + */ + public Message getMessageById(long id) { + return (Message) entityManager.createNamedQuery("getMessageById").setParameter("id", id).getSingleResult(); + } + /** * Returns all messages received while being offline. * diff --git a/src/main/java/envoy/server/net/ObjectMessageProcessor.java b/src/main/java/envoy/server/net/ObjectMessageProcessor.java index 47dae57..226fb69 100644 --- a/src/main/java/envoy/server/net/ObjectMessageProcessor.java +++ b/src/main/java/envoy/server/net/ObjectMessageProcessor.java @@ -41,17 +41,13 @@ public class ObjectMessageProcessor implements IMessageProcessor { System.out.println("Read object: " + obj.toString()); // Process object - processors.stream() - .filter(p -> p.getInputClass().isInstance(obj)) - .forEach((@SuppressWarnings( - "rawtypes" - ) ObjectProcessor p) -> { - try { - p.process(p.getInputClass().cast(obj), message.socketId, new ObjectWriteProxy(writeProxy)); - } catch (IOException e) { - e.printStackTrace(); - } - }); + processors.stream().filter(p -> p.getInputClass().isInstance(obj)).forEach((@SuppressWarnings("rawtypes") ObjectProcessor p) -> { + try { + p.process(p.getInputClass().cast(obj), message.socketId, new ObjectWriteProxy(writeProxy)); + } catch (IOException e) { + e.printStackTrace(); + } + }); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } diff --git a/src/main/java/envoy/server/net/ObjectWriteProxy.java b/src/main/java/envoy/server/net/ObjectWriteProxy.java index bd6baf4..2ec9223 100644 --- a/src/main/java/envoy/server/net/ObjectWriteProxy.java +++ b/src/main/java/envoy/server/net/ObjectWriteProxy.java @@ -8,6 +8,8 @@ import com.jenkov.nioserver.WriteProxy; import envoy.util.SerializationUtils; /** + * This class defines methods to send an object to a client.
+ *
* Project: envoy-server-standalone
* File: ObjectWriteProxy.java
* Created: 04.01.2020
@@ -19,8 +21,20 @@ public class ObjectWriteProxy { private final WriteProxy writeProxy; + /** + * Creates an instance of @link{ObjectWriteProxy}. + * + * @param writeProxy the {@link WriteProxy} to write objects to another client + * @since Envoy Server Standalone v0.1-alpha + */ public ObjectWriteProxy(WriteProxy writeProxy) { this.writeProxy = writeProxy; } + /** + * @param recipientSocketId the socket id of the recipient + * @param obj the object to return to the client + * @throws IOException if the serialization of the object failed + * @since Envoy Server Standalone v0.1-alpha + */ public void write(long recipientSocketId, Object obj) throws IOException { // Create message targeted at the client Message response = writeProxy.getMessage(); diff --git a/src/main/java/envoy/server/processors/EventProcessor.java b/src/main/java/envoy/server/processors/EventProcessor.java new file mode 100644 index 0000000..58c769f --- /dev/null +++ b/src/main/java/envoy/server/processors/EventProcessor.java @@ -0,0 +1,77 @@ +package envoy.server.processors; + +import java.io.IOException; + +import envoy.data.Message; +import envoy.data.Message.MessageStatus; +import envoy.event.Event; +import envoy.event.MessageStatusChangeEvent; +import envoy.exception.EnvoyException; +import envoy.server.ConnectionManager; +import envoy.server.ObjectProcessor; +import envoy.server.database.PersistenceManager; +import envoy.server.net.ObjectWriteProxy; + +/** + * Project: envoy-server-standalone
+ * File: EventProcessor.java
+ * Created: 10 Jan 2020
+ * + * @author Leon Hofmeister + * @since Envoy Server Standalone v0.1-alpha + */ +public class EventProcessor implements ObjectProcessor> { + + private Event event; + + /** + * Creates an instance of @link{EventProcessor}. + * + * @since Envoy Server Standalone v0.1-alpha + */ + public EventProcessor() {} + + @SuppressWarnings("unchecked") + @Override + public Class> getInputClass() { return (Class>) event.getClass(); } + + @Override + public void process(Event input, long socketId, ObjectWriteProxy writeProxy) throws IOException { + event = input; + if (event instanceof MessageStatusChangeEvent) try { + applyMessageStatusChange((MessageStatusChangeEvent) event, writeProxy); + } catch (EnvoyException e) { + e.printStackTrace(); + } + } + + /** + * Redirects messageStatus changes to the database and to the recipient of the + * {@link Message}. + * + * @param event the {@link MessageStatusChangeEvent} to adjust + * @throws EnvoyException if the {@link Message} has an invalid state + * @since Envoy Server Standalone v0.1-alpha + */ + private void applyMessageStatusChange(MessageStatusChangeEvent event, ObjectWriteProxy writeProxy) throws EnvoyException { + if (!(event.get() == MessageStatus.READ))// check that no invalid MessageStatuses are sent + throw new EnvoyException("Message" + event.getId() + "has an invalid status"); + + ConnectionManager conMan = ConnectionManager.getInstance(); + PersistenceManager perMan = PersistenceManager.getPersistenceManager(); + envoy.server.data.Message msg = perMan.getMessageById(event.getId()); + + msg.setStatus(event.get()); + msg.setReadDate(event.getDate()); + + if (conMan.isOnline(msg.getRecipient().getId())) try { + writeProxy.write(conMan.getSocketId(msg.getRecipient().getId()), event); + } catch (IOException e) { + System.err.println("Recipient online. Failed to send MessageStatusChangedEvent at message" + event.getId()); + e.printStackTrace(); + } + perMan.updateMessage(msg); + + } + +} diff --git a/src/main/java/envoy/server/LoginCredentialProcessor.java b/src/main/java/envoy/server/processors/LoginCredentialProcessor.java similarity index 66% rename from src/main/java/envoy/server/LoginCredentialProcessor.java rename to src/main/java/envoy/server/processors/LoginCredentialProcessor.java index 89261cf..e94ce91 100644 --- a/src/main/java/envoy/server/LoginCredentialProcessor.java +++ b/src/main/java/envoy/server/processors/LoginCredentialProcessor.java @@ -1,11 +1,18 @@ -package envoy.server; +package envoy.server.processors; import java.io.IOException; import java.util.ArrayList; +import java.util.Date; +import java.util.List; import envoy.data.Contacts; import envoy.data.LoginCredentials; +import envoy.data.Message.MessageStatus; import envoy.data.User; +import envoy.server.ConnectionManager; +import envoy.server.ObjectProcessor; +import envoy.server.data.Message; +import envoy.server.database.PersistenceManager; import envoy.server.net.ObjectWriteProxy; /** @@ -42,5 +49,13 @@ public class LoginCredentialProcessor implements ObjectProcessor pendingMessages = PersistenceManager.getPersistenceManager().getUnreadMessages(new envoy.server.data.User(user)); + pendingMessages.forEach((msg) -> { + msg.setReceivedDate(new Date()); + msg.setStatus(MessageStatus.RECEIVED); + PersistenceManager.getPersistenceManager().updateMessage(msg); + }); + writeProxy.write(socketId, pendingMessages); } } diff --git a/src/main/java/envoy/server/processors/MessageProcessor.java b/src/main/java/envoy/server/processors/MessageProcessor.java new file mode 100644 index 0000000..ce857de --- /dev/null +++ b/src/main/java/envoy/server/processors/MessageProcessor.java @@ -0,0 +1,47 @@ +package envoy.server.processors; + +import java.io.IOException; +import java.util.Date; + +import envoy.data.Message; +import envoy.event.MessageStatusChangeEvent; +import envoy.server.ConnectionManager; +import envoy.server.ObjectProcessor; +import envoy.server.database.PersistenceManager; +import envoy.server.net.ObjectWriteProxy; + +/** + * 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 message, long socketId, ObjectWriteProxy writeProxy) { + + ConnectionManager connectionManager = ConnectionManager.getInstance(); + message.nextStatus(); + if (connectionManager.isOnline(message.getRecipientId())) try {// if recipient is online, he receives the message directly + writeProxy.write(connectionManager.getSocketId(message.getRecipientId()), message); + } catch (IOException e) { + System.err.println("Recipient online. Failed to send message" + message.getId()); + e.printStackTrace(); + } + try {// sender receives confirmation that the server received the message + writeProxy.write(connectionManager.getSocketId(message.getSenderId()), + new MessageStatusChangeEvent(message.getId(), message.getStatus(), new Date())); + } catch (IOException e) { + e.printStackTrace(); + } + PersistenceManager.getPersistenceManager().addMessage(new envoy.server.data.Message(message)); + } +}