KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > core > subscribers > SubscriberChangeSetManager


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.team.internal.core.subscribers;
12
13 import java.util.*;
14
15 import org.eclipse.core.resources.IResource;
16 import org.eclipse.core.runtime.*;
17 import org.eclipse.core.runtime.jobs.Job;
18 import org.eclipse.core.runtime.preferences.InstanceScope;
19 import org.eclipse.osgi.util.NLS;
20 import org.eclipse.team.core.TeamException;
21 import org.eclipse.team.core.diff.IDiff;
22 import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
23 import org.eclipse.team.core.subscribers.Subscriber;
24 import org.eclipse.team.internal.core.*;
25 import org.osgi.service.prefs.Preferences;
26
27 /**
28  * This class manages the active change sets associated with a subscriber.
29  */

30 public class SubscriberChangeSetManager extends ActiveChangeSetManager {
31     
32     private static final String JavaDoc PREF_CHANGE_SETS = "changeSets"; //$NON-NLS-1$
33

34     private static final int RESOURCE_REMOVAL = 1;
35     private static final int RESOURCE_CHANGE = 2;
36     
37     private EventHandler handler;
38     private ResourceCollector collector;
39     
40     /*
41      * Background event handler for serializing and batching change set changes
42      */

43     private class EventHandler extends BackgroundEventHandler {
44
45         private List dispatchEvents = new ArrayList();
46         
47         protected EventHandler(String JavaDoc jobName, String JavaDoc errorTitle) {
48             super(jobName, errorTitle);
49         }
50
51         /* (non-Javadoc)
52          * @see org.eclipse.team.internal.core.BackgroundEventHandler#processEvent(org.eclipse.team.internal.core.BackgroundEventHandler.Event, org.eclipse.core.runtime.IProgressMonitor)
53          */

54         protected void processEvent(Event event, IProgressMonitor monitor) throws CoreException {
55             // Handle everything in the dispatch
56
if (isShutdown())
57                 throw new OperationCanceledException();
58             dispatchEvents.add(event);
59         }
60         
61         /* (non-Javadoc)
62          * @see org.eclipse.team.internal.core.BackgroundEventHandler#doDispatchEvents(org.eclipse.core.runtime.IProgressMonitor)
63          */

64         protected boolean doDispatchEvents(IProgressMonitor monitor) throws TeamException {
65             if (dispatchEvents.isEmpty()) {
66                 return false;
67             }
68             if (isShutdown())
69                 throw new OperationCanceledException();
70             ResourceDiffTree[] locked = null;
71             try {
72                 locked = beginDispath();
73                 for (Iterator iter = dispatchEvents.iterator(); iter.hasNext();) {
74                     Event event = (Event) iter.next();
75                     switch (event.getType()) {
76                     case RESOURCE_REMOVAL:
77                         handleRemove(event.getResource());
78                         break;
79                     case RESOURCE_CHANGE:
80                         handleChange(event.getResource(), ((ResourceEvent)event).getDepth());
81                         break;
82                     default:
83                         break;
84                     }
85                     if (isShutdown())
86                         throw new OperationCanceledException();
87                 }
88             } catch (CoreException e) {
89                 throw TeamException.asTeamException(e);
90             } finally {
91                 try {
92                     endDispatch(locked, monitor);
93                 } finally {
94                     dispatchEvents.clear();
95                 }
96             }
97             return true;
98         }
99
100         /*
101          * Begin input on all the sets and return the sync sets that were
102          * locked. If this method throws an exception then the client
103          * can assume that no sets were locked
104          */

105         private ResourceDiffTree[] beginDispath() {
106             ChangeSet[] sets = getSets();
107             List lockedSets = new ArrayList();
108             try {
109                 for (int i = 0; i < sets.length; i++) {
110                     ActiveChangeSet set = (ActiveChangeSet)sets[i];
111                     ResourceDiffTree tree = set.internalGetDiffTree();
112                     lockedSets.add(tree);
113                     tree.beginInput();
114                 }
115                 return (ResourceDiffTree[]) lockedSets.toArray(new ResourceDiffTree[lockedSets.size()]);
116             } catch (RuntimeException JavaDoc e) {
117                 try {
118                     for (Iterator iter = lockedSets.iterator(); iter.hasNext();) {
119                         ResourceDiffTree tree = (ResourceDiffTree) iter.next();
120                         try {
121                             tree.endInput(null);
122                         } catch (Throwable JavaDoc e1) {
123                             // Ignore so that original exception is not masked
124
}
125                     }
126                 } catch (Throwable JavaDoc e1) {
127                     // Ignore so that original exception is not masked
128
}
129                 throw e;
130             }
131         }
132
133         private void endDispatch(ResourceDiffTree[] locked, IProgressMonitor monitor) {
134             if (locked == null) {
135                 // The begin failed so there's nothing to unlock
136
return;
137             }
138             monitor.beginTask(null, 100 * locked.length);
139             for (int i = 0; i < locked.length; i++) {
140                 ResourceDiffTree tree = locked[i];
141                 try {
142                     tree.endInput(Policy.subMonitorFor(monitor, 100));
143                 } catch (RuntimeException JavaDoc e) {
144                     // Don't worry about ending every set if an error occurs.
145
// Instead, log the error and suggest a restart.
146
TeamPlugin.log(IStatus.ERROR, Messages.SubscriberChangeSetCollector_0, e);
147                     throw e;
148                 }
149             }
150             monitor.done();
151         }
152         
153         /* (non-Javadoc)
154          * @see org.eclipse.team.internal.core.BackgroundEventHandler#queueEvent(org.eclipse.team.internal.core.BackgroundEventHandler.Event, boolean)
155          */

156         protected synchronized void queueEvent(Event event, boolean front) {
157             // Override to allow access from enclosing class
158
super.queueEvent(event, front);
159         }
160         
161         /*
162          * Handle the removal
163          */

164         private void handleRemove(IResource resource) {
165             ChangeSet[] sets = getSets();
166             for (int i = 0; i < sets.length; i++) {
167                 ChangeSet set = sets[i];
168                 // This will remove any descendants from the set and callback to
169
// resourcesChanged which will batch changes
170
if (!set.isEmpty()) {
171                     set.rootRemoved(resource, IResource.DEPTH_INFINITE);
172                     if (set.isEmpty()) {
173                         remove(set);
174                     }
175                 }
176             }
177         }
178         
179         /*
180          * Handle the change
181          */

182         private void handleChange(IResource resource, int depth) throws CoreException {
183             IDiff diff = getDiff(resource);
184             if (isModified(diff)) {
185                 ActiveChangeSet[] containingSets = getContainingSets(resource);
186                 if (containingSets.length == 0) {
187                     // Consider for inclusion in the default set
188
// if the resource is not already a member of another set
189
if (getDefaultSet() != null) {
190                         getDefaultSet().add(diff);
191                      }
192                 } else {
193                     for (int i = 0; i < containingSets.length; i++) {
194                         ActiveChangeSet set = containingSets[i];
195                         // Update the sync info in the set
196
set.add(diff);
197                     }
198                 }
199             } else {
200                 removeFromAllSets(resource);
201             }
202             if (depth != IResource.DEPTH_ZERO) {
203                 IResource[] members = getSubscriber().members(resource);
204                 for (int i = 0; i < members.length; i++) {
205                     IResource member = members[i];
206                     handleChange(member, depth == IResource.DEPTH_ONE ? IResource.DEPTH_ZERO : IResource.DEPTH_INFINITE);
207                 }
208             }
209         }
210         
211         private void removeFromAllSets(IResource resource) {
212             List toRemove = new ArrayList();
213             ChangeSet[] sets = getSets();
214             for (int i = 0; i < sets.length; i++) {
215                 ChangeSet set = sets[i];
216                 if (set.contains(resource)) {
217                     set.remove(resource);
218                     if (set.isEmpty()) {
219                         toRemove.add(set);
220                     }
221                 }
222             }
223             for (Iterator iter = toRemove.iterator(); iter.hasNext();) {
224                 ActiveChangeSet set = (ActiveChangeSet) iter.next();
225                 remove(set);
226             }
227         }
228
229         private ActiveChangeSet[] getContainingSets(IResource resource) {
230             Set result = new HashSet();
231             ChangeSet[] sets = getSets();
232             for (int i = 0; i < sets.length; i++) {
233                 ChangeSet set = sets[i];
234                 if (set.contains(resource)) {
235                     result.add(set);
236                 }
237             }
238             return (ActiveChangeSet[]) result.toArray(new ActiveChangeSet[result.size()]);
239         }
240     }
241     
242     private class ResourceCollector extends SubscriberResourceCollector {
243
244         public ResourceCollector(Subscriber subscriber) {
245             super(subscriber);
246         }
247
248         /* (non-Javadoc)
249          * @see org.eclipse.team.internal.core.subscribers.SubscriberResourceCollector#remove(org.eclipse.core.resources.IResource)
250          */

251         protected void remove(IResource resource) {
252             if (handler != null)
253                 handler.queueEvent(new BackgroundEventHandler.ResourceEvent(resource, RESOURCE_REMOVAL, IResource.DEPTH_INFINITE), false);
254         }
255
256         /* (non-Javadoc)
257          * @see org.eclipse.team.internal.core.subscribers.SubscriberResourceCollector#change(org.eclipse.core.resources.IResource, int)
258          */

259         protected void change(IResource resource, int depth) {
260             if (handler != null)
261                 handler.queueEvent(new BackgroundEventHandler.ResourceEvent(resource, RESOURCE_CHANGE, depth), false);
262         }
263         
264         protected boolean hasMembers(IResource resource) {
265             return SubscriberChangeSetManager.this.hasMembers(resource);
266         }
267     }
268     
269     public SubscriberChangeSetManager(Subscriber subscriber) {
270         collector = new ResourceCollector(subscriber);
271         handler = new EventHandler(NLS.bind(Messages.SubscriberChangeSetCollector_1, new String JavaDoc[] { subscriber.getName() }), NLS.bind(Messages.SubscriberChangeSetCollector_2, new String JavaDoc[] { subscriber.getName() })); //
272
}
273     
274     /* (non-Javadoc)
275      * @see org.eclipse.team.internal.core.subscribers.ChangeSetManager#initializeSets()
276      */

277     protected void initializeSets() {
278         load(getPreferences());
279     }
280     
281     public boolean hasMembers(IResource resource) {
282         ChangeSet[] sets = getSets();
283         for (int i = 0; i < sets.length; i++) {
284             ActiveChangeSet set = (ActiveChangeSet)sets[i];
285             if (set.getDiffTree().getChildren(resource.getFullPath()).length > 0)
286                 return true;
287         }
288         if (getDefaultSet() != null)
289             return (getDefaultSet().getDiffTree().getChildren(resource.getFullPath()).length > 0);
290         return false;
291     }
292
293     /**
294      * Return the sync info for the given resource obtained
295      * from the subscriber.
296      * @param resource the resource
297      * @return the sync info for the resource
298      * @throws CoreException
299      */

300     public IDiff getDiff(IResource resource) throws CoreException {
301         Subscriber subscriber = getSubscriber();
302         return subscriber.getDiff(resource);
303     }
304     
305     /**
306      * Return the subscriber associated with this collector.
307      * @return the subscriber associated with this collector
308      */

309     public Subscriber getSubscriber() {
310         return collector.getSubscriber();
311     }
312
313     /* (non-Javadoc)
314      * @see org.eclipse.team.internal.core.subscribers.SubscriberResourceCollector#dispose()
315      */

316     public void dispose() {
317         handler.shutdown();
318         collector.dispose();
319         super.dispose();
320         save(getPreferences());
321     }
322
323     private Preferences getPreferences() {
324         return getParentPreferences().node(getSubscriberIdentifier());
325     }
326     
327     private static Preferences getParentPreferences() {
328         return getTeamPreferences().node(PREF_CHANGE_SETS);
329     }
330     
331     private static Preferences getTeamPreferences() {
332         return new InstanceScope().getNode(TeamPlugin.getPlugin().getBundle().getSymbolicName());
333     }
334     
335     /**
336      * Return the id that will uniquely identify the subscriber across
337      * restarts.
338      * @return the id that will uniquely identify the subscriber across
339      */

340     protected String JavaDoc getSubscriberIdentifier() {
341         return getSubscriber().getName();
342     }
343
344     /**
345      * Wait until the collector is done processing any events.
346      * This method is for testing purposes only.
347      * @param monitor
348      */

349     public void waitUntilDone(IProgressMonitor monitor) {
350         monitor.worked(1);
351         // wait for the event handler to process changes.
352
while(handler.getEventHandlerJob().getState() != Job.NONE) {
353             monitor.worked(1);
354             try {
355                 Thread.sleep(10);
356             } catch (InterruptedException JavaDoc e) {
357             }
358             Policy.checkCanceled(monitor);
359         }
360         monitor.worked(1);
361     }
362
363     /* (non-Javadoc)
364      * @see org.eclipse.team.internal.core.subscribers.ActiveChangeSetManager#getName()
365      */

366     protected String JavaDoc getName() {
367         return getSubscriber().getName();
368     }
369 }
370
Popular Tags