/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.communication.messaging.internal; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import de.rcenvironment.core.communication.api.NodeIdentifierService; import de.rcenvironment.core.communication.common.InstanceNodeSessionId; import de.rcenvironment.core.communication.common.SerializationException; import de.rcenvironment.core.communication.messaging.MessageEndpointHandler; import de.rcenvironment.core.communication.messaging.NetworkRequestHandler; import de.rcenvironment.core.communication.messaging.NetworkRequestHandlerMap; import de.rcenvironment.core.communication.model.NetworkRequest; import de.rcenvironment.core.communication.model.NetworkResponse; import de.rcenvironment.core.communication.model.internal.PayloadTestFuzzer; import de.rcenvironment.core.communication.protocol.NetworkResponseFactory; import de.rcenvironment.core.communication.routing.internal.NetworkFormatter; import de.rcenvironment.core.utils.common.LogUtils; /** * The default {@link MessageEndpointHandler} implementation used in RCE instances. * * @author Robert Mischke */ public class MessageEndpointHandlerImpl implements MessageEndpointHandler { private final Map<String, NetworkRequestHandler> requestHandlerMap = new HashMap<String, NetworkRequestHandler>(); private final NodeIdentifierService nodeIdentifierService; private final Log log = LogFactory.getLog(getClass()); public MessageEndpointHandlerImpl(NodeIdentifierService nodeIdentifierService) { this.nodeIdentifierService = nodeIdentifierService; } @Override public NetworkResponse onRequestArrivedAtDestination(NetworkRequest request) { // find matching handler // TODO get rid of synchronization? NetworkRequestHandler handler; synchronized (requestHandlerMap) { handler = requestHandlerMap.get(request.getMessageType()); } // actually *handle* the message outside the synchronized block if (handler != null) { try { // trigger deserialization here to catch errors early and in a defined place - misc_ro try { request.getDeserializedContent(); } catch (SerializationException e) { throw new InternalMessagingException("Error deserializing request body", e); } try { // FIXME restore or remove "previous hop" parameter InstanceNodeSessionId prevHopId = null; return handler.handleRequest(request, prevHopId); } catch (RuntimeException e) { throw new InternalMessagingException("Uncaught RuntimeException while handling remote request", e); } } catch (InternalMessagingException e) { return logAndWrapLowLevelException(request, e); } } else { Serializable loggableContent; try { loggableContent = request.getDeserializedContent(); } catch (SerializationException e) { // used for logging only loggableContent = "Failed to deserialize content: " + e; } String errorId = LogUtils.logErrorAndAssignUniqueMarker(log, "No request handler matched for message type '" + request.getMessageType() + "'; string representation of request: " + NetworkFormatter.message(loggableContent, request.accessRawMetaData())); return NetworkResponseFactory.generateResponseForInternalErrorAtRecipient(request, errorId); } } @Override public void registerRequestHandler(String messageType, NetworkRequestHandler handler) { synchronized (requestHandlerMap) { requestHandlerMap.put(messageType, handler); } } @Override public void registerRequestHandlers(NetworkRequestHandlerMap newMappings) { synchronized (requestHandlerMap) { requestHandlerMap.putAll(newMappings); } } private NetworkResponse logAndWrapLowLevelException(NetworkRequest request, InternalMessagingException e) { @SuppressWarnings("unused")// suppress Eclipse warning when the ENABLED constant is false - misc_ro boolean compressStacktrace = PayloadTestFuzzer.ENABLED && e.getCause() != null && e.getCause().getClass() == SerializationException.class; final String errorId; if (compressStacktrace) { errorId = LogUtils.logErrorAndAssignUniqueMarker(log, e.toString()); } else { if (e.getCause() != null) { errorId = LogUtils.logExceptionWithStacktraceAndAssignUniqueMarker(log, e.getMessage(), e.getCause()); } else { errorId = LogUtils.logErrorAndAssignUniqueMarker(log, e.getMessage()); } } NetworkResponse response = NetworkResponseFactory.generateResponseForInternalErrorAtRecipient(request, errorId); return response; } }