package com.netifera.platform.host.terminal.probe;
import java.util.HashMap;
import java.util.Map;
import com.netifera.platform.api.dispatcher.DispatchException;
import com.netifera.platform.api.dispatcher.DispatchMismatchException;
import com.netifera.platform.api.dispatcher.IMessageDispatcher;
import com.netifera.platform.api.dispatcher.IMessageDispatcherService;
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.ILogManager;
import com.netifera.platform.api.log.ILogger;
import com.netifera.platform.host.terminal.IPseudoTerminalFactory;
import com.netifera.platform.host.terminal.ITerminal;
import com.netifera.platform.host.terminal.ITerminalOutputHandler;
public class TerminalManager {
private ILogger logger;
private IPseudoTerminalFactory ptyFactory;
private Map<String, ITerminal> ptyMap = new HashMap<String, ITerminal>();
private Map<String, IMessenger> messengerMap = new HashMap<String, IMessenger>();
private final ITerminalOutputHandler outputHandler;
public TerminalManager() {
outputHandler = createTerminalOutputHandler();
}
private ITerminalOutputHandler createTerminalOutputHandler() {
return new ITerminalOutputHandler() {
public void terminalOutput(String ptyName, byte[] data, int length) {
byte[] sendBytes = new byte[length];
System.arraycopy(data, 0, sendBytes, 0, length);
emitMessage(ptyName, new TerminalOutput(ptyName, sendBytes));
}
public void terminalClosed(String ptyName) {
emitMessage(ptyName, new TerminalClosed(ptyName));
}
};
}
private void openTerminal(IMessenger messenger, OpenTerminal message) {
final ITerminal terminal = createTerminal(message.getCommand(), messenger);
if(terminal == null) {
logger.error("Failed to create terminal");
return;
}
emitMessage(terminal.getName(), message.createResponse(terminal.getName()));
}
private ITerminal createTerminal(String command, IMessenger messenger) {
synchronized(messengerMap) {
final ITerminal terminal = ptyFactory.openTerminal(command, outputHandler);
if(terminal != null) {
ptyMap.put(terminal.getName(), terminal);
messengerMap.put(terminal.getName(), messenger);
}
return terminal;
}
}
private void terminalInput(IMessenger messenger, TerminalInput message) {
ITerminal terminal = ptyMap.get(message.getPty());
if(terminal == null) {
logger.warning("No terminal found in terminalInput");
return;
}
terminal.sendInput(message.getInput());
}
private void terminalSizeChange(IMessenger messenger, TerminalSizeChange message) {
ITerminal terminal = ptyMap.get(message.getPtyName());
if(terminal == null) {
logger.warning("No terminal found in terminalSizeChange");
return;
}
terminal.setSize(message.getWidth(), message.getHeight());
}
private void closeTerminal(IMessenger messenger, CloseTerminal message) {
closePty(message.getPtyName());
}
private void closePty(String ptyName) {
synchronized (messengerMap) {
ITerminal terminal = ptyMap.get(ptyName);
if(terminal != null) {
terminal.close();
}
ptyMap.remove(ptyName);
messengerMap.remove(ptyName);
}
}
private void emitMessage(String ptyName, IProbeMessage message) {
IMessenger messenger;
synchronized(messengerMap) {
messenger = messengerMap.get(ptyName);
}
if(messenger == null) {
logger.error("Cannot send message because probe has no active messenger");
closePty(ptyName);
return;
}
try {
messenger.emitMessage(message);
} catch (MessengerException e) {
logger.warning("Messenger error sending message " + e.getMessage(), e);
closePty(ptyName);
}
}
private void registerHandlers(IMessageDispatcher dispatcher) {
IMessageHandler handler = new IMessageHandler() {
public void call(IMessenger messenger, IProbeMessage message)
throws DispatchException {
if(message instanceof OpenTerminal) {
openTerminal(messenger, (OpenTerminal) message);
} else if(message instanceof TerminalInput) {
terminalInput(messenger, (TerminalInput) message);
} else if(message instanceof TerminalSizeChange) {
terminalSizeChange(messenger, (TerminalSizeChange) message);
} else if(message instanceof CloseTerminal) {
closeTerminal(messenger, (CloseTerminal) message);
} else {
throw new DispatchMismatchException(message);
}
}
};
dispatcher.registerMessageHandler(OpenTerminal.ID, handler);
dispatcher.registerMessageHandler(TerminalInput.ID, handler);
dispatcher.registerMessageHandler(TerminalSizeChange.ID, handler);
dispatcher.registerMessageHandler(CloseTerminal.ID, handler);
}
protected void setMessageDispatcher(IMessageDispatcherService dispatcher) {
registerHandlers(dispatcher.getServerDispatcher());
}
protected void unsetMessageDispatcher(IMessageDispatcherService dispatcher) {
}
protected void setLogManager(ILogManager logManager) {
logger = logManager.getLogger("Terminal Manager");
}
protected void unsetLogManager(ILogManager logManager) {
}
protected void setPtyFactory(IPseudoTerminalFactory factory) {
ptyFactory = factory;
}
protected void unsetPtyFactory(IPseudoTerminalFactory factory) {
}
}