diff options
author | Michael Valenta | 2003-10-03 14:40:01 +0000 |
---|---|---|
committer | Michael Valenta | 2003-10-03 14:40:01 +0000 |
commit | 0c99eae780ae585149301a910919c41ed1bd7658 (patch) | |
tree | 122bddd428f9cd89c5f4cd31b137408198010130 | |
parent | cc798d822d1dea89fd843f10d68d630c200a523c (diff) | |
download | eclipse.platform.team-0c99eae780ae585149301a910919c41ed1bd7658.tar.gz eclipse.platform.team-0c99eae780ae585149301a910919c41ed1bd7658.tar.xz eclipse.platform.team-0c99eae780ae585149301a910919c41ed1bd7658.zip |
43249: [Team] JobStatusHandler and listeners
4 files changed, 103 insertions, 32 deletions
diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/TeamSubscriber.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/TeamSubscriber.java index 44cc90f2c..9d9387813 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/TeamSubscriber.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/core/subscribers/TeamSubscriber.java @@ -11,7 +11,6 @@ package org.eclipse.team.core.subscribers; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IResource; @@ -19,7 +18,7 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.sync.IRemoteResource; -import org.eclipse.team.internal.core.*; +import org.eclipse.team.internal.core.SubscriberManager; /** * A TeamSubscriber provides synchronization between local resources and a remote location @@ -240,8 +239,10 @@ abstract public class TeamSubscriber { * @param listener a team resource change listener */ public void addListener(ITeamResourceChangeListener listener) { - if(! listeners.contains(listener)) { - listeners.add(listener); + synchronized (listeners) { + if(! listeners.contains(listener)) { + listeners.add(listener); + } } } @@ -252,18 +253,24 @@ abstract public class TeamSubscriber { * @param listener a team resource change listener */ public void removeListener(ITeamResourceChangeListener listener) { - listeners.remove(listener); + synchronized (listeners) { + listeners.remove(listener); + } } /** * Fires a team resource change event to all registered listeners * Only listeners registered at the time this method is called are notified. + * Listener notification makes use of an ISafeRunnable to ensure that + * client exceptions do not effect the notification to other clients. */ protected void fireTeamResourceChange(final TeamDelta[] deltas) { - for (Iterator it = listeners.iterator(); it.hasNext();) { - final ITeamResourceChangeListener l = (ITeamResourceChangeListener) it.next(); - l.teamResourceChanged(deltas); + ITeamResourceChangeListener[] allListeners; + // Copy the listener list so we're not calling client code while synchronized + synchronized(listeners) { + allListeners = (ITeamResourceChangeListener[]) listeners.toArray(new ITeamResourceChangeListener[listeners.size()]); } + ((SubscriberManager)getSubscriberManager()).fireTeamResourceChange(allListeners, deltas); } /** diff --git a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/SubscriberManager.java b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/SubscriberManager.java index bd0f525e8..af9d95baa 100644 --- a/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/SubscriberManager.java +++ b/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/SubscriberManager.java @@ -23,7 +23,9 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.subscribers.ISubscriberManager; @@ -160,19 +162,31 @@ public class SubscriberManager implements ISubscriberManager, ISaveParticipant { * Fires a team resource change event to all registered listeners * Only listeners registered at the time this method is called are notified. */ - void fireTeamResourceChange(final TeamDelta[] deltas) { + protected void fireTeamResourceChange(TeamDelta[] deltas) { ITeamResourceChangeListener[] allListeners; // Copy the listener list so we're not calling client code while synchronized synchronized(listeners) { allListeners = (ITeamResourceChangeListener[]) listeners.toArray(new ITeamResourceChangeListener[listeners.size()]); } - // Fire the events - for (int i = 0; i < allListeners.length; i++) { - ITeamResourceChangeListener listener = allListeners[i]; - listener.teamResourceChanged(deltas); - } + fireTeamResourceChange(allListeners, deltas); } + public void fireTeamResourceChange(ITeamResourceChangeListener[] listeners, final TeamDelta[] deltas) { + // Notify the listeners safely so all will receive notification + for (int i = 0; i < listeners.length; i++) { + final ITeamResourceChangeListener listener = listeners[i]; + Platform.run(new ISafeRunnable() { + public void handleException(Throwable exception) { + // don't log the exception....it is already being logged in Platform#run + } + public void run() throws Exception { + listener.teamResourceChanged(deltas); + + } + }); + } + } + synchronized void restoreSubscribers() { try { SaveContext root = SaveContextXMLWriter.readXMLPluginMetaFile(TeamPlugin.getPlugin(), "subscribers"); //$NON-NLS-1$ diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/jobs/JobStatusHandler.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/jobs/JobStatusHandler.java index 6803c05fc..1216e0022 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/jobs/JobStatusHandler.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/jobs/JobStatusHandler.java @@ -17,6 +17,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; @@ -35,6 +37,30 @@ public class JobStatusHandler extends JobChangeAdapter { private Set jobs = new HashSet(); private List listeners = new ArrayList(); + /* + * Private class used to safely notify listeners of job type starts and + * finishes. Subclass override the notify(IJobListener) method to + * fire specific events inside an ISafeRunnable. + */ + private abstract class Notification implements ISafeRunnable { + private IJobListener listener; + public void handleException(Throwable exception) { + // don't log the exception....it is already being logged in Platform#run + } + public void run(IJobListener listener) { + this.listener = listener; + Platform.run(this); + } + public void run() throws Exception { + notify(listener); + } + /** + * Subsclasses overide this method to send an event safely to a lsistener + * @param listener + */ + protected abstract void notify(IJobListener listener); + } + /** * Associate the job with the given jobType and schedule the job for * immediate start. @@ -146,10 +172,17 @@ public class JobStatusHandler extends JobChangeAdapter { listeners.remove(listener); } } - - private IJobListener[] getJobListeners() { + + private void fireNotification(Notification notification) { + // Get a snapshot of the listeners so the list doesn't change while we're firing + IJobListener[] listenerArray; synchronized (listeners) { - return (IJobListener[]) listeners.toArray(new IJobListener[listeners.size()]); + listenerArray = (IJobListener[]) listeners.toArray(new IJobListener[listeners.size()]); + } + // Notify each listener in a safe manner (i.e. so their exceptions don't kill us) + for (int i = 0; i < listenerArray.length; i++) { + IJobListener listener = listenerArray[i]; + notification.run(listener); } } @@ -182,11 +215,11 @@ public class JobStatusHandler extends JobChangeAdapter { } private void fireStartNotification() { - IJobListener[] listenerArray = getJobListeners(); - for (int i = 0; i < listenerArray.length; i++) { - IJobListener listener = listenerArray[i]; - listener.started(jobType); - } + fireNotification(new Notification() { + public void notify(IJobListener listener) { + listener.started(getJobType()); + } + }); } private void jobDone(Job job) { @@ -197,11 +230,11 @@ public class JobStatusHandler extends JobChangeAdapter { } private void fireEndNotification() { - IJobListener[] listenerArray = getJobListeners(); - for (int i = 0; i < listenerArray.length; i++) { - IJobListener listener = listenerArray[i]; - listener.finished(jobType); - } + fireNotification(new Notification() { + public void notify(IJobListener listener) { + listener.finished(getJobType()); + } + }); } public boolean hasRunningJobs() { @@ -214,4 +247,11 @@ public class JobStatusHandler extends JobChangeAdapter { private boolean isEmpty() { return listeners.isEmpty() && jobs.isEmpty(); } + /** + * @return Returns the jobType. + */ + public QualifiedName getJobType() { + return jobType; + } + } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncSet.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncSet.java index 1dec633f4..e65080b1f 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncSet.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncSet.java @@ -23,8 +23,10 @@ import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; import org.eclipse.team.core.subscribers.SyncInfo; import org.eclipse.team.internal.ui.TeamUIPlugin; @@ -58,7 +60,7 @@ public class SyncSet { private void fireChanges() { // Use a synchronized block to ensure that the event we send is static - SyncSetChangedEvent event; + final SyncSetChangedEvent event; synchronized(this) { event = changes; resetChanges(); @@ -70,10 +72,18 @@ public class SyncSet { synchronized(listeners) { allListeners = (ISyncSetChangedListener[]) listeners.toArray(new ISyncSetChangedListener[listeners.size()]); } - // Fire the events + // Fire the events using an ISafeRunnable for (int i = 0; i < allListeners.length; i++) { - ISyncSetChangedListener listener = allListeners[i]; - listener.syncSetChanged(event); + final ISyncSetChangedListener listener = allListeners[i]; + Platform.run(new ISafeRunnable() { + public void handleException(Throwable exception) { + // don't log the exception....it is already being logged in Platform#run + } + public void run() throws Exception { + listener.syncSetChanged(event); + + } + }); } } @@ -243,7 +253,7 @@ public class SyncSet { } else { return new SyncInfo[] { info }; } - }; + } IContainer container = (IContainer)resource; IPath path = container.getFullPath(); Set children = (Set)parents.get(path); |