/*******************************************************************************
 * Copyright (c) 2000, 2015 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
 *     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.
		}
	}
}
