/*
* 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;
}
}