1 11 package org.eclipse.team.internal.ccvs.core; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.List ; 16 17 import org.eclipse.core.resources.*; 18 import org.eclipse.core.runtime.*; 19 import org.eclipse.osgi.util.NLS; 20 import org.eclipse.team.core.RepositoryProvider; 21 import org.eclipse.team.core.TeamException; 22 import org.eclipse.team.core.subscribers.*; 23 import org.eclipse.team.core.synchronize.SyncInfo; 24 import org.eclipse.team.core.synchronize.SyncInfoFilter; 25 import org.eclipse.team.core.variants.*; 26 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; 27 import org.eclipse.team.internal.ccvs.core.resources.RemoteFile; 28 import org.eclipse.team.internal.ccvs.core.syncinfo.CVSResourceVariantTree; 29 import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; 30 import org.eclipse.team.internal.ccvs.core.util.Util; 31 32 47 public class CVSMergeSubscriber extends CVSSyncTreeSubscriber implements IResourceChangeListener, ISubscriberChangeListener { 48 49 private final class MergeBaseTree extends CVSResourceVariantTree { 50 private PersistantResourceVariantByteStore mergedSynchronizer; 53 private MergeBaseTree(ResourceVariantByteStore cache, CVSTag tag, boolean cacheFileContentsHint, String syncKeyPrefix) { 54 super(cache, tag, cacheFileContentsHint); 55 mergedSynchronizer = new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + "0merged")); } 57 public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { 58 List unrefreshed = new ArrayList (); 60 for (int i = 0; i < resources.length; i++) { 61 IResource resource = resources[i]; 62 if (!hasResourceVariant(resource)) { 63 unrefreshed.add(resource); 64 } 65 } 66 if (unrefreshed.isEmpty()) { 67 monitor.done(); 68 return new IResource[0]; 69 } 70 IResource[] refreshed = super.refresh((IResource[]) unrefreshed.toArray(new IResource[unrefreshed.size()]), depth, monitor); 71 return refreshed; 72 } 73 public IResourceVariant getResourceVariant(IResource resource) throws TeamException { 74 byte[] mergedBytes = mergedSynchronizer.getBytes(resource); 76 if (mergedBytes != null) { 77 byte[] parentBytes = getByteStore().getBytes(resource.getParent()); 78 if (parentBytes != null) { 79 return RemoteFile.fromBytes(resource, mergedBytes, parentBytes); 80 } 81 } 82 return super.getResourceVariant(resource); 83 } 84 85 88 public void merged(IResource resource, byte[] remoteBytes) throws TeamException { 89 if (remoteBytes == null) { 90 getByteStore().deleteBytes(resource); 91 } else { 92 getByteStore().setBytes(resource, remoteBytes); 93 } 94 } 95 96 100 public boolean isMerged(IResource resource, byte[] remoteBytes) throws TeamException { 101 byte[] mergedBytes = getByteStore().getBytes(resource); 102 return Util.equals(mergedBytes, remoteBytes); 103 } 104 105 108 public void dispose() { 109 mergedSynchronizer.dispose(); 110 super.dispose(); 111 } 112 } 113 114 public static final String ID = "org.eclipse.team.cvs.ui.cvsmerge-participant"; public static final String ID_MODAL = "org.eclipse.team.cvs.ui.cvsmerge-participant-modal"; private static final String UNIQUE_ID_PREFIX = "merge-"; 118 private CVSTag start, end; 119 private List roots; 120 private CVSResourceVariantTree remoteTree; 121 private MergeBaseTree baseTree; 122 123 public CVSMergeSubscriber(IResource[] roots, CVSTag start, CVSTag end) { 124 this(getUniqueId(), roots, start, end); 125 } 126 127 private static QualifiedName getUniqueId() { 128 String uniqueId = Long.toString(System.currentTimeMillis()); 129 return new QualifiedName(ID, "CVS" + UNIQUE_ID_PREFIX + uniqueId); } 131 132 public CVSMergeSubscriber(QualifiedName id, IResource[] roots, CVSTag start, CVSTag end) { 133 super(id, NLS.bind(CVSMessages.CVSMergeSubscriber_2, new String [] { start.getName(), end.getName() })); 134 this.start = start; 135 this.end = end; 136 this.roots = new ArrayList (Arrays.asList(roots)); 137 initialize(); 138 } 139 140 143 private void initialize() { 144 QualifiedName id = getId(); 145 String syncKeyPrefix = id.getLocalName(); 146 PersistantResourceVariantByteStore remoteSynchronizer = new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + end.getName())); 147 remoteTree = new CVSResourceVariantTree(remoteSynchronizer, getEndTag(), getCacheFileContentsHint()) { 148 public IResource[] refresh(IResource[] resources, int depth, IProgressMonitor monitor) throws TeamException { 149 monitor.beginTask(null, 100); 151 try { 152 IResource[] refreshed = super.refresh(resources, depth, monitor); 153 compareWithRemote(refreshed, Policy.subMonitorFor(monitor, 50)); 154 return refreshed; 155 } finally { 156 monitor.done(); 157 } 158 } 159 }; 160 PersistantResourceVariantByteStore baseSynchronizer = new PersistantResourceVariantByteStore(new QualifiedName(SYNC_KEY_QUALIFIER, syncKeyPrefix + start.getName())); 161 baseTree = new MergeBaseTree(baseSynchronizer, getStartTag(), getCacheFileContentsHint(), syncKeyPrefix); 162 163 ResourcesPlugin.getWorkspace().addResourceChangeListener(this); 164 CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber().addListener(this); 165 } 166 167 protected SyncInfo getSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote) throws TeamException { 168 CVSMergeSyncInfo info = new CVSMergeSyncInfo(local, base, remote, this); 169 info.init(); 170 return info; 171 } 172 173 public void merged(IResource[] resources) throws TeamException { 174 for (int i = 0; i < resources.length; i++) { 175 IResource resource = resources[i]; 176 internalMerged(resource); 177 } 178 fireTeamResourceChange(SubscriberChangeEvent.asSyncChangedDeltas(this, resources)); 179 } 180 181 private void internalMerged(IResource resource) throws TeamException { 182 byte[] remoteBytes = getRemoteByteStore().getBytes(resource); 183 baseTree.merged(resource, remoteBytes); 184 } 185 186 189 public void cancel() { 190 ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); 191 remoteTree.dispose(); 192 baseTree.dispose(); 193 } 194 195 198 public IResource[] roots() { 199 return (IResource[]) roots.toArray(new IResource[roots.size()]); 200 } 201 202 205 public boolean isSupervised(IResource resource) throws TeamException { 206 return getBaseTree().hasResourceVariant(resource) || getRemoteTree().hasResourceVariant(resource); 207 } 208 209 public CVSTag getStartTag() { 210 return start; 211 } 212 213 public CVSTag getEndTag() { 214 return end; 215 } 216 217 224 public void resourceChanged(IResourceChangeEvent event) { 225 try { 226 IResourceDelta delta = event.getDelta(); 227 if(delta != null) { 228 delta.accept(new IResourceDeltaVisitor() { 229 public boolean visit(IResourceDelta delta) throws CoreException { 230 IResource resource = delta.getResource(); 231 232 if (resource.getType()==IResource.PROJECT) { 233 IProject project = (IProject)resource; 234 if (!project.isAccessible()) { 235 return false; 236 } 237 if ((delta.getFlags() & IResourceDelta.OPEN) != 0) { 238 return false; 239 } 240 if (RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId()) == null) { 241 return false; 242 } 243 } 244 245 if (roots.contains(resource)) { 246 if (delta.getKind() == IResourceDelta.REMOVED || delta.getKind() == IResourceDelta.MOVED_TO) { 247 cancel(); 248 } 249 return false; 251 } 252 return true; 254 } 255 }); 256 } 257 } catch (CoreException e) { 258 CVSProviderPlugin.log(e.getStatus()); 259 } 260 } 261 262 269 public boolean isMerged(IResource resource) throws TeamException { 270 byte[] remoteBytes = getRemoteByteStore().getBytes(resource); 271 return baseTree.isMerged(resource, remoteBytes); 272 } 273 274 280 public void subscriberResourceChanged(ISubscriberChangeEvent[] deltas) { 281 for (int i = 0; i < deltas.length; i++) { 282 ISubscriberChangeEvent delta = deltas[i]; 283 switch(delta.getFlags()) { 284 case ISubscriberChangeEvent.ROOT_REMOVED: 285 IResource resource = delta.getResource(); 286 if(roots.remove(resource)) { 287 fireTeamResourceChange(new ISubscriberChangeEvent[] {delta}); 288 } 289 break; 290 } 291 } 292 } 293 294 297 protected IResourceVariantTree getBaseTree() { 298 return baseTree; 299 } 300 301 304 protected IResourceVariantTree getRemoteTree() { 305 return remoteTree; 306 } 307 308 protected boolean getCacheFileContentsHint() { 309 return true; 310 } 311 312 315 private void compareWithRemote(IResource[] refreshed, IProgressMonitor monitor) throws CVSException, TeamException { 316 if (refreshed.length == 0) return; 318 SyncInfoFilter.ContentComparisonSyncInfoFilter contentFilter = 319 new SyncInfoFilter.ContentComparisonSyncInfoFilter(); 320 monitor.beginTask(null, refreshed.length * 100); 321 for (int i = 0; i < refreshed.length; i++) { 322 IResource resource = refreshed[i]; 323 if (resource.getType() == IResource.FILE) { 324 ICVSFile local = CVSWorkspaceRoot.getCVSFileFor((IFile)resource); 325 byte[] localBytes = local.getSyncBytes(); 326 byte[] remoteBytes = getRemoteByteStore().getBytes(resource); 327 if (remoteBytes != null 328 && localBytes != null 329 && local.exists() 330 && !ResourceSyncInfo.getRevision(remoteBytes).equals(ResourceSyncInfo.getRevision(localBytes)) 331 && contentFilter.select(getSyncInfo(resource), Policy.subMonitorFor(monitor, 100))) { 332 internalMerged(resource); 334 } 335 } 336 } 337 monitor.done(); 338 } 339 340 341 private PersistantResourceVariantByteStore getRemoteByteStore() { 342 return (PersistantResourceVariantByteStore)((CVSResourceVariantTree)getRemoteTree()).getByteStore(); 343 } 344 345 348 public boolean equals(Object other) { 349 if(this == other) return true; 350 if(! (other instanceof CVSMergeSubscriber)) return false; 351 CVSMergeSubscriber s = (CVSMergeSubscriber)other; 352 return getEndTag().equals(s.getEndTag()) && 353 getStartTag().equals(s.getStartTag()) && rootsEqual(s); 354 } 355 } 356 | Popular Tags |