Prepare handshake synchronization

Common
* Replace LocalDateTime with Instant everywhere

Client
* Display message creation date with system time zone in MessageControl
* LocalDB#users now strictly contains Users
* lastSync time stamp in LocalDB (saved per user)
* isOnline parameter in save function (lastSync updated if true)
* lastSync time stamp in LoginCredentials
* No ClientConfig#getLoginCredentials because of missing information,
  moved to LoginScene
* Pass LocalDB#lastSync to LoginCredentials in LoginScene

Server
* Explicit lastSync parameter for
  PersistenceManager#getPending(Group)Messages

This sends the correct time stamp to the server, however the JPQL
queries have yet to be adjusted.
This commit is contained in:
2020-07-16 17:04:35 +02:00
parent def31ebc4d
commit 90662b3610
23 changed files with 189 additions and 159 deletions

View File

@ -1,6 +1,6 @@
package envoy.server.data;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.Set;
import javax.persistence.*;
@ -28,7 +28,7 @@ public abstract class Contact {
protected String name;
@Column(name = "creation_date")
private LocalDateTime creationDate;
private Instant creationDate;
@ManyToMany(fetch = FetchType.EAGER)
protected Set<Contact> contacts;
@ -92,15 +92,15 @@ public abstract class Contact {
/**
* @return the creationDate
* @since Envoy Server Standalone v0.1-beta
* @since Envoy Server Standalone v0.2-beta
*/
public LocalDateTime getCreationDate() { return creationDate; }
public Instant getCreationDate() { return creationDate; }
/**
* @param creationDate the creationDate to set
* @since Envoy Server Standalone v0.1-beta
* @since Envoy Server Standalone v0.2-beta
*/
public void setCreationDate(LocalDateTime creationDate) { this.creationDate = creationDate; }
public void setCreationDate(Instant creationDate) { this.creationDate = creationDate; }
@Override
public String toString() { return String.format("%s[id=%d,name=%s, %d contact(s)]", getClass().getSimpleName(), id, name, contacts.size()); }

View File

@ -1,6 +1,6 @@
package envoy.server.data;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
@ -39,7 +39,7 @@ public class GroupMessage extends Message {
private Map<Long, envoy.data.Message.MessageStatus> memberMessageStatus;
@Column(name = "last_status_change_date")
protected LocalDateTime lastStatusChangeDate;
protected Instant lastStatusChangeDate;
/**
* The constructor for a database object.
@ -55,9 +55,9 @@ public class GroupMessage extends Message {
* into a
* database {@link GroupMessage}
* @param lastStatusChangeDate the time stamp to set
* @since Envoy Server Standalone v0.1-beta
* @since Envoy Server Standalone v0.2-beta
*/
public GroupMessage(envoy.data.GroupMessage groupMessage, LocalDateTime lastStatusChangeDate) {
public GroupMessage(envoy.data.GroupMessage groupMessage, Instant lastStatusChangeDate) {
super(groupMessage);
memberMessageStatus = groupMessage.getMemberStatuses();
this.lastStatusChangeDate = lastStatusChangeDate;
@ -92,13 +92,13 @@ public class GroupMessage extends Message {
/**
* @return the date at which one of the member statuses changed last
* @since Envoy Server Standalone v0.1-beta
* @since Envoy Server Standalone v0.2-beta
*/
public LocalDateTime getLastStatusChangeDate() { return lastStatusChangeDate; }
public Instant getLastStatusChangeDate() { return lastStatusChangeDate; }
/**
* @param date the date to set
* @since Envoy Server Standalone v0.1-beta
* @since Envoy Server Standalone v0.2-beta
*/
public void setLastStatusChangeDate(LocalDateTime date) { lastStatusChangeDate = date; }
public void setLastStatusChangeDate(Instant date) { lastStatusChangeDate = date; }
}

View File

@ -2,7 +2,7 @@ package envoy.server.data;
import static envoy.data.Message.MessageStatus.*;
import java.time.LocalDateTime;
import java.time.Instant;
import javax.persistence.*;
@ -55,13 +55,13 @@ public class Message {
protected Contact recipient;
@Column(name = "creation_date")
protected LocalDateTime creationDate;
protected Instant creationDate;
@Column(name = "received_date")
protected LocalDateTime receivedDate;
protected Instant receivedDate;
@Column(name = "read_date")
protected LocalDateTime readDate;
protected Instant readDate;
protected String text;
protected envoy.data.Message.MessageStatus status;
@ -134,7 +134,7 @@ public class Message {
* @since Envoy Server Standalone v0.1-beta
*/
public void received() {
receivedDate = LocalDateTime.now();
receivedDate = Instant.now();
status = RECEIVED;
}
@ -145,7 +145,7 @@ public class Message {
* @since Envoy Server Standalone v0.1-beta
*/
public void read() {
readDate = LocalDateTime.now();
readDate = Instant.now();
status = READ;
}
@ -190,43 +190,43 @@ public class Message {
/**
* @return the date at which a {link envoy.data.Message} has been created
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
*/
public LocalDateTime getCreationDate() { return creationDate; }
public Instant getCreationDate() { return creationDate; }
/**
* @param creationDate the creation date to set
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
* @see Message#getCreationDate()
*/
public void setCreationDate(LocalDateTime creationDate) { this.creationDate = creationDate; }
public void setCreationDate(Instant creationDate) { this.creationDate = creationDate; }
/**
* @return the date at which a {link envoy.data.Message} has been received by
* the server
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
*/
public LocalDateTime getReceivedDate() { return receivedDate; }
public Instant getReceivedDate() { return receivedDate; }
/**
* @param receivedDate the received date to set
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
* @see Message#getReceivedDate()
*/
public void setReceivedDate(LocalDateTime receivedDate) { this.receivedDate = receivedDate; }
public void setReceivedDate(Instant receivedDate) { this.receivedDate = receivedDate; }
/**
* @return the date at which a {link envoy.data.Message} has been read
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
*/
public LocalDateTime getReadDate() { return readDate; }
public Instant getReadDate() { return readDate; }
/**
* @param readDate the read date to set
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
* @see Message#getReadDate()
*/
public void setReadDate(LocalDateTime readDate) { this.readDate = readDate; }
public void setReadDate(Instant readDate) { this.readDate = readDate; }
/**
* @return the status of a {link envoy.data.Message}

View File

@ -1,6 +1,6 @@
package envoy.server.data;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.List;
import javax.persistence.EntityManager;
@ -38,7 +38,7 @@ public class PersistenceManager {
.getOnlineUsers()
.stream()
.map(this::getUserByID)
.forEach(user -> { user.setStatus(UserStatus.OFFLINE); user.setLastSeen(LocalDateTime.now()); entityManager.merge(user); });
.forEach(user -> { user.setStatus(UserStatus.OFFLINE); user.setLastSeen(Instant.now()); entityManager.merge(user); });
transaction.commit();
}));
}
@ -182,31 +182,29 @@ public class PersistenceManager {
* Returns all messages received while being offline or the ones that have
* changed.
*
* @param user the user who wants to receive his unread messages
* @param user the user who wants to receive his unread messages
* @param lastSync the time stamp of the last synchronization
* @return all messages that the client does not yet have (unread messages)
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
*/
public List<Message> getPendingMessages(User user) {
return entityManager
.createNamedQuery(Message.getPending)
.setParameter("user", user)
.setParameter("lastSeen", user.getLastSeen())
.getResultList();
public List<Message> getPendingMessages(User user, Instant lastSync) {
return entityManager.createNamedQuery(Message.getPending).setParameter("user", user).setParameter("lastSeen", lastSync).getResultList();
}
/**
* Returns all groupMessages received while being offline or the ones that have
* changed.
*
* @param user the user who wants to receive his unread groupMessages
* @param user the user who wants to receive his unread groupMessages
* @param lastSync the time stamp of the last synchronization
* @return all groupMessages that the client does not yet have (unread
* groupMessages)
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
*/
public List<GroupMessage> getPendingGroupMessages(User user) {
public List<GroupMessage> getPendingGroupMessages(User user, Instant lastSync) {
return entityManager.createNamedQuery(GroupMessage.getPendingGroupMsg)
.setParameter("userId", user.getID())
.setParameter("lastSeen", user.getLastSeen())
.setParameter("lastSeen", lastSync)
.getResultList();
}
@ -221,8 +219,7 @@ public class PersistenceManager {
* @since Envoy Server Standalone v0.1-alpha
*/
public List<User> searchUsers(String searchPhrase, long userId) {
return entityManager.createNamedQuery(
User.searchByName)
return entityManager.createNamedQuery(User.searchByName)
.setParameter("searchPhrase", searchPhrase + "%")
.setParameter("context", getUserByID(userId))
.getResultList();

View File

@ -1,6 +1,6 @@
package envoy.server.data;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.Set;
import java.util.stream.Collectors;
@ -66,7 +66,7 @@ public class User extends Contact {
private String passwordHash;
@Column(name = "last_seen")
private LocalDateTime lastSeen;
private Instant lastSeen;
private UserStatus status;
@ -92,15 +92,15 @@ public class User extends Contact {
/**
* @return the last date the user has been online
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
*/
public LocalDateTime getLastSeen() { return lastSeen; }
public Instant getLastSeen() { return lastSeen; }
/**
* @param lastSeen the latest date at which the user has been online to set
* @since Envoy Server Standalone v0.1-alpha
* @since Envoy Server Standalone v0.2-beta
*/
public void setLastSeen(LocalDateTime lastSeen) { this.lastSeen = lastSeen; }
public void setLastSeen(Instant lastSeen) { this.lastSeen = lastSeen; }
/**
* @return the status

View File

@ -1,6 +1,6 @@
package envoy.server.net;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
@ -52,7 +52,7 @@ public class ConnectionManager implements ISocketIdListener {
// Notify contacts of this users offline-going
envoy.server.data.User user = PersistenceManager.getInstance().getUserByID(getUserIDBySocketID(socketID));
user.setStatus(UserStatus.OFFLINE);
user.setLastSeen(LocalDateTime.now());
user.setLastSeen(Instant.now());
UserStatusChangeProcessor.updateUserStatus(user);
// Remove the socket

View File

@ -2,7 +2,7 @@ package envoy.server.processors;
import static envoy.data.Message.MessageStatus.*;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.Collections;
import java.util.logging.Logger;
@ -56,7 +56,7 @@ public class GroupMessageProcessor implements ObjectProcessor<GroupMessage> {
groupMessage);
try {
PersistenceManager.getInstance().addMessage(new envoy.server.data.GroupMessage(groupMessage, LocalDateTime.now()));
PersistenceManager.getInstance().addMessage(new envoy.server.data.GroupMessage(groupMessage, Instant.now()));
} catch (EntityExistsException e) {
logger.warning("Received a groupMessage with an ID that already exists");
}

View File

@ -2,7 +2,7 @@ package envoy.server.processors;
import static envoy.data.Message.MessageStatus.READ;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -42,7 +42,7 @@ public class GroupMessageStatusChangeProcessor implements ObjectProcessor<GroupM
// Apply the status change
gmsg.getMemberMessageStatus().replace(statusChange.getMemberID(), statusChange.get());
gmsg.setLastStatusChangeDate(LocalDateTime.now());
gmsg.setLastStatusChangeDate(Instant.now());
// Notifying the other members about the status change
final var userID = connectionManager.getUserIDBySocketID(socketID);
@ -59,7 +59,7 @@ public class GroupMessageStatusChangeProcessor implements ObjectProcessor<GroupM
// Notify online members about the status change
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), LocalDateTime.now()));
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), Instant.now()));
}
persistenceManager.updateMessage(gmsg);
}

View File

@ -4,7 +4,7 @@ import static envoy.data.Message.MessageStatus.*;
import static envoy.data.User.UserStatus.ONLINE;
import static envoy.event.HandshakeRejection.*;
import java.time.LocalDateTime;
import java.time.Instant;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@ -47,7 +47,7 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
@Override
public void process(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) {
// Cache this write proxy for user-independant notifications
// Cache this write proxy for user-independent notifications
UserStatusChangeProcessor.setWriteProxy(writeProxy);
if (!VersionUtil.verifyCompatibility(credentials.getClientVersion())) {
@ -98,7 +98,7 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
// Creation of a new user
user = new User();
user.setName(credentials.getIdentifier());
user.setLastSeen(LocalDateTime.now());
user.setLastSeen(Instant.now());
user.setStatus(ONLINE);
user.setPasswordHash(PasswordUtil.hash(credentials.getPassword()));
user.setContacts(new HashSet<>());
@ -117,7 +117,7 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
// Complete the handshake
writeProxy.write(socketID, user.toCommon());
final var pendingMessages = PersistenceManager.getInstance().getPendingMessages(user);
final var pendingMessages = PersistenceManager.getInstance().getPendingMessages(user, credentials.getLastSync());
pendingMessages.removeIf(GroupMessage.class::isInstance);
logger.fine("Sending " + pendingMessages.size() + " pending messages to " + user + "...");
@ -138,7 +138,7 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
} else writeProxy.write(socketID, new MessageStatusChange(msgCommon));
}
List<GroupMessage> pendingGroupMessages = PersistenceManager.getInstance().getPendingGroupMessages(user);
List<GroupMessage> pendingGroupMessages = PersistenceManager.getInstance().getPendingGroupMessages(user, credentials.getLastSync());
logger.fine("Sending " + pendingGroupMessages.size() + " pending group messages to " + user + "...");
for (var gmsg : pendingGroupMessages) {
@ -148,13 +148,13 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
if (gmsg.getMemberMessageStatus().get(user.getID()) == SENT) {
gmsg.getMemberMessageStatus().replace(user.getID(), RECEIVED);
gmsg.setLastStatusChangeDate(LocalDateTime.now());
gmsg.setLastStatusChangeDate(Instant.now());
writeProxy.write(socketID, gmsgCommon);
// Notify all online group members about the status change
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
new GroupMessageStatusChange(gmsg.getID(), RECEIVED, LocalDateTime
new GroupMessageStatusChange(gmsg.getID(), RECEIVED, Instant
.now(),
connectionManager.getUserIDBySocketID(socketID)));
@ -163,7 +163,7 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
// Notify online members about the status change
writeProxy.writeToOnlineContacts(gmsg.getRecipient().getContacts(),
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), LocalDateTime.now()));
new MessageStatusChange(gmsg.getID(), gmsg.getStatus(), Instant.now()));
}
PersistenceManager.getInstance().updateMessage(gmsg);