This repository has been archived on 2021-12-05. You can view files and clone it, but cannot push or open issues or pull requests.
envoy/server/src/main/java/envoy/server/net/ObjectMessageProcessor.java

102 lines
3.0 KiB
Java
Executable File

package envoy.server.net;
import java.io.*;
import java.lang.reflect.ParameterizedType;
import java.util.Set;
import java.util.logging.*;
import com.jenkov.nioserver.*;
import envoy.data.AuthenticatedRequest;
import envoy.util.EnvoyLog;
import envoy.server.data.PersistenceManager;
import envoy.server.processors.ObjectProcessor;
/**
* Handles incoming objects.
*
* @author Kai S. K. Engelbart
* @since Envoy Server Standalone v0.1-alpha
*/
public final class ObjectMessageProcessor implements IMessageProcessor {
private final Set<ObjectProcessor<?>> processors;
private static final Logger logger = EnvoyLog.getLogger(ObjectMessageProcessor.class);
/**
* The constructor to set the {@link ObjectProcessor}s.
*
* @param processors the {@link ObjectProcessor} to set
* @since Envoy Server Standalone v0.1-alpha
*/
public ObjectMessageProcessor(Set<ObjectProcessor<?>> processors) {
this.processors = processors;
}
@Override
public void process(Message message, WriteProxy writeProxy) {
try (ObjectInputStream in =
new ObjectInputStream(new ByteArrayInputStream(message.sharedArray, message.offset + 4,
message.length - 4))) {
Object obj = in.readObject();
if (obj == null) {
logger.warning("Received a null object");
return;
}
// authenticate requests if necessary
boolean authenticated = false;
if (obj instanceof AuthenticatedRequest)
try {
authenticated = PersistenceManager
.getInstance().getUserByID(((AuthenticatedRequest<?>) obj).getUserID())
.getID() == ConnectionManager.getInstance()
.getUserIDBySocketID(message.socketId);
// Class cast exception and NullPointerException are valid here and signify a
// failed authentication
} catch (ClassCastException | NullPointerException e) {} finally {
obj = ((AuthenticatedRequest<?>) obj).getRequest();
}
logger.log(Level.INFO,
"Received " + (authenticated ? "" : "un") + "authenticated " + obj);
refer(message.socketId, writeProxy, obj, authenticated);
} catch (IOException | ClassNotFoundException e) {
logger.log(Level.WARNING,
"An exception occurred when reading in an object: " + e);
}
}
/**
* Executes the appropriate {@link ObjectProcessor} for the given input ({@code obj}), if any is
* present.
*/
@SuppressWarnings("unchecked")
private void refer(long socketID, WriteProxy writeProxy, Object obj, boolean authenticated) {
// Get processor and input class and process object
for (@SuppressWarnings("rawtypes")
ObjectProcessor p : processors) {
Class<?> c = (Class<?>) ((ParameterizedType) p.getClass().getGenericInterfaces()[0])
.getActualTypeArguments()[0];
if (c.equals(obj.getClass())) {
if (!authenticated && p.isAuthenticationRequired()) {
logger.log(Level.INFO,
"Discarding request as no authentication has been provided");
return;
}
try {
p.process(c.cast(obj), socketID, new ObjectWriteProxy(writeProxy));
break;
} catch (IOException e) {
logger.log(Level.SEVERE, "Exception during processor execution: ", e);
}
}
}
}
}