Create CommandRouter and CommandHandler to execute request #206
@@ -3,6 +3,7 @@ package ch.unibas.dmi.dbis.cs108.casono.server;
|
|||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserCleanupJob;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserCleanupJob;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.NetworkManager;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.NetworkManager;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.CommandRouter;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.DisconnectEvent;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.DisconnectEvent;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.EventBus;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.EventBus;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.CommandParserDispatcher;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.CommandParserDispatcher;
|
||||||
@@ -28,7 +29,9 @@ public class ServerApp {
|
|||||||
|
|
||||||
EventBus eventBus = new EventBus();
|
EventBus eventBus = new EventBus();
|
||||||
CommandParserDispatcher dispatcher = new CommandParserDispatcher();
|
CommandParserDispatcher dispatcher = new CommandParserDispatcher();
|
||||||
SessionManager sessionManager = new SessionManager(eventBus, dispatcher);
|
CommandRouter router = new CommandRouter();
|
||||||
|
|
||||||
|
SessionManager sessionManager = new SessionManager(eventBus, dispatcher, router);
|
||||||
eventBus.subscribe(DisconnectEvent.class, event -> sessionManager.onDisconnect(event));
|
eventBus.subscribe(DisconnectEvent.class, event -> sessionManager.onDisconnect(event));
|
||||||
NetworkManager networkManager = new NetworkManager(port, sessionManager);
|
NetworkManager networkManager = new NetworkManager(port, sessionManager);
|
||||||
|
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.network.command;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.Request;
|
||||||
|
|
||||||
|
public interface CommandHandler<T extends Request> {
|
||||||
|
void execute(T request);
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.network.command;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.Request;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CommandRouter {
|
||||||
|
private final Map<Class<? extends Request>, CommandHandler<?>> handlers = new HashMap<>();
|
||||||
|
|
||||||
|
public <T extends Request> void register(Class<T> request, CommandHandler<T> handler) {
|
||||||
|
handlers.put(request, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safe, because during registration, it's ensured that the provided CommandHandler only
|
||||||
|
// receives requests it can handle.
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void execute(Request request) {
|
||||||
|
CommandHandler<Request> handler =
|
||||||
|
(CommandHandler<Request>) handlers.get(request.getClass());
|
||||||
|
|
||||||
|
if (handler == null) {
|
||||||
|
String requestName = request.getClass().toString();
|
||||||
|
throw new UnknownRequestException(
|
||||||
|
"Unable to execute request " + requestName + ". Type unknown", requestName);
|
||||||
|
}
|
||||||
|
handler.execute(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.network.command;
|
||||||
|
|
||||||
|
public class UnknownRequestException extends RuntimeException {
|
||||||
|
private final String requestName;
|
||||||
|
|
||||||
|
public UnknownRequestException(String message, String requestName) {
|
||||||
|
super(message);
|
||||||
|
this.requestName = requestName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequestName() {
|
||||||
|
return requestName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.server.network.sessions;
|
package ch.unibas.dmi.dbis.cs108.casono.server.network.sessions;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.CommandRouter;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.EventBus;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.EventBus;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.CommandParserDispatcher;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.CommandParserDispatcher;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.response.PrimitiveResponse;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.response.PrimitiveResponse;
|
||||||
@@ -14,6 +15,7 @@ public class Session {
|
|||||||
private final TransportLayer transport;
|
private final TransportLayer transport;
|
||||||
private final BlockingQueue<PrimitiveResponse> responseQueue;
|
private final BlockingQueue<PrimitiveResponse> responseQueue;
|
||||||
private final CommandParserDispatcher dispatcher;
|
private final CommandParserDispatcher dispatcher;
|
||||||
|
private final CommandRouter router;
|
||||||
private static final int RESPOND_QUEUE_SIZE = 32;
|
private static final int RESPOND_QUEUE_SIZE = 32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,10 +26,14 @@ public class Session {
|
|||||||
* @throws IOException if an I/O error occurs during initialization
|
* @throws IOException if an I/O error occurs during initialization
|
||||||
*/
|
*/
|
||||||
public Session(
|
public Session(
|
||||||
TransportLayer transport, EventBus eventBus, CommandParserDispatcher dispatcher) {
|
TransportLayer transport,
|
||||||
|
EventBus eventBus,
|
||||||
|
CommandParserDispatcher dispatcher,
|
||||||
|
CommandRouter router) {
|
||||||
this.id = new SessionId();
|
this.id = new SessionId();
|
||||||
this.transport = transport;
|
this.transport = transport;
|
||||||
this.dispatcher = dispatcher;
|
this.dispatcher = dispatcher;
|
||||||
|
this.router = router;
|
||||||
this.responseQueue = new ArrayBlockingQueue<>(RESPOND_QUEUE_SIZE);
|
this.responseQueue = new ArrayBlockingQueue<>(RESPOND_QUEUE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,4 +72,8 @@ public class Session {
|
|||||||
public CommandParserDispatcher getDispatcher() {
|
public CommandParserDispatcher getDispatcher() {
|
||||||
return dispatcher;
|
return dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommandRouter getRouter() {
|
||||||
|
return router;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-4
@@ -1,5 +1,6 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.server.network.sessions;
|
package ch.unibas.dmi.dbis.cs108.casono.server.network.sessions;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.CommandRouter;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.DisconnectEvent;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.DisconnectEvent;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.EventBus;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.EventBus;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.CommandParserDispatcher;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.CommandParserDispatcher;
|
||||||
@@ -16,13 +17,16 @@ public class SessionManager {
|
|||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final CommandParserDispatcher dispatcher;
|
private final CommandParserDispatcher dispatcher;
|
||||||
|
private final CommandRouter router;
|
||||||
|
|
||||||
/** Constructs a new SessionManager. */
|
/** Constructs a new SessionManager. */
|
||||||
public SessionManager(EventBus eventBus, CommandParserDispatcher dispatcher) {
|
public SessionManager(
|
||||||
|
EventBus eventBus, CommandParserDispatcher dispatcher, CommandRouter router) {
|
||||||
this.sessions = new ConcurrentHashMap<>();
|
this.sessions = new ConcurrentHashMap<>();
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.logger = LogManager.getLogger(SessionManager.class);
|
this.logger = LogManager.getLogger(SessionManager.class);
|
||||||
this.dispatcher = dispatcher;
|
this.dispatcher = dispatcher;
|
||||||
|
this.router = router;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,14 +38,16 @@ public class SessionManager {
|
|||||||
* @return newly created session
|
* @return newly created session
|
||||||
*/
|
*/
|
||||||
public Session create(TransportLayer transport) {
|
public Session create(TransportLayer transport) {
|
||||||
Session session = new Session(transport, eventBus, dispatcher);
|
Session session = new Session(transport, eventBus, dispatcher, router);
|
||||||
SessionReader reader = new SessionReader(session, eventBus);
|
SessionReader reader = new SessionReader(session, eventBus);
|
||||||
SessionWriter writer = new SessionWriter(session);
|
SessionWriter writer = new SessionWriter(session);
|
||||||
|
|
||||||
Thread readerThread = Thread.ofVirtual()
|
Thread readerThread =
|
||||||
|
Thread.ofVirtual()
|
||||||
.name("session-" + session.getId().value() + "-reader")
|
.name("session-" + session.getId().value() + "-reader")
|
||||||
.unstarted(reader);
|
.unstarted(reader);
|
||||||
Thread writerThread = Thread.ofVirtual()
|
Thread writerThread =
|
||||||
|
Thread.ofVirtual()
|
||||||
.name("session-" + session.getId().value() + "-writer")
|
.name("session-" + session.getId().value() + "-writer")
|
||||||
.unstarted(writer);
|
.unstarted(writer);
|
||||||
|
|
||||||
|
|||||||
+6
@@ -1,5 +1,6 @@
|
|||||||
package ch.unibas.dmi.dbis.cs108.casono.server.network.sessions;
|
package ch.unibas.dmi.dbis.cs108.casono.server.network.sessions;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.CommandRouter;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.DisconnectEvent;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.DisconnectEvent;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.EventBus;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.events.EventBus;
|
||||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.CommandParserDispatcher;
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.parser.CommandParserDispatcher;
|
||||||
@@ -22,6 +23,7 @@ public class SessionReader implements Runnable {
|
|||||||
private final TransportLayer transport;
|
private final TransportLayer transport;
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final CommandParserDispatcher dispatcher;
|
private final CommandParserDispatcher dispatcher;
|
||||||
|
private final CommandRouter router;
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
|
|
||||||
public SessionReader(Session session, EventBus eventBus) {
|
public SessionReader(Session session, EventBus eventBus) {
|
||||||
@@ -29,6 +31,7 @@ public class SessionReader implements Runnable {
|
|||||||
this.transport = session.getTransport();
|
this.transport = session.getTransport();
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.dispatcher = session.getDispatcher();
|
this.dispatcher = session.getDispatcher();
|
||||||
|
this.router = session.getRouter();
|
||||||
this.logger =
|
this.logger =
|
||||||
LogManager.getLogger(
|
LogManager.getLogger(
|
||||||
SessionReader.class.toString() + "-" + session.getId().value());
|
SessionReader.class.toString() + "-" + session.getId().value());
|
||||||
@@ -50,8 +53,11 @@ public class SessionReader implements Runnable {
|
|||||||
PrimitiveRequest primitiveRequest =
|
PrimitiveRequest primitiveRequest =
|
||||||
new PrimitiveRequest(
|
new PrimitiveRequest(
|
||||||
requestContext, rawRequest.command(), rawRequest.parameters());
|
requestContext, rawRequest.command(), rawRequest.parameters());
|
||||||
|
logger.debug("Converted to {}", primitiveRequest);
|
||||||
|
|
||||||
Request request = dispatcher.parse(primitiveRequest);
|
Request request = dispatcher.parse(primitiveRequest);
|
||||||
|
|
||||||
|
router.execute(request);
|
||||||
} catch (EOFException e) {
|
} catch (EOFException e) {
|
||||||
logger.info("Client disconnected");
|
logger.info("Client disconnected");
|
||||||
eventBus.publish(new DisconnectEvent(session.getId()));
|
eventBus.publish(new DisconnectEvent(session.getId()));
|
||||||
|
|||||||
Reference in New Issue
Block a user