Added status update for when a client goes offline
This commit is contained in:
		@@ -7,6 +7,11 @@ import java.util.Set;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.jenkov.nioserver.ISocketIdListener;
 | 
					import com.jenkov.nioserver.ISocketIdListener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import envoy.data.User;
 | 
				
			||||||
 | 
					import envoy.event.UserStatusChangeEvent;
 | 
				
			||||||
 | 
					import envoy.server.database.PersistenceManager;
 | 
				
			||||||
 | 
					import envoy.server.processors.UserStatusChangeProcessor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Project: <strong>envoy-server-standalone</strong><br>
 | 
					 * Project: <strong>envoy-server-standalone</strong><br>
 | 
				
			||||||
 * File: <strong>ConnectionManager.java</strong><br>
 | 
					 * File: <strong>ConnectionManager.java</strong><br>
 | 
				
			||||||
@@ -44,6 +49,11 @@ public class ConnectionManager implements ISocketIdListener {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public void socketCancelled(long socketId) {
 | 
						public void socketCancelled(long socketId) {
 | 
				
			||||||
 | 
							// notifying contacts of this users offline-going
 | 
				
			||||||
 | 
							long	clientId	= getUserIdBySocketId(socketId);
 | 
				
			||||||
 | 
							User	user		= new User(clientId, PersistenceManager.getPersistenceManager().getUserById(clientId).getName());
 | 
				
			||||||
 | 
							UserStatusChangeProcessor.updateUserStatus(new UserStatusChangeEvent(user));
 | 
				
			||||||
 | 
							// removing the socket
 | 
				
			||||||
		if (!pendingSockets.remove(socketId))
 | 
							if (!pendingSockets.remove(socketId))
 | 
				
			||||||
			sockets.entrySet().stream().filter(e -> e.getValue() == socketId).forEach(e -> sockets.remove(e.getValue()));
 | 
								sockets.entrySet().stream().filter(e -> e.getValue() == socketId).forEach(e -> sockets.remove(e.getValue()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -70,6 +80,15 @@ public class ConnectionManager implements ISocketIdListener {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	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
 | 
				
			||||||
 | 
						 * @return the userId associated with this socketId
 | 
				
			||||||
 | 
						 * @since Envoy Server Standalone v0.1-alpha
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public long getUserIdBySocketId(long socketId) {
 | 
				
			||||||
 | 
							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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,7 @@ public class LoginCredentialProcessor implements ObjectProcessor<LoginCredential
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	@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);
 | 
				
			||||||
		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);
 | 
							envoy.server.data.User user = getUser(input);
 | 
				
			||||||
@@ -45,7 +46,7 @@ public class LoginCredentialProcessor implements ObjectProcessor<LoginCredential
 | 
				
			|||||||
		if (user == null) return;
 | 
							if (user == null) return;
 | 
				
			||||||
		// 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
 | 
				
			||||||
		UserStatusChangeProcessor.updateUserStatus(new UserStatusChangeEvent(user.toCommonUser()), writeProxy);
 | 
							UserStatusChangeProcessor.updateUserStatus(new UserStatusChangeEvent(user.toCommonUser()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ConnectionManager.getInstance().registerUser(user.getId(), socketId);
 | 
							ConnectionManager.getInstance().registerUser(user.getId(), socketId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,19 +22,20 @@ import envoy.server.net.ObjectWriteProxy;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public class UserStatusChangeProcessor implements ObjectProcessor<UserStatusChangeEvent> {
 | 
					public class UserStatusChangeProcessor implements ObjectProcessor<UserStatusChangeEvent> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private static ObjectWriteProxy writeProxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	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 {
 | 
				
			||||||
 | 
					 | 
				
			||||||
		PersistenceManager perMan = PersistenceManager.getPersistenceManager();
 | 
							PersistenceManager perMan = PersistenceManager.getPersistenceManager();
 | 
				
			||||||
		// new status should not equal old status
 | 
							// new status should not equal old status
 | 
				
			||||||
		if (input.get().equals(perMan.getUserById(input.getId()).getStatus())) {
 | 
							if (input.get().equals(perMan.getUserById(input.getId()).getStatus())) {
 | 
				
			||||||
			System.out.println("Received an unnecessary UserStatusChangeEvent");
 | 
								System.out.println("Received an unnecessary UserStatusChangeEvent");
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		updateUserStatus(input, writeProxy);
 | 
							updateUserStatus(input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -42,37 +43,48 @@ public class UserStatusChangeProcessor implements ObjectProcessor<UserStatusChan
 | 
				
			|||||||
	 * Sets the {@link UserStatus} for a given user. Both offline contacts and
 | 
						 * Sets the {@link UserStatus} for a given user. Both offline contacts and
 | 
				
			||||||
	 * currently online contacts are notified.
 | 
						 * currently online contacts are notified.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @param evt        the {@link UserStatusChangeEvent} that signals the change
 | 
						 * @param evt the {@link UserStatusChangeEvent} that signals the change
 | 
				
			||||||
	 * @param writeProxy the {@link ObjectWriteProxy} that is used to send objects
 | 
					 | 
				
			||||||
	 *                   back to clients
 | 
					 | 
				
			||||||
	 * @throws IOException if sending this update failed for any contact
 | 
					 | 
				
			||||||
	 * @since Envoy Server Standalone v0.1-alpha
 | 
						 * @since Envoy Server Standalone v0.1-alpha
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public static void updateUserStatus(UserStatusChangeEvent evt, ObjectWriteProxy writeProxy) throws IOException {
 | 
						public static void updateUserStatus(UserStatusChangeEvent evt) {
 | 
				
			||||||
 | 
							// handling for newly logged in clients
 | 
				
			||||||
		PersistenceManager		perMan	= PersistenceManager.getPersistenceManager();
 | 
							PersistenceManager		perMan	= PersistenceManager.getPersistenceManager();
 | 
				
			||||||
		envoy.server.data.User	user	= perMan.getUserById(evt.getId());
 | 
							envoy.server.data.User	user	= perMan.getUserById(evt.getId());
 | 
				
			||||||
		// handling for newly logged in clients
 | 
					 | 
				
			||||||
		perMan.updateUserStatus(user, evt.get());
 | 
							perMan.updateUserStatus(user, evt.get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// handling for contacts that are already online
 | 
							// handling for contacts that are already online
 | 
				
			||||||
		notifyContacts(evt, user, writeProxy);
 | 
							notifyContacts(evt, user);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * notifies active contacts of this {@link User} that his {@link UserStatus} has
 | 
						 * notifies active contacts of this {@link User} that his {@link UserStatus} has
 | 
				
			||||||
	 * changed
 | 
						 * changed
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @param evt        the {@link UserStatusChangeEvent} to send to other clients
 | 
						 * @param evt  the {@link UserStatusChangeEvent} to send to other clients
 | 
				
			||||||
	 * @param user       the {@link User}
 | 
						 * @param user the {@link User}
 | 
				
			||||||
	 * @param writeProxy the {@link ObjectWriteProxy} that is used to send objects
 | 
					 | 
				
			||||||
	 *                   back to clients
 | 
					 | 
				
			||||||
	 * @throws IOException if sending this update failed for any contact
 | 
						 * @throws IOException if sending this update failed for any contact
 | 
				
			||||||
	 * @since Envoy Server Standalone v0.1-alpha
 | 
						 * @since Envoy Server Standalone v0.1-alpha
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public static void notifyContacts(UserStatusChangeEvent evt, envoy.server.data.User user, ObjectWriteProxy writeProxy) throws IOException {
 | 
						private static void notifyContacts(UserStatusChangeEvent evt, envoy.server.data.User user) {
 | 
				
			||||||
		ConnectionManager conMan = ConnectionManager.getInstance();
 | 
							ConnectionManager conMan = ConnectionManager.getInstance();
 | 
				
			||||||
		for (User contact : user.getContacts())
 | 
							try {
 | 
				
			||||||
			if (conMan.isOnline(contact.getId())) writeProxy.write(conMan.getSocketId(contact.getId()), evt);
 | 
								for (User contact : user.getContacts())
 | 
				
			||||||
 | 
									if (conMan.isOnline(contact.getId())) writeProxy.write(conMan.getSocketId(contact.getId()), evt);
 | 
				
			||||||
 | 
							} catch (IOException e) {
 | 
				
			||||||
 | 
								e.printStackTrace();
 | 
				
			||||||
 | 
								System.err.println("Could not notify online contacts of user" + evt.getId() + "that his status changed");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * This method is only called by the LoginCredentialProcessor because every
 | 
				
			||||||
 | 
						 * user needs to login (open a socket) before changing his status.
 | 
				
			||||||
 | 
						 * Needed to ensure propagation of events because an uninitialised writeProxy
 | 
				
			||||||
 | 
						 * would cause problems.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param writeProxy the writeProxy that is used to send objects back to clients
 | 
				
			||||||
 | 
						 * @since Envoy Server Standalone v0.1-alpha
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public static void setWriteProxy(ObjectWriteProxy writeProxy) { UserStatusChangeProcessor.writeProxy = writeProxy; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user