/* * Copyright 2006-2010 Daniel Henninger. All rights reserved. * * This software is published under the terms of the GNU Public License (GPL), * a copy of which is included in this distribution. */ package net.sf.kraken.protocols.oscar; import java.lang.ref.WeakReference; import java.util.Timer; import java.util.TimerTask; import net.kano.joscar.flap.ClientFlapConn; import net.kano.joscar.flap.FlapPacketEvent; import net.kano.joscar.flap.FlapPacketListener; import net.kano.joscar.flapcmd.DefaultFlapCmdFactory; import net.kano.joscar.flapcmd.KeepaliveFlapCmd; import net.kano.joscar.flapcmd.SnacCommand; import net.kano.joscar.net.ClientConnEvent; import net.kano.joscar.net.ClientConnListener; import net.kano.joscar.net.ConnDescriptor; import net.kano.joscar.net.ConnProcessorExceptionEvent; import net.kano.joscar.net.ConnProcessorExceptionHandler; import net.kano.joscar.snac.ClientSnacProcessor; import net.kano.joscar.snac.FamilyVersionPreprocessor; import net.kano.joscar.snac.SnacPacketEvent; import net.kano.joscar.snac.SnacPacketListener; import net.kano.joscar.snac.SnacRequest; import net.kano.joscar.snac.SnacRequestAdapter; import net.kano.joscar.snac.SnacRequestListener; import net.kano.joscar.snac.SnacResponseEvent; import net.kano.joscar.snaccmd.DefaultClientFactoryList; import org.apache.log4j.Logger; /** * Base class for all FLAP handlers. * * @author Daniel Henninger * Heavily inspired by joscardemo from the joscar project. */ public abstract class AbstractFlapConnection extends ClientFlapConn { static Logger Log = Logger.getLogger(AbstractFlapConnection.class); /** * Timer to send keep alive messages. */ public Timer timer = new Timer(); /** * Interval at which keepalive is sent. */ private int timerInterval = 180000; // 3 minutes /** * Status checker. */ KeepAliveSender keepAliveSender; private class KeepAliveSender extends TimerTask { /** * Send keepalive to OSCAR. */ @Override public void run() { try { getFlapProcessor().sendFlap(new KeepaliveFlapCmd()); } catch (Exception e) { // Probably in the middle of a shutdown. } } } public void startKeepAlive() { if (keepAliveSender == null) { keepAliveSender = new KeepAliveSender(); timer.schedule(keepAliveSender, timerInterval, timerInterval); } } public void stopKeepAlive() { if (timer != null) { try { timer.cancel(); } catch (Exception e) { // Ok then. } timer = null; } if (keepAliveSender != null) { try { keepAliveSender.cancel(); } catch (Exception e) { // Ok then } keepAliveSender = null; } } protected ClientSnacProcessor sp = new ClientSnacProcessor(getFlapProcessor()); WeakReference<OSCARSession> oscarSessionRef; public AbstractFlapConnection(ConnDescriptor cd, OSCARSession mainSession) { super(cd); // Hand off to ClientFlapConn initBaseFlapConnection(); oscarSessionRef = new WeakReference<OSCARSession>(mainSession); } private void initBaseFlapConnection() { getFlapProcessor().setFlapCmdFactory(new DefaultFlapCmdFactory()); sp.addPreprocessor(new FamilyVersionPreprocessor()); sp.getCmdFactoryMgr().setDefaultFactoryList(new DefaultClientFactoryList()); addConnListener(new ClientConnListener() { public void stateChanged(ClientConnEvent e) { handleStateChange(e); } }); getFlapProcessor().addPacketListener(new FlapPacketListener() { public void handleFlapPacket(FlapPacketEvent e) { AbstractFlapConnection.this.handleFlapPacket(e); } }); getFlapProcessor().addExceptionHandler(new ConnProcessorExceptionHandler() { public void handleException(ConnProcessorExceptionEvent event) { Log.debug(event.getType() + " FLAP ERROR: " + event.getException().getMessage() + " " + event.getReason(), event.getException()); } }); sp.addPacketListener(new SnacPacketListener() { public void handleSnacPacket(SnacPacketEvent e) { AbstractFlapConnection.this.handleSnacPacket(e); } }); } protected SnacRequestListener genericReqListener = new SnacRequestAdapter() { @Override public void handleResponse(SnacResponseEvent e) { handleSnacResponse(e); } }; public SnacRequestListener getGenericReqListener() { return genericReqListener; } public ClientSnacProcessor getSnacProcessor() { return sp; } public OSCARSession getMainSession() { return oscarSessionRef.get(); } void sendRequest(SnacRequest req) { Log.debug("Sending SNAC request: "+req); if (!req.hasListeners()) req.addListener(genericReqListener); sp.sendSnac(req); } SnacRequest request(SnacCommand cmd) { Log.debug("Sending SNAC command: "+cmd); return request(cmd, null); } SnacRequest request(SnacCommand cmd, SnacRequestListener listener) { Log.debug("Setting up SNAC request and listener: "+cmd+","+listener); SnacRequest req = new SnacRequest(cmd, listener); sendRequest(req); return req; } protected abstract void handleStateChange(ClientConnEvent e); protected abstract void handleFlapPacket(FlapPacketEvent e); protected abstract void handleSnacPacket(SnacPacketEvent e); protected abstract void handleSnacResponse(SnacResponseEvent e); }