
org.jivesoftware.smack.ReconnectionManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jamppa Show documentation
Show all versions of jamppa Show documentation
jamppa is a XMPP client/component library
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:
*
* - For the first minute it will attempt to connect once every ten seconds.
*
- For the next five minutes it will attempt to connect once a minute.
*
- 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:
*
* - First it will try 6 times every 10 seconds.
*
- Then it will try 10 times every 1 minute.
*
- 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