/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.core.resources;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.syncinfo.*;
import org.eclipse.team.internal.ccvs.core.syncinfo.ReentrantLock.CVSThreadInfo;
import org.eclipse.team.internal.ccvs.core.util.*;
import org.eclipse.team.internal.core.subscribers.BatchingLock.IFlushOperation;
import org.eclipse.team.internal.core.subscribers.BatchingLock.ThreadInfo;
import org.osgi.framework.Bundle;

/**
 * A synchronizer is responsible for managing synchronization information for local
 * CVS resources.
 * 
 * This class is thread safe but only allows one thread to modify the cache at a time. It
 * doesn't support fine grain locking on a resource basis. Lock ordering between the workspace
 * lock and the synchronizer lock is guaranteed to be deterministic. That is, the workspace
 * lock is *always* acquired before the synchronizer lock. This protects against possible
 * deadlock cases where the synchronizer lock is acquired before a workspace lock.
 * 
 * Special processing has been added for linked folders and their childen so
 * that their CVS meta files are never read or written.
 * 
 * IMPORTANT NOTICE: It is the reponsibility of the clients of EclipseSynchronizer
 * to ensure that they have wrapped operations that may modify the workspace in
 * an IWorkspaceRunnable. If this is not done, deltas may fore at inopertune times 
 * and corrupt the sync info. The wrapping could be done within the synchronizer 
 * itself but would require the creation of an inner class for each case that requires
 * it.
 * 
 * @see ResourceSyncInfo
 * @see FolderSyncInfo
 */
public class EclipseSynchronizer implements IFlushOperation {	
	private static final String IS_DIRTY_INDICATOR = SyncInfoCache.IS_DIRTY_INDICATOR;
	private static final String NOT_DIRTY_INDICATOR = SyncInfoCache.NOT_DIRTY_INDICATOR;
	private static final String RECOMPUTE_INDICATOR = SyncInfoCache.RECOMPUTE_INDICATOR; 
		
	// the cvs eclipse synchronizer is a singleton
	private static EclipseSynchronizer instance;
	
	// track resources that have changed in a given operation
	private ILock lock = Platform.getJobManager().newLock();
	private ReentrantLock resourceLock = new ReentrantLock();
	
	private SynchronizerSyncInfoCache synchronizerCache = new SynchronizerSyncInfoCache();
	private SessionPropertySyncInfoCache sessionPropertyCache = new SessionPropertySyncInfoCache(synchronizerCache);
	
	/*
	 * Package private contructor to allow specialized subclass for handling folder deletions
	 */
	EclipseSynchronizer() {		
	}
	
	/**
	 * Returns the singleton instance of the synchronizer.
	 */
	public static EclipseSynchronizer getInstance() {		
		if(instance==null) {
			instance = new EclipseSynchronizer();
		}
		return instance;
	}
	
	public SyncInfoCache getSyncInfoCacheFor(IResource resource) {
		if (resource.exists() && resource.isLocal(IResource.DEPTH_ZERO)) {
			return sessionPropertyCache;
		} else {
			return synchronizerCache;
		}
	}

	private boolean isValid(IResource resource) {
		return resource.exists() || synchronizerCache.isPhantom(resource);
	}
	
	/**
	 * Sets the folder sync info for the specified folder.
	 * The folder must exist and must not be the workspace root.
	 * 
	 * @param folder the folder
	 * @param info the folder sync info, must not be null
	 * @see #getFolderSync, #deleteFolderSync
	 */
	public void setFolderSync(IContainer folder, FolderSyncInfo info) throws CVSException {
		Assert.isNotNull(info); // enforce the use of deleteFolderSync
		// ignore folder sync on the root (i.e. CVSROOT/config/TopLevelAdmin=yes but we just ignore it)
		if (folder.getType() == IResource.ROOT) return;
		if (!isValid(folder)) {
			// This means that the folder doesn't exist and is not a phantom
			// Allow the set if the parent is a CVS folder since
			// this can occur when creating phatom folders
			if (getFolderSync(folder.getParent()) == null) {
				throw new CVSException(IStatus.ERROR, TeamException.UNABLE,
					NLS.bind(CVSMessages.EclipseSynchronizer_ErrorSettingFolderSync, new String[] { folder.getFullPath().toString() })); 
			}
		}
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(folder, null);
			try {
				beginOperation();
				// get the old info
				FolderSyncInfo oldInfo = getFolderSync(folder);
				// set folder sync and notify
				getSyncInfoCacheFor(folder).setCachedFolderSync(folder, info, true);
				// if the sync info changed from null, we may need to adjust the ancestors
				if (oldInfo == null) {
					adjustDirtyStateRecursively(folder, RECOMPUTE_INDICATOR);
				}
				folderChanged(folder);
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
	
	/**
	 * Gets the folder sync info for the specified folder.
	 * 
	 * @param folder the folder
	 * @return the folder sync info associated with the folder, or null if none.
	 * @see #setFolderSync, #deleteFolderSync
	 */
	public FolderSyncInfo getFolderSync(IContainer folder) throws CVSException {
		if (folder.getType() == IResource.ROOT || !isValid(folder)) return null;
        // Do a check outside the lock for any folder sync info
        FolderSyncInfo info = getSyncInfoCacheFor(folder).getCachedFolderSync(folder, false /* not thread safe */);
        if (info != null)
            return info;
		try {
			beginOperation();
			cacheFolderSync(folder);
			return getSyncInfoCacheFor(folder).getCachedFolderSync(folder, true /* thread safe */);
		} finally {
			endOperation();
		}
	}	

	/**
	 * Deletes the folder sync for the specified folder and the resource sync
	 * for all of its children.  Does not recurse.
	 * 
	 * @param folder the folder
	 * @see #getFolderSync, #setFolderSync
	 */
	public void deleteFolderSync(IContainer folder) throws CVSException {
		if (folder.getType() == IResource.ROOT || !isValid(folder)) return;
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(folder, null);
			try {
				beginOperation();
				// iterate over all children with sync info and prepare notifications
				// this is done first since deleting the folder sync may remove a phantom
				cacheResourceSyncForChildren(folder, true /* can modify workspace */);
				IResource[] children = folder.members(true);
				for (int i = 0; i < children.length; i++) {
					IResource resource = children[i];
					resourceChanged(resource);
					// delete resource sync for all children
					getSyncInfoCacheFor(resource).setCachedSyncBytes(resource, null, true);
				}
				// delete folder sync
				getSyncInfoCacheFor(folder).setCachedFolderSync(folder, null, true);
				folderChanged(folder);
			} catch (CoreException e) {
				throw CVSException.wrapException(e);
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}

	private void folderChanged(IContainer folder) {
		resourceLock.folderChanged(folder);
	}

	private void resourceChanged(IResource resource) {
		resourceLock.resourceChanged(resource);
	}

	/**
	 * Sets the resource sync info for the specified resource.
	 * The parent folder must exist and must not be the workspace root.
	 * 
	 * @param resource the resource
	 * @param info the resource sync info, must not be null
	 * @see #getResourceSync, #deleteResourceSync
	 */
	public void setResourceSync(IResource resource, ResourceSyncInfo info) throws CVSException {
		Assert.isNotNull(info); // enforce the use of deleteResourceSync
		IContainer parent = resource.getParent();
		if (parent == null || parent.getType() == IResource.ROOT || !isValid(parent)) {
			throw new CVSException(IStatus.ERROR, TeamException.UNABLE,
				NLS.bind(CVSMessages.EclipseSynchronizer_ErrorSettingResourceSync, new String[] { resource.getFullPath().toString() })); 
		}
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(resource, null);
			try {
				beginOperation();
				// cache resource sync for siblings, set for self, then notify
				cacheResourceSyncForChildren(parent, true /* can modify workspace */);
				setCachedResourceSync(resource, info);
				resourceChanged(resource);		
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
	
	/**
	 * Gets the resource sync info for the specified folder.
	 * 
	 * @param resource the resource
	 * @return the resource sync info associated with the resource, or null if none.
	 * @see #setResourceSync, #deleteResourceSync
	 */
	public ResourceSyncInfo getResourceSync(IResource resource) throws CVSException {
		byte[] info = getSyncBytes(resource);
		if (info == null) return null;
		return new ResourceSyncInfo(info);
	}

	/**
	 * Gets the resource sync info for the specified folder.
	 * 
	 * @param resource the resource
	 * @return the resource sync info associated with the resource, or null if none.
	 * @see #setResourceSync, #deleteResourceSync
	 */
	public byte[] getSyncBytes(IResource resource) throws CVSException {
		IContainer parent = resource.getParent();
		if (parent == null || parent.getType() == IResource.ROOT || !isValid(parent)) return null;
        // Do a quick check outside the lock to see if there are sync butes for the resource.
        byte[] info = getSyncInfoCacheFor(resource).getCachedSyncBytes(resource, false /* not thread safe */);
        if (info != null)
            return info;
		try {
			beginOperation();
			// cache resource sync for siblings, then return for self
			try {
				cacheResourceSyncForChildren(parent, false /* cannot modify workspace */);
			} catch (CVSException e) {
				if (isCannotModifySynchronizer(e) || isResourceNotFound(e)) {
					// We will resort to loading the sync info for the requested resource from disk
					byte[] bytes =  getSyncBytesFromDisk(resource);
					if (!resource.exists() && bytes != null && !ResourceSyncInfo.isDeletion(bytes)) {
						bytes = ResourceSyncInfo.convertToDeletion(bytes);
					}
					return bytes;
				} else {
					throw e;
				}
			}
			return getCachedSyncBytes(resource);
		} finally {
			endOperation();
		}
	}

	/**
	 * Sets the resource sync info for the specified resource.
	 * The parent folder must exist and must not be the workspace root.
	 * 
	 * @param resource the resource
	 * @param info the resource sync info, must not be null
	 * @see #getResourceSync, #deleteResourceSync
	 */
	public void setSyncBytes(IResource resource, byte[] syncBytes) throws CVSException {
		Assert.isNotNull(syncBytes); // enforce the use of deleteResourceSync
		IContainer parent = resource.getParent();
		if (parent == null || parent.getType() == IResource.ROOT || !isValid(parent)) {
			throw new CVSException(IStatus.ERROR, TeamException.UNABLE,
				NLS.bind(CVSMessages.EclipseSynchronizer_ErrorSettingResourceSync, new String[] { resource.getFullPath().toString() })); 
		}
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(resource, null);
			try {
				beginOperation();
				// cache resource sync for siblings, set for self, then notify
				cacheResourceSyncForChildren(parent, true /* can modify workspace */);
				setCachedSyncBytes(resource, syncBytes);
				resourceChanged(resource);		
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
		
	/**
	 * Deletes the resource sync info for the specified resource, if it exists.
	 * 
	 * @param resource the resource
	 * @see #getResourceSync, #setResourceSync
	 */
	public void deleteResourceSync(IResource resource) throws CVSException {
		IContainer parent = resource.getParent();
		if (parent == null || parent.getType() == IResource.ROOT || !isValid(parent)) return;
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(resource, null);
			try {
				beginOperation();
				// cache resource sync for siblings, delete for self, then notify
				cacheResourceSyncForChildren(parent, true /* can modify workspace */);
				if (getCachedSyncBytes(resource) != null) { // avoid redundant notifications
					setCachedSyncBytes(resource, null);
					clearDirtyIndicator(resource);
					resourceChanged(resource);
				}
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}

	/**
	 * @param resource
	 */
	private void clearDirtyIndicator(IResource resource) throws CVSException {
		getSyncInfoCacheFor(resource).flushDirtyCache(resource);
		adjustDirtyStateRecursively(resource.getParent(), RECOMPUTE_INDICATOR);
	}

	/**
	 * Gets the array of ignore patterns for the specified folder.
	 * 
	 * @param folder the folder
	 * @return the patterns, or an empty array if none
	 * @see #addIgnored
	 */
	public boolean isIgnored(IResource resource) throws CVSException {
		if (resource.getType() == IResource.ROOT || 
		    resource.getType() == IResource.PROJECT || 
		    ! resource.exists()) {
			return false;
		}
		IContainer parent = resource.getParent();
        FileNameMatcher matcher = sessionPropertyCache.getFolderIgnores(parent, false /* not thread safe */);
        if (matcher == null) {
    		try {
    			beginOperation();
                matcher = cacheFolderIgnores(parent);
    		} finally {
    			endOperation();
    		}
        }
		return matcher.match(resource.getName());
	}
	
	/**
	 * Adds a pattern to the set of ignores for the specified folder.
	 * 
	 * @param folder the folder
	 * @param pattern the pattern
	 */
	public void addIgnored(IContainer folder, String pattern) throws CVSException {
		if (folder.getType() == IResource.ROOT || ! folder.exists()) {
			throw new CVSException(IStatus.ERROR, TeamException.UNABLE,
				NLS.bind(CVSMessages.EclipseSynchronizer_ErrorSettingIgnorePattern, new String[] { folder.getFullPath().toString() })); 
		}
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(folder.getFile(new Path(SyncFileWriter.IGNORE_FILE)), null);
			try {
				beginOperation();
				String[] ignores = SyncFileWriter.readCVSIgnoreEntries(folder);
				if (ignores != null) {
					// verify that the pattern has not already been added
					for (int i = 0; i < ignores.length; i++) {
						if (ignores[i].equals(pattern)) return;
					}
					// add the pattern
					String[] oldIgnores = ignores;
					ignores = new String[oldIgnores.length + 1];
					System.arraycopy(oldIgnores, 0, ignores, 0, oldIgnores.length);
					ignores[oldIgnores.length] = pattern;
				} else {
					ignores = new String[] { pattern };
				}
				setCachedFolderIgnores(folder, ignores);
				SyncFileWriter.writeCVSIgnoreEntries(folder, ignores);
				// broadcast changes to unmanaged children - they are the only candidates for being ignored
				List possibleIgnores = new ArrayList();
				accumulateNonManagedChildren(folder, possibleIgnores);
				ResourceStateChangeListeners.getListener().resourceSyncInfoChanged((IResource[])possibleIgnores.toArray(new IResource[possibleIgnores.size()]));
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
	
	/**
	 * Returns the members of this folder including deleted resources with sync info,
	 * but excluding special resources such as CVS subdirectories.
	 *
	 * @param folder the container to list
	 * @return the array of members
	 */
	public IResource[] members(IContainer folder) throws CVSException {
		if (! isValid(folder)) return new IResource[0];
		try {				
			beginOperation();
			if (folder.getType() != IResource.ROOT) {
				// ensure that the sync info is cached so any required phantoms are created
				cacheResourceSyncForChildren(folder, false);
			}
		} catch (CVSException e) {
			if (!isCannotModifySynchronizer(e) && !isResourceNotFound(e)) {
				throw e;
			}
		} finally {
			endOperation();
		}
		try {
			return folder.members(true);
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	private boolean isCannotModifySynchronizer(CVSException e) {
		// IResourceStatus.WORKSPACE_LOCKED can occur if the resource sync is loaded 
		// during the POST_CHANGE delta phase.
		// CVSStatus.FAILED_TO_CACHE_SYNC_INFO can occur if the resource sync is loaded
		// when no scheduling rule is held.
		return (e.getStatus().getCode() == IResourceStatus.WORKSPACE_LOCKED 
				|| e.getStatus().getCode() == CVSStatus.FAILED_TO_CACHE_SYNC_INFO);
	}
	
	private boolean isResourceNotFound(CVSException e) {
		return e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND;
	}
	
	/**
	 * Begins a batch of operations in order to optimize sync file writing. 
	 * The provided scheduling rule indicates the resources
	 * that the resources affected by the operation while the returned scheduling rule
	 * is the rule obtained by the lock. It may differ from the provided rule as it must
	 * encompass any sync files that may change as a result of the operation.
	 */
	public ISchedulingRule beginBatching(ISchedulingRule resourceRule, IProgressMonitor monitor) {
		return resourceLock.acquire(resourceRule, this /* IFlushOperation */, monitor);
	}
	
	/**
	 * Ends a batch of operations. The provided rule must be the one that was returned
	 * by the corresponding call to beginBatching.
	 * <p>
	 * Progress cancellation is ignored while writting the cache to disk. This
	 * is to ensure cache to disk consistency.
	 * </p>
	 * 
	 * @param monitor the progress monitor, may be null
	 * @exception CVSException with a status with code <code>COMMITTING_SYNC_INFO_FAILED</code>
	 * if all the CVS sync information could not be written to disk.
	 */
	public void endBatching(ISchedulingRule rule, IProgressMonitor monitor) throws CVSException {
		try {
            resourceLock.release(rule, monitor);
        } catch (TeamException e) {
            throw CVSException.wrapException(e);
        }
	}
	
	/* (non-Javadoc)
	 * 
	 * Callback which is invoked when the batching resource lock is released 
	 * or when a flush is requested (see beginBatching(IResource)).
	 * 
	 * @see org.eclipse.team.internal.ccvs.core.syncinfo.ReentrantLock.IRunnableOnExit#run(org.eclipse.team.internal.ccvs.core.syncinfo.ReentrantLock.ThreadInfo, org.eclipse.core.runtime.IProgressMonitor)
	 */
	public void flush(final ThreadInfo info, IProgressMonitor monitor) throws CVSException {
		if (info != null && !info.isEmpty()) {
			try {
				ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
					public void run(IProgressMonitor pm) throws CoreException {
						IStatus status = commitCache(info, pm);
						if (!status.isOK()) {
							throw new CVSException(status);
						}
					}
				}, null, 0 /* no flags */, monitor);
			} catch (CoreException e) {
				throw CVSException.wrapException(e);
			}
		}
	}
	
	/*
	 * Begin an access to the internal data structures of the synchronizer
	 */
	private void beginOperation() {
		try {
            // Do not try to acquire the lock if the resources tree is locked
            // The reason for this is that during the resource delta phase (i.e. when the tree is locked)
            // the workspace lock is held. If we obtain our lock, there is 
            // a chance of dealock. It is OK if we don't as we are still protected
            // by scheduling rules and the workspace lock.
            if (ResourcesPlugin.getWorkspace().isTreeLocked()) return;
        } catch (RuntimeException e) {
		    // If we are not active, throw a cancel. Otherwise, propogate it.
		    // (see bug 78303)
		    if (Platform.getBundle(CVSProviderPlugin.ID).getState() == Bundle.ACTIVE) {
		        throw e;
		    } else {
		        throw new OperationCanceledException();
		    }
        }
		lock.acquire();
	}
	
	/*
	 * End an access to the internal data structures of the synchronizer
	 */
	private void endOperation() {
		try {
            // See beginOperation() for a description of why the lock is not obtained when the tree is locked
            if (ResourcesPlugin.getWorkspace().isTreeLocked()) return;
        } catch (RuntimeException e) {
		    // If we are not active, throw a cancel. Otherwise, propogate it.
		    // (see bug 78303)
		    if (Platform.getBundle(CVSProviderPlugin.ID).getState() == Bundle.ACTIVE) {
		        throw e;
		    } else {
		        throw new OperationCanceledException();
		    }
        }
		lock.release();
	}
	
	/**
	 * Flush the sync information from the in-memory cache to disk and purge
	 * the entries from the cache.
	 * <p>
	 * Recursively flushes the sync information for all resources 
	 * below the root to disk and purges the entries from memory
	 * so that the next time it is accessed it will be retrieved from disk.
	 * May flush more sync information than strictly needed, but never less.
	 * </p>
	 * 
	 * @param root the root of the subtree to purge
	 * @param deep purge sync from child folders
	 * @param monitor the progress monitor, may be null
	 */
	public void flush(IContainer root, boolean deep, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 10);
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(root, Policy.subMonitorFor(monitor, 1));
			try {
				beginOperation();
				try {
					// Flush changes to disk
					resourceLock.flush(Policy.subMonitorFor(monitor, 8));
				} catch (TeamException e) {
				    throw CVSException.wrapException(e);
                } finally {
					// Purge the in-memory cache
					sessionPropertyCache.purgeCache(root, deep);
				}
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 1));
			monitor.done();
		}
	}

	public void deconfigure(final IProject project, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(project, Policy.subMonitorFor(monitor, 10));
			// Flush the sync info
			flush(project, true /* deep */, Policy.subMonitorFor(monitor, 80));
			
			purgeDirtyCache(project, Policy.subMonitorFor(monitor, 5));
				
			// forget about pruned folders however the top level pruned folder will have resource sync (e.g. 
			// a line in the Entry file). As a result the folder is managed but is not a CVS folder.
			synchronizerCache.purgeCache(project, true);
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 5));
			monitor.done();
		}
	}

	/**
	 * Called to notify the synchronizer that meta files have changed on disk, outside 
	 * of the workbench. The cache will be flushed for this folder and it's immediate
	 * children and appropriate state change events are broadcasts to state change
	 * listeners.
	 */
	public void ignoreFilesChanged(IContainer[] roots) throws CVSException {
		for (int i = 0; i < roots.length; i++) {
			IContainer container = roots[i];
            if (container.exists()) {
    			ISchedulingRule rule = null;
    			try {
    				Set changed = new HashSet();
    				rule = beginBatching(container, null);
    				try {
    					beginOperation();
                        
                        // Record the previous ignore pattterns
                        FileNameMatcher oldIgnores = null;
                        if (sessionPropertyCache.isFolderSyncInfoCached(container)) {
                            oldIgnores = cacheFolderIgnores(container);
                        }
                        
                        // Purge the cached state for direct children of the container
    					changed.addAll(Arrays.asList(
    						sessionPropertyCache.purgeCache(container, oldIgnores == null /*flush deeply if the old patterns are not known*/)));
                        
                        // Purge the state for any children of previously ignored containers
                        if (oldIgnores != null) {
                            FileNameMatcher newIgnores = cacheFolderIgnores(container);
                            try {
                                IResource[] members = container.members();
                                for (int j = 0; j < members.length; j++) {
                                    IResource resource = members[j];
                                    if (resource.getType() == IResource.FOLDER) {
                                        String name = resource.getName();
                                        if (oldIgnores.match(name) && !newIgnores.match(name)) {
                                            changed.addAll(Arrays.asList(
                                                    sessionPropertyCache.purgeCache((IContainer)resource, true /*flush deeply*/)));
                                        }
                                    }
                                }
                            } catch (CoreException e) {
                                // Just log and continue
                                CVSProviderPlugin.log(e);
                            }
                        }
    				} finally {
    					endOperation();
    				}
    				if (!changed.isEmpty()) {
    					ResourceStateChangeListeners.getListener().resourceSyncInfoChanged(
    						(IResource[]) changed.toArray(new IResource[changed.size()]));
    				}
    			} finally {
    				if (rule != null) endBatching(rule, null);
    			}
            }
		}
	}
	
	public void syncFilesChangedExternally(IContainer[] changedMetaFiles, IFile[] externalDeletions) throws CVSException {
		List changed = new ArrayList();
		for (int i = 0; i < changedMetaFiles.length; i++) {
			IContainer container = changedMetaFiles[i];
			if (!isWithinActiveOperationScope(container)) {
				changed.addAll(Arrays.asList(
					sessionPropertyCache.purgeCache(container, false /*don't flush children*/)));
			}
		}
		for (int i = 0; i < externalDeletions.length; i++) {
			IFile file = externalDeletions[i];
			if (!isWithinActiveOperationScope(file)) {
				sessionPropertyCache.purgeCache(file.getParent(), false /*don't flush children*/);
				changed.add(file);
			}
		}
		if (!changed.isEmpty()) {
			ResourceStateChangeListeners.getListener().externalSyncInfoChange(
					(IResource[]) changed.toArray(new IResource[changed.size()]));
		}
	}
	
	/*
	 * The resource is about to be deleted by the move delete hook.
	 * In all cases (except when the resource doesn't exist), this method 
	 * will indicate that the dirty state of the parent needs to be recomputed.
	 * For managed resources, it will move the cached sync info from the session
	 * property cache into the sycnrhonizer cache, purging the session cache.
	 * @param resource the resource about to be deleted.
	 * <p>
	 * Note taht this method is not recursive. Hence, for managed resources
	 * 
	 * @returns whether children need to be prepared
	 * @throws CVSException
	 */
	/* private */ boolean prepareForDeletion(IResource resource) throws CVSException {
		if (!resource.exists()) return false;
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(resource, null);
			try {
				beginOperation();
				// Flush the dirty info for the resource and it's ancestors.
				// Although we could be smarter, we need to do this because the
				// deletion may fail.
				adjustDirtyStateRecursively(resource, RECOMPUTE_INDICATOR);
				if (resource.getType() == IResource.FILE) {
					byte[] syncBytes = getSyncBytes(resource);
					if (syncBytes != null) {
						if (ResourceSyncInfo.isAddition(syncBytes)) {
							deleteResourceSync(resource);
						} else {
							syncBytes = convertToDeletion(syncBytes);
							synchronizerCache.setCachedSyncBytes(resource, syncBytes, true);
						}
						sessionPropertyCache.purgeResourceSyncCache(resource);
						resourceChanged(resource);
					}
					return false;
				} else {
					IContainer container = (IContainer)resource;
					if (container.getType() == IResource.PROJECT) {
						synchronizerCache.flush((IProject)container);
						return false;
					} else {
						// Move the folder sync info into phantom space
						FolderSyncInfo info = getFolderSync(container);
						if (info == null) return false;
						synchronizerCache.setCachedFolderSync(container, info, true);
						folderChanged(container);
						// move the resource sync as well
						byte[] syncBytes = getSyncBytes(resource);
						synchronizerCache.setCachedSyncBytes(resource, syncBytes, true);
						sessionPropertyCache.purgeResourceSyncCache(container);
						sessionPropertyCache.purgeCache(container, false);
						return true;
					}
				}
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}
	
	/**
	 * The resource has been deleted. Make sure any cached state is cleared.
	 * This is needed because the move/delete hook is not invoked in all situations
	 * (e.g. external deletion).
	 * 
	 * @param resource
	 * @throws CVSException
	 */
	protected void handleDeleted(IResource resource) throws CVSException {
		if (resource.exists()) return;
		try {
			beginOperation();
			adjustDirtyStateRecursively(resource, RECOMPUTE_INDICATOR);
		} finally {
			endOperation();
		}
	}
	
	/**
	 * Prepare for the deletion of the target resource from within 
	 * the move/delete hook. The method is invoked by both the 
	 * deleteFile/Folder methods and for the source resource
	 * of moveFile/Folder. This method will move the cached sync info
	 * into the phantom (ISynchronizer) cache so that outgoing deletions
	 * and known remote folders are preserved.
	 * 
	 * @param resource
	 * @param monitor
	 * @throws CVSException
	 */
	public void prepareForDeletion(IResource resource, IProgressMonitor monitor) throws CVSException {
		// Move sync info to phantom space for the resource and all it's children
		monitor = Policy.monitorFor(monitor);
		try {
			beginOperation();
			monitor.beginTask(null, 100);
			try {
				resource.accept(new IResourceVisitor() {
					public boolean visit(IResource innerResource) throws CoreException {
						try {
							return prepareForDeletion(innerResource);
						} catch (CVSException e) {
							CVSProviderPlugin.log(e);
							throw new CoreException(e.getStatus());
						}
					}
				});
			} catch (CoreException e) {
				throw CVSException.wrapException(e);
			}
		} finally {
			endOperation();
			monitor.done();
		}
	}
	
	/**
	 * If not already cached, loads and caches the resource sync for the children of the container.
	 * Folder must exist and must not be the workspace root.
	 *
	 * @param container the container
	 */
	private void cacheResourceSyncForChildren(IContainer container, boolean canModifyWorkspace) throws CVSException {
		// don't try to load if the information is already cached
		if (! getSyncInfoCacheFor(container).isResourceSyncInfoCached(container)) {
			// load the sync info from disk
			byte[][] infos;
			// do not load the sync info for resources that are linked
			if (isLinkedResource(container)) {
				infos = null;
			} else {
				infos = SyncFileWriter.readAllResourceSync(container);
			}
			try {
				if (infos != null) {
					for (int i = 0; i < infos.length; i++) {
						byte[] syncBytes = infos[i];
						IPath name = new Path(null, getName(syncBytes));
						IResource resource;
						if (isFolder(syncBytes)) {
							resource = container.getFolder(name);
						} else {
							resource = container.getFile(name);
						}
						getSyncInfoCacheFor(resource).setCachedSyncBytes(resource, syncBytes, canModifyWorkspace);
					}
				}
				getSyncInfoCacheFor(container).setResourceSyncInfoCached(container);
			} catch (CVSException e) {
				if (Policy.DEBUG_METAFILE_CHANGES) {
					System.err.println("Failed to cache Entries for folder " + container.getFullPath()); //$NON-NLS-1$
				}
				throw e;
			}
		}
	}
	
	/**
	 * If not already cached, loads and caches the folder sync for the
	 * container. Folder must exist and must not be the workspace root.
	 *
	 * @param container the container
	 */
	private void cacheFolderSync(IContainer container) throws CVSException {
		// don't try to load if the information is already cached
		if (! getSyncInfoCacheFor(container).isFolderSyncInfoCached(container)) {
			// load the sync info from disk
			FolderSyncInfo info;
			// do not load the sync info for resources that are linked
			if (isLinkedResource(container)) {
				info = null;
			} else {
				info = SyncFileWriter.readFolderSync(container);
			}
			getSyncInfoCacheFor(container).setCachedFolderSync(container, info, false);
		}
	}
	
	private boolean isLinkedResource(IResource resource) {
		return CVSWorkspaceRoot.isLinkedResource(resource);
	}

	/**
	 * Load the sync info for the given resource from disk
	 * @param resource
	 * @return byte[]
	 */
	private byte[] getSyncBytesFromDisk(IResource resource) throws CVSException {
		byte[][] infos = SyncFileWriter.readAllResourceSync(resource.getParent());
		if (infos == null) return null;
		for (int i = 0; i < infos.length; i++) {
			byte[] syncBytes = infos[i];
			if (resource.getName().equals(getName(syncBytes))) {
				return syncBytes;
			}
		}
		return null;
	}
	
	/**
	 * Commits the cache after a series of operations.
	 * 
	 * Will return STATUS_OK unless there were problems writting sync 
	 * information to disk. If an error occurs a multistatus is returned
	 * with the list of reasons for the failures. Failures are recovered,
	 * and all changed resources are given a chance to be written to disk.
	 * 
	 * @param monitor the progress monitor, may be null
	 */
	/* internal use only */ IStatus commitCache(ThreadInfo threadInfo, IProgressMonitor monitor) {
		if (threadInfo.isEmpty()) {
			return SyncInfoCache.STATUS_OK;
		}
		List errors = new ArrayList();
		try {
			/*** prepare operation ***/
			// find parents of changed resources
			IResource[] changedResources = threadInfo.getChangedResources();
			IContainer[] changedFolders;
			if (threadInfo instanceof CVSThreadInfo) {
			    changedFolders = ((CVSThreadInfo)threadInfo).getChangedFolders();
			} else {
			    changedFolders = new IContainer[0];
			}
			Set dirtyParents = new HashSet();
			for (int i = 0; i < changedResources.length; i++) {
				IResource resource = changedResources[i];
				IContainer folder = resource.getParent();
				dirtyParents.add(folder);
			}
			
			monitor = Policy.monitorFor(monitor);
			int numDirty = dirtyParents.size();
			int numResources = changedFolders.length + numDirty;
			monitor.beginTask(null, numResources);
			if(monitor.isCanceled()) {
				monitor.subTask(CVSMessages.EclipseSynchronizer_UpdatingSyncEndOperationCancelled); 
			} else {
				monitor.subTask(CVSMessages.EclipseSynchronizer_UpdatingSyncEndOperation); 
			}
			
			/*** write sync info to disk ***/
			// folder sync info changes
			for (int i = 0; i < changedFolders.length; i++) {
				IContainer folder = changedFolders[i];
				if (folder.exists() && folder.getType() != IResource.ROOT) {
					try {
                        beginOperation();
						FolderSyncInfo info = sessionPropertyCache.getCachedFolderSync(folder, true);
						// Do not write the folder sync for linked resources
						if (info == null) {
							// deleted folder sync info since we loaded it
							// (but don't overwrite the sync info for linked folders
							if (!isLinkedResource(folder))
								SyncFileWriter.deleteFolderSync(folder);
							dirtyParents.remove(folder);
						} else {
							// modified or created new folder sync info since we loaded it
							SyncFileWriter.writeFolderSync(folder, info);
						}
					} catch(CVSException e) {					
						try {
							sessionPropertyCache.purgeCache(folder, true /* deep */);
						} catch(CVSException pe) {
							errors.add(pe.getStatus());
						}
						errors.add(e.getStatus());
					} finally {
                        endOperation();
                    }
				}
				monitor.worked(1);
			}

			// update progress for parents we will skip because they were deleted
			monitor.worked(numDirty - dirtyParents.size());

			// resource sync info changes
			for (Iterator it = dirtyParents.iterator(); it.hasNext();) {
				IContainer folder = (IContainer) it.next();
				if (folder.exists() && folder.getType() != IResource.ROOT) {
					// write sync info for all children in one go
					try {
                        beginOperation();
						List infos = new ArrayList();
						IResource[] children = folder.members(true);
						for (int i = 0; i < children.length; i++) {
							IResource resource = children[i];
							byte[] syncBytes = getSyncBytes(resource);
							if (syncBytes != null) {
								infos.add(syncBytes);
							}
						}
						// do not overwrite the sync info for linked resources
						if (infos.size() > 0 || !isLinkedResource(folder))
							SyncFileWriter.writeAllResourceSync(folder,
								(byte[][]) infos.toArray(new byte[infos.size()][]));
					} catch(CVSException e) {
						try {
							sessionPropertyCache.purgeCache(folder, false /* depth 1 */);
						} catch(CVSException pe) {
							errors.add(pe.getStatus());
						}							
						errors.add(e.getStatus());
					} catch (CoreException e) {
						try {
							sessionPropertyCache.purgeCache(folder, false /* depth 1 */);
						} catch(CVSException pe) {
							errors.add(pe.getStatus());
						}							
						errors.add(e.getStatus());
					} finally {
                        endOperation();
                    }
				}
				monitor.worked(1);
			}
			
			/*** broadcast events ***/
			monitor.subTask(CVSMessages.EclipseSynchronizer_NotifyingListeners); 
			Set allChanges = new HashSet();
			allChanges.addAll(Arrays.asList(changedResources));
			allChanges.addAll(Arrays.asList(changedFolders));
			allChanges.addAll(dirtyParents);	
			IResource[] resources = (IResource[]) allChanges.toArray(
				new IResource[allChanges.size()]);
			broadcastResourceStateChanges(resources);
			if ( ! errors.isEmpty()) {
				MultiStatus status = new MultiStatus(CVSProviderPlugin.ID, 
											CVSStatus.COMMITTING_SYNC_INFO_FAILED, 
											CVSMessages.EclipseSynchronizer_ErrorCommitting, 
											null);
				for (int i = 0; i < errors.size(); i++) {
					status.merge((IStatus)errors.get(i));
				}
				return status;
			}
			return SyncInfoCache.STATUS_OK;
		} finally {
			monitor.done();
		}
	}

	/**
	 * Broadcasts the resource state changes for the given resources to CVS Provider Plugin
	 */
	void broadcastResourceStateChanges(IResource[] resources) {
		if (resources.length > 0) {
			ResourceStateChangeListeners.getListener().resourceSyncInfoChanged(resources);
		}
	}

	/**
	 * Returns the resource sync info for the resource; null if none.
	 * Parent must exist and must not be the workspace root.
	 * The resource sync info for the children of the parent container MUST ALREADY BE CACHED.
	 * 
	 * @param resource the resource
	 * @return the resource sync info for the resource, or null
	 * @see #cacheResourceSyncForChildren
	 */
	private byte[] getCachedSyncBytes(IResource resource) throws CVSException {
		return getSyncInfoCacheFor(resource).getCachedSyncBytes(resource, true);
	}

	/**
	 * Returns the resource sync info for the resource; null if none.
	 * Parent must exist and must not be the workspace root.
	 * The resource sync info for the children of the parent container MUST ALREADY BE CACHED.
	 * 
	 * @param resource the resource
	 * @return the resource sync info for the resource, or null
	 * @see #cacheResourceSyncForChildren
	 */
	private void setCachedSyncBytes(IResource resource, byte[] syncBytes) throws CVSException {
		getSyncInfoCacheFor(resource).setCachedSyncBytes(resource, syncBytes, true);
		resourceChanged(resource);
	}
		
	/**
 	 * Sets the resource sync info for the resource; if null, deletes it. Parent
 	 * must exist and must not be the workspace root. The resource sync info for
 	 * the children of the parent container MUST ALREADY BE CACHED.
	 * 
	 * @param resource the resource
	 * @param info the new resource sync info
	 * @see #cacheResourceSyncForChildren
	 */
	private void setCachedResourceSync(IResource resource, ResourceSyncInfo info) throws CVSException {
		//todo
		byte[] syncBytes = null;
		if (info != null) syncBytes = info.getBytes();
		getSyncInfoCacheFor(resource).setCachedSyncBytes(resource, syncBytes, true);
	}
	
	/**
	 * If not already cached, loads and caches the folder ignores sync for the container.
	 * Folder must exist and must not be the workspace root.
	 * 
	 * @param container the container
	 * @return the folder ignore patterns, or an empty array if none
	 */
	private FileNameMatcher cacheFolderIgnores(IContainer container) throws CVSException {
		return sessionPropertyCache.getFolderIgnores(container, true);
	}
	
	/**
	 * Sets the array of folder ignore patterns for the container, must not be null.
	 * Folder must exist and must not be the workspace root.
	 * 
	 * @param container the container
	 * @param ignores the array of ignore patterns
	 */
	private void setCachedFolderIgnores(IContainer container, String[] ignores) throws CVSException {
		sessionPropertyCache.setCachedFolderIgnores(container, ignores);
	}
	
	/*
	 * Recursively adds to the possibleIgnores list all children of the given 
	 * folder that can be ignored. This method may only be invoked when a 
	 * schedling rule for the given foldr is held and when the CVs sync lock is
	 * held.
	 * 
	 * @param folder the folder to be searched
	 * @param possibleIgnores the list of IResources that can be ignored
	 */
	private void accumulateNonManagedChildren(IContainer folder, List possibleIgnores) throws CVSException {
		try {
			cacheResourceSyncForChildren(folder, true /* can modify workspace */);
			IResource[] children = folder.members();
			List folders = new ArrayList();
			// deal with all files first and then folders to be otimized for caching scheme
			for (int i = 0; i < children.length; i++) {
				IResource child = children[i];
				if(getCachedSyncBytes(child)==null) {
					possibleIgnores.add(child);
				}
				if(child.getType()!=IResource.FILE) {
					folders.add(child);
				}
			}
			for (Iterator iter = folders.iterator(); iter.hasNext();) {
				IContainer child = (IContainer) iter.next();
				accumulateNonManagedChildren(child, possibleIgnores);
			}
		} catch(CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	/**
	 * Add the entry to the CVS/Notify file. We are not initially concerned with efficiency
	 * since edit/unedit are typically issued on a small set of files.
	 * 
	 * XXX If there was a previous notify entry for the resource, it is replaced. This is
	 * probably not the proper behavior (see EclipseFile).
	 * 
	 * A value of null for info indicates that any entry for the given
	 * resource is to be removed from the Notify file.
	 * 
	 * @param resource
	 * @param info
	 */
	public void setNotifyInfo(IResource resource, NotifyInfo info) throws CVSException {
		NotifyInfo[] infos = SyncFileWriter.readAllNotifyInfo(resource.getParent());
		if (infos == null) {
			// if the file is empty and we are removing an entry, just return;
			if (info == null) return;
			infos = new NotifyInfo[] { info };
		} else {
			Map infoMap = new HashMap();
			for (int i = 0; i < infos.length; i++) {
				NotifyInfo notifyInfo = infos[i];
				infoMap.put(notifyInfo.getName(), notifyInfo);
			}
			if (info == null) {
				// if the info is null, remove the entry
				infoMap.remove(resource.getName());
			} else {
				// add the new entry to the list
				infoMap.put(info.getName(), info);
			}
			
			NotifyInfo[] newInfos = new NotifyInfo[infoMap.size()];
			int i = 0;
			for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) {
				newInfos[i++] = (NotifyInfo) iter.next();
			}
			infos = newInfos;
		}
		SyncFileWriter.writeAllNotifyInfo(resource.getParent(), infos);
	}

	/**
	 * Method getNotifyInfo.
	 * @param resource
	 * @return NotifyInfo
	 */
	public NotifyInfo getNotifyInfo(IResource resource) throws CVSException {
		NotifyInfo[] infos = SyncFileWriter.readAllNotifyInfo(resource.getParent());
		if (infos == null) return null;
		for (int i = 0; i < infos.length; i++) {
			NotifyInfo notifyInfo = infos[i];
			if (notifyInfo.getName().equals(resource.getName())) {
				return notifyInfo;
			}
		}
		return null;
	}

	/**
	 * Method deleteNotifyInfo.
	 * @param resource
	 */
	public void deleteNotifyInfo(IResource resource) throws CVSException {
		NotifyInfo[] infos = SyncFileWriter.readAllNotifyInfo(resource.getParent());
		if (infos == null) return;
		Map infoMap = new HashMap();
		for (int i = 0; i < infos.length; i++) {
			NotifyInfo notifyInfo = infos[i];
			infoMap.put(notifyInfo.getName(), notifyInfo);
		}
		infoMap.remove(resource.getName());
		NotifyInfo[] newInfos = new NotifyInfo[infoMap.size()];
		int i = 0;
		for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) {
			newInfos[i++] = (NotifyInfo) iter.next();
		}
		SyncFileWriter.writeAllNotifyInfo(resource.getParent(), newInfos);
	}
	
	/**
	 * Add the entry to the CVS/Baserev file. We are not initially concerned
	 * with efficiency since edit/unedit are typically issued on a small set of
	 * files.
	 *
	 * XXX If there was a previous notify entry for the resource, it is replaced. This is
	 * probably not the proper behavior (see EclipseFile).
	 *
	 * @param resource
	 * @param info
	 */
	public void setBaserevInfo(IResource resource, BaserevInfo info) throws CVSException {
		BaserevInfo[] infos = SyncFileWriter.readAllBaserevInfo(resource.getParent());
		if (infos == null) {
			infos = new BaserevInfo[] { info };
		} else {
			Map infoMap = new HashMap();
			for (int i = 0; i < infos.length; i++) {
				infoMap.put(infos[i].getName(), infos[i]);
			}
			infoMap.put(info.getName(), info);
			BaserevInfo[] newInfos = new BaserevInfo[infoMap.size()];
			int i = 0;
			for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) {
				newInfos[i++] = (BaserevInfo) iter.next();
			}
			infos = newInfos;
		}
		SyncFileWriter.writeAllBaserevInfo(resource.getParent(), infos);
	}

	/**
	 * Method getBaserevInfo.
	 * @param resource
	 * @return BaserevInfo
	 */
	public BaserevInfo getBaserevInfo(IResource resource) throws CVSException {
		BaserevInfo[] infos = SyncFileWriter.readAllBaserevInfo(resource.getParent());
		if (infos == null) return null;
		for (int i = 0; i < infos.length; i++) {
			BaserevInfo info = infos[i];
			if (info.getName().equals(resource.getName())) {
				return info;
			}
		}
		return null;
	}
			
	/**
	 * Method deleteNotifyInfo.
	 * @param resource
	 */
	public void deleteBaserevInfo(IResource resource) throws CVSException {
		BaserevInfo[] infos = SyncFileWriter.readAllBaserevInfo(resource.getParent());
		if (infos == null) return;
		Map infoMap = new HashMap();
		for (int i = 0; i < infos.length; i++) {
			infoMap.put(infos[i].getName(), infos[i]);
		}
		infoMap.remove(resource.getName());
		BaserevInfo[] newInfos = new BaserevInfo[infoMap.size()];
		int i = 0;
		for (Iterator iter = infoMap.values().iterator(); iter.hasNext();) {
			newInfos[i++] = (BaserevInfo) iter.next();
		}
		SyncFileWriter.writeAllBaserevInfo(resource.getParent(), newInfos);
	}

	public void copyFileToBaseDirectory(final IFile file, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(file, Policy.subMonitorFor(monitor, 10));
			ResourceSyncInfo info = getResourceSync(file);
			// The file must exist remotely and locally
			if (info == null || info.isAdded() || info.isDeleted())
				return;
			SyncFileWriter.writeFileToBaseDirectory(file, Policy.subMonitorFor(monitor, 80));
			resourceChanged(file);
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 10));
			monitor.done();
		}
	}
	
	public void restoreFileFromBaseDirectory(final IFile file, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		ISchedulingRule rule = null;
		try {
			rule = beginBatching(file, Policy.subMonitorFor(monitor, 10));
			ResourceSyncInfo info = getResourceSync(file);
			// The file must exist remotely
			if (info == null || info.isAdded())
				return;
			SyncFileWriter.restoreFileFromBaseDirectory(file, Policy.subMonitorFor(monitor, 80));
			resourceChanged(file);
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 10));
			monitor.done();
		}
	}
	
	public void deleteFileFromBaseDirectory(final IFile file, IProgressMonitor monitor) throws CVSException {
		ResourceSyncInfo info = getResourceSync(file);
		// The file must exist remotely
		if (info == null || info.isAdded())
			return;
		SyncFileWriter.deleteFileFromBaseDirectory(file, monitor);
	}
	
	/**
	 * Method isSyncInfoLoaded returns true if all the sync info for the
	 * provided resources is loaded into the internal cache.
	 * 
	 * @param resources
	 * @param i
	 * @return boolean
	 */
	public boolean isSyncInfoLoaded(IResource[] resources, int depth) throws CVSException {
		// get the folders involved
		IContainer[] folders = getParentFolders(resources, depth);
		// for all folders that have a CVS folder, ensure the sync info is cached
		for (int i = 0; i < folders.length; i++) {
			IContainer parent = folders[i];
			if (!getSyncInfoCacheFor(parent).isSyncInfoLoaded(parent)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Method ensureSyncInfoLoaded loads all the relevent sync info into the cache.
	 * This method can only be invoked when the workspace is open for modification.
	 * in other words it cannot be invoked from inside a POST_CHANGE delta listener.
	 * @param resources
	 * @param i
	 * @return Object
	 */
	public void ensureSyncInfoLoaded(IResource[] resources, int depth) throws CVSException {
		// get the folders involved
		IContainer[] folders = getParentFolders(resources, depth);
		// Cache the sync info for all the folders
		for (int i = 0; i < folders.length; i++) {
			IContainer parent = folders[i];
			ISchedulingRule rule = null;
			try {
				rule = beginBatching(parent, null);
				try {
					beginOperation();
					cacheResourceSyncForChildren(parent, true /* can modify workspace */);
					cacheFolderSync(parent);
					cacheFolderIgnores(parent);
				} finally {
					endOperation();
				}
			} finally {
				if (rule != null) endBatching(rule, null);
			}
		}
	}

	/*
	 * Collect the projects and parent folders of the resources since 
	 * thats were the sync info is kept.
	 */
	private IContainer[] getParentFolders(IResource[] resources, int depth) throws CVSException {
		final Set folders = new HashSet();
		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			folders.add(resource.getProject());
			if (resource.getType() != IResource.PROJECT) {
				folders.add(resource.getParent());
			}
			// use the depth to gather child folders when appropriate
			if (depth != IResource.DEPTH_ZERO) {
				try {
					resource.accept(new IResourceVisitor() {
						public boolean visit(IResource innerResource) throws CoreException {
							if (innerResource.getType() == IResource.FOLDER)
								folders.add(innerResource);
							// let the depth determine who we visit
							return true;
						}
					}, depth, false);
				} catch (CoreException e) {
					throw CVSException.wrapException(e);
				}
			}
		}
		return (IContainer[]) folders.toArray(new IContainer[folders.size()]);
	}
	
	/**
	 * Perform sync info batching within the context of the given resource
	 * scheduling rule while running the given ICVSRunnable.
	 * @param runnable
	 * @param monitor
	 * @throws CVSException
	 */
	public void run(ISchedulingRule resourceRule, ICVSRunnable runnable, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		ISchedulingRule rule = beginBatching(resourceRule, Policy.subMonitorFor(monitor, 1));
		try {
			runnable.run(Policy.subMonitorFor(monitor, 98));
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 1));
			monitor.done();
		}
	}
	
	/**
	 * Method isEdited returns true if a "cvs edit" was performed on the given
	 * file and no commit or unedit has yet been performed.
	 * @param iResource
	 * @return boolean
	 */
	public boolean isEdited(IFile resource) {
		return SyncFileWriter.isEdited(resource);
	}
	
	/* package */ void adjustDirtyStateRecursively(IResource resource, String indicator) throws CVSException {
		if (resource.getType() == IResource.ROOT) return;
		try {
			beginOperation();
			
			if (getSyncInfoCacheFor(resource).cachesDirtyState()) {
				if (indicator == getDirtyIndicator(resource)) {
					return;
				}
				getSyncInfoCacheFor(resource).setDirtyIndicator(resource, indicator);	
			} 					
			
			if (Policy.DEBUG_DIRTY_CACHING) {
				debug(resource, indicator, "adjusting dirty state"); //$NON-NLS-1$
			}									

			IContainer parent = resource.getParent();
			if(indicator == NOT_DIRTY_INDICATOR) {
				adjustDirtyStateRecursively(parent, RECOMPUTE_INDICATOR);
			}
			
			if(indicator == RECOMPUTE_INDICATOR) {
				adjustDirtyStateRecursively(parent, RECOMPUTE_INDICATOR);
			} 
			
			if(indicator == IS_DIRTY_INDICATOR) {
				adjustDirtyStateRecursively(parent, indicator);
			} 
		} finally {
			endOperation();
		}
	}

	protected String getDirtyIndicator(IResource resource) throws CVSException {
        // Do a check outside the lock for the dirty indicator
        String indicator = getSyncInfoCacheFor(resource).getDirtyIndicator(resource, false /* not thread safe */);
        if (indicator != null)
            return indicator;
		try {
			beginOperation();
			return getSyncInfoCacheFor(resource).getDirtyIndicator(resource, true);
		} finally {
			endOperation();
		}
	}
	
	/*
	 * Mark the given resource as either modified or clean using a persistant
	 * property. Do nothing if the modified state is already what we want.
	 * Return true if the modification state was changed.
	 */
	protected void setDirtyIndicator(IResource resource, boolean modified) throws CVSException {
		String indicator = modified ? IS_DIRTY_INDICATOR : NOT_DIRTY_INDICATOR;
		// set the dirty indicator and adjust the parent accordingly			
		adjustDirtyStateRecursively(resource, indicator);
	}

	/**
	 * Method getName.
	 * @param syncBytes
	 */
	private String getName(byte[] syncBytes) throws CVSException {
		return ResourceSyncInfo.getName(syncBytes);
	}
	
	/**
	 * Method isFolder.
	 * @param syncBytes
	 * @return boolean
	 */
	private boolean isFolder(byte[] syncBytes) {
		return ResourceSyncInfo.isFolder(syncBytes);
	}
		
	/**
	 * Method convertToDeletion.
	 * @param syncBytes
	 * @return byte[]
	 */
	private byte[] convertToDeletion(byte[] syncBytes) throws CVSException {
		return ResourceSyncInfo.convertToDeletion(syncBytes);
	}

	static public void debug(IResource resource, String indicator, String string) {
		String di = EclipseSynchronizer.IS_DIRTY_INDICATOR;
		if(indicator == EclipseSynchronizer.IS_DIRTY_INDICATOR) {
			di = "dirty";	//$NON-NLS-1$
		} else if(indicator == EclipseSynchronizer.NOT_DIRTY_INDICATOR) {
			di = "clean";	//$NON-NLS-1$
		} else {
			di = "needs recomputing";	//$NON-NLS-1$
		} 
		System.out.println("["+string + ":" + di + "]  "  + resource.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}
	
	/**
	 * @param file
	 * @return int
	 */
	public int getModificationState(IResource resource) throws CVSException {
		String indicator =  getDirtyIndicator(resource);
		if (Policy.DEBUG_DIRTY_CACHING) {
			debug(resource, indicator, "getModificationState"); //$NON-NLS-1$
		}
		if (indicator == null || indicator == RECOMPUTE_INDICATOR) {
			return ICVSFile.UNKNOWN;
		} else if (indicator == IS_DIRTY_INDICATOR) {
			return ICVSFile.DIRTY;
		} else if (indicator == NOT_DIRTY_INDICATOR) {
			return ICVSFile.CLEAN;
		} else {
			return ICVSFile.UNKNOWN;
		}
	}

	/**
	 * Return whether the resource is within the scope of a currently active
	 * CVS operation.
	 * @param resource
	 * @return
	 */
	public boolean isWithinActiveOperationScope(IResource resource) {
		return resourceLock.isWithinActiveOperationScope(resource);
	}
	
	/**
	 * Set the timestamp of the given file and set it to be CLEAN. It is
	 * assumed that this method is only invoked to reset the file timestamp
	 * to the timestamp that is in the CVS/Entries file.
	 * @param file
	 * @param time
	 * @throws CVSException
	 */
	public void setTimeStamp(EclipseFile cvsFile, long time) throws CVSException {
		ISchedulingRule rule = null;
		IFile file = (IFile)cvsFile.getIResource();
		try {
			rule = beginBatching(file, null);
			try {
				beginOperation();
				try {
					file.setLocalTimeStamp(time);
					setModified(cvsFile, ICVSFile.CLEAN);
				} catch (CoreException e) {
					throw CVSException.wrapException(e);
				}
				resourceChanged(file);		
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, null);
		}
	}

	/**
	 * React to a resource that was just moved by the move/delete hook.
	 * @param resource the resource that was moved (at its new location)
	 */
	public void postMove(IResource resource) throws CVSException {
		try {
			beginOperation();
			if (resource.getType() == IResource.FILE) {
				// Purge any copied sync info so true sync info will 
				// be obtained from the synchronizer cache
				sessionPropertyCache.purgeResourceSyncCache(resource);
			} else {
				IContainer container = (IContainer)resource;
				// Purge any copied sync info
				sessionPropertyCache.purgeCache(container, true /* deep */);
				// Dirty all resources so old sync info will be rewritten to disk
				try {
					container.accept(new IResourceVisitor() {
						public boolean visit(IResource resource) throws CoreException {
							if (getSyncBytes(resource) != null) {
								resourceChanged(resource);
							}
							if (resource.getType() != IResource.FILE) {
								if (getFolderSync((IContainer)resource) != null) {
									folderChanged((IContainer)resource);
									return true;
								}
							}
							return false;
						}
					});
				} catch (CoreException e) {
					throw CVSException.wrapException(e);
				}
				// Flush the sync info to disk
				flush(container, true /* deep */, null);
			}
		} finally {
			endOperation();
		}
	}
	
	/**
	 * This method is to be invoked only from the move/delete hook. It's purpose
	 * is to obtain the sync look in order to prevent other threads from accessing
	 * sync info while the move/delete is taking place.
	 * @param runnable
	 * @param monitor
	 * @throws CVSException
	 */
	public void performMoveDelete(ICVSRunnable runnable, IProgressMonitor monitor) throws CVSException {
		ISchedulingRule rule = null;
		try {
			monitor.beginTask(null, 100);
			rule = beginBatching(null, null);
			try {
				beginOperation();
				runnable.run(Policy.subMonitorFor(monitor, 95));
			} finally {
				endOperation();
			}
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 5));
			monitor.done();
		}
	}
	
	/**
	 * Compute the modification state for the given file. If the modificationState is
	 * ICVSFile.UNKNOWN, it is computed. However, if it is CLEAN or DIRTY, 
	 * it is set accordingly. CLEAN or DIRTY can only be used if the caller is protected
	 * from resource modifications (either by a scheduling rule or inside a delta handler).
	 * @param file
	 * @param modificationState
	 * @return true if the file is dirty
	 */
	public boolean setModified(EclipseFile cvsFile, int modificationState) throws CVSException {
		try {
			beginOperation();
			boolean dirty;
			if (modificationState == ICVSFile.UNKNOWN) {
				dirty = cvsFile.isDirty();
			} else {
				dirty = modificationState == ICVSFile.DIRTY;
			}
			setDirtyIndicator(cvsFile.getIResource(), dirty);
			return dirty;
		} finally {
			endOperation();
		}

	}

	/**
	 * Set the modified state of the folder. This method can be called when no resource locks are
	 * held. It will check the cached modification state of all the folder's children before setting.
	 * If the states of the children do not match, the state for the folder is not cached.
	 * @param folder
	 * @param modified
	 */
	public void setModified(ICVSFolder cvsFolder, boolean modified) throws CVSException {
		try {
			beginOperation();
			IContainer folder = (IContainer)cvsFolder.getIResource();
			// The drop out condition for clean or dirty are the opposite.
			// (i.e. if modified and a dirty is found we can set the indicator
			// and if not modified and a dirty or unknown is found we cannot set the indicator)
			boolean okToSet = !modified;
			// Obtain the children while we're locked to ensure some were not added or changed
			ICVSResource[] children = cvsFolder.members(ICVSFolder.ALL_UNIGNORED_MEMBERS);
			for (int i = 0; i < children.length; i++) {
				IResource resource = children[i].getIResource();
				if (modified) {
					if (getDirtyIndicator(resource) == IS_DIRTY_INDICATOR) {
						okToSet = true;
						break;
					}
				} else {
					if (getDirtyIndicator(resource) != NOT_DIRTY_INDICATOR) {
						okToSet = false;
						break;
					}
				}
			}
			if (okToSet) {
				setDirtyIndicator(folder, modified);
			}
		} finally {
			endOperation();
		}
	}
	
	public boolean wasPhantom(IResource resource) {
		if (resource.exists()) {
			try {
				return (synchronizerCache.getCachedSyncBytes(resource, true) != null 
					|| (resource.getType() == IResource.FOLDER
							&& synchronizerCache.hasCachedFolderSync((IContainer)resource)));
			} catch (CVSException e) {
				// Log and assume resource is not a phantom
				CVSProviderPlugin.log(e);
			}
		}
		return false;
	}
	
	/**
	 * Method called from background handler when resources that are mapped to CVS are recreated
	 * @param resources
	 * @param monitor
	 * @throws CVSException
	 */
	public void resourcesRecreated(IResource[] resources, IProgressMonitor monitor) throws CVSException {
		if (resources.length == 0) return;
		ISchedulingRule rule = null;
		ISchedulingRule projectsRule = getProjectRule(resources);
		try {
			monitor = Policy.monitorFor(monitor);
			monitor.beginTask(null, 100);
			rule = beginBatching(projectsRule, monitor);
			for (int i = 0; i < resources.length; i++) {
				IResource resource = resources[i];
				try {
					created(resource);
				} catch (CVSException e) {
					CVSProviderPlugin.log(e);
				}
			}
		} finally {
			if (rule != null) endBatching(rule, Policy.subMonitorFor(monitor, 5));
			monitor.done();
		}
	}
	
	private ISchedulingRule getProjectRule(IResource[] resources) {
		HashSet set = new HashSet();
		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			set.add(resource.getProject());
		}
		IProject[] projects = (IProject[]) set.toArray(new IProject[set.size()]);
		if (projects.length == 1) {
			return projects[0];
		}
		return new MultiRule(projects);
	}

	protected void created(IResource resource) throws CVSException {
		try {
			beginOperation();
			if (resource.exists()) {
				restoreResourceSync(resource);
				if (resource.getType() == IResource.FOLDER) {
					restoreFolderSync((IFolder)resource);
				}
			}
		} finally {
			endOperation();
		}
	}
	
	/*
	 * Restore the folder sync info for the given folder
	 */
	private void restoreFolderSync(IFolder folder) throws CVSException {
		try {
			// set the dirty count using what was cached in the phantom it
			beginOperation();
			FolderSyncInfo folderInfo = synchronizerCache.getCachedFolderSync(folder, true);
			if (folderInfo != null) {
				// There is folder sync info to restore
				if (folder.getFolder(SyncFileWriter.CVS_DIRNAME).exists()) {
					// There is already a CVS subdirectory which indicates that
					// either the folder was recreated by an external tool or that
					// a folder with CVS information was copied from another location.
					// To know the difference, we need to compare the folder sync info.
					// If they are mapped to the same root and repository then just
					// purge the phantom info. Otherwise, keep the original sync info.

					// Get the new folder sync info
					FolderSyncInfo newFolderInfo = getFolderSync(folder);
					if (newFolderInfo.getRoot().equals(folderInfo.getRoot())
							&& newFolderInfo.getRepository().equals(folderInfo.getRepository())) {
						// The folder is the same so use what is on disk.
						// Fall through to ensure that the Root and Repository files exist
					} else {
						// The folder is mapped to a different location.
						// Purge new resource sync before restoring from phantom
						ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(folder);
						ICVSResource[] children = cvsFolder.members(ICVSFolder.MANAGED_MEMBERS);
						for (int i = 0; i < children.length; i++) {
							ICVSResource resource = children[i];
							deleteResourceSync(resource.getIResource());
						}
					}
				}

				// set the sync info using what was cached in the phantom
				setFolderSync(folder, folderInfo);
				// purge the dirty cache so any old persisted dirty state is purged
				sessionPropertyCache.purgeDirtyCache(folder);
				// if there are managed members, indicate that 1 is changed so the Entries file is written
				IResource[] members = members(folder);
				for (int i = 0; i < members.length; i++) {
					IResource resource = members[i];
					if (getSyncBytes(resource) != null) {
						resourceChanged(resource);
						break;
					}
				}
			}
		} finally {
			try {
				endOperation();
			} finally {
				synchronizerCache.flush(folder);
			}
		}
	}

	/*
	 * Restore the resource sync info for the given resource.
	 */
	private void restoreResourceSync(IResource resource) throws CVSException {
		try {
			beginOperation();
			byte[] syncBytes = synchronizerCache.getCachedSyncBytes(resource, true);
			if (syncBytes != null) {
				if (!ResourceSyncInfo.isFolder(syncBytes)) {
					syncBytes = ResourceSyncInfo.convertFromDeletion(syncBytes);
				}
				byte[] newBytes = getSyncBytes(resource);
				if (newBytes != null && !ResourceSyncInfo.isFolder(newBytes)) {
					newBytes = ResourceSyncInfo.convertFromDeletion(newBytes);
				}
				if (newBytes == null || Util.equals(syncBytes, newBytes)) {
					// only move the sync info if there is no new sync info
					setSyncBytes(resource, syncBytes);
				}
			}
		} finally {
			try {
				endOperation();
			} finally {
				synchronizerCache.setCachedSyncBytes(resource, null, true);
			}
		}
	}
	
	private void purgeDirtyCache(IProject project, IProgressMonitor monitor) throws CVSException {
		sessionPropertyCache.purgeDirtyCache(project);
	}
}
