package com.esri.geoevent.solutions.transport.irc.jerklib; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import com.esri.geoevent.solutions.transport.irc.jerklib.events.ConnectionCompleteEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.IRCEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.JoinCompleteEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.JoinEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.KickEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.NickChangeEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.NickInUseEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.PartEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.QuitEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.events.IRCEvent.Type; import com.esri.geoevent.solutions.transport.irc.jerklib.events.impl.NickChangeEventImpl; import com.esri.geoevent.solutions.transport.irc.jerklib.events.modes.ModeEvent; import com.esri.geoevent.solutions.transport.irc.jerklib.listeners.IRCEventListener; import static com.esri.geoevent.solutions.transport.irc.jerklib.events.IRCEvent.Type.*; /** * Class that will only handle events that effect internal states/caches. * Like channel nick lists. All events will be added to the ConnectionManager * for relaying. You can change the internal behavior of Jerklib by overriding * methods in this class or by adding/removing event handlers. * * @see IRCEventListener * @author mohadib * */ public class DefaultInternalEventHandler implements IRCEventListener { private ConnectionManager manager; private Map<Type, IRCEventListener> stratMap = new HashMap<Type, IRCEventListener>(); private Logger log = Logger.getLogger(this.getClass().getName()); /** * Creates a new DefaultInternalEventHandler associated with * the given ConnectionManager * * @param manager */ public DefaultInternalEventHandler(ConnectionManager manager) { this.manager = manager; initStratMap(); } /** * Adds an IRCEventListener to handle a given event Type. * This should only be used if you want to effect the internal * behavior of Jerklib. * * @param type * @param listener */ public void addEventHandler(Type type , IRCEventListener listener) { stratMap.put(type, listener); } /** * Removes any internal IRCEventListeners registered * to handle the Type passed in. This effects the internal * behavior of Jerklib. * * @param type * @return true if a listener was removed , else false. */ public boolean removeEventHandler(Type type) { return stratMap.remove(type) != null; } /** * Returns the event handler registerd to the Type given. * * @param type * @return The handler or null if no handler for Type */ public IRCEventListener getEventHandler(Type type) { return stratMap.get(type); } /* (non-Javadoc) * @see com.esri.ges.transport.Irc.jerklib.listeners.IRCEventListener#receiveEvent(com.esri.ges.transport.Irc.jerklib.events.IRCEvent) */ public void receiveEvent(IRCEvent event) { IRCEventListener l = stratMap.get(event.getType()); if(l != null) { l.receiveEvent(event); } else { Session session = event.getSession(); String data = event.getRawEventData(); String command = new EventToken(data).command(); if(command.equals("PING")) { session.getConnection().pong(event); } else if(command.equals("PONG")) { session.getConnection().gotPong(); } } manager.addToRelayList(event); } /** * Called when a JoinCompleteEvent is received * @param e the event */ public void joinComplete(IRCEvent e) { JoinCompleteEvent jce = (JoinCompleteEvent)e; e.getSession().addChannel(jce.getChannel()); jce.getSession().sayRaw("MODE " + jce.getChannel().getName()); } /** * Called when a JoinEvent is received. * * @param e the event */ public void join(IRCEvent e) { JoinEvent je = (JoinEvent)e; je.getChannel().addNick(je.getNick()); } /** * Called when a QuitEvent is received. * * @param e the event */ public void quit(IRCEvent e) { QuitEvent qe = (QuitEvent)e; e.getSession().removeNickFromAllChannels(qe.getNick()); } /** * Called when a PartEvent is received. * * @param e the event */ public void part(IRCEvent e) { PartEvent pe = (PartEvent)e; if(!pe.getChannel().removeNick(pe.getWho())) { log.severe("Could Not remove nick " + pe.getWho() + " from " + pe.getChannelName()); } if (pe.getWho().equalsIgnoreCase(e.getSession().getNick())) { pe.getSession().removeChannel(pe.getChannel()); } } /** * Called when a NickChangeEvent is received * * @param e the event */ public void nick(IRCEvent e) { NickChangeEvent nce = (NickChangeEvent)e; e.getSession().nickChanged(nce.getOldNick(), nce.getNewNick()); if(nce.getOldNick().equals(e.getSession().getNick())) { nce.getSession().updateProfileSuccessfully(true); } } /** * Called when a NickInUseEvent is received * * @param e the event */ public void nickInUse(IRCEvent e) { Session session = e.getSession(); if(!session.isLoggedIn() && session.getShouldUseAltNicks()) { Profile p = session.getRequestedConnection().getProfile(); NickInUseEvent niu = (NickInUseEvent)e; String usedNick = niu.getInUseNick(); String newNick = ""; if(usedNick.equals(p.getFirstNick())) { /* if first nick same as second will cause a loop*/ if(p.getFirstNick().equals(p.getSecondNick())) return; newNick = p.getSecondNick(); } else if(usedNick.equals(p.getSecondNick())) { /* if second nick same as third will cause a loop*/ if(p.getSecondNick().equals(p.getThirdNick())) return; newNick = p.getThirdNick(); } if(newNick.length() > 0) { session.changeNick(newNick); } } } /** * Called when a KickEvent is received * * @param e the event */ public void kick(IRCEvent e) { KickEvent ke = (KickEvent)e; if (!ke.getChannel().removeNick(ke.getWho())) { log.info("COULD NOT REMOVE NICK " + ke.getWho() + " from channel " + ke.getChannel().getName()); } Session session = e.getSession(); if (ke.getWho().equals(session.getNick())) { session.removeChannel(ke.getChannel()); if (session.isRejoinOnKick()) { session.join(ke.getChannel().getName()); } } } /** * Called when ConnectionComplete event is received. * * @param e the event */ public void connectionComplete(IRCEvent e) { /* sometimes the server will change the nick when connecting * for instance , if the nick is too long it will be trunckated * need to check if this happend and send a nick update event */ EventToken token = new EventToken(e.getRawEventData()); Session session = e.getSession(); String nick = token.arg(0); String profileNick = session.getNick(); if(!nick.equalsIgnoreCase(profileNick)) { Profile pi = (Profile)session.getRequestedConnection().getProfile(); pi.setActualNick(nick); NickChangeEvent nce = new NickChangeEventImpl ( token.data(), session, profileNick, nick, "", "" ); manager.addToRelayList(nce); } ConnectionCompleteEvent ccEvent = (ConnectionCompleteEvent)e; session.getConnection().setHostName(ccEvent.getActualHostName()); session.loginSuccess(); session.connected(); } /** * Called when a ModeEvent is received * * @param event */ public void mode(IRCEvent event) { ModeEvent me = (ModeEvent)event; if(me.getModeType() == ModeEvent.ModeType.CHANNEL) { // update channel modes me.getChannel().updateModes(me.getModeAdjustments()); } else { //user mode me.getSession().updateUserModes(me.getModeAdjustments()); } } private void initStratMap() { stratMap.put(CONNECT_COMPLETE, new IRCEventListener() { public void receiveEvent(IRCEvent e) { connectionComplete(e); } }); stratMap.put(JOIN_COMPLETE, new IRCEventListener() { public void receiveEvent(IRCEvent e) { joinComplete(e); } }); stratMap.put(JOIN, new IRCEventListener() { public void receiveEvent(IRCEvent e) { join(e); } }); stratMap.put(QUIT, new IRCEventListener() { public void receiveEvent(IRCEvent e) { quit(e); } }); stratMap.put(PART, new IRCEventListener() { public void receiveEvent(IRCEvent e) { part(e); } }); stratMap.put(NICK_CHANGE, new IRCEventListener() { public void receiveEvent(IRCEvent e) { nick(e); } }); stratMap.put(NICK_IN_USE, new IRCEventListener() { public void receiveEvent(IRCEvent e) { nickInUse(e); } }); stratMap.put(KICK_EVENT, new IRCEventListener() { public void receiveEvent(IRCEvent e) { kick(e); } }); stratMap.put(MODE_EVENT, new IRCEventListener() { public void receiveEvent(IRCEvent e) { mode(e); } }); } }