1 11 package org.eclipse.team.internal.ccvs.ui.mappings; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.HashSet ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Set ; 19 20 import org.eclipse.core.resources.IResource; 21 import org.eclipse.core.runtime.*; 22 import org.eclipse.core.runtime.jobs.Job; 23 import org.eclipse.team.core.TeamException; 24 import org.eclipse.team.core.diff.*; 25 import org.eclipse.team.core.diff.provider.DiffTree; 26 import org.eclipse.team.core.subscribers.Subscriber; 27 import org.eclipse.team.core.synchronize.SyncInfo; 28 import org.eclipse.team.core.synchronize.SyncInfoSet; 29 import org.eclipse.team.core.variants.IResourceVariant; 30 import org.eclipse.team.internal.ccvs.core.*; 31 import org.eclipse.team.internal.ccvs.core.mapping.CVSCheckedInChangeSet; 32 import org.eclipse.team.internal.ccvs.core.resources.RemoteResource; 33 import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; 34 import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin; 35 import org.eclipse.team.internal.ccvs.ui.Policy; 36 import org.eclipse.team.internal.ccvs.ui.operations.RemoteLogOperation.LogEntryCache; 37 import org.eclipse.team.internal.ccvs.ui.subscriber.CVSChangeSetCollector; 38 import org.eclipse.team.internal.ccvs.ui.subscriber.LogEntryCacheUpdateHandler; 39 import org.eclipse.team.internal.ccvs.ui.subscriber.LogEntryCacheUpdateHandler.ILogsFetchedListener; 40 import org.eclipse.team.internal.core.mapping.SyncInfoToDiffConverter; 41 import org.eclipse.team.internal.core.subscribers.*; 42 import org.eclipse.team.internal.ui.Utils; 43 import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; 44 import org.eclipse.team.ui.synchronize.SynchronizePageActionGroup; 45 46 public class CheckedInChangeSetCollector extends BatchingChangeSetManager implements ILogsFetchedListener { 47 48 52 private static final String LOG_ENTRY_HANDLER = CVSUIPlugin.ID + ".LogEntryHandler"; 54 57 private class CVSUpdatableSyncInfo extends CVSSyncInfo { 58 public int kind; 59 public CVSUpdatableSyncInfo(int kind, IResource local, IResourceVariant base, IResourceVariant remote, Subscriber s) { 60 super(local, base, remote, s); 61 this.kind = kind; 62 } 63 64 protected int calculateKind() throws TeamException { 65 return kind; 66 } 67 } 68 69 IDiffChangeListener diffTreeListener = new IDiffChangeListener() { 70 public void propertyChanged(IDiffTree tree, int property, IPath[] paths) { 71 } 73 public void diffsChanged(IDiffChangeEvent event, IProgressMonitor monitor) { 74 if (event.getTree().isEmpty()) { 75 ChangeSet changeSet = getChangeSet(event.getTree()); 76 if (changeSet != null) { 77 remove(changeSet); 78 } 79 } else { 80 ChangeSet changeSet = getChangeSet(event.getTree()); 81 if (changeSet != null) { 82 fireResourcesChangedEvent(changeSet, getAffectedPaths(event)); 83 } 84 } 85 } 86 private IPath[] getAffectedPaths(IDiffChangeEvent event) { 87 Set result = new HashSet (); 88 IPath[] removed = event.getRemovals(); 89 for (int i = 0; i < removed.length; i++) { 90 IPath path = removed[i]; 91 result.add(path); 92 } 93 IDiff[] diffs = event.getAdditions(); 94 for (int j = 0; j < diffs.length; j++) { 95 IDiff diff = diffs[j]; 96 result.add(diff.getPath()); 97 } 98 diffs = event.getChanges(); 99 for (int j = 0; j < diffs.length; j++) { 100 IDiff diff = diffs[j]; 101 result.add(diff.getPath()); 102 } 103 return (IPath[]) result.toArray(new IPath[result.size()]); 104 } 105 }; 106 107 private final ISynchronizePageConfiguration configuration; 108 private boolean disposed; 109 private LogEntryCache logEntryCache; 110 private final Subscriber subscriber; 111 112 private HashSet updatedSets; 113 114 public CheckedInChangeSetCollector(ISynchronizePageConfiguration configuration, Subscriber subscriber) { 115 this.configuration = configuration; 116 this.subscriber = subscriber; 117 } 118 119 125 public final ISynchronizePageConfiguration getConfiguration() { 126 return configuration; 127 } 128 129 protected void handleSetAdded(ChangeSet set) { 130 ((DiffChangeSet)set).getDiffTree().addDiffChangeListener(diffTreeListener); 131 super.handleSetAdded(set); 132 if (updatedSets != null) { 133 updatedSets.add(set); 134 ((DiffTree)((DiffChangeSet)set).getDiffTree()).beginInput(); 135 } 136 } 137 138 protected void handleSetRemoved(ChangeSet set) { 139 ((DiffChangeSet)set).getDiffTree().removeDiffChangeListener(diffTreeListener); 140 super.handleSetRemoved(set); 141 } 142 143 protected ChangeSet getChangeSet(IDiffTree tree) { 144 ChangeSet[] sets = getSets(); 145 for (int i = 0; i < sets.length; i++) { 146 ChangeSet changeSet = sets[i]; 147 if (((DiffChangeSet)changeSet).getDiffTree() == tree) { 148 return changeSet; 149 } 150 } 151 return null; 152 } 153 154 public void handleChange(IDiffChangeEvent event) { 155 List removals = new ArrayList (); 156 List additions = new ArrayList (); 157 removals.addAll(Arrays.asList(event.getRemovals())); 158 additions.addAll(Arrays.asList(event.getAdditions())); 159 IDiff[] changed = event.getChanges(); 160 for (int i = 0; i < changed.length; i++) { 161 IDiff diff = changed[i]; 162 additions.add(diff); 163 removals.add(diff.getPath()); 164 } 165 if (!removals.isEmpty()) { 166 remove((IPath[]) removals.toArray(new IPath[removals.size()])); 167 } 168 if (!additions.isEmpty()) { 169 add((IDiff[]) additions.toArray(new IDiff[additions.size()])); 170 } 171 } 172 173 protected void remove(IPath[] paths) { 174 ChangeSet[] sets = getSets(); 175 for (int i = 0; i < sets.length; i++) { 176 DiffChangeSet set = (DiffChangeSet)sets[i]; 177 set.remove(paths); 178 } 179 } 180 181 public synchronized LogEntryCacheUpdateHandler getLogEntryHandler() { 182 LogEntryCacheUpdateHandler handler = (LogEntryCacheUpdateHandler)getConfiguration().getProperty(LOG_ENTRY_HANDLER); 183 if (handler == null) { 184 handler = initializeLogEntryHandler(getConfiguration()); 185 } 186 handler.setListener(this); 187 return handler; 188 } 189 190 193 private LogEntryCacheUpdateHandler initializeLogEntryHandler(final ISynchronizePageConfiguration configuration) { 194 final LogEntryCacheUpdateHandler logEntryHandler = new LogEntryCacheUpdateHandler(configuration); 195 configuration.setProperty(LOG_ENTRY_HANDLER, logEntryHandler); 196 configuration.addActionContribution(new SynchronizePageActionGroup() { 198 public void dispose() { 199 super.dispose(); 200 LogEntryCacheUpdateHandler handler = (LogEntryCacheUpdateHandler)configuration.getProperty(LOG_ENTRY_HANDLER); 201 if (handler != null) { 202 handler.shutdown(); 203 configuration.setProperty(LOG_ENTRY_HANDLER, null); 204 } 205 } 206 }); 207 return logEntryHandler; 208 } 209 210 protected void add(IDiff[] diffs) { 211 LogEntryCacheUpdateHandler handler = getLogEntryHandler(); 212 if (handler != null) 213 try { 214 handler.fetch(getSyncInfos(diffs)); 215 } catch (CVSException e) { 216 CVSUIPlugin.log(e); 217 } 218 } 219 220 private SyncInfo[] getSyncInfos(IDiff[] diffs) { 221 SyncInfoSet set = new SyncInfoSet(); 222 for (int i = 0; i < diffs.length; i++) { 223 IDiff diff = diffs[i]; 224 set.add(getConverter().asSyncInfo(diff, getSubscriber().getResourceComparator())); 225 } 226 return set.getSyncInfos(); 227 } 228 229 public Subscriber getSubscriber() { 230 return subscriber; 231 } 232 233 236 public void dispose() { 237 disposed = true; 240 LogEntryCacheUpdateHandler handler = getLogEntryHandler(); 241 if (handler != null) handler.setListener(null); 242 getConfiguration().setProperty(CVSChangeSetCollector.CVS_CHECKED_IN_COLLECTOR, null); 243 logEntryCache = null; 244 super.dispose(); 245 } 246 247 251 private void handleRemoteChanges(final SyncInfo[] infos, final LogEntryCache logEntries, final IProgressMonitor monitor) { 252 try { 253 beginSetUpdate(); 254 addLogEntries(infos, logEntries, monitor); 255 } finally { 256 endSetUpdate(monitor); 257 } 258 } 259 260 private void beginSetUpdate() { 261 updatedSets = new HashSet (); 262 } 263 264 private void endSetUpdate(IProgressMonitor monitor) { 265 for (Iterator iter = updatedSets.iterator(); iter.hasNext();) { 266 DiffChangeSet set = (DiffChangeSet) iter.next(); 267 try { 268 ((DiffTree)set.getDiffTree()).endInput(monitor); 269 } catch (RuntimeException e) { 270 CVSUIPlugin.log(IStatus.ERROR, "Internal error", e); } 272 } 273 updatedSets = null; 274 } 275 276 280 private void addLogEntries(SyncInfo[] commentInfos, LogEntryCache logs, IProgressMonitor monitor) { 281 try { 282 monitor.beginTask(null, commentInfos.length * 10); 283 if (logs != null) { 284 for (int i = 0; i < commentInfos.length; i++) { 285 addSyncInfoToCommentNode(commentInfos[i], logs); 286 monitor.worked(10); 287 } 288 } 289 } finally { 290 monitor.done(); 291 } 292 } 293 294 300 private void addSyncInfoToCommentNode(SyncInfo info, LogEntryCache logs) { 301 LogEntryCacheUpdateHandler handler = getLogEntryHandler(); 302 if (handler != null) { 303 ICVSRemoteResource remoteResource = handler.getRemoteResource(info); 304 if(handler.getSubscriber() instanceof CVSCompareSubscriber && remoteResource != null) { 305 addMultipleRevisions(info, logs, remoteResource); 306 } else { 307 addSingleRevision(info, logs, remoteResource); 308 } 309 } 310 } 311 312 319 private void addSingleRevision(SyncInfo info, LogEntryCache logs, ICVSRemoteResource remoteResource) { 320 ILogEntry logEntry = logs.getLogEntry(remoteResource); 321 if (remoteResource != null && !remoteResource.isFolder()) { 322 try { 325 String remoteRevision = ((ICVSRemoteFile) remoteResource).getRevision(); 326 if (isDeletedRemotely(info)) { 327 ILogEntry[] logEntries = logs.getLogEntries(remoteResource); 328 for (int i = 0; i < logEntries.length; i++) { 329 ILogEntry entry = logEntries[i]; 330 String revision = entry.getRevision(); 331 if (entry.isDeletion() && ResourceSyncInfo.isLaterRevision(revision, remoteRevision)) { 332 logEntry = entry; 333 } 334 } 335 } 336 } catch (TeamException e) { 337 } 339 } 340 addRemoteChange(info, remoteResource, logEntry); 341 } 342 343 350 private void addMultipleRevisions(SyncInfo info, LogEntryCache logs, ICVSRemoteResource remoteResource) { 351 ILogEntry[] logEntries = logs.getLogEntries(remoteResource); 352 if(logEntries == null || logEntries.length == 0) { 353 addRemoteChange(info, null, null); 356 } else { 357 for (int i = 0; i < logEntries.length; i++) { 358 ILogEntry entry = logEntries[i]; 359 addRemoteChange(info, remoteResource, entry); 360 } 361 } 362 } 363 364 private boolean isDeletedRemotely(SyncInfo info) { 365 int kind = info.getKind(); 366 if(kind == (SyncInfo.INCOMING | SyncInfo.DELETION)) return true; 367 if(SyncInfo.getDirection(kind) == SyncInfo.CONFLICTING && info.getRemote() == null) return true; 368 return false; 369 } 370 371 374 private void addRemoteChange(SyncInfo info, ICVSRemoteResource remoteResource, ILogEntry logEntry) { 375 if (disposed) return; 376 LogEntryCacheUpdateHandler handler = getLogEntryHandler(); 377 if(handler != null && remoteResource != null && logEntry != null && handler.isRemoteChange(info)) { 378 if(requiresCustomSyncInfo(info, remoteResource, logEntry)) { 379 info = new CVSUpdatableSyncInfo(info.getKind(), info.getLocal(), info.getBase(), (RemoteResource)logEntry.getRemoteFile(), getSubscriber()); 380 try { 381 info.init(); 382 } catch (TeamException e) { 383 } 385 } 386 IDiff diff = getConverter().getDeltaFor(info); 387 IResourceVariant base = info.getBase(); 389 IResourceVariant remote = info.getRemote(); 390 if ((base == null && remote != null) || (remote == null && base != null) || (remote != null && base != null && !base.equals(remote))) { 391 synchronized(this) { 392 CVSCheckedInChangeSet set = getChangeSetFor(logEntry); 393 if (set == null) { 394 set = createChangeSetFor(logEntry); 395 add(set); 396 } 397 set.add(diff); 398 } 399 } 400 } else { 401 } 405 } 406 407 private SyncInfoToDiffConverter getConverter() { 408 SyncInfoToDiffConverter converter = (SyncInfoToDiffConverter)Utils.getAdapter(subscriber, SyncInfoToDiffConverter.class); 409 if (converter == null) 410 converter = SyncInfoToDiffConverter.getDefault(); 411 return converter; 412 } 413 414 private CVSCheckedInChangeSet createChangeSetFor(ILogEntry logEntry) { 415 return new CVSCheckedInChangeSet(logEntry); 416 } 417 418 private CVSCheckedInChangeSet getChangeSetFor(ILogEntry logEntry) { 419 ChangeSet[] sets = getSets(); 420 for (int i = 0; i < sets.length; i++) { 421 ChangeSet set = sets[i]; 422 if (set instanceof CVSCheckedInChangeSet && 423 set.getComment().equals(logEntry.getComment()) && 424 ((CVSCheckedInChangeSet)set).getAuthor().equals(logEntry.getAuthor())) { 425 return (CVSCheckedInChangeSet)set; 426 } 427 } 428 return null; 429 } 430 431 private boolean requiresCustomSyncInfo(SyncInfo info, ICVSRemoteResource remoteResource, ILogEntry logEntry) { 432 if (logEntry.isDeletion()) return false; 434 IResourceVariant remote = info.getRemote(); 437 if (remote == null) return true; 438 return !remote.equals(remoteResource); 439 } 440 441 444 public void waitUntilDone(IProgressMonitor monitor) { 445 monitor.worked(1); 446 LogEntryCacheUpdateHandler handler = getLogEntryHandler(); 448 if (handler != null) { 449 while(handler.getEventHandlerJob().getState() != Job.NONE) { 450 monitor.worked(1); 451 try { 452 Thread.sleep(10); 453 } catch (InterruptedException e) { 454 } 455 Policy.checkCanceled(monitor); 456 } 457 } 458 monitor.worked(1); 459 } 460 461 464 public void logEntriesFetched(SyncInfoSet set, LogEntryCache logEntryCache, IProgressMonitor monitor) { 465 if (disposed) return; 466 this.logEntryCache = logEntryCache; 468 try { 469 beginInput(); 470 handleRemoteChanges(set.getSyncInfos(), logEntryCache, monitor); 471 } finally { 472 endInput(monitor); 473 } 474 } 475 476 public ICVSRemoteFile getImmediatePredecessor(ICVSRemoteFile file) throws TeamException { 477 if (logEntryCache != null) 478 return logEntryCache.getImmediatePredecessor(file); 479 return null; 480 } 481 } 482 | Popular Tags |