diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityEventDispatcher.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityEventDispatcher.java
new file mode 100644
index 000000000..10f044405
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityEventDispatcher.java
@@ -0,0 +1,235 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.sysactivity;
+
+import net.java.sip.communicator.service.sysactivity.*;
+import net.java.sip.communicator.service.sysactivity.event.*;
+import net.java.sip.communicator.util.*;
+
+import java.util.*;
+
+/**
+ * The class implements a dispatch event thread. The thread will
+ * fire event every time it is added through the fireSystemActivityEvent()
+ * method and would then deliver it to a registered listener if any.
+ * If the event has time set we used it as a delay before dispatching the event.
+ *
+ * @author Damian Minkov
+ */
+public class SystemActivityEventDispatcher
+ implements Runnable
+{
+ /**
+ * Our class logger.
+ */
+ private static Logger logger =
+ Logger.getLogger(SystemActivityEventDispatcher.class);
+
+ /**
+ * A list of listeners registered for system activity events.
+ */
+ private final List listeners =
+ new LinkedList();
+
+ /**
+ * start/stop indicator.
+ */
+ private boolean stopped = true;
+
+ /**
+ * The thread that runs this dispatcher.
+ */
+ private Thread dispatcherThread = null;
+
+ /**
+ * The events to dispatch.
+ */
+ private Map eventsToDispatch
+ = new LinkedHashMap();
+
+ /**
+ * Registers a listener that would be notified of changes that have occurred
+ * in the underlying system.
+ *
+ * @param listener the listener that we'd like to register for changes in
+ * the underlying system.
+ */
+ public void addSystemActivityChangeListener(
+ SystemActivityChangeListener listener)
+ {
+ synchronized(listeners)
+ {
+ if(!listeners.contains(listener))
+ {
+ listeners.add(listener);
+
+ if(dispatcherThread == null)
+ {
+ dispatcherThread = new Thread(this);
+ dispatcherThread.start();
+ }
+ }
+ }
+ }
+
+ /**
+ * Remove the specified listener so that it won't receive further
+ * notifications of changes that occur in the underlying system
+ *
+ * @param listener the listener to remove.
+ */
+ public void removeSystemActivityChangeListener(
+ SystemActivityChangeListener listener)
+ {
+ synchronized(listeners)
+ {
+ listeners.remove(listener);
+ }
+ }
+
+ /**
+ * Interrupts this dispatcher so that it would no longer disptach events.
+ */
+ public void stop()
+ {
+ synchronized(eventsToDispatch)
+ {
+ stopped = true;
+ eventsToDispatch.notifyAll();
+
+ dispatcherThread = null;
+ }
+ }
+
+ /**
+ * Delivers the specified event to all registered listeners.
+ *
+ * @param evt the SystemActivityEvent that we'd like delivered to
+ * all registered message listeners.
+ */
+ protected void fireSystemActivityEvent(SystemActivityEvent evt)
+ {
+ fireSystemActivityEvent(evt, 0);
+ }
+
+ /**
+ * Delivers the specified event to all registered listeners.
+ *
+ * @param evt the SystemActivityEvent that we'd like delivered to
+ * all registered message listeners.
+ * @param wait time in ms. to wait before firing the event.
+ */
+ protected void fireSystemActivityEvent(SystemActivityEvent evt, int wait)
+ {
+ synchronized(eventsToDispatch)
+ {
+ eventsToDispatch.put(evt, wait);
+
+ eventsToDispatch.notifyAll();
+
+ if(dispatcherThread == null && listeners.size() > 0)
+ {
+ dispatcherThread = new Thread(this);
+ dispatcherThread.start();
+ }
+ }
+ }
+
+ /**
+ * Delivers the specified event to the listener.
+ *
+ * @param evt the SystemActivityEvent that we'd like delivered to
+ * the listener.
+ * @param listener that will receive the event.
+ */
+ private void fireSystemActivityEvent(SystemActivityEvent evt,
+ SystemActivityChangeListener listener)
+ {
+ if (logger.isDebugEnabled())
+ logger.debug("Dispatching SystemActivityEvent Listeners="
+ + listeners.size() + " evt=" + evt);
+
+ try
+ {
+ listener.activityChanged(evt);
+ }
+ catch (Throwable e)
+ {
+ logger.error("Error delivering event", e);
+ }
+ }
+
+ /**
+ * Runs the waiting thread.
+ */
+ public void run()
+ {
+ try
+ {
+ stopped = false;
+
+ while(!stopped)
+ {
+ Map.Entry eventToProcess = null;
+ List listenersCopy;
+
+ synchronized(eventsToDispatch)
+ {
+ if(eventsToDispatch.size() == 0)
+ {
+ try {
+ eventsToDispatch.wait();
+ }
+ catch (InterruptedException iex){}
+ }
+
+ //no point in dispatching if there's no one
+ //listening
+ if (listeners.size() == 0)
+ continue;
+
+ //store the ref of the listener in case someone resets
+ //it before we've had a chance to notify it.
+ listenersCopy = new ArrayList
+ (listeners);
+
+ Iterator> iter =
+ eventsToDispatch.entrySet().iterator();
+ if(iter.hasNext())
+ {
+ eventToProcess = iter.next();
+ iter.remove();
+ }
+ }
+
+ if(eventToProcess != null && listenersCopy != null)
+ {
+ if(eventToProcess.getValue() > 0)
+ synchronized(this)
+ {
+ try{
+ wait(eventToProcess.getValue());
+ }catch(Throwable t){}
+ }
+
+ for (int i = 0; i < listenersCopy.size(); i++)
+ {
+ fireSystemActivityEvent(
+ eventToProcess.getKey(),
+ listenersCopy.get(i));
+ }
+ }
+
+ eventToProcess = null;
+ listenersCopy = null;
+ }
+ } catch(Throwable t)
+ {
+ logger.error("Error dispatching thread ended unexpectedly", t);
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java
index 705d2ea2e..f88fc9077 100644
--- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java
+++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java
@@ -30,10 +30,10 @@ public class SystemActivityNotificationsServiceImpl
SystemActivityNotificationsServiceImpl.class.getName());
/**
- * A list of listeners registered for system activity events.
+ * The thread dispatcher of network change events.
*/
- private final List activityChangeListeners =
- new LinkedList();
+ private SystemActivityEventDispatcher eventDispatcher =
+ new SystemActivityEventDispatcher();
/**
* A list of listeners registered for idle events.
@@ -130,6 +130,8 @@ public void stop()
NetworkManagerListenerImpl.getInstance().stop();
}
+ eventDispatcher.stop();
+
running = false;
synchronized(this)
@@ -148,13 +150,7 @@ public void stop()
public void addSystemActivityChangeListener(
SystemActivityChangeListener listener)
{
- synchronized (activityChangeListeners)
- {
- if (!activityChangeListeners.contains(listener))
- {
- activityChangeListeners.add(listener);
- }
- }
+ eventDispatcher.addSystemActivityChangeListener(listener);
}
/**
@@ -166,10 +162,7 @@ public void addSystemActivityChangeListener(
public void removeSystemActivityChangeListener(
SystemActivityChangeListener listener)
{
- synchronized (activityChangeListeners)
- {
- activityChangeListeners.remove(listener);
- }
+ eventDispatcher.removeSystemActivityChangeListener(listener);
}
/**
@@ -416,28 +409,15 @@ else if(idleTime != 0)
*/
protected void fireSystemActivityEvent(SystemActivityEvent evt)
{
- Collection listeners;
- synchronized (this.activityChangeListeners)
- {
- listeners = new ArrayList(
- this.activityChangeListeners);
- }
-
- if (logger.isDebugEnabled())
- logger.debug("Dispatching SystemActivityEvent Listeners="
- + listeners.size() + " evt=" + evt);
-
- for (SystemActivityChangeListener listener : listeners)
+ // give time to java to dispatch same
+ // event and populate its network interfaces
+ if(evt.getEventID() == SystemActivityEvent.EVENT_NETWORK_CHANGE
+ && OSUtils.IS_WINDOWS)
{
- try
- {
- listener.activityChanged(evt);
- }
- catch (Throwable e)
- {
- logger.error("Error delivering event", e);
- }
+ eventDispatcher.fireSystemActivityEvent(evt, 500);
}
+ else
+ eventDispatcher.fireSystemActivityEvent(evt);
}
/**