Made Server Less Error Prone #107
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package envoy.data;
 | 
					package envoy.data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.Serializable;
 | 
					import java.io.Serializable;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This interface should be used for any type supposed to be a {@link Message} attachment (i.e.
 | 
					 * This interface should be used for any type supposed to be a {@link Message} attachment (i.e.
 | 
				
			||||||
@@ -63,9 +64,9 @@ public final class Attachment implements Serializable {
 | 
				
			|||||||
	 * @since Envoy Common v0.1-beta
 | 
						 * @since Envoy Common v0.1-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public Attachment(byte[] data, String name, AttachmentType type) {
 | 
						public Attachment(byte[] data, String name, AttachmentType type) {
 | 
				
			||||||
		this.data	= data;
 | 
							this.data	= Objects.requireNonNull(data);
 | 
				
			||||||
		this.name	= name;
 | 
							this.name	= Objects.requireNonNull(name);
 | 
				
			||||||
		this.type	= type;
 | 
							this.type	= Objects.requireNonNull(type);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,8 +29,8 @@ public abstract class Contact implements Serializable {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public Contact(long id, String name, Set<? extends Contact> contacts) {
 | 
						public Contact(long id, String name, Set<? extends Contact> contacts) {
 | 
				
			||||||
		this.id			= id;
 | 
							this.id			= id;
 | 
				
			||||||
		this.name		= name;
 | 
							this.name		= Objects.requireNonNull(name);
 | 
				
			||||||
		this.contacts	= contacts;
 | 
							this.contacts	= contacts == null ? new HashSet<>() : contacts;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,7 +38,8 @@ public final class GroupMessage extends Message {
 | 
				
			|||||||
		Map<Long, MessageStatus> memberStatuses) {
 | 
							Map<Long, MessageStatus> memberStatuses) {
 | 
				
			||||||
		super(id, senderID, groupID, creationDate, receivedDate, readDate, text, attachment, status,
 | 
							super(id, senderID, groupID, creationDate, receivedDate, readDate, text, attachment, status,
 | 
				
			||||||
			forwarded);
 | 
								forwarded);
 | 
				
			||||||
		this.memberStatuses = memberStatuses;
 | 
							this.memberStatuses =
 | 
				
			||||||
 | 
								memberStatuses == null ? new HashMap<>() : memberStatuses;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package envoy.data;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import java.io.Serializable;
 | 
					import java.io.Serializable;
 | 
				
			||||||
import java.time.Instant;
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Contains a {@link User}'s login / registration information as well as the client version.
 | 
					 * Contains a {@link User}'s login / registration information as well as the client version.
 | 
				
			||||||
@@ -22,12 +23,12 @@ public final class LoginCredentials implements Serializable {
 | 
				
			|||||||
	private LoginCredentials(String identifier, String password, boolean registration,
 | 
						private LoginCredentials(String identifier, String password, boolean registration,
 | 
				
			||||||
		boolean token, String clientVersion,
 | 
							boolean token, String clientVersion,
 | 
				
			||||||
		Instant lastSync) {
 | 
							Instant lastSync) {
 | 
				
			||||||
		this.identifier		= identifier;
 | 
							this.identifier		= Objects.requireNonNull(identifier);
 | 
				
			||||||
		this.password		= password;
 | 
							this.password		= Objects.requireNonNull(password);
 | 
				
			||||||
		this.registration	= registration;
 | 
							this.registration	= registration;
 | 
				
			||||||
		this.token			= token;
 | 
							this.token			= token;
 | 
				
			||||||
		this.clientVersion	= clientVersion;
 | 
							this.clientVersion	= Objects.requireNonNull(clientVersion);
 | 
				
			||||||
		this.lastSync		= lastSync;
 | 
							this.lastSync		= lastSync == null ? Instant.EPOCH : lastSync;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package envoy.data;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import java.io.Serializable;
 | 
					import java.io.Serializable;
 | 
				
			||||||
import java.time.Instant;
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dev.kske.eventbus.IEvent;
 | 
					import dev.kske.eventbus.IEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -80,9 +81,9 @@ public class Message implements Serializable, IEvent {
 | 
				
			|||||||
		this.creationDate	= creationDate;
 | 
							this.creationDate	= creationDate;
 | 
				
			||||||
		this.receivedDate	= receivedDate;
 | 
							this.receivedDate	= receivedDate;
 | 
				
			||||||
		this.readDate		= readDate;
 | 
							this.readDate		= readDate;
 | 
				
			||||||
		this.text			= text;
 | 
							this.text			= text == null ? "" : text;
 | 
				
			||||||
		this.attachment		= attachment;
 | 
							this.attachment		= attachment;
 | 
				
			||||||
		this.status			= status;
 | 
							this.status			= Objects.requireNonNull(status);
 | 
				
			||||||
		this.forwarded		= forwarded;
 | 
							this.forwarded		= forwarded;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,7 +86,7 @@ public final class User extends Contact {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public User(long id, String name, UserStatus status, Set<Contact> contacts) {
 | 
						public User(long id, String name, UserStatus status, Set<Contact> contacts) {
 | 
				
			||||||
		super(id, name, contacts);
 | 
							super(id, name, contacts);
 | 
				
			||||||
		this.status = status;
 | 
							this.status = Objects.requireNonNull(status);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package envoy.event;
 | 
					package envoy.event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.Serializable;
 | 
					import java.io.Serializable;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dev.kske.eventbus.IEvent;
 | 
					import dev.kske.eventbus.IEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,7 +21,16 @@ public abstract class Event<T> implements IEvent, Serializable {
 | 
				
			|||||||
	private static final long serialVersionUID = 0L;
 | 
						private static final long serialVersionUID = 0L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected Event(T value) {
 | 
						protected Event(T value) {
 | 
				
			||||||
		this.value = value;
 | 
							this(value, false);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * This constructor is reserved for {@link Valueless} events. No other event should contain null
 | 
				
			||||||
 | 
						 * values. Only use if really necessary. Using this constructor with {@code true} implies that
 | 
				
			||||||
 | 
						 * the user has to manually check if the value of the event is null.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						protected Event(T value, boolean canBeNull) {
 | 
				
			||||||
 | 
							this.value = canBeNull ? value : Objects.requireNonNull(value);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
@@ -46,7 +56,7 @@ public abstract class Event<T> implements IEvent, Serializable {
 | 
				
			|||||||
		private static final long serialVersionUID = 0L;
 | 
							private static final long serialVersionUID = 0L;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected Valueless() {
 | 
							protected Valueless() {
 | 
				
			||||||
			super(null);
 | 
								super(null, true);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Override
 | 
							@Override
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,7 @@ public class GroupCreationResult extends Event<Group> {
 | 
				
			|||||||
	 * @since Envoy Common v0.2-beta
 | 
						 * @since Envoy Common v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public GroupCreationResult() {
 | 
						public GroupCreationResult() {
 | 
				
			||||||
		super(null);
 | 
							super(null, true);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,8 @@ package envoy.event;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import static envoy.event.ElementOperation.*;
 | 
					import static envoy.event.ElementOperation.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import envoy.data.*;
 | 
					import envoy.data.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -30,7 +32,7 @@ public final class GroupResize extends Event<User> {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public GroupResize(User user, Group group, ElementOperation operation) {
 | 
						public GroupResize(User user, Group group, ElementOperation operation) {
 | 
				
			||||||
		super(user);
 | 
							super(user);
 | 
				
			||||||
		this.operation = operation;
 | 
							this.operation = Objects.requireNonNull(operation);
 | 
				
			||||||
		final var contained = group.getContacts().contains(user);
 | 
							final var contained = group.getContacts().contains(user);
 | 
				
			||||||
		if (contained && operation.equals(ADD))
 | 
							if (contained && operation.equals(ADD))
 | 
				
			||||||
			throw new IllegalArgumentException(String.format("Cannot add %s to %s!", user, group));
 | 
								throw new IllegalArgumentException(String.format("Cannot add %s to %s!", user, group));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ public final class IsTyping extends Event<Long> {
 | 
				
			|||||||
	 * @param destinationID the ID of the contact the user wrote to
 | 
						 * @param destinationID the ID of the contact the user wrote to
 | 
				
			||||||
	 * @since Envoy Common v0.2-beta
 | 
						 * @since Envoy Common v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public IsTyping(Long sourceID, long destinationID) {
 | 
						public IsTyping(long sourceID, long destinationID) {
 | 
				
			||||||
		super(sourceID);
 | 
							super(sourceID);
 | 
				
			||||||
		this.destinationID = destinationID;
 | 
							this.destinationID = destinationID;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@ public final class IssueProposal extends Event<String> {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public IssueProposal(String title, String description, boolean isBug) {
 | 
						public IssueProposal(String title, String description, boolean isBug) {
 | 
				
			||||||
		super(escape(title));
 | 
							super(escape(title));
 | 
				
			||||||
		this.description	= sanitizeDescription(description);
 | 
							this.description	= description == null ? "" : sanitizeDescription(description);
 | 
				
			||||||
		bug					= isBug;
 | 
							bug					= isBug;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -37,8 +37,8 @@ public final class IssueProposal extends Event<String> {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public IssueProposal(String title, String description, String user, boolean isBug) {
 | 
						public IssueProposal(String title, String description, String user, boolean isBug) {
 | 
				
			||||||
		super(escape(title));
 | 
							super(escape(title));
 | 
				
			||||||
		this.description	=
 | 
							this.description	= description == null ? ""
 | 
				
			||||||
			sanitizeDescription(description) + String.format("<br>Submitted by user %s.", user);
 | 
								: sanitizeDescription(description) + String.format("<br>Submitted by user %s.", user);
 | 
				
			||||||
		bug					= isBug;
 | 
							bug					= isBug;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package envoy.event;
 | 
					package envoy.event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.time.Instant;
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import envoy.data.Message;
 | 
					import envoy.data.Message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,7 +27,7 @@ public class MessageStatusChange extends Event<Message.MessageStatus> {
 | 
				
			|||||||
	public MessageStatusChange(long id, Message.MessageStatus status, Instant date) {
 | 
						public MessageStatusChange(long id, Message.MessageStatus status, Instant date) {
 | 
				
			||||||
		super(status);
 | 
							super(status);
 | 
				
			||||||
		this.id		= id;
 | 
							this.id		= id;
 | 
				
			||||||
		this.date	= date;
 | 
							this.date	= Objects.requireNonNull(date);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,7 @@
 | 
				
			|||||||
package envoy.event;
 | 
					package envoy.event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import envoy.data.Contact;
 | 
					import envoy.data.Contact;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -21,7 +23,7 @@ public final class PasswordChangeRequest extends Event<String> {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public PasswordChangeRequest(String newPassword, String oldPassword, long userID) {
 | 
						public PasswordChangeRequest(String newPassword, String oldPassword, long userID) {
 | 
				
			||||||
		super(newPassword);
 | 
							super(newPassword);
 | 
				
			||||||
		this.oldPassword	= oldPassword;
 | 
							this.oldPassword	= Objects.requireNonNull(oldPassword);
 | 
				
			||||||
		id					= userID;
 | 
							id					= userID;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,7 @@
 | 
				
			|||||||
package envoy.event.contact;
 | 
					package envoy.event.contact;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import envoy.data.User;
 | 
					import envoy.data.User;
 | 
				
			||||||
import envoy.event.*;
 | 
					import envoy.event.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -24,7 +26,7 @@ public final class UserOperation extends Event<User> {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public UserOperation(User contact, ElementOperation operationType) {
 | 
						public UserOperation(User contact, ElementOperation operationType) {
 | 
				
			||||||
		super(contact);
 | 
							super(contact);
 | 
				
			||||||
		this.operationType = operationType;
 | 
							this.operationType = Objects.requireNonNull(operationType);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
package envoy.server.data;
 | 
					package envoy.server.data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.time.Instant;
 | 
					import java.time.Instant;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.*;
 | 
				
			||||||
import java.util.logging.Level;
 | 
					import java.util.logging.Level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.persistence.*;
 | 
					import javax.persistence.*;
 | 
				
			||||||
@@ -223,6 +223,9 @@ public final class PersistenceManager {
 | 
				
			|||||||
	 * @since Envoy Server Standalone v0.2-beta
 | 
						 * @since Envoy Server Standalone v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public List<Message> getPendingMessages(User user, Instant lastSync) {
 | 
						public List<Message> getPendingMessages(User user, Instant lastSync) {
 | 
				
			||||||
 | 
							if (user == null)
 | 
				
			||||||
 | 
								return new ArrayList<>();
 | 
				
			||||||
 | 
							lastSync = Objects.requireNonNullElse(lastSync, Instant.EPOCH);
 | 
				
			||||||
		return entityManager.createNamedQuery(Message.getPending).setParameter("user", user)
 | 
							return entityManager.createNamedQuery(Message.getPending).setParameter("user", user)
 | 
				
			||||||
			.setParameter("lastSeen", lastSync).getResultList();
 | 
								.setParameter("lastSeen", lastSync).getResultList();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -236,6 +239,9 @@ public final class PersistenceManager {
 | 
				
			|||||||
	 * @since Envoy Server Standalone v0.2-beta
 | 
						 * @since Envoy Server Standalone v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public List<GroupMessage> getPendingGroupMessages(User user, Instant lastSync) {
 | 
						public List<GroupMessage> getPendingGroupMessages(User user, Instant lastSync) {
 | 
				
			||||||
 | 
							if (user == null)
 | 
				
			||||||
 | 
								return new ArrayList<>();
 | 
				
			||||||
 | 
							lastSync = Objects.requireNonNullElse(lastSync, Instant.EPOCH);
 | 
				
			||||||
		return entityManager.createNamedQuery(GroupMessage.getPendingGroupMsg)
 | 
							return entityManager.createNamedQuery(GroupMessage.getPendingGroupMsg)
 | 
				
			||||||
			.setParameter("userId", user.getID())
 | 
								.setParameter("userId", user.getID())
 | 
				
			||||||
			.setParameter("lastSeen", lastSync)
 | 
								.setParameter("lastSeen", lastSync)
 | 
				
			||||||
@@ -277,6 +283,7 @@ public final class PersistenceManager {
 | 
				
			|||||||
	 * @since Envoy Server v0.3-beta
 | 
						 * @since Envoy Server v0.3-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void addContactBidirectional(Contact contact1, Contact contact2) {
 | 
						public void addContactBidirectional(Contact contact1, Contact contact2) {
 | 
				
			||||||
 | 
							if (!(contact1 == null || contact2 == null)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Add users to each others contact list
 | 
								// Add users to each others contact list
 | 
				
			||||||
			contact1.getContacts().add(contact2);
 | 
								contact1.getContacts().add(contact2);
 | 
				
			||||||
@@ -288,6 +295,7 @@ public final class PersistenceManager {
 | 
				
			|||||||
				entityManager.merge(contact2);
 | 
									entityManager.merge(contact2);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Removes a contact from the contact list of another contact and vice versa.
 | 
						 * Removes a contact from the contact list of another contact and vice versa.
 | 
				
			||||||
@@ -308,6 +316,7 @@ public final class PersistenceManager {
 | 
				
			|||||||
	 * @since Envoy Server v0.3-beta
 | 
						 * @since Envoy Server v0.3-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void removeContactBidirectional(Contact contact1, Contact contact2) {
 | 
						public void removeContactBidirectional(Contact contact1, Contact contact2) {
 | 
				
			||||||
 | 
							if (!(contact1 == null || contact2 == null)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Remove users from each others contact list
 | 
								// Remove users from each others contact list
 | 
				
			||||||
			contact1.getContacts().remove(contact2);
 | 
								contact1.getContacts().remove(contact2);
 | 
				
			||||||
@@ -319,6 +328,7 @@ public final class PersistenceManager {
 | 
				
			|||||||
				entityManager.merge(contact2);
 | 
									entityManager.merge(contact2);
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @param user the User whose contacts should be retrieved
 | 
						 * @param user the User whose contacts should be retrieved
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user