1 11 package org.eclipse.team.internal.core.subscribers; 12 13 import java.util.*; 14 15 import org.eclipse.core.resources.IFile; 16 import org.eclipse.core.resources.IResource; 17 import org.eclipse.core.runtime.*; 18 import org.eclipse.core.runtime.jobs.Job; 19 import org.eclipse.core.runtime.preferences.*; 20 import org.eclipse.osgi.util.NLS; 21 import org.eclipse.team.core.ITeamStatus; 22 import org.eclipse.team.core.TeamException; 23 import org.eclipse.team.core.subscribers.Subscriber; 24 import org.eclipse.team.core.synchronize.*; 25 import org.eclipse.team.internal.core.*; 26 import org.osgi.service.prefs.BackingStoreException; 27 import org.osgi.service.prefs.Preferences; 28 29 32 public class SubscriberChangeSetCollector extends ChangeSetCollector implements ISyncInfoSetChangeListener { 33 34 private static final String PREF_CHANGE_SETS = "changeSets"; private static final String CTX_DEFAULT_SET = "defaultSet"; 37 private static final int RESOURCE_REMOVAL = 1; 38 private static final int RESOURCE_CHANGE = 2; 39 40 private ActiveChangeSet defaultSet; 41 private EventHandler handler; 42 private ResourceCollector collector; 43 44 47 private class EventHandler extends BackgroundEventHandler { 48 49 private List dispatchEvents = new ArrayList(); 50 51 protected EventHandler(String jobName, String errorTitle) { 52 super(jobName, errorTitle); 53 } 54 55 58 protected void processEvent(Event event, IProgressMonitor monitor) throws CoreException { 59 if (isShutdown()) 61 throw new OperationCanceledException(); 62 dispatchEvents.add(event); 63 } 64 65 68 protected boolean doDispatchEvents(IProgressMonitor monitor) throws TeamException { 69 if (dispatchEvents.isEmpty()) { 70 return false; 71 } 72 if (isShutdown()) 73 throw new OperationCanceledException(); 74 SyncInfoTree[] locked = null; 75 try { 76 locked = beginDispath(); 77 for (Iterator iter = dispatchEvents.iterator(); iter.hasNext();) { 78 Event event = (Event) iter.next(); 79 switch (event.getType()) { 80 case RESOURCE_REMOVAL: 81 handleRemove(event.getResource()); 82 break; 83 case RESOURCE_CHANGE: 84 handleChange(event.getResource(), ((ResourceEvent)event).getDepth()); 85 break; 86 default: 87 break; 88 } 89 if (isShutdown()) 90 throw new OperationCanceledException(); 91 } 92 } finally { 93 try { 94 endDispatch(locked, monitor); 95 } finally { 96 dispatchEvents.clear(); 97 } 98 } 99 return true; 100 } 101 102 107 private SyncInfoTree[] beginDispath() { 108 ChangeSet[] sets = getSets(); 109 List lockedSets = new ArrayList(); 110 try { 111 for (int i = 0; i < sets.length; i++) { 112 ChangeSet set = sets[i]; 113 SyncInfoTree syncInfoSet = set.getSyncInfoSet(); 114 lockedSets.add(syncInfoSet); 115 syncInfoSet.beginInput(); 116 } 117 return (SyncInfoTree[]) lockedSets.toArray(new SyncInfoTree[lockedSets.size()]); 118 } catch (RuntimeException e) { 119 try { 120 for (Iterator iter = lockedSets.iterator(); iter.hasNext();) { 121 SyncInfoTree tree = (SyncInfoTree) iter.next(); 122 try { 123 tree.endInput(null); 124 } catch (Throwable e1) { 125 } 127 } 128 } catch (Throwable e1) { 129 } 131 throw e; 132 } 133 } 134 135 private void endDispatch(SyncInfoTree[] locked, IProgressMonitor monitor) { 136 if (locked == null) { 137 return; 139 } 140 monitor.beginTask(null, 100 * locked.length); 141 for (int i = 0; i < locked.length; i++) { 142 SyncInfoTree tree = locked[i]; 143 try { 144 tree.endInput(Policy.subMonitorFor(monitor, 100)); 145 } catch (RuntimeException e) { 146 TeamPlugin.log(IStatus.ERROR, Messages.SubscriberChangeSetCollector_0, e); throw e; 150 } 151 } 152 monitor.done(); 153 } 154 155 158 protected synchronized void queueEvent(Event event, boolean front) { 159 super.queueEvent(event, front); 161 } 162 163 166 private void handleRemove(IResource resource) { 167 ChangeSet[] sets = getSets(); 168 for (int i = 0; i < sets.length; i++) { 169 ChangeSet set = sets[i]; 170 if (!set.isEmpty()) { 173 set.rootRemoved(resource, IResource.DEPTH_INFINITE); 174 if (set.isEmpty()) { 175 remove(set); 176 } 177 } 178 } 179 } 180 181 184 private void handleChange(IResource resource, int depth) throws TeamException { 185 SyncInfo syncInfo = getSyncInfo(resource); 186 if (isModified(syncInfo)) { 187 ActiveChangeSet[] containingSets = getContainingSets(resource); 188 if (containingSets.length == 0) { 189 if (defaultSet != null) { 192 defaultSet.add(syncInfo); 193 } 194 } else { 195 for (int i = 0; i < containingSets.length; i++) { 196 ActiveChangeSet set = containingSets[i]; 197 set.getSyncInfoSet().add(syncInfo); 199 } 200 } 201 } else { 202 removeFromAllSets(resource); 203 } 204 if (depth != IResource.DEPTH_ZERO) { 205 IResource[] members = getSubscriber().members(resource); 206 for (int i = 0; i < members.length; i++) { 207 IResource member = members[i]; 208 handleChange(member, depth == IResource.DEPTH_ONE ? IResource.DEPTH_ZERO : IResource.DEPTH_INFINITE); 209 } 210 } 211 } 212 213 private void removeFromAllSets(IResource resource) { 214 List toRemove = new ArrayList(); 215 ChangeSet[] sets = getSets(); 216 for (int i = 0; i < sets.length; i++) { 217 ChangeSet set = sets[i]; 218 if (set.contains(resource)) { 219 set.remove(resource); 220 if (set.isEmpty()) { 221 toRemove.add(set); 222 } 223 } 224 } 225 for (Iterator iter = toRemove.iterator(); iter.hasNext();) { 226 ActiveChangeSet set = (ActiveChangeSet) iter.next(); 227 remove(set); 228 } 229 } 230 231 private ActiveChangeSet[] getContainingSets(IResource resource) { 232 Set result = new HashSet(); 233 ChangeSet[] sets = getSets(); 234 for (int i = 0; i < sets.length; i++) { 235 ChangeSet set = sets[i]; 236 if (set.contains(resource)) { 237 result.add(set); 238 } 239 } 240 return (ActiveChangeSet[]) result.toArray(new ActiveChangeSet[result.size()]); 241 } 242 } 243 244 private class ResourceCollector extends SubscriberResourceCollector { 245 246 public ResourceCollector(Subscriber subscriber) { 247 super(subscriber); 248 } 249 250 253 protected void remove(IResource resource) { 254 handler.queueEvent(new BackgroundEventHandler.ResourceEvent(resource, RESOURCE_REMOVAL, IResource.DEPTH_INFINITE), false); 255 } 256 257 260 protected void change(IResource resource, int depth) { 261 handler.queueEvent(new BackgroundEventHandler.ResourceEvent(resource, RESOURCE_CHANGE, depth), false); 262 } 263 264 protected boolean hasMembers(IResource resource) { 265 return SubscriberChangeSetCollector.this.hasMembers(resource); 266 } 267 } 268 269 public SubscriberChangeSetCollector(Subscriber subscriber) { 270 collector = new ResourceCollector(subscriber); 271 load(); 272 handler = new EventHandler(NLS.bind(Messages.SubscriberChangeSetCollector_1, new String [] { subscriber.getName() }), NLS.bind(Messages.SubscriberChangeSetCollector_2, new String [] { subscriber.getName() })); } 274 275 public boolean hasMembers(IResource resource) { 276 ChangeSet[] sets = getSets(); 277 for (int i = 0; i < sets.length; i++) { 278 ChangeSet set = sets[i]; 279 if (set.getSyncInfoSet().hasMembers(resource)); 280 } 281 if (defaultSet != null) 282 return (defaultSet.getSyncInfoSet().hasMembers(resource)); 283 return false; 284 } 285 286 290 public void add(ChangeSet set) { 291 Assert.isTrue(set instanceof ActiveChangeSet); 292 if (!contains(set)) { 293 super.add(set); 294 handleAddedResources(set, set.getSyncInfoSet().getSyncInfos()); 295 } 296 } 297 298 305 protected boolean isSingleSetPerResource() { 306 return true; 307 } 308 309 318 public ActiveChangeSet createSet(String title, SyncInfo[] infos) { 319 ActiveChangeSet commitSet = new ActiveChangeSet(this, title); 320 if (infos != null && infos.length > 0) { 321 commitSet.add(infos); 322 } 323 return commitSet; 324 } 325 326 334 public ActiveChangeSet createSet(String title, IFile[] files) throws TeamException { 335 List infos = new ArrayList(); 336 for (int i = 0; i < files.length; i++) { 337 IFile file = files[i]; 338 SyncInfo info = getSyncInfo(file); 339 if (info != null) { 340 infos.add(info); 341 } 342 } 343 return createSet(title, (SyncInfo[]) infos.toArray(new SyncInfo[infos.size()])); 344 } 345 346 351 public void makeDefault(ActiveChangeSet set) { 352 if (!contains(set)) { 354 add(set); 355 } 356 ActiveChangeSet oldSet = defaultSet; 357 defaultSet = set; 358 fireDefaultChangedEvent(oldSet, defaultSet); 359 } 360 361 366 public ActiveChangeSet getDefaultSet() { 367 return defaultSet; 368 } 369 375 public boolean isDefault(ActiveChangeSet set) { 376 return set == defaultSet; 377 } 378 379 386 protected SyncInfo getSyncInfo(IResource resource) throws TeamException { 387 Subscriber subscriber = getSubscriber(); 388 SyncInfo info = subscriber.getSyncInfo(resource); 389 return info; 390 } 391 392 396 public Subscriber getSubscriber() { 397 return collector.getSubscriber(); 398 } 399 400 protected boolean isModified(SyncInfo info) { 401 if (info != null) { 402 if (info.getComparator().isThreeWay()) { 403 int dir = (info.getKind() & SyncInfo.DIRECTION_MASK); 404 return dir == SyncInfo.OUTGOING || dir == SyncInfo.CONFLICTING; 405 } else { 406 return (info.getKind() & SyncInfo.CHANGE_MASK) == SyncInfo.CHANGE; 407 } 408 } 409 return false; 410 } 411 412 415 public void dispose() { 416 handler.shutdown(); 417 collector.dispose(); 418 super.dispose(); 419 save(); 420 } 421 422 private void save() { 423 Preferences prefs = getPreferences(); 424 try { 426 String [] oldSetNames = prefs.childrenNames(); 427 for (int i = 0; i < oldSetNames.length; i++) { 428 String string = oldSetNames[i]; 429 prefs.node(string).removeNode(); 430 } 431 } catch (BackingStoreException e) { 432 TeamPlugin.log(IStatus.ERROR, NLS.bind("An error occurred purging the sommit set state for {0}", new String [] { getSubscriber().getName() }), e); } 434 ChangeSet[] sets = getSets(); 435 for (int i = 0; i < sets.length; i++) { 436 ChangeSet set = sets[i]; 437 if (set instanceof ActiveChangeSet && !set.isEmpty()) { 438 Preferences child = prefs.node(((ActiveChangeSet)set).getTitle()); 439 ((ActiveChangeSet)set).save(child); 440 } 441 } 442 if (defaultSet != null) { 443 prefs.put(CTX_DEFAULT_SET, defaultSet.getTitle()); 444 } 445 try { 446 prefs.flush(); 447 } catch (BackingStoreException e) { 448 TeamPlugin.log(IStatus.ERROR, NLS.bind(Messages.SubscriberChangeSetCollector_3, new String [] { getSubscriber().getName() }), e); } 450 } 451 452 private void load() { 453 Preferences prefs = getPreferences(); 454 String defaultSetTitle = prefs.get(CTX_DEFAULT_SET, null); 455 try { 456 String [] childNames = prefs.childrenNames(); 457 for (int i = 0; i < childNames.length; i++) { 458 String string = childNames[i]; 459 Preferences childPrefs = prefs.node(string); 460 ActiveChangeSet set = createSet(string, childPrefs); 461 if (!set.isEmpty()) { 462 if (defaultSet == null && defaultSetTitle != null && set.getTitle().equals(defaultSetTitle)) { 463 defaultSet = set; 464 } 465 add(set); 466 } 467 } 468 } catch (BackingStoreException e) { 469 TeamPlugin.log(IStatus.ERROR, NLS.bind(Messages.SubscriberChangeSetCollector_4, new String [] { getSubscriber().getName() }), e); } 471 } 472 473 479 protected ActiveChangeSet createSet(String title, Preferences childPrefs) { 480 ActiveChangeSet changeSet = new ActiveChangeSet(this, title); 481 changeSet.init(childPrefs); 482 return changeSet; 483 } 484 485 private Preferences getPreferences() { 486 return getParentPreferences().node(getSubscriberIdentifier()); 487 } 488 489 private static Preferences getParentPreferences() { 490 return getTeamPreferences().node(PREF_CHANGE_SETS); 491 } 492 493 private static Preferences getTeamPreferences() { 494 return new InstanceScope().getNode(TeamPlugin.getPlugin().getBundle().getSymbolicName()); 495 } 496 497 502 protected String getSubscriberIdentifier() { 503 return getSubscriber().getName(); 504 } 505 506 509 public void syncInfoSetReset(SyncInfoSet set, IProgressMonitor monitor) { 510 handleSyncSetChange(set, set.getSyncInfos(), set.getResources()); 511 } 512 513 516 public void syncInfoChanged(ISyncInfoSetChangeEvent event, IProgressMonitor monitor) { 517 SyncInfoSet set = event.getSet(); 518 handleSyncSetChange(set, event.getAddedResources(), getAllResources(event)); 519 } 520 521 private IResource[] getAllResources(ISyncInfoSetChangeEvent event) { 522 Set allResources = new HashSet(); 523 SyncInfo[] addedResources = event.getAddedResources(); 524 for (int i = 0; i < addedResources.length; i++) { 525 SyncInfo info = addedResources[i]; 526 allResources.add(info.getLocal()); 527 } 528 SyncInfo[] changedResources = event.getChangedResources(); 529 for (int i = 0; i < changedResources.length; i++) { 530 SyncInfo info = changedResources[i]; 531 allResources.add(info.getLocal()); 532 } 533 allResources.addAll(Arrays.asList(event.getRemovedResources())); 534 return (IResource[]) allResources.toArray(new IResource[allResources.size()]); 535 } 536 537 private void handleAddedResources(ChangeSet set, SyncInfo[] infos) { 538 if (isSingleSetPerResource()) { 539 IResource[] resources = new IResource[infos.length]; 540 for (int i = 0; i < infos.length; i++) { 541 resources[i] = infos[i].getLocal(); 542 } 543 ChangeSet[] sets = getSets(); 545 for (int i = 0; i < sets.length; i++) { 546 ChangeSet otherSet = sets[i]; 547 if (otherSet != set) { 548 otherSet.remove(resources); 549 } 550 } 551 } 552 } 553 554 private void handleSyncSetChange(SyncInfoSet set, SyncInfo[] addedInfos, IResource[] allAffectedResources) { 555 ChangeSet changeSet = getChangeSet(set); 556 if (set.isEmpty() && changeSet != null) { 557 remove(changeSet); 558 } 559 fireResourcesChangedEvent(changeSet, allAffectedResources); 560 handleAddedResources(changeSet, addedInfos); 561 } 562 563 566 public void syncInfoSetErrors(SyncInfoSet set, ITeamStatus[] errors, IProgressMonitor monitor) { 567 } 569 570 573 protected ISyncInfoSetChangeListener getChangeSetChangeListener() { 574 return this; 575 } 576 577 581 public void waitUntilDone(IProgressMonitor monitor) { 582 monitor.worked(1); 583 while(handler.getEventHandlerJob().getState() != Job.NONE) { 585 monitor.worked(1); 586 try { 587 Thread.sleep(10); 588 } catch (InterruptedException e) { 589 } 590 Policy.checkCanceled(monitor); 591 } 592 monitor.worked(1); 593 } 594 } 595 | Popular Tags |