package eu.jucy.connectiondebugger; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import logger.LoggerFactory; import org.apache.log4j.Level; import org.apache.log4j.Logger; import helpers.GH; import helpers.Observable; import helpers.StatusObject; import helpers.StatusObject.ChangeType; import uc.protocols.ConnectionProtocol; import uc.protocols.ConnectionState; import uc.protocols.IConnectionDebugger; import uc.protocols.IProtocolCommand; public class ConnectionDebugger extends Observable<StatusObject> implements IConnectionDebugger { private static final Logger logger = LoggerFactory.make(Level.DEBUG); private int storeCommand = 3000; private InetAddress ia; private ConnectionProtocol current; private CryptoInfo currentCI; private final List<SentCommand> lastCommands = Collections.synchronizedList(new LinkedList<SentCommand>()); private final Map<IProtocolCommand<?>,CommandStat> commandCounter = new HashMap<IProtocolCommand<?>,CommandStat>(); private long trafficTotal; public void notifyAttachable(InetAddress ia, ConnectionProtocol attacheTo) { if (current != null) { current.unregisterDebugger(this); } init(attacheTo); logger.debug("Attached : "+ia+" connection: "+attacheTo); } public void init(InetAddress ia) { this.ia = ia; ConnectionProtocol.addNotifyAttachable(ia, this); } public void init(ConnectionProtocol cp) { current = cp; current.registerDebugger(this); if (current.isEncrypted()) { currentCI = new CryptoInfo(); cp.getConnection().getCryptoInfo(currentCI); notifyObservers(new StatusObject(currentCI,ChangeType.CHANGED)); } } public void dispose() { if (current != null) { current.unregisterDebugger(this); } if (ia != null) { ConnectionProtocol.removeNotifyAttachable(ia); } } @Override public void receivedCommand(IProtocolCommand<?> commandHandler, boolean wellFormed, String command) { ReceivedCommand rc = new ReceivedCommand(commandHandler, command, wellFormed); CommandStat cs; synchronized(commandCounter) { cs = commandCounter.get(rc.getCommandHandler()); if (cs == null) { cs = new CommandStat(rc.getCommandHandler()); commandCounter.put(rc.getCommandHandler(), cs); notifyObservers(new StatusObject(cs,ChangeType.ADDED)); } synchronized(cs) { cs.frequency++; cs.lastCommand = command; try { int traf = command.getBytes(current.getCharset().name()).length + 1; //\n/| char is one byte in size and not counted here otherwise.. trafficTotal += traf; cs.trafficCommand += traf; } catch (UnsupportedEncodingException e) { throw new IllegalStateException(); } } } notifyObservers(new StatusObject(cs,ChangeType.CHANGED)); add(rc); } public long getTrafficTotal() { synchronized (commandCounter) { return trafficTotal; } } public Collection<CommandStat> getCommandCounter() { return Collections.unmodifiableCollection(commandCounter.values()); } public void sentCommand(String sent) { if (!GH.isEmpty(sent)) { SentCommand sc = new SentCommand(sent.substring(0, sent.length()-1),false); add(sc); } } public void statusChanged(ConnectionState newStatus, ConnectionProtocol cp) { if (newStatus == ConnectionState.CONNECTED) { if (cp.isEncrypted()) { currentCI = new CryptoInfo(); cp.getConnection().getCryptoInfo(currentCI); logger.debug("Connected: "+newStatus); notifyObservers(new StatusObject(currentCI,ChangeType.CHANGED)); } } add(new SentCommand(newStatus)); } private void add(SentCommand sc) { lastCommands.add(sc); notifyObservers(new StatusObject(sc,ChangeType.ADDED)); while (lastCommands.size() > storeCommand) { SentCommand removed = lastCommands.remove(0); notifyObservers(new StatusObject(removed,ChangeType.REMOVED)); } } public void clear() { lastCommands.clear(); synchronized(commandCounter) { commandCounter.clear(); } } public List<SentCommand> getLastCommands() { return lastCommands; } public static class CommandStat { private final String commandName; private int frequency; private String lastCommand = ""; private long trafficCommand; public CommandStat(IProtocolCommand<?> com) { commandName = com.getClass().getSimpleName(); } public String getCommandName() { return commandName; } public synchronized int getFrequency() { return frequency; } public synchronized String getLastCommand() { return lastCommand; } public synchronized long getTrafficTotal() { return trafficCommand; } } }