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.
This commit is contained in:
		| @@ -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}.<br> | ||||
| @@ -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<LoginCredentials, User> { | ||||
| public class LoginCredentialProcessor implements ObjectProcessor<LoginCredentials> { | ||||
|  | ||||
| 	// TODO: Acquire user IDs from database | ||||
| 	private static long currentUserId = 1; | ||||
| @@ -22,10 +27,20 @@ public class LoginCredentialProcessor implements ObjectProcessor<LoginCredential | ||||
| 	public Class<LoginCredentials> 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); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package envoy.server; | ||||
|  | ||||
| import envoy.data.Message; | ||||
| import envoy.server.net.ObjectWriteProxy; | ||||
|  | ||||
| /** | ||||
|  * This {@link ObjectProcessor} handles incoming {@link Message}s.<br> | ||||
| @@ -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<Message, Void> { | ||||
| public class MessageProcessor implements ObjectProcessor<Message> { | ||||
|  | ||||
| 	@Override | ||||
| 	public Class<Message> 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<Message, Void> { | ||||
| 		} | ||||
|  | ||||
| 		// TODO: Add message to database | ||||
| 		return null; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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.<br> | ||||
| @@ -10,13 +14,12 @@ package envoy.server; | ||||
|  * | ||||
|  * @author Kai S. K. Engelbart | ||||
|  * @param <T> type of the request object | ||||
|  * @param <U> type of the response object | ||||
|  * @since Envoy Server Standalone v0.1-alpha | ||||
|  */ | ||||
| public interface ObjectProcessor<T, U> { | ||||
| public interface ObjectProcessor<T> { | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the Class of the request object | ||||
| 	 * @return the class of the request object | ||||
| 	 * @since Envoy Server Standalone v0.1-alpha | ||||
| 	 */ | ||||
| 	Class<T> getInputClass(); | ||||
| @@ -27,5 +30,5 @@ public interface ObjectProcessor<T, U> { | ||||
| 	 * @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; | ||||
| } | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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<User>					contacts; | ||||
|  | ||||
| 	/** | ||||
|   | ||||
| @@ -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<ObjectProcessor<?, ?>>	processors; | ||||
| 	private final Set<ObjectProcessor<?>> 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<ObjectProcessor<?, ?>> processors) { | ||||
| 		this.processors			= processors; | ||||
| 	} | ||||
| 	public ObjectMessageProcessor(Set<ObjectProcessor<?>> 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(); | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										34
									
								
								src/main/java/envoy/server/net/ObjectWriteProxy.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/main/java/envoy/server/net/ObjectWriteProxy.java
									
									
									
									
									
										Normal file
									
								
							| @@ -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: <strong>envoy-server-standalone</strong><br> | ||||
|  * File: <strong>ObjectWriteProxy.java</strong><br> | ||||
|  * Created: <strong>04.01.2020</strong><br> | ||||
|  *  | ||||
|  * @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); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										29
									
								
								src/main/resources/META-INF/persistence.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/main/resources/META-INF/persistence.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" | ||||
| 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
| 	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence | ||||
|              http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" | ||||
| 	version="2.1"> | ||||
|  | ||||
| 	<persistence-unit name="envoy" | ||||
| 		transaction-type="RESOURCE_LOCAL"> | ||||
|  | ||||
| 		<properties> | ||||
| 			<property name="javax.persistence.jdbc.driver" | ||||
| 				value="org.postgresql.Driver" /> <!-- DB Driver --> | ||||
| 			<property name="javax.persistence.jdbc.url" | ||||
| 				value="jdbc:postgresql://localhost/envoy" /> <!-- BD Mane --> | ||||
| 			<property name="javax.persistence.jdbc.user" value="envoy" /> <!-- DB User --> | ||||
| 			<property name="javax.persistence.jdbc.password" | ||||
| 				value="envoy" /> <!-- DB Password --> | ||||
|  | ||||
| 			<property name="hibernate.dialect" | ||||
| 				value="org.hibernate.dialect.PostgreSQL95Dialect" /> <!-- DB Dialect --> | ||||
| 			<property name="hibernate.hbm2ddl.auto" value="update" /> <!-- create / create-drop / update --> | ||||
|  | ||||
| 			<property name="hibernate.show_sql" value="true" /> <!-- Show SQL in console --> | ||||
| 			<property name="hibernate.format_sql" value="true" /> <!-- Show SQL formatted --> | ||||
| 		</properties> | ||||
|  | ||||
| 	</persistence-unit> | ||||
|  | ||||
| </persistence> | ||||
		Reference in New Issue
	
	Block a user