/*******************************************************************************
 * 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
 *     Anton Leherbauer (Wind River) - [198591] Allow Builder to specify scheduling rule
 *     Francis Lynch (Wind River) - [301563] Save and load tree snapshots
 *     Markus Schorn (Wind River) - [306575] Save snapshot location with project
 *     Broadcom Corporation - ongoing development
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 473427
 *******************************************************************************/
package org.eclipse.core.internal.resources;

import java.net.URI;
import java.util.*;
import org.eclipse.core.filesystem.*;
import org.eclipse.core.internal.events.LifecycleEvent;
import org.eclipse.core.internal.utils.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.team.IMoveDeleteHook;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentTypeMatcher;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;

public class Project extends Container implements IProject {
	/**
	 * Option constant (value 2) indicating that the snapshot location shall be
	 * persisted with the project for autoloading the snapshot when the project
	 * is imported in another workspace.
	 * <p>
	 * <strong>EXPERIMENTAL</strong>. This constant has been added as
	 * part of a work in progress. There is no guarantee that this API will
	 * work or that it will remain the same. Please do not use this API without
	 * consulting with the Platform Core team.
	 * </p>
	 * @see #saveSnapshot(int, URI, IProgressMonitor)
	 * @since 3.6
	 */
	public static final int SNAPSHOT_SET_AUTOLOAD = 2;

	protected Project(IPath path, Workspace container) {
		super(path, container);
	}

	protected void assertCreateRequirements(IProjectDescription description) throws CoreException {
		checkDoesNotExist();
		checkDescription(this, description, false);
		URI location = description.getLocationURI();
		if (location != null)
			return;
		//if the project is in the default location, need to check for collision with existing folder of different case
		if (!Workspace.caseSensitive) {
			IFileStore store = getStore();
			IFileInfo localInfo = store.fetchInfo();
			if (localInfo.exists()) {
				String name = getLocalManager().getLocalName(store);
				if (name != null && !store.getName().equals(name)) {
					String msg = NLS.bind(Messages.resources_existsLocalDifferentCase, new Path(store.toString()).removeLastSegments(1).append(name).toOSString());
					throw new ResourceException(IResourceStatus.CASE_VARIANT_EXISTS, getFullPath(), msg, null);
				}
			}
		}
	}

	/*
	 * If the creation boolean is true then this method is being called on project creation.
	 * Otherwise it is being called via #setDescription. The difference is that we don't allow
	 * some description fields to change value after project creation. (e.g. project location)
	 */
	protected MultiStatus basicSetDescription(ProjectDescription description, int updateFlags) {
		String message = Messages.resources_projectDesc;
		MultiStatus result = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_WRITE_METADATA, message, null);
		ProjectDescription current = internalGetDescription();
		current.setComment(description.getComment());
		current.setSnapshotLocationURI(description.getSnapshotLocationURI());

		// set the build order before setting the references or the natures
		current.setBuildSpec(description.getBuildSpec(true));

		// set the references before the natures
		boolean flushOrder = false;
		IProject[] oldReferences = current.getReferencedProjects();
		IProject[] newReferences = description.getReferencedProjects();
		if (!Arrays.equals(oldReferences, newReferences)) {
			current.setReferencedProjects(newReferences);
			flushOrder = true;
		}
		// Update the dynamic state
		flushOrder |= current.updateDynamicState(description);

		if (flushOrder)
			workspace.flushBuildOrder();

		// the natures last as this may cause recursive calls to setDescription.
		if ((updateFlags & IResource.AVOID_NATURE_CONFIG) == 0)
			workspace.getNatureManager().configureNatures(this, current, description, result);
		else
			current.setNatureIds(description.getNatureIds(false));
		return result;
	}

	@Override
	public void build(int trigger, IProgressMonitor monitor) throws CoreException {
		if (!isAccessible())
			return;
		internalBuild(getActiveBuildConfig(), trigger, null, null, monitor);
	}

	@Override
	public void build(int trigger, String builderName, Map<String, String> args, IProgressMonitor monitor) throws CoreException {
		Assert.isNotNull(builderName);
		if (!isAccessible())
			return;
		internalBuild(getActiveBuildConfig(), trigger, builderName, args, monitor);
	}

	@Override
	public void build(IBuildConfiguration config, int trigger, IProgressMonitor monitor) throws CoreException {
		Assert.isNotNull(config);
		// If project isn't accessible, or doesn't contain the build configuration, nothing to do.
		if (!isAccessible() || !hasBuildConfig(config.getName()))
			return;
		internalBuild(config, trigger, null, null, monitor);
	}

	/**
	 * Checks that this resource is accessible.  Typically this means that it
	 * exists.  In the case of projects, they must also be open.
	 * If phantom is true, phantom resources are considered.
	 *
	 * @exception CoreException if this resource is not accessible
	 */
	@Override
	public void checkAccessible(int flags) throws CoreException {
		super.checkAccessible(flags);
		if (!isOpen(flags)) {
			String message = NLS.bind(Messages.resources_mustBeOpen, getName());
			throw new ResourceException(IResourceStatus.PROJECT_NOT_OPEN, getFullPath(), message, null);
		}
	}

	/**
	 * Checks validity of the given project description.
	 */
	protected void checkDescription(IProject project, IProjectDescription desc, boolean moving) throws CoreException {
		URI location = desc.getLocationURI();
		String message = Messages.resources_invalidProjDesc;
		MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INVALID_VALUE, message, null);
		status.merge(workspace.validateName(desc.getName(), IResource.PROJECT));
		if (moving) {
			// if we got here from a move call then we should check the location in the description since
			// its possible that we want to do a rename without moving the contents. (and we shouldn't
			// throw an Overlapping mapping exception in this case) So if the source description's location
			// is null (we are using the default) or if the locations aren't equal, then validate the location
			// of the new description. Otherwise both locations aren't null and they are equal so ignore validation.
			URI sourceLocation = internalGetDescription().getLocationURI();
			if (sourceLocation == null || !sourceLocation.equals(location))
				status.merge(workspace.validateProjectLocationURI(project, location));
		} else
			// otherwise continue on like before
			status.merge(workspace.validateProjectLocationURI(project, location));
		if (!status.isOK())
			throw new ResourceException(status);
	}

	@Override
	public void close(IProgressMonitor monitor) throws CoreException {
		String msg = NLS.bind(Messages.resources_closing_1, getName());
		SubMonitor subMonitor = SubMonitor.convert(monitor, msg, 100);
		final ISchedulingRule rule = workspace.getRuleFactory().modifyRule(this);
		try {
			workspace.prepareOperation(rule, subMonitor.newChild(1));
			ResourceInfo info = getResourceInfo(false, false);
			int flags = getFlags(info);
			checkExists(flags, true);
			subMonitor.subTask(msg);
			if (!isOpen(flags))
				return;
			// Signal that this resource is about to be closed.  Do this at the very
			// beginning so that infrastructure pieces have a chance to do clean up
			// while the resources still exist.
			workspace.beginOperation(true);
			workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_CLOSE, this));
			// flush the build order early in case there is a problem
			workspace.flushBuildOrder();
			IProgressMonitor sub = subMonitor.newChild(49, SubMonitor.SUPPRESS_SUBTASK);
			IStatus saveStatus = workspace.getSaveManager().save(ISaveContext.PROJECT_SAVE, this, sub);
			internalClose(subMonitor.newChild(49));
			if (saveStatus != null && !saveStatus.isOK())
				throw new ResourceException(saveStatus);
		} catch (OperationCanceledException e) {
			workspace.getWorkManager().operationCanceled();
			throw e;
		} finally {
			workspace.endOperation(rule, true);
		}
	}

	@Override
	public void copy(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
		// FIXME - the logic here for copying projects needs to be moved to Resource.copy
		//   so that IResource.copy(IPath,int,IProgressMonitor) works properly for
		//   projects and honours all update flags
		monitor = Policy.monitorFor(monitor);
		if (destination.segmentCount() == 1) {
			// copy project to project
			String projectName = destination.segment(0);
			IProjectDescription desc = getDescription();
			desc.setName(projectName);
			desc.setLocation(null);
			((ProjectDescription) desc).setSnapshotLocationURI(null);
			internalCopy(desc, updateFlags, monitor);
		} else {
			// will fail since we're trying to copy a project to a non-project
			checkCopyRequirements(destination, IResource.PROJECT, updateFlags);
		}
	}

	@Override
	public void copy(IProjectDescription destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
		// FIXME - the logic here for copying projects needs to be moved to Resource.copy
		//   so that IResource.copy(IProjectDescription,int,IProgressMonitor) works properly for
		//   projects and honours all update flags
		Assert.isNotNull(destination);
		internalCopy(destination, updateFlags, monitor);
	}

	protected void copyMetaArea(IProject source, IProject destination, IProgressMonitor monitor) throws CoreException {
		IFileStore oldMetaArea = EFS.getFileSystem(EFS.SCHEME_FILE).getStore(workspace.getMetaArea().locationFor(source));
		IFileStore newMetaArea = EFS.getFileSystem(EFS.SCHEME_FILE).getStore(workspace.getMetaArea().locationFor(destination));
		oldMetaArea.copy(newMetaArea, EFS.NONE, monitor);
	}

	@Override
	public void create(IProgressMonitor monitor) throws CoreException {
		create(null, monitor);
	}

	@Override
	public void create(IProjectDescription description, IProgressMonitor monitor) throws CoreException {
		create(description, IResource.NONE, monitor);
	}

	@Override
	public void create(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {
		monitor = Policy.monitorFor(monitor);
		try {
			monitor.beginTask(Messages.resources_create, Policy.totalWork);
			checkValidPath(path, PROJECT, false);
			final ISchedulingRule rule = workspace.getRuleFactory().createRule(this);
			try {
				workspace.prepareOperation(rule, monitor);
				if (description == null) {
					description = new ProjectDescription();
					description.setName(getName());
				}
				assertCreateRequirements(description);
				workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_CREATE, this));
				workspace.beginOperation(true);
				workspace.createResource(this, updateFlags);
				workspace.getMetaArea().create(this);
				ProjectInfo info = (ProjectInfo) getResourceInfo(false, true);

				// setup description to obtain project location
				ProjectDescription desc = (ProjectDescription) ((ProjectDescription) description).clone();
				desc.setLocationURI(FileUtil.canonicalURI(description.getLocationURI()));
				desc.setName(getName());
				internalSetDescription(desc, false);
				// see if there potentially are already contents on disk
				final boolean hasSavedDescription = getLocalManager().hasSavedDescription(this);
				boolean hasContent = hasSavedDescription;
				//if there is no project description, there might still be content on disk
				if (!hasSavedDescription)
					hasContent = getLocalManager().hasSavedContent(this);
				try {
					// look for a description on disk
					if (hasSavedDescription) {
						updateDescription();
						//make sure the .location file is written
						workspace.getMetaArea().writePrivateDescription(this);
					} else {
						//write out the project
						writeDescription(IResource.FORCE);
					}
				} catch (CoreException e) {
					workspace.deleteResource(this);
					throw e;
				}
				// inaccessible projects have a null modification stamp.
				// set this after setting the description as #setDescription
				// updates the stamp
				info.clearModificationStamp();
				//if a project already had content on disk, mark the project as having unknown children
				if (hasContent)
					info.set(ICoreConstants.M_CHILDREN_UNKNOWN);
				workspace.getSaveManager().requestSnapshot();
			} catch (OperationCanceledException e) {
				workspace.getWorkManager().operationCanceled();
				throw e;
			} finally {
				workspace.endOperation(rule, true);
			}
		} finally {
			monitor.done();
		}
	}

	@Override
	public void delete(boolean deleteContent, boolean force, IProgressMonitor monitor) throws CoreException {
		int updateFlags = force ? IResource.FORCE : IResource.NONE;
		updateFlags |= deleteContent ? IResource.ALWAYS_DELETE_PROJECT_CONTENT : IResource.NEVER_DELETE_PROJECT_CONTENT;
		delete(updateFlags, monitor);
	}

	@Override
	public void delete(boolean force, IProgressMonitor monitor) throws CoreException {
		int updateFlags = force ? IResource.FORCE : IResource.NONE;
		delete(updateFlags, monitor);
	}

	@Override
	public void deleteResource(boolean convertToPhantom, MultiStatus status) throws CoreException {
		super.deleteResource(convertToPhantom, status);
		// Clear the history store.
		clearHistory(null);
		// Delete the project metadata.
		workspace.getMetaArea().delete(this);
	}

	@Override
	protected void fixupAfterMoveSource() throws CoreException {
		workspace.deleteResource(this);
		// check if we deleted a preferences file
		ProjectPreferences.deleted(this);
	}

	@Override
	public IBuildConfiguration getActiveBuildConfig() throws CoreException {
		ResourceInfo info = getResourceInfo(false, false);
		int flags = getFlags(info);
		checkAccessible(flags);
		return internalGetActiveBuildConfig();
	}

	@Override
	public IBuildConfiguration getBuildConfig(String configName) throws CoreException {
		if (configName == null)
			return getActiveBuildConfig();
		ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
		checkAccessible(getFlags(info));
		IBuildConfiguration[] configs = internalGetBuildConfigs(false);
		for (IBuildConfiguration config : configs) {
			if (config.getName().equals(configName)) {
				return config;
			}
		}
		throw new ResourceException(IResourceStatus.BUILD_CONFIGURATION_NOT_FOUND, getFullPath(), null, null);
	}

	@Override
	public IBuildConfiguration[] getBuildConfigs() throws CoreException {
		ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
		checkAccessible(getFlags(info));
		return internalGetBuildConfigs(true);
	}

	@Override
	public IContentTypeMatcher getContentTypeMatcher() throws CoreException {
		return workspace.getContentDescriptionManager().getContentTypeMatcher(this);
	}

	@Override
	public String getDefaultCharset(boolean checkImplicit) {
		// non-existing resources default to parent's charset
		if (!exists())
			return checkImplicit ? ResourcesPlugin.getEncoding() : null;
		return workspace.getCharsetManager().getCharsetFor(getFullPath(), checkImplicit);
	}

	@Override
	public IProjectDescription getDescription() throws CoreException {
		ResourceInfo info = getResourceInfo(false, false);
		checkAccessible(getFlags(info));
		ProjectDescription description = ((ProjectInfo) info).getDescription();
		//if the project is currently in the middle of being created, the description might not be available yet
		if (description == null)
			checkAccessible(NULL_FLAG);
		return (IProjectDescription) description.clone();
	}

	@Override
	public IProjectNature getNature(String natureID) throws CoreException {
		// Has it already been initialized?
		ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
		checkAccessible(getFlags(info));
		IProjectNature nature = info.getNature(natureID);
		if (nature == null) {
			// Not initialized yet. Does this project have the nature?
			if (!hasNature(natureID))
				return null;
			nature = workspace.getNatureManager().createNature(this, natureID);
			info.setNature(natureID, nature);
		}
		return nature;
	}

	@Override
	public IContainer getParent() {
		return workspace.getRoot();
	}

	@Override
	@Deprecated
	public IPath getPluginWorkingLocation(IPluginDescriptor plugin) {
		if (plugin == null)
			return null;
		return getWorkingLocation(plugin.getUniqueIdentifier());
	}

	@Override
	public IProject getProject() {
		return this;
	}

	@Override
	public IPath getProjectRelativePath() {
		return Path.EMPTY;
	}

	@Override
	public IPath getRawLocation() {
		ProjectDescription description = internalGetDescription();
		return description == null ? null : description.getLocation();
	}

	@Override
	public URI getRawLocationURI() {
		ProjectDescription description = internalGetDescription();
		return description == null ? null : description.getLocationURI();
	}

	@Override
	public IBuildConfiguration[] getReferencedBuildConfigs(String configName, boolean includeMissing) throws CoreException {
		ResourceInfo info = getResourceInfo(false, false);
		checkAccessible(getFlags(info));
		ProjectDescription description = ((ProjectInfo) info).getDescription();
		//if the project is currently in the middle of being created, the description might not be available yet
		if (description == null)
			checkAccessible(NULL_FLAG);
		if (!hasBuildConfig(configName))
			throw new ResourceException(IResourceStatus.BUILD_CONFIGURATION_NOT_FOUND, getFullPath(), null, null);
		return internalGetReferencedBuildConfigs(configName, includeMissing);
	}

	@Override
	public IProject[] getReferencedProjects() throws CoreException {
		ResourceInfo info = getResourceInfo(false, false);
		checkAccessible(getFlags(info));
		ProjectDescription description = ((ProjectInfo) info).getDescription();
		//if the project is currently in the middle of being created, the description might not be available yet
		if (description == null)
			checkAccessible(NULL_FLAG);
		return description.getAllReferences(true);
	}

	@Override
	public void clearCachedDynamicReferences() {
		ResourceInfo info = getResourceInfo(false, false);
		if (info == null) {
			// If the project is not open there is no cached state and so there is nothing to do.
			return;
		}
		ProjectDescription description = ((ProjectInfo) info).getDescription();
		if (description == null) {
			// If the project is in the process of being created there is no cached state and nothing to do.
			return;
		}
		description.clearCachedDynamicReferences(null);
	}

	@Override
	public IProject[] getReferencingProjects() {
		IProject[] projects = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
		List<IProject> result = new ArrayList<>(projects.length);
		for (IProject p : projects) {
			Project project = (Project) p;
			if (!project.isAccessible())
				continue;
			ProjectDescription description = project.internalGetDescription();
			if (description == null)
				continue;
			IProject[] references = description.getAllReferences(false);
			for (IProject reference : references)
				if (reference.equals(this)) {
					result.add(project);
					break;
				}
		}
		return result.toArray(new IProject[result.size()]);
	}

	@Override
	public int getType() {
		return PROJECT;
	}

	@Override
	public IPath getWorkingLocation(String id) {
		if (id == null || !exists())
			return null;
		IPath result = workspace.getMetaArea().getWorkingLocation(this, id);
		result.toFile().mkdirs();
		return result;
	}

	@Override
	public boolean hasBuildConfig(String configName) throws CoreException {
		ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
		checkAccessible(getFlags(info));
		return internalHasBuildConfig(configName);
	}

	@Override
	public boolean hasNature(String natureID) throws CoreException {
		checkAccessible(getFlags(getResourceInfo(false, false)));
		// use #internal method to avoid copy but still throw an
		// exception if the resource doesn't exist.
		IProjectDescription desc = internalGetDescription();
		if (desc == null)
			checkAccessible(NULL_FLAG);
		return desc.hasNature(natureID);
	}

	/**
	 * Implements all build methods on IProject.
	 */
	protected void internalBuild(final IBuildConfiguration config, final int trigger, final String builderName, final Map<String, String> args, IProgressMonitor monitor) throws CoreException {
		workspace.run(new ICoreRunnable() {
			@Override
			public void run(IProgressMonitor innerMonitor) throws CoreException {
				innerMonitor = Policy.monitorFor(innerMonitor);
				final ISchedulingRule projectBuildRule = workspace.getBuildManager().getRule(config, trigger, builderName, args);
				final boolean relaxed = Job.getJobManager().currentRule() == null && workspace.isRelaxedRule(projectBuildRule);

				// PRE + POST_BUILD, and the build itself are allowed to modify resources, so require the current thread's scheduling rule
				// to either contain the WR or be null. Therefore, if not null, ensure it contains the WR rule...
				final ISchedulingRule notificationsRule = relaxed ? null : workspace.getRoot();
				try {
					innerMonitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
					try {
						workspace.prepareOperation(notificationsRule, innerMonitor);
						if (!shouldBuild())
							return;
						workspace.beginOperation(true);
						workspace.aboutToBuild(Project.this, trigger);
					} finally {
						workspace.endOperation(notificationsRule, false);
					}
					try {
						IStatus result;
						workspace.prepareOperation(projectBuildRule, innerMonitor);
						//don't open the tree eagerly because it will be wasted if no build occurs
						workspace.beginOperation(false);
						result = workspace.getBuildManager().build(config, trigger, builderName, args, Policy.subMonitorFor(innerMonitor, Policy.opWork));
						if (!result.isOK())
							throw new ResourceException(result);
					} finally {
						workspace.endOperation(projectBuildRule, false);
						try {
							workspace.prepareOperation(notificationsRule, innerMonitor);
							//don't open the tree eagerly because it will be wasted if no change occurs
							workspace.beginOperation(false);
							workspace.broadcastBuildEvent(Project.this, IResourceChangeEvent.POST_BUILD, trigger);
							//building may close the tree, so open it
							if (workspace.getElementTree().isImmutable())
								workspace.newWorkingTree();
						} finally {
							workspace.endOperation(notificationsRule, false);
						}
					}
				} finally {
					innerMonitor.done();
				}
			}

			/**
			 * Returns whether this project should be built for a given trigger.
			 * @return <code>true</code> if the build should proceed, and <code>false</code> otherwise.
			 */
			private boolean shouldBuild() {
				ResourceInfo info = getResourceInfo(false, false);
				int flags = getFlags(info);
				if (!exists(flags, true) || !isOpen(flags))
					return false;
				return true;
			}

		}, null, IWorkspace.AVOID_UPDATE, monitor);
	}

	/**
	 * Closes the project.  This is called during restore when there is a failure
	 * to read the project description.  Since it is called during workspace restore,
	 * it cannot start any operations.
	 */
	protected void internalClose(IProgressMonitor monitor) throws CoreException {
		SubMonitor subMonitor = SubMonitor.convert(monitor, 2);
		workspace.flushBuildOrder();
		getMarkerManager().removeMarkers(this, IResource.DEPTH_INFINITE);
		subMonitor.worked(1);
		// remove each member from the resource tree.
		// DO NOT use resource.delete() as this will delete it from disk as well.
		IResource[] members = members(IContainer.INCLUDE_PHANTOMS | IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN);
		subMonitor.setWorkRemaining(members.length);
		for (IResource member2 : members) {
			Resource member = (Resource) member2;
			workspace.deleteResource(member);
			subMonitor.worked(1);
		}
		// finally mark the project as closed.
		ResourceInfo info = getResourceInfo(false, true);
		info.clear(M_OPEN);
		info.clearSessionProperties();
		info.clearModificationStamp();
		info.setSyncInfo(null);
	}

	protected void internalCopy(IProjectDescription destDesc, int updateFlags, IProgressMonitor monitor) throws CoreException {
		monitor = Policy.monitorFor(monitor);
		try {
			String message = NLS.bind(Messages.resources_copying, getFullPath());
			monitor.beginTask(message, Policy.totalWork);
			String destName = destDesc.getName();
			IPath destPath = new Path(destName).makeAbsolute();
			Project destination = (Project) workspace.getRoot().getProject(destName);
			final ISchedulingRule rule = workspace.getRuleFactory().copyRule(this, destination);
			try {
				workspace.prepareOperation(rule, monitor);
				// The following assert method throws CoreExceptions as stated in the IProject.copy API
				// and assert for programming errors. See checkCopyRequirements for more information.
				assertCopyRequirements(destPath, IResource.PROJECT, updateFlags);
				checkDescription(destination, destDesc, false);
				workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_COPY, this, destination, updateFlags));

				workspace.beginOperation(true);
				getLocalManager().refresh(this, DEPTH_INFINITE, true, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100));

				// close the property store so incorrect info is not copied to the destination
				getPropertyManager().closePropertyStore(this);
				getLocalManager().getHistoryStore().closeHistoryStore(this);

				// copy the meta area for the project
				copyMetaArea(this, destination, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));

				// copy just the project and not its children yet (tree node, properties)
				internalCopyProjectOnly(destination, destDesc, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));

				// set the description
				destination.internalSetDescription(destDesc, false);

				//create the directory for the new project
				destination.getStore().mkdir(EFS.NONE, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));

				// call super.copy for each child (excluding project description file)
				//make it a best effort copy
				message = Messages.resources_copyProblem;
				MultiStatus problems = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, message, null);

				IResource[] children = members(IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN);
				final int childCount = children.length;
				final int childWork = childCount > 1 ? Policy.opWork * 50 / 100 / (childCount - 1) : 0;
				for (int i = 0; i < childCount; i++) {
					IResource child = children[i];
					if (!isProjectDescriptionFile(child)) {
						try {
							child.copy(destPath.append(child.getName()), updateFlags, Policy.subMonitorFor(monitor, childWork));
						} catch (CoreException e) {
							problems.merge(e.getStatus());
						}
					}
				}

				// write out the new project description to the meta area
				try {
					destination.writeDescription(IResource.FORCE);
				} catch (CoreException e) {
					try {
						destination.delete((updateFlags & IResource.FORCE) != 0, null);
					} catch (CoreException e2) {
						// ignore and rethrow the exception that got us here
					}
					throw e;
				}
				monitor.worked(Policy.opWork * 5 / 100);

				// refresh local
				monitor.subTask(Messages.resources_updating);
				getLocalManager().refresh(destination, DEPTH_INFINITE, true, Policy.subMonitorFor(monitor, Policy.opWork * 10 / 100));
				if (!problems.isOK())
					throw new ResourceException(problems);
			} catch (OperationCanceledException e) {
				workspace.getWorkManager().operationCanceled();
				throw e;
			} finally {
				workspace.endOperation(rule, true);
			}
		} finally {
			monitor.done();
		}
	}

	/*
	 * Copies just the project and no children. Does NOT copy the meta area.
	 */
	protected void internalCopyProjectOnly(IResource destination, IProjectDescription destDesc, IProgressMonitor monitor) throws CoreException {
		// close the property store so bogus values aren't copied to the destination
		getPropertyManager().closePropertyStore(this);
		getLocalManager().getHistoryStore().closeHistoryStore(this);
		// copy the tree and properties
		workspace.copyTree(this, destination.getFullPath(), IResource.DEPTH_ZERO, IResource.NONE, false);
		getPropertyManager().copy(this, destination, IResource.DEPTH_ZERO);

		ProjectInfo info = (ProjectInfo) ((Resource) destination).getResourceInfo(false, true);

		//copy the hidden metadata that we store in the project description
		ProjectDescription projectDesc = (ProjectDescription) destDesc;
		ProjectDescription internalDesc = ((Project) destination.getProject()).internalGetDescription();
		projectDesc.setLinkDescriptions(internalDesc.getLinks());
		projectDesc.setFilterDescriptions(internalDesc.getFilters());
		projectDesc.setVariableDescriptions(internalDesc.getVariables());

		//clear properties, markers, and description for the new project, because they shouldn't be copied.
		info.description = null;
		info.natures = null;
		info.setMarkers(null);
		info.clearSessionProperties();
	}

	/**
	 * Like {@link #getActiveBuildConfig()} but doesn't check accessibility.
	 * Project must be accessible.
	 * @see #getActiveBuildConfig()
	 */
	IBuildConfiguration internalGetActiveBuildConfig() {
		String configName = internalGetDescription().activeConfiguration;
		try {
			if (configName != null)
				return getBuildConfig(configName);
		} catch (CoreException e) {
			// Build configuration doesn't exist; treat the first as active.
		}
		return internalGetBuildConfigs(false)[0];
	}

	/**
	 * @return IBuildConfiguration[] always contains at least one build configuration
	 */
	public IBuildConfiguration[] internalGetBuildConfigs(boolean makeCopy) {
		ProjectDescription desc = internalGetDescription();
		if (desc == null)
			return new IBuildConfiguration[] {new BuildConfiguration(this, IBuildConfiguration.DEFAULT_CONFIG_NAME)};
		return desc.getBuildConfigs(this, makeCopy);
	}

	/**
	 * This is an internal helper method. This implementation is different from the API
	 * method getDescription(). This one does not check the project accessibility. It exists
	 * in order to prevent "chicken and egg" problems in places like the project creation.
	 * It may return null.
	 */
	public ProjectDescription internalGetDescription() {
		ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
		if (info == null)
			return null;
		return info.getDescription();
	}

	/**
	 * Returns the IBuildConfigurations referenced by the passed in build configuration
	 * @param configName to find references for
	 * @return IBuildConfiguration[] of referenced configurations; never null.
	 */
	public IBuildConfiguration[] internalGetReferencedBuildConfigs(String configName, boolean includeMissing) {
		ProjectDescription description = internalGetDescription();
		IBuildConfiguration[] refs = description.getAllBuildConfigReferences(configName, false);
		Collection<IBuildConfiguration> configs = new LinkedHashSet<>(refs.length);
		for (IBuildConfiguration ref : refs) {
			try {
				configs.add((((BuildConfiguration) ref).getBuildConfig()));
			} catch (CoreException e) {
				// The project isn't accessible, or the build configuration doesn't exist
				// on the project.  If requested return the full set of build references which may
				// be useful to API consumers
				if (includeMissing)
					configs.add(ref);
			}
		}
		return configs.toArray(new IBuildConfiguration[configs.size()]);
	}

	boolean internalHasBuildConfig(String configName) {
		return internalGetDescription().hasBuildConfig(configName);
	}

	/**
	 * Sets this project's description to the given value.  This is the body of the
	 * corresponding API method but is needed separately since it is used
	 * during workspace restore (i.e., when you cannot do an operation)
	 */
	void internalSetDescription(IProjectDescription value, boolean incrementContentId) {
		// Project has been added / removed. Build order is out-of-step
		workspace.flushBuildOrder();

		ProjectInfo info = (ProjectInfo) getResourceInfo(false, true);
		info.setDescription((ProjectDescription) value);
		getLocalManager().setLocation(this, info, value.getLocationURI());
		if (incrementContentId) {
			info.incrementContentId();
			//if the project is not accessible, stamp will be null and should remain null
			if (info.getModificationStamp() != NULL_STAMP)
				workspace.updateModificationStamp(info);
		}
	}

	@Override
	public void internalSetLocal(boolean flag, int depth) throws CoreException {
		// do nothing for projects, but call for its children
		if (depth == IResource.DEPTH_ZERO)
			return;
		if (depth == IResource.DEPTH_ONE)
			depth = IResource.DEPTH_ZERO;
		// get the children via the workspace since we know that this
		// resource exists (it is local).
		IResource[] children = getChildren(IResource.NONE);
		for (IResource element : children)
			((Resource) element).internalSetLocal(flag, depth);
	}

	@Override
	public boolean isAccessible() {
		return isOpen();
	}

	@Override
	public boolean isDerived(int options) {
		//projects are never derived
		return false;
	}

	@Override
	public boolean isLinked(int options) {
		return false;//projects are never linked
	}

	@Override
	public boolean isVirtual() {
		return false; // projects are never virtual
	}

	@Override
	public boolean isTeamPrivateMember(int options) {
		return false;//projects are never team private members
	}

	@Deprecated
	@Override
	public boolean isLocal(int depth) {
		// the flags parameter is ignored for projects so pass anything
		return isLocal(-1, depth);
	}

	@Deprecated
	@Override
	public boolean isLocal(int flags, int depth) {
		// don't check the flags....projects are always local
		if (depth == DEPTH_ZERO)
			return true;
		if (depth == DEPTH_ONE)
			depth = DEPTH_ZERO;
		// get the children via the workspace since we know that this
		// resource exists (it is local).
		IResource[] children = getChildren(IResource.NONE);
		for (int i = 0; i < children.length; i++)
			if (!children[i].isLocal(depth))
				return false;
		return true;
	}

	@Override
	public boolean isNatureEnabled(String natureId) throws CoreException {
		checkAccessible(getFlags(getResourceInfo(false, false)));
		return workspace.getNatureManager().isNatureEnabled(this, natureId);
	}

	@Override
	public boolean isOpen() {
		ResourceInfo info = getResourceInfo(false, false);
		return isOpen(getFlags(info));
	}

	public boolean isOpen(int flags) {
		return flags != NULL_FLAG && ResourceInfo.isSet(flags, M_OPEN);
	}

	/**
	 * Returns true if this resource represents the project description file, and
	 * false otherwise.
	 */
	protected boolean isProjectDescriptionFile(IResource resource) {
		return resource.getType() == IResource.FILE && resource.getFullPath().segmentCount() == 2 && resource.getName().equals(IProjectDescription.DESCRIPTION_FILE_NAME);
	}

	@Override
	public void loadSnapshot(int options, URI snapshotLocation, IProgressMonitor monitor) throws CoreException {
		// load a snapshot of refresh information when project is not opened
		if (isOpen()) {
			String message = Messages.resources_projectMustNotBeOpen;
			MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, null);
			throw new CoreException(status);
		}
		internalLoadSnapshot(options, snapshotLocation, monitor);
	}

	/**
	 * Loads a snapshot of project meta-data from the given location URI.
	 * Like {@link IProject#loadSnapshot(int, URI, IProgressMonitor)} but can be
	 * called when the project is open.
	 *
	 * @see IProject#saveSnapshot(int, URI, IProgressMonitor)
	 */
	private void internalLoadSnapshot(int options, URI snapshotLocation, IProgressMonitor monitor) throws CoreException {
		if ((options & SNAPSHOT_TREE) != 0) {
			// ensure that path variables are resolved: only ws accessible while project is closed
			snapshotLocation = workspace.getPathVariableManager().resolveURI(snapshotLocation);
			if (!snapshotLocation.isAbsolute()) {
				String message = NLS.bind(Messages.projRead_badSnapshotLocation, snapshotLocation.toString());
				throw new CoreException(new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, message, null));
			}
			// copy the snapshot from the URI into the project metadata
			IPath snapshotPath = workspace.getMetaArea().getRefreshLocationFor(this);
			IFileStore snapshotFileStore = EFS.getStore(org.eclipse.core.filesystem.URIUtil.toURI(snapshotPath));
			EFS.getStore(snapshotLocation).copy(snapshotFileStore, EFS.OVERWRITE, monitor);
		}
	}

	@Override
	public void move(IProjectDescription destination, boolean force, IProgressMonitor monitor) throws CoreException {
		Assert.isNotNull(destination);
		move(destination, force ? IResource.FORCE : IResource.NONE, monitor);
	}

	@Override
	public void move(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {
		Assert.isNotNull(description);
		monitor = Policy.monitorFor(monitor);
		try {
			String message = NLS.bind(Messages.resources_moving, getFullPath());
			monitor.beginTask(message, Policy.totalWork);
			IProject destination = workspace.getRoot().getProject(description.getName());
			final ISchedulingRule rule = workspace.getRuleFactory().moveRule(this, destination);
			try {
				workspace.prepareOperation(rule, monitor);
				// The following assert method throws CoreExceptions as stated in the IResource.move API
				// and assert for programming errors. See checkMoveRequirements for more information.
				if (!getName().equals(description.getName())) {
					IPath destPath = Path.ROOT.append(description.getName());
					assertMoveRequirements(destPath, IResource.PROJECT, updateFlags);
				}
				checkDescription(destination, description, true);
				workspace.beginOperation(true);
				message = Messages.resources_moveProblem;
				MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, null);
				WorkManager workManager = workspace.getWorkManager();
				ResourceTree tree = new ResourceTree(getLocalManager(), workManager.getLock(), status, updateFlags);
				IMoveDeleteHook hook = workspace.getMoveDeleteHook();
				workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_MOVE, this, destination, updateFlags));
				int depth = 0;
				try {
					depth = workManager.beginUnprotected();
					if (!hook.moveProject(tree, this, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork / 2)))
						tree.standardMoveProject(this, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork / 2));
				} finally {
					workManager.endUnprotected(depth);
				}
				// Invalidate the tree for further use by clients.
				tree.makeInvalid();
				if (!tree.getStatus().isOK())
					throw new ResourceException(tree.getStatus());
				// make sure the move operation is remembered
				workspace.getSaveManager().requestSnapshot();
			} catch (OperationCanceledException e) {
				workspace.getWorkManager().operationCanceled();
				throw e;
			} finally {
				workspace.endOperation(rule, true);
			}
		} finally {
			monitor.done();
		}
	}

	@Override
	public void open(int updateFlags, IProgressMonitor monitor) throws CoreException {
		monitor = Policy.monitorFor(monitor);
		try {
			String msg = NLS.bind(Messages.resources_opening_1, getName());
			monitor.beginTask(msg, Policy.totalWork);
			monitor.subTask(msg);
			final ISchedulingRule rule = workspace.getRuleFactory().modifyRule(this);
			try {
				workspace.prepareOperation(rule, monitor);
				ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
				int flags = getFlags(info);
				checkExists(flags, true);
				if (isOpen(flags))
					return;

				workspace.beginOperation(true);
				// flush the build order early in case there is a problem
				workspace.flushBuildOrder();
				info = (ProjectInfo) getResourceInfo(false, true);
				info.set(M_OPEN);
				//clear the unknown children immediately to avoid background refresh
				boolean unknownChildren = info.isSet(M_CHILDREN_UNKNOWN);
				if (unknownChildren)
					info.clear(M_CHILDREN_UNKNOWN);
				// the M_USED flag is used to indicate the difference between opening a project
				// for the first time and opening it from a previous close (restoring it from disk)
				boolean used = info.isSet(M_USED);
				boolean snapshotLoaded = false;
				if (!used && !workspace.getMetaArea().getRefreshLocationFor(this).toFile().exists()) {
					//auto-load a refresh snapshot if it is set
					final boolean hasSavedDescription = getLocalManager().hasSavedDescription(this);
					if (hasSavedDescription) {
						ProjectDescription updatedDesc = info.getDescription();
						if (updatedDesc != null) {
							URI autoloadURI = updatedDesc.getSnapshotLocationURI();
							if (autoloadURI != null) {
								try {
									autoloadURI = getPathVariableManager().resolveURI(autoloadURI);
									internalLoadSnapshot(SNAPSHOT_TREE, autoloadURI, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));
									snapshotLoaded = true;
								} catch (CoreException ce) {
									//Log non-existing autoload snapshot as warning only
									String msgerr = NLS.bind(Messages.projRead_cannotReadSnapshot, getName(), ce.getLocalizedMessage());
									Policy.log(new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, msgerr));
								}
							}
						}
					}
				}
				boolean minorIssuesDuringRestore = false;
				if (used) {
					minorIssuesDuringRestore = workspace.getSaveManager().restore(this, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100));
				} else {
					info.set(M_USED);
					//reconcile any links and groups in the project description
					IStatus result = reconcileLinksAndGroups(info.getDescription());
					if (!result.isOK())
						throw new CoreException(result);
					workspace.updateModificationStamp(info);
					monitor.worked(Policy.opWork * (snapshotLoaded ? 15 : 20) / 100);
				}
				startup();
				//request a refresh if the project is new and has unknown members on disk
				// or restore of the project is not fully successful
				if ((!used && unknownChildren) || !minorIssuesDuringRestore) {
					boolean refreshed = false;
					if (!used) {
						refreshed = workspace.getSaveManager().restoreFromRefreshSnapshot(this, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100));
						if (refreshed) { // account for the refresh work
							monitor.worked(Policy.opWork * 60 / 100);
						}
					}
					//refresh either in background or foreground
					if (!refreshed) {
						if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
							workspace.refreshManager.refresh(this);
							monitor.worked(Policy.opWork * 60 / 100);
						} else {
							refreshLocal(IResource.DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 60 / 100));
						}
					}
				}
				//creation of this project may affect overlapping resources
				workspace.getAliasManager().updateAliases(this, getStore(), IResource.DEPTH_INFINITE, monitor);
			} catch (OperationCanceledException e) {
				workspace.getWorkManager().operationCanceled();
				throw e;
			} finally {
				workspace.endOperation(rule, true);
			}
		} finally {
			monitor.done();
		}
	}

	@Override
	public void open(IProgressMonitor monitor) throws CoreException {
		open(IResource.NONE, monitor);
	}

	/**
	 * The project description file has changed on disk, resulting in a changed
	 * set of linked resources.  Perform the necessary creations and deletions of
	 * links to bring the links in sync with those described in the project description.
	 * @param newDescription the new project description that may have
	 * 	changed link descriptions.
	 * @return status ok if everything went well, otherwise an ERROR multi-status
	 * 	describing the problems encountered.
	 */
	public IStatus reconcileLinksAndGroups(ProjectDescription newDescription) {
		String msg = Messages.links_errorLinkReconcile;
		HashMap<IPath, LinkDescription> newLinks = newDescription.getLinks();
		MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.OPERATION_FAILED, msg, null);
		//walk over old linked resources and remove those that are no longer defined
		ProjectDescription oldDescription = internalGetDescription();
		if (oldDescription != null) {
			HashMap<IPath, LinkDescription> oldLinks = oldDescription.getLinks();
			if (oldLinks != null) {
				for (LinkDescription oldLink : oldLinks.values()) {
					Resource oldLinkResource = (Resource) findMember(oldLink.getProjectRelativePath());
					if (oldLinkResource == null || !oldLinkResource.isLinked())
						continue;
					LinkDescription newLink = null;
					if (newLinks != null)
						newLink = newLinks.get(oldLink.getProjectRelativePath());
					//if the new link is missing, or has different (raw) location or gender, then remove old link
					if (newLink == null || !newLink.getLocationURI().equals(oldLinkResource.getRawLocationURI()) || newLink.getType() != oldLinkResource.getType()) {
						try {
							oldLinkResource.delete(IResource.NONE, null);
							//refresh the resource, because removing a link can reveal a previously hidden resource in parent
							oldLinkResource.refreshLocal(IResource.DEPTH_INFINITE, null);
						} catch (CoreException e) {
							status.merge(e.getStatus());
						}
					}
				}
			}
		}
		// walk over new links and groups and create if necessary
		// Recreate them in order of the higher up in the tree hierarchy first,
		// so we don't have to create intermediate directories that would turn
		// out
		// to be groups or link folders.
		if (newLinks == null)
			return status;
		//sort links to avoid creating nested links before their parents
		TreeSet<LinkDescription> newLinksAndGroups = new TreeSet<>((arg0, arg1) -> {
			int numberOfSegments0 = arg0.getProjectRelativePath().segmentCount();
			int numberOfSegments1 = arg1.getProjectRelativePath().segmentCount();
			if (numberOfSegments0 != numberOfSegments1)
				return numberOfSegments0 - numberOfSegments1;
			else if (arg0.equals(arg1))
				return 0;

			return -1;
		});
		if (newLinks != null)
			newLinksAndGroups.addAll(newLinks.values());

		for (LinkDescription newLink : newLinksAndGroups) {
			try {
				Resource toLink = workspace.newResource(getFullPath().append(newLink.getProjectRelativePath()), newLink.getType());
				IContainer parent = toLink.getParent();
				if (parent != null && !parent.exists() && parent.getType() == FOLDER)
					((Folder) parent).ensureExists(Policy.monitorFor(null));
				if (!toLink.exists() || !toLink.isLinked()) {
					if (newLink.isGroup())
						((Folder) toLink).create(IResource.REPLACE | IResource.VIRTUAL, true, null);
					else
						toLink.createLink(newLink.getLocationURI(), IResource.REPLACE | IResource.ALLOW_MISSING_LOCAL, null);
				}
			} catch (CoreException e) {
				status.merge(e.getStatus());
			}
		}
		return status;
	}

	@Override
	public void saveSnapshot(int options, URI snapshotLocation, IProgressMonitor monitor) throws CoreException {
		monitor = Policy.monitorFor(monitor);
		try {
			monitor.beginTask("", Policy.totalWork); //$NON-NLS-1$
			//Project must be open such that variables can be resolved
			checkAccessible(getFlags(getResourceInfo(false, false)));
			//URI must not be null and must not refer to undefined path variables
			URI resolvedSnapshotLocation = getPathVariableManager().resolveURI(snapshotLocation);
			if (resolvedSnapshotLocation == null || !resolvedSnapshotLocation.isAbsolute()) {
				String message = NLS.bind(Messages.projRead_badSnapshotLocation, resolvedSnapshotLocation);
				throw new CoreException(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, message, null));
			}
			if ((options & SNAPSHOT_TREE) != 0) {
				// write a snapshot of refresh information
				try {
					IProgressMonitor sub = Policy.subMonitorFor(monitor, Policy.opWork / 2);
					workspace.getSaveManager().saveRefreshSnapshot(this, resolvedSnapshotLocation, sub);
				} catch (OperationCanceledException e) {
					//workspace.getWorkManager().operationCanceled();
					throw e;
				}
			}
			if ((options & SNAPSHOT_SET_AUTOLOAD) != 0) {
				IProgressMonitor sub = Policy.subMonitorFor(monitor, Policy.opWork / 2);
				//Make absolute URI inside the project relative
				if (snapshotLocation != null && snapshotLocation.isAbsolute()) {
					snapshotLocation = getPathVariableManager().convertToRelative(snapshotLocation, false, "PROJECT_LOC"); //$NON-NLS-1$
				}
				IProjectDescription desc = getDescription();
				((ProjectDescription) desc).setSnapshotLocationURI(snapshotLocation);
				setDescription(desc, IResource.KEEP_HISTORY | IResource.AVOID_NATURE_CONFIG, sub);
			}
		} finally {
			monitor.done();
		}
	}

	@Override
	public void setDescription(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {
		// FIXME - update flags should be honored:
		//    KEEP_HISTORY means capture .project file in local history
		//    FORCE means overwrite any existing .project file
		monitor = Policy.monitorFor(monitor);
		try {
			monitor.beginTask(Messages.resources_setDesc, Policy.totalWork);
			ISchedulingRule rule = null;
			if ((updateFlags & IResource.AVOID_NATURE_CONFIG) != 0)
				rule = workspace.getRuleFactory().modifyRule(this);
			else
				rule = workspace.getRoot();
			try {
				//need to use root rule because nature configuration calls third party code
				workspace.prepareOperation(rule, monitor);
				ResourceInfo info = getResourceInfo(false, false);
				checkAccessible(getFlags(info));
				//if nothing has changed, we don't need to do anything
				ProjectDescription oldDescription = internalGetDescription();
				ProjectDescription newDescription = (ProjectDescription) description;
				boolean hasPublicChanges = oldDescription.hasPublicChanges(newDescription);
				boolean hasPrivateChanges = oldDescription.hasPrivateChanges(newDescription);
				if (!hasPublicChanges && !hasPrivateChanges)
					return;
				checkDescription(this, newDescription, false);
				//If we're out of sync and !FORCE, then fail.
				//If the file is missing, we want to write the new description then throw an exception.
				boolean hadSavedDescription = true;
				if (((updateFlags & IResource.FORCE) == 0)) {
					hadSavedDescription = getLocalManager().hasSavedDescription(this);
					if (hadSavedDescription && !getLocalManager().isDescriptionSynchronized(this)) {
						String message = NLS.bind(Messages.resources_projectDescSync, getName());
						throw new ResourceException(IResourceStatus.OUT_OF_SYNC_LOCAL, getFullPath(), message, null);
					}
				}
				//see if we have an old .prj file
				if (!hadSavedDescription)
					hadSavedDescription = workspace.getMetaArea().hasSavedProject(this);
				workspace.beginOperation(true);
				MultiStatus status = basicSetDescription(newDescription, updateFlags);
				if (hadSavedDescription && !status.isOK())
					throw new CoreException(status);
				//write the new description to the .project file
				writeDescription(oldDescription, updateFlags, hasPublicChanges, hasPrivateChanges);
				//increment the content id even for private changes
				info = getResourceInfo(false, true);
				info.incrementContentId();
				workspace.updateModificationStamp(info);
				if (!hadSavedDescription) {
					String msg = NLS.bind(Messages.resources_missingProjectMetaRepaired, getName());
					status.merge(new ResourceStatus(IResourceStatus.MISSING_DESCRIPTION_REPAIRED, getFullPath(), msg));
				}
				if (!status.isOK())
					throw new CoreException(status);
			} finally {
				workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.POST_PROJECT_CHANGE, this));
				workspace.endOperation(rule, true);
			}
		} finally {
			monitor.done();
		}
	}

	@Override
	public void setDescription(IProjectDescription description, IProgressMonitor monitor) throws CoreException {
		// funnel all operations to central method
		setDescription(description, IResource.KEEP_HISTORY, monitor);
	}

	/**
	 * Restore the non-persisted state for the project.  For example, read and set
	 * the description from the local meta area.  Also, open the property store etc.
	 * This method is used when an open project is restored and so emulates
	 * the behaviour of open().
	 */
	protected void startup() throws CoreException {
		if (!isOpen())
			return;
		workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_OPEN, this));
	}

	@Override
	public void touch(IProgressMonitor monitor) throws CoreException {
		monitor = Policy.monitorFor(monitor);
		try {
			String message = NLS.bind(Messages.resources_touch, getFullPath());
			monitor.beginTask(message, Policy.totalWork);
			final ISchedulingRule rule = workspace.getRuleFactory().modifyRule(this);
			try {
				workspace.prepareOperation(rule, monitor);
				workspace.beginOperation(true);
				super.touch(Policy.subMonitorFor(monitor, Policy.opWork));
			} catch (OperationCanceledException e) {
				workspace.getWorkManager().operationCanceled();
				throw e;
			} finally {
				workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.POST_PROJECT_CHANGE, this));
				workspace.endOperation(rule, true);
			}
		} finally {
			monitor.done();
		}
	}

	/**
	 * The project description file on disk is better than the description in memory.
	 * Make sure the project description in memory is synchronized with the
	 * description file contents.
	 */
	protected void updateDescription() throws CoreException {
		if (ProjectDescription.isWriting)
			return;
		ProjectDescription.isReading = true;
		try {
			ProjectDescription description = getLocalManager().read(this, false);
			//links can only be created if the project is open
			IStatus result = null;
			if (isOpen())
				result = reconcileLinksAndGroups(description);
			internalSetDescription(description, true);
			if (result != null && !result.isOK())
				throw new CoreException(result);
		} finally {
			workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.POST_PROJECT_CHANGE, this));
			ProjectDescription.isReading = false;
		}
	}

	/**
	 * Writes the project's current description file to disk.
	 */
	public void writeDescription(int updateFlags) throws CoreException {
		writeDescription(internalGetDescription(), updateFlags, true, true);
	}

	/**
	 * Writes the project description file to disk.  This is the only method
	 * that should ever be writing the description, because it ensures that
	 * the description isn't then immediately discovered as an incoming
	 * change and read back from disk.
	 * @param description The description to write
	 * @param updateFlags The write operation update flags
	 * @param hasPublicChanges Whether the public sections of the description have changed
	 * @param hasPrivateChanges Whether the private sections of the description have changed
	 * @exception CoreException On failure to write the description
	 */
	public void writeDescription(IProjectDescription description, int updateFlags, boolean hasPublicChanges, boolean hasPrivateChanges) throws CoreException {
		if (ProjectDescription.isReading)
			return;
		ProjectDescription.isWriting = true;
		try {
			getLocalManager().internalWrite(this, description, updateFlags, hasPublicChanges, hasPrivateChanges);
		} finally {
			ProjectDescription.isWriting = false;
		}
	}
}
