package com.netifera.platform.internal.dispatcher;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.netifera.platform.api.channels.IChannelMessageSerializer;
import com.netifera.platform.api.channels.IChannelTransport;
import com.netifera.platform.api.dispatcher.DispatchException;
import com.netifera.platform.api.dispatcher.IMessageDispatcher;
import com.netifera.platform.api.dispatcher.IMessageHandler;
import com.netifera.platform.api.dispatcher.IMessenger;
import com.netifera.platform.api.dispatcher.IProbeMessage;
import com.netifera.platform.api.dispatcher.MessengerException;
import com.netifera.platform.api.log.ILogger;
import com.netifera.platform.dispatcher.StatusMessage;
import com.netifera.platform.internal.dispatcher.channels.ChannelMessageSerializer;
/*
* Dispatcher for registering message handlers and delivering incoming <code>ProbeMessage</code>
* objects to those handlers.
*/
public class MessageDispatcher implements IMessageDispatcher {
/*
* Map named type to message handler.
*/
private final Map<String, IMessageHandler> messageMap = new HashMap<String, IMessageHandler>();
private final ILogger logger;
MessageDispatcher(ILogger logger) {
this.logger = logger;
}
public void registerMessageHandler(String messageName, IMessageHandler handler) {
synchronized(messageMap) {
messageMap.put(messageName, handler);
}
logger.debug("Registering handler for message: " + messageName);
}
public void dispatch(IMessenger source, IProbeMessage message) throws MessengerException {
logger.debug("Message " + message.getNamedType() + " seq: " + message.getSequenceNumber());
IMessageHandler handler;
synchronized(messageMap) {
handler = messageMap.get(message.getNamedType());
}
if(handler == null) {
logger.warning("Unhandled message type "+message.getNamedType()+" received (" + message.toString() + ")");
source.emitMessage(StatusMessage.createUnhandledMessageError(message.getSequenceNumber()));
return;
}
try {
handler.call(source, message);
} catch(DispatchException e) {
logger.warning("Error dispatching message " + message.getNamedType() + ": " + e.getMessage());
}
catch(Exception e) {
logger.error("Unhandled exception dispatching message " + message.getNamedType(), e);
}
}
public Set<String> messagesHandled() {
return messageMap.keySet();
}
Messenger createMessenger(IChannelTransport transport) throws IOException {
logger.debug("Creating messenger for channel transport: " + transport);
if(!transport.isConnected()) {
throw new IllegalStateException("Cannot create messenger on closed channel");
}
final IChannelMessageSerializer serializer = ChannelMessageSerializer.createClientSerializer(transport, logger);
final Messenger m = new Messenger(serializer, this, logger);
m.start();
return m;
}
}