package er.imadaptor; public class IMConnectionTester implements Runnable, IMessageListener { private static final String PING_MESSAGE = "~Ping~"; private static final String PONG_MESSAGE = "~Pong~"; private IInstantMessenger _watcher; private IInstantMessenger _watched; private Object _pingPongMessageLock; private int _failureCount; private boolean _pinged; private boolean _ponged; private long _pingPongFrequencyMillis; private long _timeoutMillis; private long _lastConnectionAttempt; private boolean _running; public IMConnectionTester(IInstantMessenger watcher, IInstantMessenger watched, long pingPongFrequencyMillis, long timeoutMillis) { _running = true; _pingPongMessageLock = new Object(); _watcher = watcher; _watched = watched; _pingPongFrequencyMillis = pingPongFrequencyMillis; _timeoutMillis = timeoutMillis; synchronized (_pingPongMessageLock) { _watched.addMessageListener(this); _watcher.addMessageListener(this); } } public void stop() { _running = false; } public void messageReceived(IInstantMessenger instantMessenger, String buddyName, String message) { System.out.println("IMConnectionTester.messageReceived: " + buddyName + ", " + message); if (instantMessenger == _watched && _watcher.getScreenName().equals(buddyName) && IMConnectionTester.PING_MESSAGE.equals(message)) { synchronized (_pingPongMessageLock) { try { System.out.println("IMConnectionTester.testConnection: Sending PONG to " + _watcher.getScreenName()); _watched.sendMessage(buddyName, IMConnectionTester.PONG_MESSAGE, false); } catch (MessageException e) { // We failed to pong! e.printStackTrace(); } } } else if (instantMessenger == _watcher && _watched.getScreenName().equals(buddyName) && IMConnectionTester.PONG_MESSAGE.equals(message)) { synchronized (_pingPongMessageLock) { _ponged = true; System.out.println("IMConnectionTester.testConnection: Recevied PONG from " + _watched.getScreenName()); _pingPongMessageLock.notifyAll(); } } } protected void testConnection() throws IMConnectionException { if (_running && !_watched.isConnected()) { _watched.connect(); _failureCount = 0; } if (_running && !_watcher.isConnected()) { _watcher.connect(); _failureCount = 0; } synchronized (_pingPongMessageLock) { try { System.out.println("IMConnectionTester.testConnection: Sending PING to " + _watched.getScreenName()); _watcher.sendMessage(_watched.getScreenName(), IMConnectionTester.PING_MESSAGE, false); _ponged = false; _pingPongMessageLock.wait(_timeoutMillis); if (!_ponged) { System.out.println("IMConnectionTester.testConnection: " + _watcher.getScreenName() + " did not respond to PING"); _failureCount++; if (_running && _failureCount > 5) { System.out.println("IMConnectionTester.reconnect: Reconnecting " + _watched.getScreenName()); _watched.connect(); _failureCount = 0; } } } catch (MessageException e) { e.printStackTrace(); } catch (InterruptedException e) { // ignore } finally { _pinged = false; _ponged = false; } } } public void run() { while (_running) { try { Thread.sleep(_pingPongFrequencyMillis); } catch (InterruptedException e) { // who cares } if (_running) { // System.out.println("IMConnectionTester.run: Testing " + myWatched.getScreenName()); try { testConnection(); } catch (Throwable t) { t.printStackTrace(); } } } } }