1 11 package org.eclipse.team.internal.ccvs.core.resources; 12 13 import java.util.*; 14 15 import org.eclipse.core.resources.IContainer; 16 import org.eclipse.core.resources.IFolder; 17 import org.eclipse.core.resources.IProject; 18 import org.eclipse.core.resources.IResource; 19 import org.eclipse.core.resources.IResourceStatus; 20 import org.eclipse.core.resources.ISynchronizer; 21 import org.eclipse.core.resources.ResourcesPlugin; 22 import org.eclipse.core.runtime.CoreException; 23 import org.eclipse.core.runtime.IPath; 24 import org.eclipse.team.internal.ccvs.core.CVSException; 25 import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; 26 import org.eclipse.team.internal.ccvs.core.ICVSFolder; 27 import org.eclipse.team.internal.ccvs.core.ICVSResource; 28 import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo; 29 import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; 30 import org.eclipse.team.internal.ccvs.core.util.Util; 31 32 36 class SynchronizerSyncInfoCache extends SyncInfoCache { 37 38 Map pendingCacheWrites = new HashMap(); 40 private static final Object BYTES_REMOVED = new byte[0]; 41 42 public SynchronizerSyncInfoCache() { 43 getWorkspaceSynchronizer().add(FOLDER_SYNC_KEY); 44 getWorkspaceSynchronizer().add(RESOURCE_SYNC_KEY); 45 } 46 49 private ISynchronizer getWorkspaceSynchronizer() { 50 return ResourcesPlugin.getWorkspace().getSynchronizer(); 51 } 52 53 void flush(IProject project) throws CVSException { 54 purgeCache(project, true); 55 } 56 57 61 void flush(IFolder folder) throws CVSException { 62 purgeCache(folder, false); 63 } 64 65 74 FolderSyncInfo getCachedFolderSync(IContainer container, boolean threadSafeAccess) throws CVSException { 75 byte[] bytes = internalGetCachedSyncBytes(container); 76 if (bytes == null) return null; 77 return FolderSyncInfo.getFolderSyncInfo(bytes); 78 } 79 80 boolean hasCachedFolderSync(IContainer container) throws CVSException { 81 return internalGetCachedSyncBytes(container) != null; 82 }; 83 84 88 private byte[] internalGetCachedSyncBytes(IContainer container) throws CVSException { 89 try { 90 return getWorkspaceSynchronizer().getSyncInfo(FOLDER_SYNC_KEY, container); 91 } catch (CoreException e) { 92 throw CVSException.wrapException(e); 93 } 94 } 95 104 void setCachedFolderSync(IContainer container, FolderSyncInfo info, boolean canModifyWorkspace) throws CVSException { 105 try { 106 if (info == null) { 107 if (container.exists() || container.isPhantom()) { 108 getWorkspaceSynchronizer().flushSyncInfo(FOLDER_SYNC_KEY, container, IResource.DEPTH_ZERO); 109 } 110 } else { 111 getWorkspaceSynchronizer().setSyncInfo(FOLDER_SYNC_KEY, container, info.getBytes()); 112 } 113 } catch (CoreException e) { 114 throw CVSException.wrapException(e); 115 } 116 } 117 118 121 byte[] getCachedSyncBytes(IResource resource, boolean threadSafeAccess) throws CVSException { 122 try { 123 byte[] bytes = null; 124 if (!hasPendingCacheRemoval(resource)) { 125 bytes = getPendingCacheWrite(resource); 126 if (bytes == null) { 127 bytes = getWorkspaceSynchronizer().getSyncInfo(RESOURCE_SYNC_KEY, resource); 128 } 129 } 130 if (bytes != null && resource.getType() == IResource.FILE) { 131 if (ResourceSyncInfo.isAddition(bytes)) { 132 bytes = null; 135 } else if (!ResourceSyncInfo.isDeletion(bytes)) { 136 bytes = ResourceSyncInfo.convertToDeletion(bytes); 138 } 139 } 140 return bytes; 141 } catch (CoreException e) { 142 throw CVSException.wrapException(e); 143 } 144 } 145 146 149 void setCachedSyncBytes(IResource resource, byte[] syncBytes, boolean canModifyWorkspace) throws CVSException { 150 byte[] oldBytes = getCachedSyncBytes(resource, true); 151 try { 152 if (syncBytes == null) { 153 if (oldBytes != null) { 154 if (canModifyWorkspace) { 155 if (resource.exists() || resource.isPhantom()) { 156 getWorkspaceSynchronizer().flushSyncInfo(RESOURCE_SYNC_KEY, resource, IResource.DEPTH_ZERO); 157 } 158 removePendingCacheWrite(resource); 159 } else { 160 if (resource.exists() || resource.isPhantom()) { 161 setPendingCacheWriteToDelete(resource); 162 } 163 } 164 } 165 } else { 166 if (oldBytes == null || !equals(syncBytes, oldBytes)) { 171 if (canModifyWorkspace) { 172 getWorkspaceSynchronizer().setSyncInfo(RESOURCE_SYNC_KEY, resource, syncBytes); 173 removePendingCacheWrite(resource); 174 } else { 175 setPendingCacheWrite(resource, syncBytes); 176 } 177 } 178 } 179 } catch (CoreException e) { 180 throw CVSException.wrapException(e); 181 } 182 } 183 184 187 private boolean equals(byte[] syncBytes, byte[] oldBytes) throws CVSException { 188 if (!ResourceSyncInfo.isFolder(syncBytes)) { 189 syncBytes = ResourceSyncInfo.convertToDeletion(syncBytes); 190 } 191 if (!ResourceSyncInfo.isFolder(oldBytes)) { 192 try { 193 oldBytes = ResourceSyncInfo.convertToDeletion(oldBytes); 194 } catch (CVSException e) { 195 CVSProviderPlugin.log(e); 196 return false; 197 } 198 } 199 return Util.equals(syncBytes, oldBytes); 200 } 201 202 205 String getDirtyIndicator(IResource resource, boolean threadSafeAccess) throws CVSException { 206 if (resource.getType() == IResource.FILE) { 207 return getCachedSyncBytes(resource, threadSafeAccess) != null ? 209 IS_DIRTY_INDICATOR : 210 NOT_DIRTY_INDICATOR; 211 } else { 212 return calculateDirtyCountForPhantomFolder((IContainer)resource); 213 } 214 } 215 216 219 void setDirtyIndicator(IResource resource, String indicator) throws CVSException { 220 } 223 224 227 public boolean cachesDirtyState() { 228 return false; 231 } 232 233 void flushDirtyCache(IResource container) throws CVSException { 234 } 236 237 boolean isSyncInfoLoaded(IContainer parent) throws CVSException { 238 return true; 239 } 240 241 244 boolean isResourceSyncInfoCached(IContainer container) throws CVSException { 245 return true; 247 } 248 249 252 void setResourceSyncInfoCached(IContainer container) throws CVSException { 253 } 255 258 boolean isFolderSyncInfoCached(IContainer container) throws CVSException { 259 return true; 260 } 261 262 266 private String calculateDirtyCountForPhantomFolder(IContainer parent) throws CVSException { 267 ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(parent); 268 if(getCachedFolderSync(parent, true) == null) { 269 return NOT_DIRTY_INDICATOR; 270 } 271 272 String indicator = NOT_DIRTY_INDICATOR; 273 ICVSResource[] children = cvsFolder.members(ICVSFolder.MANAGED_MEMBERS | ICVSFolder.PHANTOM_MEMBERS); 274 for (int i = 0; i < children.length; i++) { 275 ICVSResource resource = children[i]; 276 if (resource.isFolder()) { 279 indicator = calculateDirtyCountForPhantomFolder((IContainer)resource.getIResource()); 280 } else { 281 indicator = IS_DIRTY_INDICATOR; 283 break; 284 } 285 } 286 return indicator; 287 } 288 289 293 public void purgeCache(IContainer root, boolean deep) throws CVSException { 294 int depth = deep ? IResource.DEPTH_INFINITE : IResource.DEPTH_ZERO; 295 try { 296 if (root.exists() || root.isPhantom()) { 297 getWorkspaceSynchronizer().flushSyncInfo(RESOURCE_SYNC_KEY, root, depth); 298 } 299 if (root.exists() || root.isPhantom()) { 300 getWorkspaceSynchronizer().flushSyncInfo(FOLDER_SYNC_KEY, root, depth); 301 } 302 if (deep) { 303 removePendingCacheWritesUnder(root); 304 } else { 305 removePendingCacheWrite(root); 306 } 307 } catch (CoreException e) { 308 if (e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND) { 309 return; 311 } 312 throw CVSException.wrapException(e); 313 } 314 315 } 316 317 public boolean isPhantom(IResource resource) { 318 return resource.isPhantom() || hasPendingCacheWrite(resource); 319 } 320 321 public IResource[] members(IContainer folder) throws CoreException { 322 IResource[] pendingWrites = getPendingCacheWrites(); 323 if (pendingWrites != null){ 324 HashSet cachedResources = new HashSet(); 325 for (int i = 0; i < pendingWrites.length; i++) { 326 IResource resource = pendingWrites[i]; 327 if (resource.getParent().equals(folder)) 328 cachedResources.add(resource); 329 } 330 331 if (cachedResources.size() != 0){ 332 IResource[] resources = folder.members(true); 333 IResource[] cachedResourcesArray = (IResource[]) cachedResources.toArray(new IResource[cachedResources.size()]); 334 IResource[]finalResources = new IResource[resources.length + cachedResourcesArray.length]; 335 System.arraycopy(resources, 0, finalResources, 0, resources.length); 336 System.arraycopy(cachedResourcesArray, 0, finalResources, resources.length, cachedResourcesArray.length); 337 return finalResources; 338 } 339 } 340 try { 341 return folder.members(true); 342 } catch (CoreException e) { 343 if (e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND) 344 return new IResource[0]; 345 throw e; 346 } 347 } 348 349 354 private boolean hasPendingCacheWrite(IResource resource) { 355 synchronized (pendingCacheWrites) { 356 return pendingCacheWrites.containsKey(resource); 357 } 358 } 359 360 private byte[] getPendingCacheWrite(IResource resource) { 361 synchronized (pendingCacheWrites) { 362 Object object = pendingCacheWrites.get(resource); 363 if (object instanceof byte[]) { 364 return (byte[])object; 365 } 366 return null; 367 } 368 } 369 370 private boolean hasPendingCacheRemoval(IResource resource) { 371 synchronized (pendingCacheWrites) { 372 Object object = pendingCacheWrites.get(resource); 373 return object == BYTES_REMOVED; 374 } 375 } 376 377 private void setPendingCacheWrite(IResource resource, byte[] syncBytes) { 378 synchronized (pendingCacheWrites) { 379 pendingCacheWrites.put(resource, syncBytes); 380 } 381 } 382 383 private void setPendingCacheWriteToDelete(IResource resource) { 384 synchronized (pendingCacheWrites) { 385 pendingCacheWrites.put(resource, BYTES_REMOVED); 386 } 387 } 388 389 private void removePendingCacheWrite(IResource resource) { 390 synchronized (pendingCacheWrites) { 391 pendingCacheWrites.remove(resource); 392 } 393 } 394 395 private void removePendingCacheWritesUnder(IContainer root) { 396 synchronized (pendingCacheWrites) { 397 IPath fullPath = root.getFullPath(); 398 for (Iterator iter = pendingCacheWrites.keySet().iterator(); iter.hasNext();) { 399 IResource resource = (IResource) iter.next(); 400 if (fullPath.isPrefixOf(resource.getFullPath())) { 401 iter.remove(); 402 } 403 } 404 } 405 } 406 407 413 private IResource[] getPendingCacheWrites() { 414 synchronized (pendingCacheWrites) { 415 if (pendingCacheWrites.isEmpty()) 416 return null; 417 return (IResource[]) pendingCacheWrites.keySet().toArray(new IResource[pendingCacheWrites.size()]); 418 } 419 } 420 } 421 | Popular Tags |