Created method to extract all currently online members of a group

additionally, refactored every ".Id" to ".ID"
This commit is contained in:
delvh 2020-03-26 20:14:09 +01:00
parent f91b193d59
commit 0057c66d99
11 changed files with 79 additions and 66 deletions

View File

@ -1,15 +1,14 @@
package envoy.server.net; package envoy.server.net;
import java.util.Date; import java.util.*;
import java.util.HashMap; import java.util.stream.Collectors;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.jenkov.nioserver.ISocketIdListener; import com.jenkov.nioserver.ISocketIdListener;
import envoy.data.User.UserStatus; import envoy.data.User.UserStatus;
import envoy.server.data.Group;
import envoy.server.data.PersistenceManager; import envoy.server.data.PersistenceManager;
import envoy.server.data.User;
import envoy.server.processors.UserStatusChangeProcessor; import envoy.server.processors.UserStatusChangeProcessor;
/** /**
@ -48,60 +47,74 @@ public class ConnectionManager implements ISocketIdListener {
public static ConnectionManager getInstance() { return connectionManager; } public static ConnectionManager getInstance() { return connectionManager; }
@Override @Override
public void socketCancelled(long socketId) { public void socketCancelled(long socketID) {
if (!pendingSockets.remove(socketId)) { if (!pendingSockets.remove(socketID)) {
// Notify contacts of this users offline-going // Notify contacts of this users offline-going
envoy.server.data.User user = PersistenceManager.getInstance().getUserById(getUserIdBySocketId(socketId)); envoy.server.data.User user = PersistenceManager.getInstance().getUserById(getUserIdBySocketId(socketID));
user.setStatus(UserStatus.OFFLINE); user.setStatus(UserStatus.OFFLINE);
user.setLastSeen(new Date()); user.setLastSeen(new Date());
UserStatusChangeProcessor.updateUserStatus(user); UserStatusChangeProcessor.updateUserStatus(user);
// Remove the socket // Remove the socket
sockets.entrySet().removeIf(e -> e.getValue() == socketId); sockets.entrySet().removeIf(e -> e.getValue() == socketID);
} }
} }
@Override @Override
public void socketRegistered(long socketId) { pendingSockets.add(socketId); } public void socketRegistered(long socketID) { pendingSockets.add(socketID); }
/** /**
* Associates a socket ID with a user ID. * Associates a socket ID with a user ID.
* *
* @param userId the user ID * @param userID the user ID
* @param socketId the socket ID * @param socketID the socket ID
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
public void registerUser(long userId, long socketId) { public void registerUser(long userID, long socketID) {
sockets.put(userId, socketId); sockets.put(userID, socketID);
pendingSockets.remove(socketId); pendingSockets.remove(socketID);
} }
/** /**
* @param userId the ID of the user registered at a socket * @param userID the ID of the user registered at a socket
* @return the ID of the socket * @return the ID of the socket
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
public long getSocketId(long userId) { return sockets.get(userId); } public long getSocketId(long userID) { return sockets.get(userID); }
/** /**
* @param socketId the id of the socket whose User is needed * @param socketID the id of the socket whose User is needed
* @return the userId associated with this socketId * @return the userId associated with this socketId
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
public long getUserIdBySocketId(long socketId) { public long getUserIdBySocketId(long socketID) {
return sockets.entrySet().stream().filter(entry -> entry.getValue().equals(socketId)).findFirst().get().getKey(); return sockets.entrySet().stream().filter(entry -> entry.getValue().equals(socketID)).findFirst().get().getKey();
} }
/** /**
* @param userId the ID of the user to check for * @param userID the ID of the user to check for
* @return {@code true} if the user is online * @return {@code true} if the user is online
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
public boolean isOnline(long userId) { return sockets.containsKey(userId); } public boolean isOnline(long userID) { return sockets.containsKey(userID); }
/** /**
* @return the userId of all users who are currently online * @return the userIDs of all users who are currently online
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
public Set<Long> getOnlineUsers() { return sockets.keySet(); } public Set<Long> getOnlineUsers() { return sockets.keySet(); }
/**
* Returns all members of a group who are currently online.
*
* @param group the group to search for
* @return a set of all IDs of currently active members in this group
* @since Envoy Server Standalone v0.1-beta
*/
public Set<Long> getOnlineUsersOfGroup(Group group) {
Set<Long> onlineMembers = new HashSet<>();
Set<Long> members = group.getMembers().stream().map(User::getID).collect(Collectors.toSet());
members.forEach(userID -> { if (isOnline(userID)) onlineMembers.add(userID); });
return onlineMembers;
}
} }

View File

@ -30,15 +30,15 @@ public class ObjectWriteProxy {
public ObjectWriteProxy(WriteProxy writeProxy) { this.writeProxy = writeProxy; } public ObjectWriteProxy(WriteProxy writeProxy) { this.writeProxy = writeProxy; }
/** /**
* @param recipientSocketId the socket id of the recipient * @param recipientSocketID the socket id of the recipient
* @param obj the object to return to the client * @param obj the object to return to the client
* @throws IOException if the serialization of the object failed * @throws IOException if the serialization of the object failed
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
public void write(long recipientSocketId, Object obj) throws IOException { public void write(long recipientSocketID, Object obj) throws IOException {
// Create message targeted at the client // Create message targeted at the client
Message response = writeProxy.getMessage(); Message response = writeProxy.getMessage();
response.socketId = recipientSocketId; response.socketId = recipientSocketID;
// Serialize object to byte array // Serialize object to byte array
byte[] objBytes = SerializationUtils.writeToByteArray(obj); byte[] objBytes = SerializationUtils.writeToByteArray(obj);

View File

@ -25,15 +25,15 @@ public class ContactOperationProcessor implements ObjectProcessor<ContactOperati
public void process(ContactOperationEvent evt, long socketId, ObjectWriteProxy writeProxy) throws IOException { public void process(ContactOperationEvent evt, long socketId, ObjectWriteProxy writeProxy) throws IOException {
switch (evt.getOperationType()) { switch (evt.getOperationType()) {
case ADD: case ADD:
final long userId = ConnectionManager.getInstance().getUserIdBySocketId(socketId); final long userID = ConnectionManager.getInstance().getUserIdBySocketId(socketId);
final long contactId = evt.get().getID(); final long contactId = evt.get().getID();
System.out.printf("Adding user %s to the contact list of user %d.%n", evt.get(), userId); System.out.printf("Adding user %s to the contact list of user %d.%n", evt.get(), userID);
PersistenceManager.getInstance().addUserContact(userId, contactId); PersistenceManager.getInstance().addUserContact(userID, contactId);
// Notify the contact if online // Notify the contact if online
if (ConnectionManager.getInstance().isOnline(contactId)) writeProxy.write(connectionManager.getSocketId(contactId), if (ConnectionManager.getInstance().isOnline(contactId)) writeProxy.write(connectionManager.getSocketId(contactId),
new Contacts(Arrays.asList(PersistenceManager.getInstance().getUserById(userId).toCommon()))); new Contacts(Arrays.asList(PersistenceManager.getInstance().getUserById(userID).toCommon())));
break; break;
default: default:
System.err.printf("Received %s with an unsupported operation.%n", evt); System.err.printf("Received %s with an unsupported operation.%n", evt);

View File

@ -30,10 +30,10 @@ public class ContactsRequestEventProcessor implements ObjectProcessor<ContactSea
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
@Override @Override
public void process(ContactSearchRequest request, long socketId, ObjectWriteProxy writeProxy) throws IOException { public void process(ContactSearchRequest request, long socketID, ObjectWriteProxy writeProxy) throws IOException {
writeProxy.write(socketId, writeProxy.write(socketID,
new ContactSearchResult(PersistenceManager.getInstance() new ContactSearchResult(PersistenceManager.getInstance()
.searchUsers(request.get(), ConnectionManager.getInstance().getUserIdBySocketId(socketId)) .searchUsers(request.get(), ConnectionManager.getInstance().getUserIdBySocketId(socketID))
.stream() .stream()
.map(User::toCommon) .map(User::toCommon)
.collect(Collectors.toList()))); .collect(Collectors.toList())));

View File

@ -19,13 +19,13 @@ public class GroupCreationProcessor implements ObjectProcessor<GroupCreationEven
private final PersistenceManager persistenceManager = PersistenceManager.getInstance(); private final PersistenceManager persistenceManager = PersistenceManager.getInstance();
@Override @Override
public void process(GroupCreationEvent input, long socketId, ObjectWriteProxy writeProxy) throws IOException { public void process(GroupCreationEvent input, long socketID, ObjectWriteProxy writeProxy) throws IOException {
envoy.server.data.Group group = new envoy.server.data.Group(); envoy.server.data.Group group = new envoy.server.data.Group();
group.setName(input.get()); group.setName(input.get());
// TODO adjust event, so it sends a members list as well, which can be initially // TODO adjust event, so it sends a members list as well, which can be initially
// set here // set here
persistenceManager.addContact(group); persistenceManager.addContact(group);
writeProxy.write(socketId, group); // TODO Prepare the client to receive the group object after sending the writeProxy.write(socketID, group); // TODO Prepare the client to receive the group object after sending the
// groupCreationEvent to the server. // groupCreationEvent to the server.
} }

View File

@ -25,11 +25,11 @@ public class IDGeneratorRequestProcessor implements ObjectProcessor<IDGeneratorR
public Class<IDGeneratorRequest> getInputClass() { return IDGeneratorRequest.class; } public Class<IDGeneratorRequest> getInputClass() { return IDGeneratorRequest.class; }
@Override @Override
public void process(IDGeneratorRequest input, long socketId, ObjectWriteProxy writeProxy) throws IOException { public void process(IDGeneratorRequest input, long socketID, ObjectWriteProxy writeProxy) throws IOException {
System.out.println("Received id generation request."); System.out.println("Received id generation request.");
var generator = createIDGenerator(); var generator = createIDGenerator();
System.out.println("Sending new id generator " + generator); System.out.println("Sending new id generator " + generator);
writeProxy.write(socketId, generator); writeProxy.write(socketID, generator);
} }
/** /**
@ -44,10 +44,10 @@ public class IDGeneratorRequestProcessor implements ObjectProcessor<IDGeneratorR
* @since Envoy Server Standalone v0.1-beta * @since Envoy Server Standalone v0.1-beta
*/ */
public static IDGenerator createIDGenerator(long range) { public static IDGenerator createIDGenerator(long range) {
ConfigItem currentId = PersistenceManager.getInstance().getConfigItemById("currentMessageId"); ConfigItem currentID = PersistenceManager.getInstance().getConfigItemById("currentMessageId");
IDGenerator generator = new IDGenerator(Integer.parseInt(currentId.getValue()), range); IDGenerator generator = new IDGenerator(Integer.parseInt(currentID.getValue()), range);
currentId.setValue(String.valueOf(Integer.parseInt(currentId.getValue()) + range)); currentID.setValue(String.valueOf(Integer.parseInt(currentID.getValue()) + range));
PersistenceManager.getInstance().updateConfigItem(currentId); PersistenceManager.getInstance().updateConfigItem(currentID);
return generator; return generator;
} }
} }

View File

@ -38,18 +38,18 @@ public class LoginCredentialProcessor implements ObjectProcessor<LoginCredential
private final ConnectionManager connectionManager = ConnectionManager.getInstance(); private final ConnectionManager connectionManager = ConnectionManager.getInstance();
@Override @Override
public void process(LoginCredentials input, long socketId, ObjectWriteProxy writeProxy) throws IOException { public void process(LoginCredentials input, long socketID, ObjectWriteProxy writeProxy) throws IOException {
UserStatusChangeProcessor.setWriteProxy(writeProxy); UserStatusChangeProcessor.setWriteProxy(writeProxy);
System.out.println(String.format("Received login credentials %s from socket ID %d", input, socketId)); System.out.println(String.format("Received login credentials %s from socket ID %d", input, socketID));
envoy.server.data.User user = getUser(input, socketId, writeProxy); envoy.server.data.User user = getUser(input, socketID, writeProxy);
// Not logged in successfully // Not logged in successfully
if (user == null) { if (user == null) {
System.out.println("Rejecting handshake on socket " + socketId); System.out.println("Rejecting handshake on socket " + socketID);
return; return;
} }
connectionManager.registerUser(user.getID(), socketId); connectionManager.registerUser(user.getID(), socketID);
// Notifies contacts of this users online-going and updates his status in the // Notifies contacts of this users online-going and updates his status in the
// database // database
@ -62,14 +62,14 @@ public class LoginCredentialProcessor implements ObjectProcessor<LoginCredential
// Complete handshake // Complete handshake
System.out.println("Sending user..."); System.out.println("Sending user...");
writeProxy.write(socketId, user.toCommon()); writeProxy.write(socketID, user.toCommon());
System.out.println("Sending contacts..."); System.out.println("Sending contacts...");
writeProxy.write(socketId, contacts); writeProxy.write(socketID, contacts);
System.out.println("Acquiring pending messages for the client..."); System.out.println("Acquiring pending messages for the client...");
List<Message> pendingMessages = PersistenceManager.getInstance().getUnreadMessages(user); List<Message> pendingMessages = PersistenceManager.getInstance().getUnreadMessages(user);
for (Message msg : pendingMessages) { for (Message msg : pendingMessages) {
System.out.println("Sending message " + msg.toCommonMessage()); System.out.println("Sending message " + msg.toCommonMessage());
writeProxy.write(socketId, msg.toCommonMessage()); writeProxy.write(socketID, msg.toCommonMessage());
msg.setReceivedDate(new Date()); msg.setReceivedDate(new Date());
msg.setStatus(MessageStatus.RECEIVED); msg.setStatus(MessageStatus.RECEIVED);
PersistenceManager.getInstance().updateMessage(msg); PersistenceManager.getInstance().updateMessage(msg);
@ -79,13 +79,13 @@ public class LoginCredentialProcessor implements ObjectProcessor<LoginCredential
@Override @Override
public Class<LoginCredentials> getInputClass() { return LoginCredentials.class; } public Class<LoginCredentials> getInputClass() { return LoginCredentials.class; }
private envoy.server.data.User getUser(LoginCredentials credentials, long socketId, ObjectWriteProxy writeProxy) throws IOException { private envoy.server.data.User getUser(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) throws IOException {
return credentials.isRegistration() ? newUser(credentials, socketId, writeProxy) : checkForExistingUser(credentials, socketId, writeProxy); return credentials.isRegistration() ? newUser(credentials, socketID, writeProxy) : checkForExistingUser(credentials, socketID, writeProxy);
} }
/** /**
* @param credentials the input to evaluate * @param credentials the input to evaluate
* @param socketId the socket ID at which the client performing the handshake * @param socketID the socket ID at which the client performing the handshake
* is connected * is connected
* @param writeProxy the {@link ObjectWriteProxy} to use if login was not * @param writeProxy the {@link ObjectWriteProxy} to use if login was not
* successful * successful
@ -93,34 +93,34 @@ public class LoginCredentialProcessor implements ObjectProcessor<LoginCredential
* @throws IOException if sending the failed login back to the client failed * @throws IOException if sending the failed login back to the client failed
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
private envoy.server.data.User checkForExistingUser(LoginCredentials credentials, long socketId, ObjectWriteProxy writeProxy) throws IOException { private envoy.server.data.User checkForExistingUser(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) throws IOException {
try { try {
envoy.server.data.User user = persistenceManager.getUserByName(credentials.getIdentifier()); envoy.server.data.User user = persistenceManager.getUserByName(credentials.getIdentifier());
// Checking if user is already online // Checking if user is already online
if (connectionManager.isOnline(user.getID())) { if (connectionManager.isOnline(user.getID())) {
writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.ALREADY_ONLINE)); writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.ALREADY_ONLINE));
return null; return null;
} }
// Evaluating the correctness of the password hash // Evaluating the correctness of the password hash
if (!Arrays.equals(credentials.getPasswordHash(), user.getPasswordHash())) { if (!Arrays.equals(credentials.getPasswordHash(), user.getPasswordHash())) {
writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.WRONG_PASSWORD)); writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.WRONG_PASSWORD));
return null; return null;
} }
return user; return user;
} catch (NoResultException e) { } catch (NoResultException e) {
// Checking if user exists // Checking if user exists
writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.USER_DOES_NOT_EXIST)); writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.USER_DOES_NOT_EXIST));
} catch (InputMismatchException e) { } catch (InputMismatchException e) {
// Checking if the given password hash is correct // Checking if the given password hash is correct
writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.WRONG_PASSWORD)); writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.WRONG_PASSWORD));
} }
return null; return null;
} }
/** /**
* @param credentials the credentials upon which to create the new {@link User} * @param credentials the credentials upon which to create the new {@link User}
* @param socketId the socketID at which the client performing the handshake * @param socketID the socketID at which the client performing the handshake
* is connected * is connected
* @param writeProxy the write proxy used to notify the client about handshake * @param writeProxy the write proxy used to notify the client about handshake
* rejection * rejection
@ -128,12 +128,12 @@ public class LoginCredentialProcessor implements ObjectProcessor<LoginCredential
* @throws IOException if sending the failed login back to the client failed * @throws IOException if sending the failed login back to the client failed
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
private envoy.server.data.User newUser(LoginCredentials credentials, long socketId, ObjectWriteProxy writeProxy) throws IOException { private envoy.server.data.User newUser(LoginCredentials credentials, long socketID, ObjectWriteProxy writeProxy) throws IOException {
try { try {
// Checking that no user already has this identifier // Checking that no user already has this identifier
PersistenceManager.getInstance().getUserByName(credentials.getIdentifier()); PersistenceManager.getInstance().getUserByName(credentials.getIdentifier());
// this code only gets executed if this user already exists // this code only gets executed if this user already exists
writeProxy.write(socketId, new HandshakeRejectionEvent(HandshakeRejectionEvent.USER_EXISTS_ALREADY)); writeProxy.write(socketID, new HandshakeRejectionEvent(HandshakeRejectionEvent.USER_EXISTS_ALREADY));
return null; return null;
} catch (NoResultException e) { } catch (NoResultException e) {
// Creation of a new user // Creation of a new user

View File

@ -26,7 +26,7 @@ import envoy.server.net.ObjectWriteProxy;
public class MessageProcessor implements ObjectProcessor<Message> { public class MessageProcessor implements ObjectProcessor<Message> {
@Override @Override
public void process(Message message, long socketId, ObjectWriteProxy writeProxy) { public void process(Message message, long socketID, ObjectWriteProxy writeProxy) {
message.nextStatus(); message.nextStatus();
ConnectionManager connectionManager = ConnectionManager.getInstance(); ConnectionManager connectionManager = ConnectionManager.getInstance();
Contact recipient = PersistenceManager.getInstance().getContactById(message.getID()); Contact recipient = PersistenceManager.getInstance().getContactById(message.getID());
@ -36,7 +36,7 @@ public class MessageProcessor implements ObjectProcessor<Message> {
sendToUser(connectionManager, message, writeProxy); sendToUser(connectionManager, message, writeProxy);
// Sending a messageStatusChangeEvent to the sender // Sending a messageStatusChangeEvent to the sender
try { try {
writeProxy.write(socketId, new MessageStatusChangeEvent(message)); writeProxy.write(socketID, new MessageStatusChangeEvent(message));
} catch (IOException e) { } catch (IOException e) {
System.err.println("Could not send messageStatusChangeEvent to the sender of this message with ID: " + message.getID()); System.err.println("Could not send messageStatusChangeEvent to the sender of this message with ID: " + message.getID());
e.printStackTrace(); e.printStackTrace();

View File

@ -23,7 +23,7 @@ public class MessageStatusChangeProcessor implements ObjectProcessor<MessageStat
private final ConnectionManager connectionManager = ConnectionManager.getInstance(); private final ConnectionManager connectionManager = ConnectionManager.getInstance();
@Override @Override
public void process(MessageStatusChangeEvent input, long socketId, ObjectWriteProxy writeProxy) throws IOException { public void process(MessageStatusChangeEvent input, long socketID, ObjectWriteProxy writeProxy) throws IOException {
// Any other status than READ is not supposed to be sent to the server // Any other status than READ is not supposed to be sent to the server
if (input.get() != MessageStatus.READ) throw new IOException(new EnvoyException("Message " + input + " has an invalid status")); if (input.get() != MessageStatus.READ) throw new IOException(new EnvoyException("Message " + input + " has an invalid status"));

View File

@ -26,10 +26,10 @@ public interface ObjectProcessor<T> {
/** /**
* @param input the request object * @param input the request object
* @param socketId the ID of the socket from which the object was received * @param socketID the ID of the socket from which the object was received
* @param writeProxy the object that allows writing to a client * @param writeProxy the object that allows writing to a client
* @throws IOException if something went wrong during processing * @throws IOException if something went wrong during processing
* @since Envoy Server Standalone v0.1-alpha * @since Envoy Server Standalone v0.1-alpha
*/ */
void process(T input, long socketId, ObjectWriteProxy writeProxy) throws IOException; void process(T input, long socketID, ObjectWriteProxy writeProxy) throws IOException;
} }

View File

@ -28,7 +28,7 @@ public class UserStatusChangeProcessor implements ObjectProcessor<UserStatusChan
public Class<UserStatusChangeEvent> getInputClass() { return UserStatusChangeEvent.class; } public Class<UserStatusChangeEvent> getInputClass() { return UserStatusChangeEvent.class; }
@Override @Override
public void process(UserStatusChangeEvent input, long socketId, ObjectWriteProxy writeProxy) throws IOException { public void process(UserStatusChangeEvent input, long socketID, ObjectWriteProxy writeProxy) throws IOException {
// new status should not equal old status // new status should not equal old status
if (input.get().equals(persistenceManager.getUserById(input.getID()).getStatus())) { if (input.get().equals(persistenceManager.getUserById(input.getID()).getStatus())) {
System.out.println("Received an unnecessary UserStatusChangeEvent"); System.out.println("Received an unnecessary UserStatusChangeEvent");