1 11 package org.eclipse.team.core.synchronize; 12 13 import java.util.ArrayList ; 14 import java.util.Collections ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import org.eclipse.core.resources.IResource; 23 import org.eclipse.core.resources.IWorkspaceRunnable; 24 import org.eclipse.core.runtime.*; 25 import org.eclipse.core.runtime.jobs.ILock; 26 import org.eclipse.core.runtime.jobs.Job; 27 import org.eclipse.team.core.ITeamStatus; 28 import org.eclipse.team.core.TeamStatus; 29 import org.eclipse.team.core.synchronize.FastSyncInfoFilter.SyncInfoDirectionFilter; 30 import org.eclipse.team.internal.core.Policy; 31 import org.eclipse.team.internal.core.TeamPlugin; 32 import org.eclipse.team.internal.core.subscribers.SyncInfoStatistics; 33 import org.eclipse.team.internal.core.subscribers.SyncSetChangedEvent; 34 35 45 public class SyncInfoSet { 46 private Map resources = Collections.synchronizedMap(new HashMap ()); 49 50 private SyncInfoStatistics statistics = new SyncInfoStatistics(); 52 53 private Map errors = new HashMap (); 55 56 private boolean lockedForModification; 57 58 61 public SyncInfoSet() { 62 } 63 64 70 public SyncInfoSet(SyncInfo[] infos) { 71 this(); 72 for (int i = 0; i < infos.length; i++) { 74 internalAdd(infos[i]); 75 } 76 } 77 78 83 public synchronized SyncInfo[] getSyncInfos() { 84 return (SyncInfo[]) resources.values().toArray(new SyncInfo[resources.size()]); 85 } 86 87 94 public IResource[] getResources() { 95 SyncInfo[] infos = getSyncInfos(); 96 List resources = new ArrayList (); 97 for (int i = 0; i < infos.length; i++) { 98 SyncInfo info = infos[i]; 99 resources.add(info.getLocal()); 100 } 101 return (IResource[]) resources.toArray(new IResource[resources.size()]); 102 } 103 104 112 public synchronized SyncInfo getSyncInfo(IResource resource) { 113 return (SyncInfo)resources.get(resource.getFullPath()); 114 } 115 116 122 public synchronized int size() { 123 return resources.size(); 124 } 125 126 139 public long countFor(int kind, int mask) { 140 return statistics.countFor(kind, mask); 141 } 142 143 150 public boolean hasConflicts() { 151 return countFor(SyncInfo.CONFLICTING, SyncInfo.DIRECTION_MASK) > 0; 152 } 153 154 159 public synchronized boolean isEmpty() { 160 return resources.isEmpty(); 161 } 162 163 168 protected synchronized void internalAdd(SyncInfo info) { 169 Assert.isTrue(!lockedForModification); 170 IResource local = info.getLocal(); 171 IPath path = local.getFullPath(); 172 SyncInfo oldSyncInfo = (SyncInfo)resources.put(path, info); 173 if(oldSyncInfo == null) { 174 statistics.add(info); 175 } else { 176 statistics.remove(oldSyncInfo); 177 statistics.add(info); 178 } 179 } 180 181 187 protected synchronized SyncInfo internalRemove(IResource resource) { 188 Assert.isTrue(!lockedForModification); 189 IPath path = resource.getFullPath(); 190 SyncInfo info = (SyncInfo)resources.remove(path); 191 if (info != null) { 192 statistics.remove(info); 193 } 194 return info; 195 } 196 197 203 public void addSyncSetChangedListener(ISyncInfoSetChangeListener listener) { 204 synchronized(listeners) { 205 listeners.add(listener); 206 } 207 } 208 209 215 public void removeSyncSetChangedListener(ISyncInfoSetChangeListener listener) { 216 synchronized(listeners) { 217 listeners.remove(listener); 218 } 219 } 220 221 224 public void clear() { 225 try { 226 beginInput(); 227 errors.clear(); 228 resources.clear(); 229 statistics.clear(); 230 getChangeEvent().reset(); 231 } finally { 232 endInput(null); 233 } 234 } 235 236 251 private void run(IWorkspaceRunnable runnable, IProgressMonitor monitor) { 252 monitor = Policy.monitorFor(monitor); 253 monitor.beginTask(null, 100); 254 try { 255 beginInput(); 256 runnable.run(Policy.subMonitorFor(monitor, 80)); 257 } catch (CoreException e) { 258 addError(new TeamStatus(IStatus.ERROR, TeamPlugin.ID, ITeamStatus.SYNC_INFO_SET_ERROR, e.getMessage(), e, null)); 259 } finally { 260 endInput(Policy.subMonitorFor(monitor, 20)); 261 } 262 } 263 264 281 public void connect(final ISyncInfoSetChangeListener listener, IProgressMonitor monitor) { 282 run(new IWorkspaceRunnable() { 283 public void run(IProgressMonitor monitor) { 284 try { 285 monitor.beginTask(null, 100); 286 addSyncSetChangedListener(listener); 287 listener.syncInfoSetReset(SyncInfoSet.this, Policy.subMonitorFor(monitor, 95)); 288 } finally { 289 monitor.done(); 290 } 291 } 292 }, monitor); 293 } 294 295 private ILock lock = Job.getJobManager().newLock(); 296 297 private Set listeners = Collections.synchronizedSet(new HashSet ()); 298 299 private SyncSetChangedEvent changes = createEmptyChangeEvent(); 300 301 316 public void add(SyncInfo info) { 317 try { 318 beginInput(); 319 boolean alreadyExists = getSyncInfo(info.getLocal()) != null; 320 internalAdd(info); 321 if (alreadyExists) { 322 getChangeEvent().changed(info); 323 } else { 324 getChangeEvent().added(info); 325 } 326 } finally { 327 endInput(null); 328 } 329 } 330 331 336 public void addAll(SyncInfoSet set) { 337 try { 338 beginInput(); 339 SyncInfo[] infos = set.getSyncInfos(); 340 for (int i = 0; i < infos.length; i++) { 341 add(infos[i]); 342 } 343 } finally { 344 endInput(null); 345 } 346 } 347 348 353 public synchronized void remove(IResource resource) { 354 try { 355 beginInput(); 356 SyncInfo info = internalRemove(resource); 357 getChangeEvent().removed(resource, info); 358 } finally { 359 endInput(null); 360 } 361 } 362 363 368 public void removeAll(IResource[] resources) { 369 try { 370 beginInput(); 371 for (int i = 0; i < resources.length; i++) { 372 remove(resources[i]); 373 } 374 } finally { 375 endInput(null); 376 } 377 } 378 379 382 public void removeConflictingNodes() { 383 rejectNodes(new SyncInfoDirectionFilter(SyncInfo.CONFLICTING)); 384 } 385 386 389 public void removeOutgoingNodes() { 390 rejectNodes(new SyncInfoDirectionFilter(SyncInfo.OUTGOING)); 391 } 392 393 396 public void removeIncomingNodes() { 397 rejectNodes(new SyncInfoDirectionFilter(SyncInfo.INCOMING)); 398 } 399 400 406 public boolean hasNodes(FastSyncInfoFilter filter) { 407 SyncInfo[] infos = getSyncInfos(); 408 for (int i = 0; i < infos.length; i++) { 409 SyncInfo info = infos[i]; 410 if (info != null && filter.select(info)) { 411 return true; 412 } 413 } 414 return false; 415 } 416 417 423 public void selectNodes(FastSyncInfoFilter filter) { 424 try { 425 beginInput(); 426 SyncInfo[] infos = getSyncInfos(); 427 for (int i = 0; i < infos.length; i++) { 428 SyncInfo info = infos[i]; 429 if (info == null || !filter.select(info)) { 430 remove(info.getLocal()); 431 } 432 } 433 } finally { 434 endInput(null); 435 } 436 } 437 438 444 public void rejectNodes(FastSyncInfoFilter filter) { 445 try { 446 beginInput(); 447 SyncInfo[] infos = getSyncInfos(); 448 for (int i = 0; i < infos.length; i++) { 449 SyncInfo info = infos[i]; 450 if (info != null && filter.select(info)) { 451 remove(info.getLocal()); 452 } 453 } 454 } finally { 455 endInput(null); 456 } 457 } 458 459 465 public SyncInfo[] getNodes(FastSyncInfoFilter filter) { 466 List result = new ArrayList (); 467 SyncInfo[] infos = getSyncInfos(); 468 for (int i = 0; i < infos.length; i++) { 469 SyncInfo info = infos[i]; 470 if (info != null && filter.select(info)) { 471 result.add(info); 472 } 473 } 474 return (SyncInfo[]) result.toArray(new SyncInfo[result.size()]); 475 } 476 477 483 public boolean hasIncomingChanges() { 484 return countFor(SyncInfo.INCOMING, SyncInfo.DIRECTION_MASK) > 0; 485 } 486 487 493 public boolean hasOutgoingChanges() { 494 return countFor(SyncInfo.OUTGOING, SyncInfo.DIRECTION_MASK) > 0; 495 } 496 497 517 public void beginInput() { 518 lock.acquire(); 519 } 520 521 527 public void endInput(IProgressMonitor monitor) { 528 try { 529 if (lock.getDepth() == 1) { 530 fireChanges(Policy.monitorFor(monitor)); 533 } 534 } finally { 535 lock.release(); 536 } 537 } 538 539 543 protected void resetChanges() { 544 changes = createEmptyChangeEvent(); 545 } 546 547 552 protected SyncSetChangedEvent createEmptyChangeEvent() { 553 return new SyncSetChangedEvent(this); 554 } 555 556 private void fireChanges(final IProgressMonitor monitor) { 557 final SyncSetChangedEvent event; 559 synchronized(this) { 560 event = getChangeEvent(); 561 resetChanges(); 562 } 563 if(event.isEmpty() && ! event.isReset()) return; 566 ISyncInfoSetChangeListener[] allListeners = getListeners(); 567 final ITeamStatus[] newErrors = event.getErrors(); 569 monitor.beginTask(null, 100 + (newErrors.length > 0 ? 50 : 0) * allListeners.length); 570 for (int i = 0; i < allListeners.length; i++) { 571 final ISyncInfoSetChangeListener listener = allListeners[i]; 572 SafeRunner.run(new ISafeRunnable() { 573 public void handleException(Throwable exception) { 574 } 576 public void run() throws Exception { 577 try { 578 lockedForModification = true; 579 if (event.isReset()) { 580 listener.syncInfoSetReset(SyncInfoSet.this, Policy.subMonitorFor(monitor, 100)); 581 } else { 582 listener.syncInfoChanged(event, Policy.subMonitorFor(monitor, 100)); 583 } 584 if (newErrors.length > 0) { 585 listener.syncInfoSetErrors(SyncInfoSet.this, newErrors, Policy.subMonitorFor(monitor, 50)); 586 } 587 } finally { 588 lockedForModification = false; 589 } 590 } 591 }); 592 } 593 monitor.done(); 594 } 595 596 600 protected ISyncInfoSetChangeListener[] getListeners() { 601 ISyncInfoSetChangeListener[] allListeners; 602 synchronized(listeners) { 603 allListeners = (ISyncInfoSetChangeListener[]) listeners.toArray(new ISyncInfoSetChangeListener[listeners.size()]); 604 } 605 return allListeners; 606 } 607 608 613 protected SyncSetChangedEvent getChangeEvent() { 614 return changes; 615 } 616 617 631 public void addError(ITeamStatus status) { 632 try { 633 beginInput(); 634 errors.put(status.getResource(), status); 635 getChangeEvent().errorOccurred(status); 636 } finally { 637 endInput(null); 638 } 639 } 640 641 647 public ITeamStatus[] getErrors() { 648 return (ITeamStatus[]) errors.values().toArray(new ITeamStatus[errors.size()]); 649 } 650 651 658 public Iterator iterator() { 659 return resources.values().iterator(); 660 } 661 } 662 | Popular Tags |