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 com.jenkov.nioserver.Message; import envoy.data.AuthenticatedRequest; import envoy.util.EnvoyLog; import envoy.server.data.*; 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> 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> 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) { Contact contact = PersistenceManager.getInstance() .getContactByID(((AuthenticatedRequest) obj).getUserID()); // Validating the authenticity of the request if (contact == null || contact instanceof Group || !((AuthenticatedRequest) obj).getAuthentication() .equals(((User) contact).getAuthToken())) { // Invalid request logger.log(Level.INFO, "A user tried to perform an authenticated request but could not identify himself. Discarding request."); return; } // Valid request logger.log(Level.INFO, "A user successfully authenticated a request for " + obj); authenticated = true; obj = ((AuthenticatedRequest) obj).getRequest(); } else logger.log(Level.FINE, "Received unauthenticated " + obj); refer(message.socketId, writeProxy, obj, authenticated); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } /** * 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); } } } } }