/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Serge Beauchamp (Freescale Semiconductor) - [229633] Project Path Variable Support
 *******************************************************************************/
package org.eclipse.core.internal.resources;

import java.net.URI;
import org.eclipse.core.filesystem.*;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.localstore.FileSystemResourceManager;
import org.eclipse.core.internal.properties.IPropertyManager;
import org.eclipse.core.internal.utils.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.team.IResourceTree;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.osgi.util.NLS;

/**
 * @since 2.0
 *
 * Implementation note: Since the move/delete hook involves running third
 * party code, the workspace lock is not held.  This means the workspace
 * lock must be re-acquired whenever we need to manipulate the workspace
 * in any way.  All entry points from third party code back into the tree must
 * be done in an acquire/release pair.
 */
class ResourceTree implements IResourceTree {
	private boolean isValid = true;
	private final FileSystemResourceManager localManager;
	/**
	 * The lock to acquire when the workspace needs to be manipulated
	 */
	private ILock lock;
	private MultiStatus multistatus;
	private int updateFlags;

	/**
	 * Constructor for this class.
	 */
	public ResourceTree(FileSystemResourceManager localManager, ILock lock, MultiStatus status, int updateFlags) {
		super();
		this.localManager = localManager;
		this.lock = lock;
		this.multistatus = status;
		this.updateFlags = updateFlags;
	}

	/**
	 * @see IResourceTree#addToLocalHistory(IFile)
	 */
	@Override
	public void addToLocalHistory(IFile file) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			if (!file.exists())
				return;
			IFileStore store = localManager.getStore(file);
			final IFileInfo fileInfo = store.fetchInfo();
			if (!fileInfo.exists())
				return;
			localManager.getHistoryStore().addState(file.getFullPath(), store, fileInfo, false);
		} finally {
			lock.release();
		}
	}

	private IFileStore computeDestinationStore(IProjectDescription destDescription) throws CoreException {
		URI destLocation = destDescription.getLocationURI();
		// Use the default area if necessary for the destination.
		if (destLocation == null) {
			IPath rootLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation();
			destLocation = rootLocation.append(destDescription.getName()).toFile().toURI();
		}
		return EFS.getStore(destLocation);
	}

	/**
	 * @see IResourceTree#computeTimestamp(IFile)
	 */
	@Override
	public long computeTimestamp(IFile file) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			if (!file.getProject().exists())
				return NULL_TIMESTAMP;
			return internalComputeTimestamp(file);
		} finally {
			lock.release();
		}
	}

	/**
	 * Copies the local history of source to destination.  Note that if source
	 * is an IFolder, it is assumed that the same structure exists under destination
	 * and the local history of any IFile under source will be copied to the
	 * associated IFile under destination.
	 */
	private void copyLocalHistory(IResource source, IResource destination) {
		localManager.getHistoryStore().copyHistory(source, destination, true);
	}

	/**
	 * @see IResourceTree#deletedFile(IFile)
	 */
	@Override
	public void deletedFile(IFile file) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			// Do nothing if the resource doesn't exist.
			if (!file.exists())
				return;
			try {
				// Delete properties, generate marker deltas, and remove the node from the workspace tree.
				((Resource) file).deleteResource(true, null);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorDeleting, file.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, file.getFullPath(), message, e);
				failed(status);
			}
		} finally {
			lock.release();
		}
	}

	/**
	 * @see IResourceTree#deletedFolder(IFolder)
	 */
	@Override
	public void deletedFolder(IFolder folder) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			// Do nothing if the resource doesn't exist.
			if (!folder.exists())
				return;
			try {
				// Delete properties, generate marker deltas, and remove the node from the workspace tree.
				((Resource) folder).deleteResource(true, null);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorDeleting, folder.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, folder.getFullPath(), message, e);
				failed(status);
			}
		} finally {
			lock.release();
		}
	}

	/**
	 * @see IResourceTree#deletedProject(IProject)
	 */
	@Override
	public void deletedProject(IProject target) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			// Do nothing if the resource doesn't exist.
			if (!target.exists())
				return;
			// Delete properties, generate marker deltas, and remove the node from the workspace tree.
			try {
				((Project) target).deleteResource(false, null);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorDeleting, target.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, target.getFullPath(), message, e);
				// log the status but don't return until we try and delete the rest of the project info
				failed(status);
			}
		} finally {
			lock.release();
		}
	}

	/**
	 * Makes sure that the destination directory for a project move is unoccupied.
	 * Returns true if successful, and false if the move should be aborted
	 */
	private boolean ensureDestinationEmpty(IProject source, IFileStore destinationStore, IProgressMonitor monitor) throws CoreException {
		String message;
		//Make sure the destination location is unoccupied
		if (!destinationStore.fetchInfo().exists())
			return true;
		//check for existing children
		if (destinationStore.childNames(EFS.NONE, Policy.subMonitorFor(monitor, 0)).length > 0) {
			//allow case rename to proceed
			if (((Resource) source).getStore().equals(destinationStore))
				return true;
			//fail because the destination is occupied
			message = NLS.bind(Messages.localstore_resourceExists, destinationStore);
			IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, null);
			failed(status);
			return false;
		}
		//delete the destination directory to allow for efficient renaming
		destinationStore.delete(EFS.NONE, Policy.subMonitorFor(monitor, 0));
		return true;
	}

	/**
	 * This operation has failed for the given reason. Add it to this
	 * resource tree's status.
	 */
	@Override
	public void failed(IStatus reason) {
		Assert.isLegal(isValid);
		multistatus.add(reason);
	}

	/**
	 * Returns the status object held onto by this resource tree.
	 */
	protected IStatus getStatus() {
		return multistatus;
	}

	/**
	 * @see IResourceTree#getTimestamp(IFile)
	 */
	@Override
	public long getTimestamp(IFile file) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			if (!file.exists())
				return NULL_TIMESTAMP;
			ResourceInfo info = ((File) file).getResourceInfo(false, false);
			return info == null ? NULL_TIMESTAMP : info.getLocalSyncInfo();
		} finally {
			lock.release();
		}
	}

	/**
	 * Returns the local timestamp for a file.
	 *
	 * @param file
	 * @return The local file system timestamp
	 */
	private long internalComputeTimestamp(IFile file) {
		IFileInfo fileInfo = localManager.getStore(file).fetchInfo();
		return fileInfo.exists() ? fileInfo.getLastModified() : NULL_TIMESTAMP;
	}

	/**
	 * Helper method for #standardDeleteFile. Returns a boolean indicating whether or
	 * not the delete was successful.
	 */
	private boolean internalDeleteFile(IFile file, int flags, IProgressMonitor monitor) {
		try {
			String message = NLS.bind(Messages.resources_deleting, file.getFullPath());
			monitor.beginTask(message, Policy.totalWork);
			Policy.checkCanceled(monitor);

			// Do nothing if the file doesn't exist in the workspace.
			if (!file.exists()) {
				// Indicate that the delete was successful.
				return true;
			}
			// Don't delete contents if this is a linked resource
			if (file.isLinked()) {
				deletedFile(file);
				return true;
			}
			// If the file doesn't exist on disk then signal to the workspace to delete the
			// file and return.
			IFileStore fileStore = localManager.getStore(file);
			boolean localExists = fileStore.fetchInfo().exists();
			if (!localExists) {
				deletedFile(file);
				// Indicate that the delete was successful.
				return true;
			}

			boolean keepHistory = (flags & IResource.KEEP_HISTORY) != 0;
			boolean force = (flags & IResource.FORCE) != 0;

			// Add the file to the local history if requested by the user.
			if (keepHistory)
				addToLocalHistory(file);
			monitor.worked(Policy.totalWork / 4);

			// We want to fail if force is false and the file is not synchronized with the
			// local file system.
			if (!force) {
				boolean inSync = isSynchronized(file, IResource.DEPTH_ZERO);
				// only want to fail if the file still exists.
				if (!inSync && localExists) {
					message = NLS.bind(Messages.localstore_resourceIsOutOfSync, file.getFullPath());
					IStatus status = new ResourceStatus(IResourceStatus.OUT_OF_SYNC_LOCAL, file.getFullPath(), message);
					failed(status);
					// Indicate that the delete was unsuccessful.
					return false;
				}
			}
			monitor.worked(Policy.totalWork / 4);

			// Try to delete the file from the file system.
			try {
				fileStore.delete(EFS.NONE, Policy.subMonitorFor(monitor, Policy.totalWork / 4));
				// If the file was successfully deleted from the file system the
				// workspace tree should be updated accordingly.
				deletedFile(file);
				// Indicate that the delete was successful.
				return true;
			} catch (CoreException e) {
				message = NLS.bind(Messages.resources_couldnotDelete, fileStore.toString());
				IStatus status = new ResourceStatus(IResourceStatus.FAILED_DELETE_LOCAL, file.getFullPath(), message, e);
				failed(status);
			}
			// Indicate that the delete was unsuccessful.
			return false;
		} finally {
			monitor.done();
		}
	}

	/**
	 * Helper method for #standardDeleteFolder. Returns a boolean indicating
	 * whether or not the deletion of this folder was successful. Does a best effort
	 * delete of this resource and its children.
	 */
	private boolean internalDeleteFolder(IFolder folder, int flags, IProgressMonitor monitor) {
		String message = NLS.bind(Messages.resources_deleting, folder.getFullPath());
		monitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
		monitor.subTask(message);
		Policy.checkCanceled(monitor);

		// Do nothing if the folder doesn't exist in the workspace.
		if (!folder.exists())
			return true;

		// Don't delete contents if this is a linked resource
		if (folder.isLinked()) {
			deletedFolder(folder);
			return true;
		}

		// If the folder doesn't exist on disk then update the tree and return.
		IFileStore fileStore = localManager.getStore(folder);
		if (!fileStore.fetchInfo().exists()) {
			deletedFolder(folder);
			return true;
		}

		try {
			//this will delete local and workspace
			localManager.delete(folder, flags, Policy.subMonitorFor(monitor, Policy.totalWork));
		} catch (CoreException ce) {
			message = NLS.bind(Messages.localstore_couldnotDelete, folder.getFullPath());
			IStatus status = new ResourceStatus(IStatus.ERROR, IResourceStatus.FAILED_DELETE_LOCAL, folder.getFullPath(), message, ce);
			failed(status);
			return false;
		}
		return true;
	}

	/**
	 * Does a best-effort delete on this resource and all its children.
	 */
	private boolean internalDeleteProject(IProject project, int flags, IProgressMonitor monitor) {
		// Recursively delete each member of the project.
		IResource[] members = null;
		try {
			members = project.members(IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN);
		} catch (CoreException e) {
			String message = NLS.bind(Messages.resources_errorMembers, project.getFullPath());
			IStatus status = new ResourceStatus(IStatus.ERROR, project.getFullPath(), message, e);
			failed(status);
			// Indicate that the delete was unsuccessful.
			return false;
		}
		boolean deletedChildren = true;
		for (IResource member : members) {
			IResource child = member;
			switch (child.getType()) {
				case IResource.FILE :
					// ignore the .project file for now and delete it last
					if (!IProjectDescription.DESCRIPTION_FILE_NAME.equals(child.getName()))
						deletedChildren &= internalDeleteFile((IFile) child, flags, Policy.subMonitorFor(monitor, Policy.totalWork / members.length));
					break;
				case IResource.FOLDER :
					deletedChildren &= internalDeleteFolder((IFolder) child, flags, Policy.subMonitorFor(monitor, Policy.totalWork / members.length));
					break;
			}
		}
		IFileStore projectStore = localManager.getStore(project);
		// Check to see if the children were deleted ok. If there was a problem
		// just return as the problem should have been logged by the recursive
		// call to the child.
		if (!deletedChildren)
			// Indicate that the delete was unsuccessful.
			return false;

		//Check if there are any undiscovered children of the project on disk other than description file
		String[] children;
		try {
			children = projectStore.childNames(EFS.NONE, null);
		} catch (CoreException e) {
			//treat failure to access the directory as a non-existent directory
			children = new String[0];
		}
		boolean force = BitMask.isSet(flags, IResource.FORCE);
		if (!force && (children.length != 1 || !IProjectDescription.DESCRIPTION_FILE_NAME.equals(children[0]))) {
			String message = NLS.bind(Messages.localstore_resourceIsOutOfSync, project.getName());
			failed(new ResourceStatus(IResourceStatus.OUT_OF_SYNC_LOCAL, project.getFullPath(), message));
			return false;
		}

		//Now delete the project description file
		IResource file = project.findMember(IProjectDescription.DESCRIPTION_FILE_NAME);
		if (file == null) {
			//the .project have may have been recreated on disk automatically by snapshot
			IFileStore dotProject = projectStore.getChild(IProjectDescription.DESCRIPTION_FILE_NAME);
			try {
				dotProject.delete(EFS.NONE, null);
			} catch (CoreException e) {
				failed(e.getStatus());
			}
		} else {
			boolean deletedProjectFile = internalDeleteFile((IFile) file, flags, Policy.monitorFor(null));
			if (!deletedProjectFile) {
				String message = NLS.bind(Messages.resources_couldnotDelete, file.getFullPath());
				IStatus status = new ResourceStatus(IResourceStatus.FAILED_DELETE_LOCAL, file.getFullPath(), message);
				failed(status);
				// Indicate that the delete was unsuccessful.
				return false;
			}
		}

		//children are deleted, so now delete the parent
		try {
			projectStore.delete(EFS.NONE, null);
			deletedProject(project);
			// Indicate that the delete was successful.
			return true;
		} catch (CoreException e) {
			String message = NLS.bind(Messages.resources_couldnotDelete, projectStore.toString());
			IStatus status = new ResourceStatus(IResourceStatus.FAILED_DELETE_LOCAL, project.getFullPath(), message, e);
			failed(status);
			// Indicate that the delete was unsuccessful.
			return false;
		}
	}

	/**
	 * Return <code>true</code> if there is a change in the content area for the project.
	 */
	private boolean isContentChange(IProject project, IProjectDescription destDescription) {
		IProjectDescription srcDescription = ((Project) project).internalGetDescription();
		URI srcLocation = srcDescription.getLocationURI();
		URI destLocation = destDescription.getLocationURI();
		if (srcLocation == null || destLocation == null)
			return true;
		//don't use URIUtil because we want to treat case rename as a content change
		return !srcLocation.equals(destLocation);
	}

	/**
	 * Return <code>true</code> if there is a change in the name of the project.
	 */
	private boolean isNameChange(IProject project, IProjectDescription description) {
		return !project.getName().equals(description.getName());
	}

	/**
	 * Refreshes the resource hierarchy with its children. In case of failure
	 * adds an appropriate status to the resource tree's status.
	 */
	private void safeRefresh(IResource resource) {
		try {
			resource.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
		} catch (CoreException ce) {
			IStatus status = new ResourceStatus(IStatus.ERROR, IResourceStatus.FAILED_DELETE_LOCAL, resource.getFullPath(), Messages.refresh_refreshErr, ce);
			failed(status);
		}
	}

	/**
	 * @see IResourceTree#isSynchronized(IResource, int)
	 */
	@Override
	public boolean isSynchronized(IResource resource, int depth) {
		try {
			lock.acquire();
			return localManager.isSynchronized(resource, depth);
		} finally {
			lock.release();
		}
	}

	/**
	 * The specific operation for which this tree was created has completed and this tree
	 * should not be used anymore. Ensure that this is the case by making it invalid. This
	 * is checked by all API methods.
	 */
	void makeInvalid() {
		this.isValid = false;
	}

	/**
	 * @see IResourceTree#movedFile(IFile, IFile)
	 */
	@Override
	public void movedFile(IFile source, IFile destination) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			// Do nothing if the resource doesn't exist.
			if (!source.exists())
				return;
			// If the destination already exists then we have a problem.
			if (destination.exists()) {
				String message = NLS.bind(Messages.resources_mustNotExist, destination.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, destination.getFullPath(), message);
				// log the status but don't return until we try and move the rest of the resource information.
				failed(status);
			}

			// Move the resource's persistent properties.
			IPropertyManager propertyManager = ((Resource) source).getPropertyManager();
			try {
				propertyManager.copy(source, destination, IResource.DEPTH_ZERO);
				propertyManager.deleteProperties(source, IResource.DEPTH_ZERO);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorPropertiesMove, source.getFullPath(), destination.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
				// log the status but don't return until we try and move the rest of the resource information.
				failed(status);
			}

			// Move the node in the workspace tree.
			Workspace workspace = (Workspace) source.getWorkspace();
			try {
				workspace.move((Resource) source, destination.getFullPath(), IResource.DEPTH_ZERO, updateFlags, false);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorMoving, source.getFullPath(), destination.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
				// log the status but don't return until we try and move the rest of the resource information.
				failed(status);
			}

			// Generate the marker deltas.
			try {
				workspace.getMarkerManager().moved(source, destination, IResource.DEPTH_ZERO);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorMarkersDelete, source.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
				failed(status);
			}

			// Copy the local history information
			copyLocalHistory(source, destination);
		} finally {
			lock.release();
		}
	}

	/**
	 * @see IResourceTree#movedFolderSubtree(IFolder, IFolder)
	 */
	@Override
	public void movedFolderSubtree(IFolder source, IFolder destination) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			// Do nothing if the source resource doesn't exist.
			if (!source.exists())
				return;
			// If the destination already exists then we have an error.
			if (destination.exists()) {
				String message = NLS.bind(Messages.resources_mustNotExist, destination.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, destination.getFullPath(), message);
				failed(status);
				return;
			}

			// Move the folder properties.
			int depth = IResource.DEPTH_INFINITE;
			IPropertyManager propertyManager = ((Resource) source).getPropertyManager();
			try {
				propertyManager.copy(source, destination, depth);
				propertyManager.deleteProperties(source, depth);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorPropertiesMove, source.getFullPath(), destination.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
				// log the status but don't return until we try and move the rest of the resource info
				failed(status);
			}

			// Create the destination node in the tree.
			Workspace workspace = (Workspace) source.getWorkspace();
			try {
				workspace.move((Resource) source, destination.getFullPath(), depth, updateFlags, false);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorMoving, source.getFullPath(), destination.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
				// log the status but don't return until we try and move the rest of the resource info
				failed(status);
			}

			// Generate the marker deltas.
			try {
				workspace.getMarkerManager().moved(source, destination, depth);
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorMarkersDelete, source.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
				failed(status);
			}

			// Copy the local history for this folder
			copyLocalHistory(source, destination);
		} finally {
			lock.release();
		}
	}

	/**
	 * @see IResourceTree#movedProjectSubtree(IProject, IProjectDescription)
	 */
	@Override
	public boolean movedProjectSubtree(IProject project, IProjectDescription destDescription) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			// Do nothing if the source resource doesn't exist.
			if (!project.exists())
				return true;

			Project source = (Project) project;
			Project destination = (Project) source.getWorkspace().getRoot().getProject(destDescription.getName());
			Workspace workspace = (Workspace) source.getWorkspace();
			int depth = IResource.DEPTH_INFINITE;

			// If the name of the source and destination projects are not the same then
			// rename the meta area and make changes in the tree.
			if (isNameChange(source, destDescription)) {
				if (destination.exists()) {
					String message = NLS.bind(Messages.resources_mustNotExist, destination.getFullPath());
					IStatus status = new ResourceStatus(IStatus.ERROR, destination.getFullPath(), message);
					failed(status);
					return false;
				}

				// Rename the project metadata area. Close the property store to flush everything to disk
				try {
					source.getPropertyManager().closePropertyStore(source);
					localManager.getHistoryStore().closeHistoryStore(source);
				} catch (CoreException e) {
					String message = NLS.bind(Messages.properties_couldNotClose, source.getFullPath());
					IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
					// log the status but don't return until we try and move the rest of the resource info
					failed(status);
				}
				final IFileSystem fileSystem = EFS.getLocalFileSystem();
				IFileStore oldMetaArea = fileSystem.getStore(workspace.getMetaArea().locationFor(source));
				IFileStore newMetaArea = fileSystem.getStore(workspace.getMetaArea().locationFor(destination));
				try {
					oldMetaArea.move(newMetaArea, EFS.NONE, new NullProgressMonitor());
				} catch (CoreException e) {
					String message = NLS.bind(Messages.resources_moveMeta, oldMetaArea, newMetaArea);
					IStatus status = new ResourceStatus(IResourceStatus.FAILED_WRITE_METADATA, destination.getFullPath(), message, e);
					// log the status but don't return until we try and move the rest of the resource info
					failed(status);
				}

				// Move the workspace tree.
				try {
					workspace.move(source, destination.getFullPath(), depth, updateFlags, true);
				} catch (CoreException e) {
					String message = NLS.bind(Messages.resources_errorMoving, source.getFullPath(), destination.getFullPath());
					IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
					// log the status but don't return until we try and move the rest of the resource info
					failed(status);
				}

				// Clear stale state on the destination project.
				((ProjectInfo) destination.getResourceInfo(false, true)).fixupAfterMove();

				// Generate marker deltas.
				try {
					workspace.getMarkerManager().moved(source, destination, depth);
				} catch (CoreException e) {
					String message = NLS.bind(Messages.resources_errorMarkersMove, source.getFullPath(), destination.getFullPath());
					IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
					// log the status but don't return until we try and move the rest of the resource info
					failed(status);
				}
				// Copy the local history
				copyLocalHistory(source, destination);
			}

			// Write the new project description on the destination project.
			try {
				//moving linked resources may have modified the description in memory
				((ProjectDescription) destDescription).setLinkDescriptions(destination.internalGetDescription().getLinks());
				// moving filters may have modified the description in memory
				((ProjectDescription) destDescription).setFilterDescriptions(destination.internalGetDescription().getFilters());
				// moving variables may have modified the description in memory
				((ProjectDescription) destDescription).setVariableDescriptions(destination.internalGetDescription().getVariables());
				destination.internalSetDescription(destDescription, true);
				destination.writeDescription(IResource.FORCE);
			} catch (CoreException e) {
				String message = Messages.resources_projectDesc;
				IStatus status = new ResourceStatus(IStatus.ERROR, destination.getFullPath(), message, e);
				failed(status);
			}

			// write the private project description, including the project location
			try {
				workspace.getMetaArea().writePrivateDescription(destination);
			} catch (CoreException e) {
				failed(e.getStatus());
			}

			// Do a refresh on the destination project to pick up any newly discovered resources
			try {
				destination.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
			} catch (CoreException e) {
				String message = NLS.bind(Messages.resources_errorRefresh, destination.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, destination.getFullPath(), message, e);
				failed(status);
				return false;
			}
			return true;
		} finally {
			lock.release();
		}
	}

	/**
	 * Helper method for moving the project content. Determines the content location
	 * based on the project description. (default location or user defined?)
	 */
	private void moveProjectContent(IProject source, IFileStore destStore, int flags, IProgressMonitor monitor) throws CoreException {
		try {
			String message = NLS.bind(Messages.resources_moving, source.getFullPath());
			monitor.beginTask(message, 10);
			IProjectDescription srcDescription = source.getDescription();
			URI srcLocation = srcDescription.getLocationURI();
			// If the locations are the same (and non-default) then there is nothing to do.
			if (srcLocation != null && URIUtil.equals(srcLocation, destStore.toURI()))
				return;

			//If this is a replace, just make sure the destination location exists, and return
			boolean replace = (flags & IResource.REPLACE) != 0;
			if (replace) {
				destStore.mkdir(EFS.NONE, Policy.subMonitorFor(monitor, 10));
				return;
			}

			// Move the contents on disk.
			localManager.move(source, destStore, flags, Policy.subMonitorFor(monitor, 9));

			//if this is a deep move, move the contents of any linked resources
			if ((flags & IResource.SHALLOW) == 0) {
				IResource[] children = source.members();
				for (IResource element : children) {
					if (element.isLinked()) {
						message = NLS.bind(Messages.resources_moving, element.getFullPath());
						monitor.subTask(message);
						IFileStore linkDestination = destStore.getChild(element.getName());
						try {
							localManager.move(element, linkDestination, flags, Policy.monitorFor(null));
						} catch (CoreException ce) {
							//log the failure, but keep trying on remaining links
							failed(ce.getStatus());
						}
					}
				}
			}
			monitor.worked(1);
		} finally {
			monitor.done();
		}
	}

	/**
	 * @see IResourceTree#standardDeleteFile(IFile, int, IProgressMonitor)
	 */
	@Override
	public void standardDeleteFile(IFile file, int flags, IProgressMonitor monitor) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			internalDeleteFile(file, flags, monitor);
		} finally {
			lock.release();
		}
	}

	/**
	 * @see IResourceTree#standardDeleteFolder(IFolder, int, IProgressMonitor)
	 */
	@Override
	public void standardDeleteFolder(IFolder folder, int flags, IProgressMonitor monitor) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			internalDeleteFolder(folder, flags, monitor);
		} catch (OperationCanceledException oce) {
			safeRefresh(folder);
			throw oce;
		} finally {
			lock.release();
			monitor.done();
		}
	}

	/**
	 * @see IResourceTree#standardDeleteProject(IProject, int, IProgressMonitor)
	 */
	@Override
	public void standardDeleteProject(IProject project, int flags, IProgressMonitor monitor) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			String message = NLS.bind(Messages.resources_deleting, project.getFullPath());
			monitor.beginTask(message, Policy.totalWork);
			// Do nothing if the project doesn't exist in the workspace tree.
			if (!project.exists())
				return;

			boolean alwaysDeleteContent = (flags & IResource.ALWAYS_DELETE_PROJECT_CONTENT) != 0;
			boolean neverDeleteContent = (flags & IResource.NEVER_DELETE_PROJECT_CONTENT) != 0;
			boolean success = true;

			// Delete project content.  Don't do anything if the user specified explicitly asked
			// not to delete the project content or if the project is closed and
			// ALWAYS_DELETE_PROJECT_CONTENT was not specified.
			if (alwaysDeleteContent || (project.isOpen() && !neverDeleteContent)) {
				// Force is implied if alwaysDeleteContent is true or if the project is in sync
				// with the local file system.
				if (alwaysDeleteContent || isSynchronized(project, IResource.DEPTH_INFINITE)) {
					flags |= IResource.FORCE;
				}

				// If the project is open we have to recursively try and delete all the files doing best-effort.
				if (project.isOpen()) {
					success = internalDeleteProject(project, flags, monitor);
					if (!success) {
						IFileStore store = localManager.getStore(project);
						message = NLS.bind(Messages.resources_couldnotDelete, store.toString());
						IStatus status = new ResourceStatus(IResourceStatus.FAILED_DELETE_LOCAL, project.getFullPath(), message);
						failed(status);
					}
					return;
				}

				// If the project is closed we can short circuit this operation and delete all the files on disk.
				// The .project file is deleted at the end of the operation.
				try {
					IFileStore projectStore = localManager.getStore(project);
					IFileStore members[] = projectStore.childStores(EFS.NONE, null);
					for (int i = 0; i < members.length; i++) {
						if (!IProjectDescription.DESCRIPTION_FILE_NAME.equals(members[i].getName()))
							members[i].delete(EFS.NONE, Policy.subMonitorFor(monitor, Policy.totalWork * 7 / 8 / members.length));
					}
					projectStore.delete(EFS.NONE, Policy.subMonitorFor(monitor, Policy.totalWork * 7 / 8 / (members.length > 0 ? members.length : 1)));
				} catch (OperationCanceledException oce) {
					safeRefresh(project);
					throw oce;
				} catch (CoreException ce) {
					message = NLS.bind(Messages.localstore_couldnotDelete, project.getFullPath());
					IStatus status = new ResourceStatus(IStatus.ERROR, IResourceStatus.FAILED_DELETE_LOCAL, project.getFullPath(), message, ce);
					failed(status);
					return;
				}
			}

			// Signal that the workspace tree should be updated that the project has been deleted.
			if (success)
				deletedProject(project);
			else {
				message = NLS.bind(Messages.localstore_couldnotDelete, project.getFullPath());
				IStatus status = new ResourceStatus(IResourceStatus.FAILED_DELETE_LOCAL, project.getFullPath(), message);
				failed(status);
			}
		} finally {
			lock.release();
			monitor.done();
		}
	}

	/**
	 * @see IResourceTree#standardMoveFile(IFile, IFile, int, IProgressMonitor)
	 */
	@Override
	public void standardMoveFile(IFile source, IFile destination, int flags, IProgressMonitor monitor) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			String message = NLS.bind(Messages.resources_moving, source.getFullPath());
			monitor.subTask(message);

			// These pre-conditions should all be ok but just in case...
			if (!source.exists() || destination.exists() || !destination.getParent().isAccessible())
				throw new IllegalArgumentException();

			boolean force = (flags & IResource.FORCE) != 0;
			boolean keepHistory = (flags & IResource.KEEP_HISTORY) != 0;
			boolean isDeep = (flags & IResource.SHALLOW) == 0;

			// If the file is not in sync with the local file system and force is false,
			// then signal that we have an error.
			if (!force && !isSynchronized(source, IResource.DEPTH_INFINITE)) {
				message = NLS.bind(Messages.localstore_resourceIsOutOfSync, source.getFullPath());
				IStatus status = new ResourceStatus(IResourceStatus.OUT_OF_SYNC_LOCAL, source.getFullPath(), message);
				failed(status);
				return;
			}
			monitor.worked(Policy.totalWork / 4);

			// Add the file contents to the local history if requested by the user.
			if (keepHistory)
				addToLocalHistory(source);
			monitor.worked(Policy.totalWork / 4);

			//for shallow move of linked resources, nothing needs to be moved in the file system
			if (!isDeep && source.isLinked()) {
				movedFile(source, destination);
				return;
			}

			// If the file was successfully moved in the file system then the workspace
			// tree needs to be updated accordingly. Otherwise signal that we have an error.
			IFileStore destStore = null;
			boolean failedDeletingSource = false;
			try {
				destStore = localManager.getStore(destination);
				//ensure parent of destination exists
				destStore.getParent().mkdir(EFS.NONE, Policy.subMonitorFor(monitor, 0));
				localManager.move(source, destStore, flags, monitor);
			} catch (CoreException e) {
				failed(e.getStatus());
				// did the fail occur after copying to the destination?
				failedDeletingSource = destStore != null && destStore.fetchInfo().exists();
				// if so, we should proceed
				if (!failedDeletingSource)
					return;
			}
			movedFile(source, destination);
			updateMovedFileTimestamp(destination, internalComputeTimestamp(destination));
			if (failedDeletingSource) {
				//recreate source file to ensure we are not out of sync
				try {
					source.refreshLocal(IResource.DEPTH_INFINITE, null);
				} catch (CoreException e) {
					//ignore secondary failure - we have already logged the main failure
				}
			}
			monitor.worked(Policy.totalWork / 4);
			return;
		} finally {
			lock.release();
			monitor.done();
		}
	}

	/**
	 * @see IResourceTree#standardMoveFolder(IFolder, IFolder, int, IProgressMonitor)
	 */
	@Override
	public void standardMoveFolder(IFolder source, IFolder destination, int flags, IProgressMonitor monitor) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			String message = NLS.bind(Messages.resources_moving, source.getFullPath());
			monitor.beginTask(message, 100);

			// These pre-conditions should all be ok but just in case...
			if (!source.exists() || destination.exists() || !destination.getParent().isAccessible())
				throw new IllegalArgumentException();

			// Check to see if we are synchronized with the local file system. If we are in sync then we can
			// short circuit this method and do a file system only move. Otherwise we have to recursively
			// try and move all resources, doing it in a best-effort manner.
			boolean force = (flags & IResource.FORCE) != 0;
			if (!force && !isSynchronized(source, IResource.DEPTH_INFINITE)) {
				message = NLS.bind(Messages.localstore_resourceIsOutOfSync, source.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message);
				failed(status);
				return;
			}
			monitor.worked(20);

			//for linked resources, nothing needs to be moved in the file system
			boolean isDeep = (flags & IResource.SHALLOW) == 0;
			if (!isDeep && (source.isLinked() || source.isVirtual())) {
				movedFolderSubtree(source, destination);
				return;
			}

			// Move the resources in the file system. Only the FORCE flag is valid here so don't
			// have to worry about clearing the KEEP_HISTORY flag.
			IFileStore destStore = null;
			boolean failedDeletingSource = false;
			try {
				destStore = localManager.getStore(destination);
				localManager.move(source, destStore, flags, Policy.subMonitorFor(monitor, 60));
			} catch (CoreException e) {
				failed(e.getStatus());
				// did the fail occur after copying to the destination?
				failedDeletingSource = destStore != null && destStore.fetchInfo().exists();
				// if so, we should proceed
				if (!failedDeletingSource)
					return;
			}
			movedFolderSubtree(source, destination);
			monitor.worked(20);
			updateTimestamps(destination, isDeep);
			if (failedDeletingSource) {
				//the move could have been partially successful, so refresh to ensure we are in sync
				try {
					source.refreshLocal(IResource.DEPTH_INFINITE, null);
					destination.refreshLocal(IResource.DEPTH_INFINITE, null);
				} catch (CoreException e) {
					//ignore secondary failures -we have already logged main failure
				}
			}
		} finally {
			lock.release();
			monitor.done();
		}
	}

	/**
	 * @see IResourceTree#standardMoveProject(IProject, IProjectDescription, int, IProgressMonitor)
	 */
	@Override
	public void standardMoveProject(IProject source, IProjectDescription description, int flags, IProgressMonitor monitor) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			String message = NLS.bind(Messages.resources_moving, source.getFullPath());
			monitor.beginTask(message, Policy.totalWork);

			// Double-check this pre-condition.
			if (!source.isAccessible())
				throw new IllegalArgumentException();

			// If there is nothing to do on disk then signal to make the workspace tree
			// changes.
			if (!isContentChange(source, description)) {
				movedProjectSubtree(source, description);
				return;
			}

			// Check to see if we are synchronized with the local file system.
			boolean force = (flags & IResource.FORCE) != 0;
			if (!force && !isSynchronized(source, IResource.DEPTH_INFINITE)) {
				// FIXME: make this a best effort move?
				message = NLS.bind(Messages.localstore_resourceIsOutOfSync, source.getFullPath());
				IStatus status = new ResourceStatus(IResourceStatus.OUT_OF_SYNC_LOCAL, source.getFullPath(), message);
				failed(status);
				return;
			}

			IFileStore destinationStore;
			try {
				destinationStore = computeDestinationStore(description);
				//destination can be non-empty on replace
				if ((flags & IResource.REPLACE) == 0)
					if (!ensureDestinationEmpty(source, destinationStore, monitor))
						return;
			} catch (CoreException e) {
				//must fail if the destination location cannot be accessd (undefined file system)
				message = NLS.bind(Messages.localstore_couldNotMove, source.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
				failed(status);
				return;
			}

			// Move the project content in the local file system.
			try {
				moveProjectContent(source, destinationStore, flags, Policy.subMonitorFor(monitor, Policy.totalWork * 3 / 4));
			} catch (CoreException e) {
				message = NLS.bind(Messages.localstore_couldNotMove, source.getFullPath());
				IStatus status = new ResourceStatus(IStatus.ERROR, source.getFullPath(), message, e);
				failed(status);
				//refresh the project because it might have been partially moved
				try {
					source.refreshLocal(IResource.DEPTH_INFINITE, null);
				} catch (CoreException e2) {
					//ignore secondary failures
				}
			}

			// If we got this far the project content has been moved on disk (if necessary)
			// and we need to update the workspace tree.
			movedProjectSubtree(source, description);
			monitor.worked(Policy.totalWork * 1 / 8);

			boolean isDeep = (flags & IResource.SHALLOW) == 0;
			updateTimestamps(source.getWorkspace().getRoot().getProject(description.getName()), isDeep);
			monitor.worked(Policy.totalWork * 1 / 8);
		} finally {
			lock.release();
			monitor.done();
		}
	}

	/**
	 * @see IResourceTree#updateMovedFileTimestamp(IFile, long)
	 */
	@Override
	public void updateMovedFileTimestamp(IFile file, long timestamp) {
		Assert.isLegal(isValid);
		try {
			lock.acquire();
			// Do nothing if the file doesn't exist in the workspace tree.
			if (!file.exists())
				return;
			// Update the timestamp in the tree.
			ResourceInfo info = ((Resource) file).getResourceInfo(false, true);
			// The info should never be null since we just checked that the resource exists in the tree.
			localManager.updateLocalSync(info, timestamp);
			//remove the linked bit since this resource has been moved in the file system
			info.clear(ICoreConstants.M_LINK);
		} finally {
			lock.release();
		}
	}

	/**
	 * Helper method to update all the timestamps in the tree to match
	 * those in the file system. Used after a #move.
	 */
	private void updateTimestamps(IResource root, final boolean isDeep) {
		IResourceVisitor visitor = resource -> {
			if (resource.isLinked()) {
				if (isDeep && !((Resource) resource).isUnderVirtual()) {
					//clear the linked resource bit, if any
					ResourceInfo info = ((Resource) resource).getResourceInfo(false, true);
					info.clear(ICoreConstants.M_LINK);
				}
				return true;
			}
			//only needed if underlying file system does not preserve timestamps
			//				if (resource.getType() == IResource.FILE) {
			//					IFile file = (IFile) resource;
			//					updateMovedFileTimestamp(file, computeTimestamp(file));
			//				}
			return true;
		};
		try {
			root.accept(visitor, IResource.DEPTH_INFINITE, IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN);
		} catch (CoreException e) {
			// No exception should be thrown.
		}
	}
}
