aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamian Minkov <damencho@jitsi.org>2012-06-19 14:24:22 +0000
committerDamian Minkov <damencho@jitsi.org>2012-06-19 14:24:22 +0000
commit161d186f5e7ca53b63bdb20c88101b863d9a3498 (patch)
treee083717663936d84283046881025575c7e01f40e
parent5d5788b116924f06343a68c73d70dab1579ca24c (diff)
downloadjitsi-161d186f5e7ca53b63bdb20c88101b863d9a3498.zip
jitsi-161d186f5e7ca53b63bdb20c88101b863d9a3498.tar.gz
jitsi-161d186f5e7ca53b63bdb20c88101b863d9a3498.tar.bz2
Fixes handling away status after successful reconnection.
Fixes a problem in reconnect plugin where several reconnects can happen, after several reconnection retries. Fixes reconnection after xmpp connection throws ConnectException or NoRouteToHostException.
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java9
-rw-r--r--src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java8
-rw-r--r--src/net/java/sip/communicator/plugin/generalconfig/autoaway/AutoAwayWatcher.java271
-rw-r--r--src/net/java/sip/communicator/plugin/generalconfig/generalconfig.manifest.mf1
-rw-r--r--src/net/java/sip/communicator/plugin/reconnectplugin/ReconnectPluginActivator.java18
5 files changed, 255 insertions, 52 deletions
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
index 3b2953e..f306b85 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
@@ -905,7 +905,16 @@ public class ProtocolProviderServiceJabberImpl
//socket could not be opened
if (ex.getWrappedThrowable() instanceof ConnectException
|| ex.getWrappedThrowable() instanceof NoRouteToHostException)
+ {
+ //as we got an exception not handled in connectAndLogin
+ //no state was set, so fire it here so we can continue
+ //with the re-register process
+ fireRegistrationStateChanged(getRegistrationState(),
+ RegistrationState.CONNECTION_FAILED,
+ RegistrationStateChangeEvent.REASON_SERVER_NOT_FOUND, null);
+
throw ex;
+ }
// don't attempt to append the service name if it's already there
if (!qualifiedUserID)
diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java
index 4f945fc..c3dc2f5 100644
--- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java
+++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java
@@ -369,8 +369,12 @@ public class SystemActivityNotificationsServiceImpl
}
else if(idleTime != 0)
{
- long minIdleSetting =
- Collections.min(idleChangeListeners.values());
+ long minIdleSetting = CHECK_FOR_IDLE_DEFAULT;
+
+ if(!idleChangeListeners.isEmpty())
+ minIdleSetting =
+ Collections.min(idleChangeListeners.values());
+
int newSetting = (int)(minIdleSetting - idleTime) + 1000;
if(newSetting > 0)
diff --git a/src/net/java/sip/communicator/plugin/generalconfig/autoaway/AutoAwayWatcher.java b/src/net/java/sip/communicator/plugin/generalconfig/autoaway/AutoAwayWatcher.java
index ec44875..38f6710 100644
--- a/src/net/java/sip/communicator/plugin/generalconfig/autoaway/AutoAwayWatcher.java
+++ b/src/net/java/sip/communicator/plugin/generalconfig/autoaway/AutoAwayWatcher.java
@@ -9,9 +9,11 @@ package net.java.sip.communicator.plugin.generalconfig.autoaway;
import net.java.sip.communicator.plugin.generalconfig.*;
import net.java.sip.communicator.service.configuration.*;
import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.sysactivity.*;
import net.java.sip.communicator.service.sysactivity.event.*;
import net.java.sip.communicator.util.*;
+import org.osgi.framework.*;
import java.beans.*;
import java.util.*;
@@ -21,15 +23,27 @@ import java.util.*;
* @author Damian Minkov
*/
public class AutoAwayWatcher
- implements SystemActivityChangeListener
+ implements ServiceListener,
+ RegistrationStateChangeListener
{
/**
+ * The logger.
+ */
+ private static final Logger logger
+ = Logger.getLogger(AutoAwayWatcher.class);
+
+ /**
* The states of providers before going to away.
*/
private final Map<ProtocolProviderService, PresenceStatus> lastStates
= new HashMap<ProtocolProviderService, PresenceStatus>();
/**
+ * Listens for idle events.
+ */
+ private IdleListener idleListener = null;
+
+ /**
* Creates AutoAway handler.
* @param configurationService the config service.
*/
@@ -53,35 +67,73 @@ public class AutoAwayWatcher
if(Boolean.parseBoolean((String)evt.getNewValue()))
start();
else
- stop();
+ stopInner();
}
}
);
// listens for changes in configured value.
configurationService.addPropertyChangeListener(
- Preferences.TIMER,
- new PropertyChangeListener()
+ Preferences.TIMER,
+ new PropertyChangeListener()
+ {
+ public void propertyChange(PropertyChangeEvent evt)
{
- public void propertyChange(PropertyChangeEvent evt)
- {
- stop();
- start();
- }
+ stopInner();
+ start();
}
+ }
);
+
+ // listen for new providers
+ GeneralConfigPluginActivator.bundleContext.addServiceListener(this);
+
+ // lets check current providers
+ ServiceReference[] protocolProviderRefs = null;
+ try
+ {
+ protocolProviderRefs = GeneralConfigPluginActivator.bundleContext
+ .getServiceReferences(ProtocolProviderService.class.getName(),
+ null);
+ }
+ catch (InvalidSyntaxException ex)
+ {
+ // this shouldn't happen since we're providing no parameter string
+ // but let's log just in case.
+ logger.error(
+ "Error while retrieving service refs", ex);
+ return;
+ }
+
+ // in case we found any
+ if (protocolProviderRefs != null)
+ {
+ for (int i = 0; i < protocolProviderRefs.length; i++)
+ {
+ ProtocolProviderService provider = (ProtocolProviderService)
+ GeneralConfigPluginActivator.bundleContext
+ .getService(protocolProviderRefs[i]);
+
+ this.handleProviderAdded(provider);
+ }
+ }
}
/**
* Starts and add needed listeners.
*/
- public void start()
+ private void start()
{
- getSystemActivityNotificationsService()
- .addIdleSystemChangeListener(
- StatusUpdateThread.getTimer()*60*1000, this);
- getSystemActivityNotificationsService()
- .addSystemActivityChangeListener(this);
+ if(idleListener == null)
+ {
+ idleListener = new IdleListener();
+
+ getSystemActivityNotificationsService()
+ .addIdleSystemChangeListener(
+ StatusUpdateThread.getTimer()*60*1000, idleListener);
+ getSystemActivityNotificationsService()
+ .addSystemActivityChangeListener(idleListener);
+ }
}
/**
@@ -89,34 +141,23 @@ public class AutoAwayWatcher
*/
public void stop()
{
- getSystemActivityNotificationsService()
- .removeIdleSystemChangeListener(this);
- getSystemActivityNotificationsService()
- .removeSystemActivityChangeListener(this);
+ GeneralConfigPluginActivator.bundleContext.removeServiceListener(this);
+ stopInner();
}
/**
- * Listens for activities and set corresponding statuses.
- *
- * @param event the <tt>NotificationActionTypeEvent</tt>, which is
+ * Stops and removes the listeners, without the global service listener.
*/
- public void activityChanged(SystemActivityEvent event)
+ private void stopInner()
{
- switch(event.getEventID())
- {
- case SystemActivityEvent.EVENT_DISPLAY_SLEEP:
- case SystemActivityEvent.EVENT_SCREEN_LOCKED:
- case SystemActivityEvent.EVENT_SCREENSAVER_START:
- case SystemActivityEvent.EVENT_SYSTEM_IDLE:
- changeProtocolsToAway();
- break;
- case SystemActivityEvent.EVENT_DISPLAY_WAKE:
- case SystemActivityEvent.EVENT_SCREEN_UNLOCKED:
- case SystemActivityEvent.EVENT_SCREENSAVER_STOP:
- case SystemActivityEvent.EVENT_SYSTEM_IDLE_END:
- changeProtocolsToPreviousState();
- break;
- }
+ if(idleListener == null)
+ return;
+
+ getSystemActivityNotificationsService()
+ .removeIdleSystemChangeListener(idleListener);
+ getSystemActivityNotificationsService()
+ .removeSystemActivityChangeListener(idleListener);
+ idleListener = null;
}
/**
@@ -126,7 +167,7 @@ public class AutoAwayWatcher
private void changeProtocolsToAway()
{
for (ProtocolProviderService protocolProviderService
- : GeneralConfigPluginActivator.getProtocolProviders())
+ : GeneralConfigPluginActivator.getProtocolProviders())
{
OperationSetPresence presence
= protocolProviderService
@@ -143,7 +184,7 @@ public class AutoAwayWatcher
continue;
}
- lastStates.put(protocolProviderService, status);
+ addProviderToLastStates(protocolProviderService, status);
PresenceStatus newStatus =
StatusUpdateThread.findAwayStatus(presence);
@@ -173,14 +214,15 @@ public class AutoAwayWatcher
for (ProtocolProviderService protocolProviderService
: GeneralConfigPluginActivator.getProtocolProviders())
{
- if (lastStates.get(protocolProviderService) != null)
+ PresenceStatus lastState
+ = lastStates.get(protocolProviderService);
+
+ if (lastState != null)
{
- PresenceStatus lastState
- = lastStates.get(protocolProviderService);
OperationSetPresence presence
= protocolProviderService
.getOperationSet(
- OperationSetPresence.class);
+ OperationSetPresence.class);
try
{
presence
@@ -192,7 +234,7 @@ public class AutoAwayWatcher
} catch (OperationFailedException e)
{
}
- lastStates.remove(protocolProviderService);
+ removeProviderFromLastStates(protocolProviderService);
}
}
}
@@ -208,4 +250,143 @@ public class AutoAwayWatcher
GeneralConfigPluginActivator.bundleContext,
SystemActivityNotificationsService.class);
}
+
+ /**
+ * When new protocol provider is registered we add our
+ * registration change listener.
+ * If unregistered remove reference to the provider and the
+ * registration change listener.
+ *
+ * @param serviceEvent ServiceEvent
+ */
+ public void serviceChanged(ServiceEvent serviceEvent)
+ {
+ Object sService = GeneralConfigPluginActivator.bundleContext
+ .getService(serviceEvent.getServiceReference());
+
+ // we don't care if the source service is not a protocol provider
+ if (! (sService instanceof ProtocolProviderService))
+ {
+ return;
+ }
+
+ if (serviceEvent.getType() == ServiceEvent.REGISTERED)
+ {
+ this.handleProviderAdded((ProtocolProviderService)sService);
+ }
+ else if (serviceEvent.getType() == ServiceEvent.UNREGISTERING)
+ {
+ this.handleProviderRemoved( (ProtocolProviderService) sService);
+ }
+ }
+
+ /**
+ * Used to set registration state change listener.
+ *
+ * @param provider ProtocolProviderService
+ */
+ private synchronized void handleProviderAdded(
+ ProtocolProviderService provider)
+ {
+ provider.addRegistrationStateChangeListener(this);
+ }
+
+ /**
+ * Removes the registration change listener.
+ *
+ * @param provider the ProtocolProviderService that has been unregistered.
+ */
+ private void handleProviderRemoved(ProtocolProviderService provider)
+ {
+ provider.removeRegistrationStateChangeListener(this);
+ }
+
+ /**
+ * Remove provider from list with last statuses.
+ * If this is the last provider stop listening for idle events.
+ * @param provider
+ */
+ private synchronized void removeProviderFromLastStates(
+ ProtocolProviderService provider)
+ {
+ lastStates.remove(provider);
+
+ if(lastStates.size() == 0)
+ {
+ stopInner();
+ }
+ }
+
+ /**
+ * Remember provider's last status, normally before setting it to away.
+ * If needed start listening for idle events.
+ * @param provider the provider.
+ * @param status the status to save.
+ */
+ private synchronized void addProviderToLastStates(
+ ProtocolProviderService provider, PresenceStatus status)
+ {
+ if(lastStates.size() == 0)
+ {
+ start();
+ }
+
+ lastStates.put(provider, status);
+ }
+
+ /**
+ * Listens for provider states.
+ * @param evt
+ */
+ public void registrationStateChanged(RegistrationStateChangeEvent evt)
+ {
+ if(evt.getSource() instanceof ProtocolProviderService)
+ {
+ if(evt.getNewState().equals(RegistrationState.UNREGISTERED)
+ || evt.getNewState().equals(RegistrationState.CONNECTION_FAILED))
+ {
+ removeProviderFromLastStates(evt.getProvider());
+ }
+ else if(evt.getNewState().equals(
+ RegistrationState.REGISTERED))
+ {
+ // we have at least one provider, so lets start listening
+ if(lastStates.size() == 0)
+ {
+ start();
+ }
+ }
+ }
+ }
+
+ /**
+ * Listener waiting for idle state change.
+ */
+ private class IdleListener
+ implements SystemActivityChangeListener
+ {
+ /**
+ * Listens for activities and set corresponding statuses.
+ *
+ * @param event the <tt>NotificationActionTypeEvent</tt>, which is
+ */
+ public void activityChanged(SystemActivityEvent event)
+ {
+ switch(event.getEventID())
+ {
+ case SystemActivityEvent.EVENT_DISPLAY_SLEEP:
+ case SystemActivityEvent.EVENT_SCREEN_LOCKED:
+ case SystemActivityEvent.EVENT_SCREENSAVER_START:
+ case SystemActivityEvent.EVENT_SYSTEM_IDLE:
+ changeProtocolsToAway();
+ break;
+ case SystemActivityEvent.EVENT_DISPLAY_WAKE:
+ case SystemActivityEvent.EVENT_SCREEN_UNLOCKED:
+ case SystemActivityEvent.EVENT_SCREENSAVER_STOP:
+ case SystemActivityEvent.EVENT_SYSTEM_IDLE_END:
+ changeProtocolsToPreviousState();
+ break;
+ }
+ }
+ }
}
diff --git a/src/net/java/sip/communicator/plugin/generalconfig/generalconfig.manifest.mf b/src/net/java/sip/communicator/plugin/generalconfig/generalconfig.manifest.mf
index 91d7c24..e5741a7 100644
--- a/src/net/java/sip/communicator/plugin/generalconfig/generalconfig.manifest.mf
+++ b/src/net/java/sip/communicator/plugin/generalconfig/generalconfig.manifest.mf
@@ -9,6 +9,7 @@ Import-Package: org.osgi.framework,
net.java.sip.communicator.service.contactlist,
net.java.sip.communicator.service.contactlist.event,
net.java.sip.communicator.service.protocol,
+ net.java.sip.communicator.service.protocol.event,
net.java.sip.communicator.service.gui,
net.java.sip.communicator.service.gui.event,
net.java.sip.communicator.service.resources,
diff --git a/src/net/java/sip/communicator/plugin/reconnectplugin/ReconnectPluginActivator.java b/src/net/java/sip/communicator/plugin/reconnectplugin/ReconnectPluginActivator.java
index a4ee972..3fa83c1 100644
--- a/src/net/java/sip/communicator/plugin/reconnectplugin/ReconnectPluginActivator.java
+++ b/src/net/java/sip/communicator/plugin/reconnectplugin/ReconnectPluginActivator.java
@@ -553,13 +553,17 @@ public class ReconnectPluginActivator
if(timer == null || task == null)
return;
- currentlyReconnecting.put(pp, task);
+ // cancel any existing task before overriding it
+ if(currentlyReconnecting.containsKey(pp))
+ currentlyReconnecting.remove(pp).cancel();
- if (logger.isTraceEnabled())
- logger.trace("Reconnect " + pp +
- " after " + task.delay + " ms.");
+ currentlyReconnecting.put(pp, task);
- timer.schedule(task, task.delay);
+ if (logger.isTraceEnabled())
+ logger.trace("Reconnect " + pp +
+ " after " + task.delay + " ms.");
+
+ timer.schedule(task, task.delay);
}
return;
}
@@ -801,6 +805,10 @@ public class ReconnectPluginActivator
return;
}
+ // cancel any existing task before overriding it
+ if(currentlyReconnecting.containsKey(pp))
+ currentlyReconnecting.remove(pp).cancel();
+
currentlyReconnecting.put(pp, task);
if (logger.isTraceEnabled())