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,16 +283,18 @@ 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);
|
||||||
contact2.getContacts().add(contact1);
|
contact2.getContacts().add(contact1);
|
||||||
|
|
||||||
// Synchronize changes with the database
|
// Synchronize changes with the database
|
||||||
transaction(() -> {
|
transaction(() -> {
|
||||||
entityManager.merge(contact1);
|
entityManager.merge(contact1);
|
||||||
entityManager.merge(contact2);
|
entityManager.merge(contact2);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -308,16 +316,18 @@ 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);
|
||||||
contact2.getContacts().remove(contact1);
|
contact2.getContacts().remove(contact1);
|
||||||
|
|
||||||
// Synchronize changes with the database
|
// Synchronize changes with the database
|
||||||
transaction(() -> {
|
transaction(() -> {
|
||||||
entityManager.merge(contact1);
|
entityManager.merge(contact1);
|
||||||
entityManager.merge(contact2);
|
entityManager.merge(contact2);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user