All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jivesoftware.smack.ReconnectionManager Maven / Gradle / Ivy

The newest version!
/**
 *
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jivesoftware.smack;

import java.util.Random;

import org.apache.log4j.Logger;
import org.jivesoftware.smack.packet.StreamError;

/**
 * Handles the automatic reconnection process. Every time a connection is
 * dropped without the application explictly closing it, the manager
 * automatically tries to reconnect to the server.
 * 

* * The reconnection mechanism will try to reconnect periodically: *

    *
  1. For the first minute it will attempt to connect once every ten seconds. *
  2. For the next five minutes it will attempt to connect once a minute. *
  3. If that fails it will indefinitely try to connect once every five * minutes. *
* * @author Francisco Vives */ public class ReconnectionManager implements ConnectionListener { private static Logger log = Logger.getLogger(ReconnectionManager.class .getName()); // Holds the connection to the server private Connection connection; private Thread reconnectionThread; private int randomBase = new Random().nextInt(11) + 5; // between 5 and 15 // seconds // Holds the state of the reconnection boolean done = false; static { // Create a new PrivacyListManager on every established connection. In // the init() // method of PrivacyListManager, we'll add a listener that will delete // the // instance when the connection is closed. Connection .addConnectionCreationListener(new ConnectionCreationListener() { public void connectionCreated(Connection connection) { connection .addConnectionListener(new ReconnectionManager( connection)); } }); } private ReconnectionManager(Connection connection) { this.connection = connection; } /** * Returns true if the reconnection mechanism is enabled. * * @return true if automatic reconnections are allowed. */ private boolean isReconnectionAllowed() { return !done && !connection.isConnected() && connection.isReconnectionAllowed(); } /** * Starts a reconnection mechanism if it was configured to do that. The * algorithm is been executed when the first connection error is detected. *

* The reconnection mechanism will try to reconnect periodically in this * way: *

    *
  1. First it will try 6 times every 10 seconds. *
  2. Then it will try 10 times every 1 minute. *
  3. Finally it will try indefinitely every 5 minutes. *
*/ synchronized protected void reconnect() { if (this.isReconnectionAllowed()) { // Since there is no thread running, creates a new one to attempt // the reconnection. // avoid to run duplicated reconnectionThread -- fd: 16/09/2010 if (reconnectionThread != null && reconnectionThread.isAlive()) return; reconnectionThread = new Thread() { /** * Holds the current number of reconnection attempts */ private int attempts = 0; /** * Returns the number of seconds until the next reconnection * attempt. * * @return the number of seconds until the next reconnection * attempt. */ private int timeDelay() { attempts++; if (attempts > 13) { return randomBase * 6 * 5; // between 2.5 and 7.5 // minutes (~5 minutes) } if (attempts > 7) { return randomBase * 6; // between 30 and 90 seconds (~1 // minutes) } return randomBase; // 10 seconds } /** * The process will try the reconnection until the connection * succeed or the user cancell it */ public void run() { // The process will try to reconnect until the connection is // established or // the user cancel the reconnection process {@link // Connection#disconnect()} while (ReconnectionManager.this.isReconnectionAllowed()) { // Find how much time we should wait until the next // reconnection int remainingSeconds = timeDelay(); // Sleep until we're ready for the next reconnection // attempt. Notify // listeners once per second about how much time remains // before the next // reconnection attempt. while (ReconnectionManager.this.isReconnectionAllowed() && remainingSeconds > 0) { try { Thread.sleep(1000); remainingSeconds--; ReconnectionManager.this .notifyAttemptToReconnectIn(remainingSeconds); } catch (InterruptedException e1) { log.warn("Sleeping thread interrupted"); // Notify the reconnection has failed ReconnectionManager.this .notifyReconnectionFailed(e1); } } // Makes a reconnection attempt try { if (ReconnectionManager.this .isReconnectionAllowed()) { connection.connect(); } } catch (XMPPException e) { // Fires the failed reconnection notification ReconnectionManager.this .notifyReconnectionFailed(e); } } } }; reconnectionThread.setName("Smack Reconnection Manager"); reconnectionThread.setDaemon(true); reconnectionThread.start(); } } /** * Fires listeners when a reconnection attempt has failed. * * @param exception * the exception that occured. */ protected void notifyReconnectionFailed(Exception exception) { if (isReconnectionAllowed()) { for (ConnectionListener listener : connection.connectionListeners) { listener.reconnectionFailed(exception); } } } /** * Fires listeners when The Connection will retry a reconnection. Expressed * in seconds. * * @param seconds * the number of seconds that a reconnection will be attempted * in. */ protected void notifyAttemptToReconnectIn(int seconds) { if (isReconnectionAllowed()) { for (ConnectionListener listener : connection.connectionListeners) { listener.reconnectingIn(seconds); } } } public void connectionClosed() { done = true; } public void connectionClosedOnError(Exception e) { done = false; if (e instanceof XMPPException) { XMPPException xmppEx = (XMPPException) e; StreamError error = xmppEx.getStreamError(); // Make sure the error is not null if (error != null) { String reason = error.getCode(); if ("conflict".equals(reason)) { return; } } } if (this.isReconnectionAllowed()) { this.reconnect(); } } public void reconnectingIn(int seconds) { // ignore } public void reconnectionFailed(Exception e) { // ignore } /** * The connection has successfull gotten connected. */ public void reconnectionSuccessful() { // ignore } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy