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

import java.io.IOException;
import java.util.*;

import org.eclipse.core.internal.events.*;
import org.eclipse.core.internal.localstore.CoreFileSystemLibrary;
import org.eclipse.core.internal.localstore.FileSystemResourceManager;
import org.eclipse.core.internal.properties.PropertyManager;
import org.eclipse.core.internal.utils.*;
import org.eclipse.core.internal.watson.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.team.IMoveDeleteHook;
import org.eclipse.core.resources.team.TeamHook;
import org.eclipse.core.runtime.*;


public class Workspace extends PlatformObject implements IWorkspace, ICoreConstants {

	protected WorkspaceDescription description;
	protected LocalMetaArea localMetaArea;
	protected boolean openFlag = false;
	protected ElementTree tree;
	protected ElementTree operationTree;		// tree at the start of the current operation
	protected SaveManager saveManager;
	protected BuildManager buildManager;
	protected NatureManager natureManager;
	protected NotificationManager notificationManager;
	protected FileSystemResourceManager fileSystemManager;
	protected PathVariableManager pathVariableManager;
	protected PropertyManager propertyManager;
	protected MarkerManager markerManager;
	protected WorkManager workManager;
	protected AliasManager aliasManager;
	protected long nextNodeId = 0;
	protected long nextModificationStamp = 0;
	protected long nextMarkerId = 0;
	protected Synchronizer synchronizer;
	protected IProject[] buildOrder = null;
	protected IWorkspaceRoot defaultRoot = new WorkspaceRoot(Path.ROOT, this);
	
	protected final ArrayList lifecycleListeners = new ArrayList(10);

	protected static final String REFRESH_ON_STARTUP = "-refresh"; //$NON-NLS-1$
	
	/**
	 * File modification validation.  If it is true and validator is null, we try/initialize 
	 * validator first time through.  If false, there is no validator.
	 */
	protected boolean shouldValidate = true;
	/**
	 * The currently installed file modification validator.
	 */
	protected IFileModificationValidator validator = null;
	
	/**
	 * The currently installed Move/Delete hook.
	 */
	protected IMoveDeleteHook moveDeleteHook = null;
	
	/**
	 * The currently installed team hook.
	 */
	protected TeamHook teamHook = null;

	// whether the resources plugin is in debug mode.
	public static boolean DEBUG = false;

	/**
		This field is used to control the access to the workspace tree
	    inside operations. It is useful when calling alien code. Since
	    we usually are in the same thread as the alien code we are calling,
	    our concurrency model would allow the alien code to run operations
	    that could change the tree. If this field is set to true, a
	    beginOperation(true) fails, so the alien code would fail and be logged
	    in our SafeRunnable wrappers, not affecting the normal workspace operation.
	 */
	protected boolean treeLocked;

	/** indicates if the workspace crashed in a previous session */
	protected boolean crashed = false;
public Workspace() {
	super();
	localMetaArea = new LocalMetaArea();
	tree = new ElementTree();
	/* tree should only be modified during operations */
	tree.immutable();
	treeLocked = true;
	tree.setTreeData(newElement(IResource.ROOT));
}
/**
 * Adds a listener for internal workspace lifecycle events.  There is no way to
 * remove lifecycle listeners.
 */
public void addLifecycleListener(ILifecycleListener listener) {
	lifecycleListeners.add(listener);
}
/**
 * @see IWorkspace
 */
public void addResourceChangeListener(IResourceChangeListener listener) {
	notificationManager.addListener(listener, IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.POST_CHANGE);
}
/**
 * @see IWorkspace
 */
public void addResourceChangeListener(IResourceChangeListener listener, int eventMask) {
	notificationManager.addListener(listener, eventMask);
}
/** 
 * @see IWorkspace
 */
public ISavedState addSaveParticipant(Plugin plugin, ISaveParticipant participant) throws CoreException {
	Assert.isNotNull(plugin, "Plugin must not be null"); //$NON-NLS-1$
	Assert.isNotNull(participant, "Participant must not be null"); //$NON-NLS-1$
	return saveManager.addParticipant(plugin, participant);
}
public void beginOperation(boolean createNewTree) throws CoreException {
	WorkManager workManager = getWorkManager();
	workManager.incrementNestedOperations();
	if (!workManager.isBalanced())
		Assert.isTrue(false, "Operation was not prepared."); //$NON-NLS-1$
	if (treeLocked && createNewTree) {
		String message = Policy.bind("resources.cannotModify"); //$NON-NLS-1$
		throw new ResourceException(IResourceStatus.ERROR, null, message, null);
	}
	if (workManager.getPreparedOperationDepth() > 1) {
		if (createNewTree && tree.isImmutable())
			newWorkingTree();
		return;
	}
	if (createNewTree) {
		// stash the current tree as the basis for this operation.
		operationTree = tree;
		newWorkingTree();
	}
}
private void broadcastChanges(ElementTree currentTree, int type, boolean lockTree, boolean updateState, IProgressMonitor monitor) {
	if (operationTree == null)
		return;
	monitor.subTask(Policy.bind("resources.updating")); //$NON-NLS-1$
	notificationManager.broadcastChanges(currentTree, type, lockTree, updateState);
}
/**
 * Broadcasts an internal workspace lifecycle event to interested
 * internal listeners.
 */
protected void broadcastEvent(LifecycleEvent event) throws CoreException {
	
}

public void build(int trigger, IProgressMonitor monitor) throws CoreException {
	monitor = Policy.monitorFor(monitor);
	try {
		monitor.beginTask(null, Policy.opWork);
		try {
			prepareOperation();
			beginOperation(true);
			getBuildManager().build(trigger, Policy.subMonitorFor(monitor, Policy.opWork));
		} finally {
			getWorkManager().avoidAutoBuild();
			endOperation(false, Policy.subMonitorFor(monitor, Policy.buildWork));
		}
	} finally {
		monitor.done();
	}
}
/**
 * Notify the relevant infrastructure pieces that the given project is being
 * changed (e.g., setDescription, move, copy...) and various parts of 
 * the workspace need to be
 * notified so they can update cached structures etc.
 */
public void changing(IProject project) throws CoreException {
	buildManager.changing(project);
	natureManager.changing(project);
	notificationManager.changing(project);
	propertyManager.changing(project);
	markerManager.changing(project);
	aliasManager.changing(project);
}
/**
 * @see IWorkspace#checkpoint
 */
public void checkpoint(boolean build) {
	boolean immutable = true;
	try {
		/* if it was not called by the current operation, just ignore */
		if (!getWorkManager().isCurrentOperation())
			return;
		immutable = tree.isImmutable();
		broadcastChanges(tree, IResourceChangeEvent.PRE_AUTO_BUILD, false, false, Policy.monitorFor(null));
		if (build && isAutoBuilding())
			getBuildManager().build(IncrementalProjectBuilder.AUTO_BUILD, Policy.monitorFor(null));
		broadcastChanges(tree, IResourceChangeEvent.POST_AUTO_BUILD, false, false, Policy.monitorFor(null));
		broadcastChanges(tree, IResourceChangeEvent.POST_CHANGE, true, true, Policy.monitorFor(null));
		getMarkerManager().resetMarkerDeltas();
	} catch (CoreException e) {
		// ignore any CoreException.  There shouldn't be any as the buildmanager and notification manager
		// should be catching and logging...
	} finally {
		if (!immutable)
			newWorkingTree();
	}
}
/**
 * Deletes all the files and directories from the given root down (inclusive).
 * Returns false if we could not delete some file or an exception occurred
 * at any point in the deletion.
 * Even if an exception occurs, a best effort is made to continue deleting.
 */
public static boolean clear(java.io.File root) {
	boolean result = true;
	if (root.isDirectory()) {
		String[] list = root.list();
		// for some unknown reason, list() can return null.  
		// Just skip the children If it does.
		if (list != null)
			for (int i = 0; i < list.length; i++)
				result &= clear(new java.io.File(root, list[i]));
	}
	try {
		if (root.exists())
			result &= root.delete();
	} catch (Exception e) {
		result = false;
	}
	return result;
}
/**
 * Closes this workspace; ignored if this workspace is not open.
 * The state of this workspace is not saved before the workspace
 * is shut down.
 * <p> 
 * If the workspace was saved immediately prior to closing,
 * it will have the same set of projects
 * (open or closed) when reopened for a subsequent session.
 * Otherwise, closing a workspace may lose some or all of the
 * changes made since the last save or snapshot.
 * </p>
 * <p>
 * Note that session properties are discarded when a workspace is closed.
 * </p>
 * <p>
 * This method is long-running; progress and cancellation are provided
 * by the given progress monitor.
 * </p>
 *
 * @param monitor a progress monitor, or <code>null</code> if progress
 *    reporting and cancellation are not desired
 * @exception CoreException if the workspace could not be shutdown.
 */
public void close(IProgressMonitor monitor) throws CoreException {
	monitor = Policy.monitorFor(monitor);
	try {
		String msg = Policy.bind("resources.closing.0"); //$NON-NLS-1$
		int rootCount = tree.getChildCount(Path.ROOT);
		monitor.beginTask(msg, rootCount + 2);
		monitor.subTask(msg);
		//this operation will never end because the world is going away
		try {
			prepareOperation();
			if (isOpen()) {
				beginOperation(true);
				IProject[] projects = getRoot().getProjects();
				for (int i = 0; i < projects.length; i++) {
					//notify managers of closing so they can cleanup
					closing(projects[i]);
					monitor.worked(1);
				}
				//empty the workspace tree so we leave in a clean state
				deleteResource(getRoot());
				openFlag = false;
			}
			// endOperation not needed here
		} finally {
			// Shutdown needs to be executed anyway. Doesn't matter if the workspace was not open.
			shutdown(Policy.subMonitorFor(monitor, 2, SubProgressMonitor.SUPPRESS_SUBTASK_LABEL));
		}
	} finally {
		monitor.done();
	}
}
/**
 * Notify the relevant infrastructure pieces that the given project is being
 * closed.  
 */
protected void closing(IProject project) throws CoreException {
	buildManager.closing(project);
	natureManager.closing(project);
	notificationManager.closing(project);
	propertyManager.closing(project);
	markerManager.closing(project);
	aliasManager.closing(project);
}

/**
 * Implementation of API method declared on IWorkspace.
 * 
 * @deprecated Replaced by <code>IWorkspace.computeProjectOrder</code>, which
 * produces a more usable result when there are cycles in project reference
 * graph.
 */
public IProject[][] computePrerequisiteOrder(IProject[] targets) {
	return computePrerequisiteOrder1(targets);
}

/*
 * Compatible reimplementation of 
 * <code>IWorkspace.computePrerequisiteOrder</code> using 
 * <code>IWorkspace.computeProjectOrder</code>.
 * 
 * @since 2.1
 */
private IProject[][] computePrerequisiteOrder1(IProject[] projects) {
	IWorkspace.ProjectOrder r = computeProjectOrder(projects);
	if (!r.hasCycles) {
		return new IProject[][] {r.projects, new IProject[0]};
	}
	// when there are cycles, we need to remove all knotted projects from
	// r.projects to form result[0] and merge all knots to form result[1]
	// Set<IProject> bad
	Set bad = new HashSet();
	// Set<IProject> bad
	Set keepers = new HashSet(Arrays.asList(r.projects));
	for (int i = 0; i < r.knots.length; i++) {
		IProject[] knot = r.knots[i];
		for (int j = 0; j < knot.length; j++) {
			IProject project = knot[j];
			// keep only selected projects in knot
			if (keepers.contains(project)) {
				bad.add(project);
			}
		}
	}
	IProject[] result2 = new IProject[bad.size()];
	bad.toArray(result2);
	// List<IProject> p
	List p = new LinkedList();
	p.addAll(Arrays.asList(r.projects));
	for (Iterator it = p.listIterator(); it.hasNext(); ) {
		IProject project = (IProject) it.next();
		if (bad.contains(project)) {
			// remove knotted projects from the main answer
			it.remove();
		}
	}
	IProject[] result1 = new IProject[p.size()];
	p.toArray(result1);
	return new IProject[][] {result1, result2};
}

/**
 * Implementation of API method declared on IWorkspace.
 * 
 * @since 2.1
 */
public ProjectOrder computeProjectOrder(IProject[] projects) {
	
	// compute the full project order for all accessible projects
	ProjectOrder fullProjectOrder = computeFullProjectOrder();

	// "fullProjectOrder.projects" contains no inaccessible projects
	// but might contain accessible projects omitted from "projects"
	// optimize common case where "projects" includes everything
	int accessibleCount = 0;
	for (int i = 0; i < projects.length; i++) {
		if (projects[i].isAccessible()) {
			accessibleCount++;
		}
	}
	// no filtering required if the subset accounts for the full list
	if (accessibleCount == fullProjectOrder.projects.length) {
		return fullProjectOrder;
	}

	// otherwise we need to eliminate mention of other projects...
	// ... from "fullProjectOrder.projects"...		
	// Set<IProject> keepers
	Set keepers = new HashSet(Arrays.asList(projects));
	// List<IProject> p
	List reducedProjects = new ArrayList(fullProjectOrder.projects.length);
	for (int i = 0; i < fullProjectOrder.projects.length; i++) {
		IProject project = fullProjectOrder.projects[i];
		if (keepers.contains(project)) {
			// remove projects not in the initial subset
			reducedProjects.add(project);
		}
	}
	IProject[] p1 = new IProject[reducedProjects.size()];
	reducedProjects.toArray(p1);
	
	// ... and from "fullProjectOrder.knots"		
	// List<IProject[]> k
	List reducedKnots = new ArrayList(fullProjectOrder.knots.length);
	for (int i = 0; i < fullProjectOrder.knots.length; i++) {
		IProject[] knot = fullProjectOrder.knots[i];
		List x = new ArrayList(knot.length);
		for (int j = 0; j < knot.length; j++) {
			IProject project = knot[j];
			if (keepers.contains(project)) {
				x.add(project);
			}
		}
		// keep knots containing 2 or more projects in the specified subset
		if (x.size() > 1) {
			reducedKnots.add(x.toArray(new IProject[x.size()]));
		}
	}
	IProject[][] k1 = new IProject[reducedKnots.size()][];
	// okay to use toArray here because reducedKnots elements are IProject[]
	reducedKnots.toArray(k1);
	return new ProjectOrder(p1, (k1.length > 0), k1);
}

/**
 * Computes the global total ordering of all open projects in the
 * workspace based on project references. If an existing and open project P
 * references another existing and open project Q also included in the list,
 * then Q should come before P in the resulting ordering. Closed and non-
 * existent projects are ignored, and will not appear in the result. References
 * to non-existent or closed projects are also ignored, as are any self-
 * references.
 * <p>
 * When there are choices, the choice is made in a reasonably stable way. For
 * example, given an arbitrary choice between two projects, the one with the
 * lower collating project name is usually selected.
 * </p>
 * <p>
 * When the project reference graph contains cyclic references, it is
 * impossible to honor all of the relationships. In this case, the result
 * ignores as few relationships as possible.  For example, if P2 references P1,
 * P4 references P3, and P2 and P3 reference each other, then exactly one of the
 * relationships between P2 and P3 will have to be ignored. The outcome will be
 * either [P1, P2, P3, P4] or [P1, P3, P2, P4]. The result also contains
 * complete details of any cycles present.
 * </p>
 *
 * @return result describing the global project order
 * @since 2.1
 */
private ProjectOrder computeFullProjectOrder() {
	
	// determine the full set of accessible projects in the workspace
	// order the set in descending alphabetical order of project name
	SortedSet allAccessibleProjects = new TreeSet(new Comparator() {
		public int compare(Object x, Object y) {
			IProject px = (IProject) x;
			IProject py = (IProject) y;
			return py.getName().compareTo(px.getName());
		}});
	IProject[] allProjects = getRoot().getProjects();
	// List<IProject[]> edges
	List edges = new ArrayList(allProjects.length);
	for (int i = 0; i < allProjects.length; i++) {
		IProject project = allProjects[i];
		// ignore projects that are not accessible
		if (project.isAccessible()) {
			allAccessibleProjects.add(project);
			IProject[] refs= null;
			try {
				refs = project.getReferencedProjects();
			} catch (CoreException e) {
				// can't happen - project is accessible
			}
			for (int j = 0; j < refs.length; j++) {
				IProject ref = refs[j];
				// ignore self references and references to projects that are
				// not accessible
				if (ref.isAccessible() && !ref.equals(project)) {
					edges.add(new IProject[] {project, ref});
				}
			}
		}
	}
	
	ProjectOrder fullProjectOrder =
		ComputeProjectOrder.computeProjectOrder(allAccessibleProjects, edges);
	return fullProjectOrder;
}

/*
 * @see IWorkspace#copy
 */
public IStatus copy(IResource[] resources, IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
	monitor = Policy.monitorFor(monitor);
	try {
		int opWork = Math.max(resources.length, 1);
		int totalWork = Policy.totalWork * opWork / Policy.opWork;
		String message = Policy.bind("resources.copying.0"); //$NON-NLS-1$
		monitor.beginTask(message, totalWork);
		Assert.isLegal(resources != null);
		if (resources.length == 0)
			return ResourceStatus.OK_STATUS;
		// to avoid concurrent changes to this array
		resources = (IResource[]) resources.clone();
		IPath parentPath = null;
		message = Policy.bind("resources.copyProblem"); //$NON-NLS-1$
		MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, message, null);
		try {
			prepareOperation();
			beginOperation(true);
			for (int i = 0; i < resources.length; i++) {
				Policy.checkCanceled(monitor);
				IResource resource = resources[i];
				if (resource == null || isDuplicate(resources, i)) {
					monitor.worked(1);
					continue;
				}
				// test siblings
				if (parentPath == null)
					parentPath = resource.getFullPath().removeLastSegments(1);
				if (parentPath.equals(resource.getFullPath().removeLastSegments(1))) {
					// test copy requirements
					try {
						IPath destinationPath = destination.append(resource.getName());
						IStatus requirements = ((Resource) resource).checkCopyRequirements(destinationPath, resource.getType(), updateFlags);
						if (requirements.isOK()) {
							try {
								resource.copy(destinationPath, updateFlags, Policy.subMonitorFor(monitor, 1));
							} catch (CoreException e) {
								status.merge(e.getStatus());
							}
						} else {
							monitor.worked(1);
							status.merge(requirements);
						}
					} catch (CoreException e) {
						monitor.worked(1);
						status.merge(e.getStatus());
					}
				} else {
					monitor.worked(1);
					message = Policy.bind("resources.notChild", resources[i].getFullPath().toString(), parentPath.toString()); //$NON-NLS-1$
					status.merge(new ResourceStatus(IResourceStatus.OPERATION_FAILED, resources[i].getFullPath(), message));
				}
			}
		} catch (OperationCanceledException e) {
			getWorkManager().operationCanceled();
			throw e;
		} finally {
			endOperation(true, Policy.subMonitorFor(monitor, totalWork - opWork));
		}
		if (status.matches(IStatus.ERROR))
			throw new ResourceException(status);
		return status.isOK() ? ResourceStatus.OK_STATUS : (IStatus) status;
	} finally {
		monitor.done();
	}
}

/**
 * @see IWorkspace#copy
 */
public IStatus copy(IResource[] resources, IPath destination, boolean force, IProgressMonitor monitor) throws CoreException {
	int updateFlags = force ? IResource.FORCE : IResource.NONE;
	return copy(resources, destination, updateFlags , monitor);
}

protected void copyTree(IResource source, IPath destination, int depth, boolean phantom, boolean overwrite) throws CoreException {
	copyTree(source, destination, depth, phantom, overwrite, false);
}
protected void copyTree(IResource source, IPath destination, int depth, boolean phantom, boolean overwrite, boolean keepSyncInfo) throws CoreException {
	// FIXME: change this method signature to use the int updateFlags rather than the booleans.

	// retrieve the resource at the destination if there is one (phantoms included).
	// if there isn't one, then create a new handle based on the type that we are
	// trying to copy
	IResource destinationResource = getRoot().findMember(destination, true);
	if (destinationResource == null) {
		int destinationType;
		if (source.getType() == IResource.FILE)
			destinationType = IResource.FILE;
		else
			if (destination.segmentCount() == 1)
				destinationType = IResource.PROJECT;
			else
				destinationType = IResource.FOLDER;
		destinationResource = newResource(destination, destinationType);
	}

	// create the resource at the destination
	ResourceInfo sourceInfo = ((Resource) source).getResourceInfo(true, false);
	if (destinationResource.getType() != source.getType()) {
		sourceInfo = (ResourceInfo) sourceInfo.clone();
		sourceInfo.setType(destinationResource.getType());
	}
	ResourceInfo newInfo = createResource(destinationResource, sourceInfo, phantom, overwrite, keepSyncInfo);
	// get/set the node id from the source's resource info so we can later put it in the
	// info for the destination resource. This will help us generate the proper deltas,
	// indicating a move rather than a add/delete
	long nodeid = ((Resource) source).getResourceInfo(true, false).getNodeId();
	newInfo.setNodeId(nodeid);

	// preserve local sync info
	ResourceInfo oldInfo = ((Resource) source).getResourceInfo(true, false);
	newInfo.setFlags(newInfo.getFlags() | (oldInfo.getFlags() & M_LOCAL_EXISTS));
	
	// update link locations in project descriptions
	if (source.isLinked()) {
		newInfo.set(ICoreConstants.M_LINK);
		//create new link location
		Project project = (Project)destinationResource.getProject();
		project.internalGetDescription().setLinkLocation(destinationResource.getName(), 
			new LinkDescription(destinationResource, source.getLocation()));
		project.writeDescription(IResource.NONE);
	}

	// do the recursion. if we have a file then it has no members so return. otherwise
	// recursively call this method on the container's members if the depth tells us to
	if (depth == IResource.DEPTH_ZERO || source.getType() == IResource.FILE)
		return;
	if (depth == IResource.DEPTH_ONE)
		depth = IResource.DEPTH_ZERO;
	int flags = phantom ? IContainer.INCLUDE_PHANTOMS : IResource.NONE;
	flags |= IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS;
	IResource[] children = ((IContainer) source).members(flags);
	for (int i = 0; i < children.length; i++) {
		IResource child = children[i];
		IPath childPath = destination.append(child.getName());
		copyTree(child, childPath, depth, phantom, overwrite, keepSyncInfo);
	}
}
/**
 * Returns the number of resources in a subtree of the resource tree.
 * @param path The subtree to count resources for
 * @param depth The depth of the subtree to count
 * @param phantom If true, phantoms are included, otherwise they are ignored.
 */
public int countResources(IPath root, int depth, final boolean phantom) {
	if (!tree.includes(root))
		return 0;
	switch (depth) {
		case IResource.DEPTH_ZERO:
			return 1;
		case IResource.DEPTH_ONE:
			return 1 + tree.getChildCount(root);
		case IResource.DEPTH_INFINITE:
			final int[] count = new int[1];
			IElementContentVisitor visitor = new IElementContentVisitor() {
				public void visitElement(ElementTree tree, IPath elementPath, Object elementContents) {
					if (phantom || !((ResourceInfo)elementContents).isSet(M_PHANTOM))
						count[0]++;
				}
			};
			new ElementTreeIterator().iterate(tree, visitor, root);
			return count[0];
	}
	return 0;
}
public ResourceInfo createResource(IResource resource, ResourceInfo info, boolean phantom, boolean overwrite) throws CoreException {
	return createResource(resource, info, phantom, overwrite, false);
}
/*
 * Creates the given resource in the tree and returns the new resource info object.  
 * If phantom is true, the created element is marked as a phantom.
 * If there is already be an element in the tree for the given resource
 * in the given state (i.e., phantom), a CoreException is thrown.  
 * If there is already a phantom in the tree and the phantom flag is false, 
 * the element is overwritten with the new element. (but the synchronization
 * information is preserved) If the specified resource info is null, then create
 * a new one.
 * 
 * If keepSyncInfo is set to be true, the sync info in the given ResourceInfo is NOT
 * cleared before being created and thus any sync info already existing at that namespace
 * (as indicated by an already existing phantom resource) will be lost.
 */
public ResourceInfo createResource(IResource resource, ResourceInfo info, boolean phantom, boolean overwrite, boolean keepSyncInfo) throws CoreException {
	info = info == null ? newElement(resource.getType()) : (ResourceInfo) info.clone();
	ResourceInfo original = getResourceInfo(resource.getFullPath(), true, false);
	if (phantom) {
		info.set(M_PHANTOM);
		info.setModificationStamp(IResource.NULL_STAMP);
	}
	// if nothing existed at the destination then just create the resource in the tree
	if (original == null) {
		// we got here from a copy/move. we don't want to copy over any sync info
		// from the source so clear it.
		if (!keepSyncInfo)
			info.setSyncInfo(null);
		tree.createElement(resource.getFullPath(), info);
	} else {
		// if overwrite==true then slam the new info into the tree even if one existed before
		if (overwrite || (!phantom && original.isSet(M_PHANTOM))) {
			// copy over the sync info and flags from the old resource info
			// since we are replacing a phantom with a real resource
			// DO NOT set the sync info dirty flag because we want to
			// preserve the old sync info so its not dirty
			// XXX: must copy over the generic sync info from the old info to the new
			// XXX: do we really need to clone the sync info here?
			if (!keepSyncInfo)
				info.setSyncInfo(original.getSyncInfo(true));
			// mark the markers bit as dirty so we snapshot an empty marker set for
			// the new resource
			info.set(ICoreConstants.M_MARKERS_SNAP_DIRTY);
			tree.setElementData(resource.getFullPath(), info);
		} else {
			String message = Policy.bind("resources.mustNotExist", resource.getFullPath().toString()); //$NON-NLS-1$
			throw new ResourceException(IResourceStatus.RESOURCE_EXISTS, resource.getFullPath(), message, null);
		}
	}
	return info;
}
/**
 * Notify relevant infrastructure pieces that a linked resource is being
 * created.
 */
public void creating(IResource linkedResource) {
	aliasManager.creating(linkedResource);
}


/*
 * Creates the given resource in the tree and returns the new resource info object.  
 * If phantom is true, the created element is marked as a phantom.
 * If there is already be an element in the tree for the given resource
 * in the given state (i.e., phantom), a CoreException is thrown.  
 * If there is already a phantom in the tree and the phantom flag is false, 
 * the element is overwritten with the new element. (but the synchronization
 * information is preserved)
 */
public ResourceInfo createResource(IResource resource, boolean phantom) throws CoreException {
	return createResource(resource, null, phantom, false);
}
public ResourceInfo createResource(IResource resource, boolean phantom, boolean overwrite) throws CoreException {
	return createResource(resource, null, phantom, overwrite);
}
public static WorkspaceDescription defaultWorkspaceDescription() {
	return new WorkspaceDescription("Workspace"); //$NON-NLS-1$
}

/*
 * @see IWorkspace#delete
 */
public IStatus delete(IResource[] resources, int updateFlags, IProgressMonitor monitor) throws CoreException {
	monitor = Policy.monitorFor(monitor);
	try {
		int opWork = Math.max(resources.length, 1);
		int totalWork = Policy.totalWork * opWork / Policy.opWork;
		String message = Policy.bind("resources.deleting.0"); //$NON-NLS-1$
		monitor.beginTask(message, totalWork);
		message = Policy.bind("resources.deleteProblem"); //$NON-NLS-1$
		MultiStatus result = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, message, null);
		if (resources.length == 0)
			return result;
		resources = (IResource[]) resources.clone(); // to avoid concurrent changes to this array
		try {
			prepareOperation();
			beginOperation(true);
			for (int i = 0; i < resources.length; i++) {
				Policy.checkCanceled(monitor);
				Resource resource = (Resource) resources[i];
				if (resource == null) {
					monitor.worked(1);
					continue;
				}
				try {
					resource.delete(updateFlags, Policy.subMonitorFor(monitor, 1));
				} catch (CoreException e) {
					// Don't really care about the exception unless the resource is still around.
					ResourceInfo info = resource.getResourceInfo(false, false);
					if (resource.exists(resource.getFlags(info), false)) {
						message = Policy.bind("resources.couldnotDelete", resource.getFullPath().toString()); //$NON-NLS-1$
						result.merge(new ResourceStatus(IResourceStatus.FAILED_DELETE_LOCAL, resource.getFullPath(), message));
						result.merge(e.getStatus());
					}
				}
			}
			if (result.matches(IStatus.ERROR))
				throw new ResourceException(result);
			return result;
		} catch (OperationCanceledException e) {
			getWorkManager().operationCanceled();
			throw e;
		} finally {
			endOperation(true, Policy.subMonitorFor(monitor, totalWork - opWork));
		}
	} finally {
		monitor.done();
	}
}

/*
 * @see IWorkspace#delete
 */
public IStatus delete(IResource[] resources, boolean force, IProgressMonitor monitor) throws CoreException {
	int updateFlags = force ? IResource.FORCE : IResource.NONE;
	updateFlags |= IResource.KEEP_HISTORY;
	return delete(resources, updateFlags, monitor);
}

/**
 * @see IWorkspace
 */
public void deleteMarkers(IMarker[] markers) throws CoreException {
	Assert.isNotNull(markers);
	if (markers.length == 0)
		return;
	// clone to avoid outside changes
	markers = (IMarker[]) markers.clone();
	try {
		prepareOperation();
		beginOperation(true);
		for (int i = 0; i < markers.length; ++i)
			if (markers[i] != null && markers[i].getResource() != null)
				markerManager.removeMarker(markers[i].getResource(), markers[i].getId());
	} finally {
		endOperation(false, null);
	}
}
/**
 * Delete the given resource from the current tree of the receiver.
 * This method simply removes the resource from the tree.  No cleanup or 
 * other management is done.  Use IResource.delete for proper deletion.
 * If the given resource is the root, all of its children (i.e., all projects) are
 * deleted but the root is left.
 */
void deleteResource(IResource resource) {
	IPath path = resource.getFullPath();
	if (path.equals(Path.ROOT)) {
		IProject[] children = getRoot().getProjects();
		for (int i = 0; i < children.length; i++)
			tree.deleteElement(children[i].getFullPath());
	} else
		tree.deleteElement(path);
}
/**
 * Notify the relevant infrastructure pieces that the given project is being
 * deleted. 
 */
protected void deleting(IProject project) throws CoreException {
	buildManager.deleting(project);
	natureManager.deleting(project);
	notificationManager.deleting(project);
	propertyManager.deleting(project);
	markerManager.deleting(project);
	aliasManager.deleting(project);
}
/**
 * Notify relevant infrastructure pieces that a linked resources is being
 * deleted.  This is needed because the linked resource location is no longer
 * available after the operation is completed.
 */
protected void deleting(IResource linkedResource) throws CoreException {
	aliasManager.deleting(linkedResource);
}
	
/**
 * For debugging purposes only.  Dumps plugin stats to console
 */
public void dumpStats() {
	EventStats.dumpStats();
}
/**
 * End an operation (group of resource changes).
 * Notify interested parties that some resource changes have taken place.
 * This is used in the middle of batch executions to broadcast intermediate
 * results.  All registered resource change listeners are notified.  If autobuilding
 * is enabled, a build is run.
 */
public void endOperation(boolean build, IProgressMonitor monitor) throws CoreException {
	WorkManager workManager = getWorkManager();
	try {
		workManager.setBuild(build);
		// if we are not exiting a top level operation then just decrement the count and return
		if (workManager.getPreparedOperationDepth() > 1) 
			return;
			
		// do the following in a try/finally to ensure that the operation tree is null'd at the end
		// as we are completing a top level operation.
		try {
			// if the tree is locked we likely got here in some finally block after a failed begin.
			// Since the tree is locked, nothing could have been done so there is nothing to do.
			Assert.isTrue(!(treeLocked && workManager.shouldBuild()), "The tree should not be locked."); //$NON-NLS-1$
			// check for a programming error on using beginOperation/endOperation
			Assert.isTrue(workManager.getPreparedOperationDepth() > 0, "Mismatched begin/endOperation"); //$NON-NLS-1$
	
			// At this time we need to rebalance the nested operations. It is necessary because
			// build() and snapshot() should not fail if they are called.
			workManager.rebalanceNestedOperations();
	
			// If autobuild is on, give each open project a chance to build.  We have to tell each one
			// because there is no way of knowing whether or not there is a relevant change
			// for the project without computing the delta for each builder in each project relative
			// to its last built state.  If we have guaranteed corelation between the notification delta
			// and the last time autobuild was done, then we could look at the notification delta and
			// see which projects had changed and only build them.  Currently there is no such
			// guarantee.   
			// Note that  building a project when there is actually nothing to do is not free but
			// is should not be too expensive.  The computed delta will be empty and so the builder itself
			// will not actually be run.  This does require however the delta computation.
			//
			// This is done in a try finally to ensure that we always decrement the operation count.
			// The operationCount cannot be decremented before this as the build must be done
			// inside an operation.  Note that we only ever get here if we are at a top level operation.
			// As such, the operationCount will always be 0 (zero) after this.
			OperationCanceledException cancel = null;
			CoreException signal = null;
			monitor = Policy.monitorFor(monitor);
			monitor.subTask(Policy.bind("resources.updating")); //$NON-NLS-1$
			broadcastChanges(tree, IResourceChangeEvent.PRE_AUTO_BUILD, false, false, Policy.monitorFor(null));
			if (isAutoBuilding() && shouldBuild()) {
				try {
					getBuildManager().build(IncrementalProjectBuilder.AUTO_BUILD, monitor);
				} catch (OperationCanceledException e) {
					cancel = e;
				} catch (CoreException sig) {
					signal = sig;
				}
			}
			broadcastChanges(tree, IResourceChangeEvent.POST_AUTO_BUILD, false, false, Policy.monitorFor(null));
			broadcastChanges(tree, IResourceChangeEvent.POST_CHANGE, true, true, Policy.monitorFor(null));
			getMarkerManager().resetMarkerDeltas();
			// Perform a snapshot if we are sufficiently out of date.  Be sure to make the tree immutable first
			tree.immutable();
			saveManager.snapshotIfNeeded();
			//make sure the monitor subtask message is cleared.
			monitor.subTask(""); //$NON-NLS-1$
			if (cancel != null)
				throw cancel;
			if (signal != null)
				throw signal;
		} finally {
			// make sure that the tree is immutable.  Only do this if we are ending a top-level operation.
			tree.immutable();
			operationTree = null;
		}
	} finally {
		workManager.checkOut();
	}
}

/**
 * Flush the build order cache for the workspace.  Only needed if the
 * description does not already have a build order.  That is, if this
 * is really a cache.
 */
protected void flushBuildOrder() {
	if (description.getBuildOrder(false) == null)
		buildOrder = null;
}
/** 
 * @see IWorkspace
 */
public void forgetSavedTree(String pluginId) {
	Assert.isNotNull(pluginId, "PluginId must not be null"); //$NON-NLS-1$
	saveManager.forgetSavedTree(pluginId);
}
/**
 * Returns this workspace's build manager
 */
public BuildManager getBuildManager() {
	return buildManager;
}

/**
 * Returns the order in which open projects in this workspace will be built.
 * <p>
 * The project build order is based on information specified in the workspace
 * description. The projects are built in the order specified by
 * <code>IWorkspaceDescription.getBuildOrder</code>; closed or non-existent
 * projects are ignored and not included in the result. If
 * <code>IWorkspaceDescription.getBuildOrder</code> is non-null, the default
 * build order is used; again, only open projects are included in the result.
 * </p>
 * <p>
 * The returned value is cached in the <code>buildOrder</code> field.
 * </p>
 * 
 * @return the list of currently open projects in the workspace in the order in
 * which they would be built by <code>IWorkspace.build</code>.
 * @see IWorkspace#build
 * @see IWorkspaceDescription#getBuildOrder
 * @since 2.1
 */
public IProject[] getBuildOrder() {
	if (buildOrder != null) {
		// return previously-computed and cached project build order
		return buildOrder;
	}
	// see if a particular build order is specified
	String[] order = description.getBuildOrder(false);
	if (order != null) {
		// convert from project names to project handles
		// and eliminate non-existent and closed projects
		List projectList = new ArrayList(order.length);
		for (int i = 0; i < order.length; i++) {
			IProject project = getRoot().getProject(order[i]);
			//FIXME should non-accessible projects be removed?
			if (project.isAccessible()) {
				projectList.add(project);
			}
		}
		buildOrder = new IProject[projectList.size()];
		projectList.toArray(buildOrder);
	} else {
		// use default project build order
		// computed for all accessible projects in workspace
		buildOrder = computeFullProjectOrder().projects;
	}
	return buildOrder;
}

/**
 * @see IWorkspace#getDanglingReferences
 */
public Map getDanglingReferences() {
	IProject[] projects = getRoot().getProjects();
	Map result = new HashMap(projects.length);
	for (int i = 0; i < projects.length; i++) {
		Project project = (Project) projects[i];
		if (!project.isAccessible())
			continue;
		IProject[] refs = project.internalGetDescription().getReferencedProjects(false);
		List dangling = new ArrayList(refs.length);
		for (int j = 0; j < refs.length; j++)
			if (!refs[i].exists())
				dangling.add(refs[i]);
		if (!dangling.isEmpty())
			result.put(projects[i], dangling.toArray(new IProject[dangling.size()]));
	}
	return result;
}
/**
 * @see IWorkspace
 */
public IWorkspaceDescription getDescription() {
	return (IWorkspaceDescription) description.clone();
}
/** 
 * Returns the current element tree for this workspace
 */
public ElementTree getElementTree() {
	return tree;
}
public FileSystemResourceManager getFileSystemManager() {
	return fileSystemManager;
}
/**
 * Returns the marker manager for this workspace
 */
public MarkerManager getMarkerManager() {
	return markerManager;
}
public LocalMetaArea getMetaArea() {
	return localMetaArea;
}
protected IMoveDeleteHook getMoveDeleteHook() {
	if (moveDeleteHook == null)
		initializeMoveDeleteHook();
	return moveDeleteHook;
}
/**
 * @see IWorkspace#getNatureDescriptor(String)
 */
public IProjectNatureDescriptor getNatureDescriptor(String natureId) {
	return natureManager.getNatureDescriptor(natureId);
}
/**
 * @see IWorkspace#getNatureDescriptors()
 */
public IProjectNatureDescriptor[] getNatureDescriptors() {
	return natureManager.getNatureDescriptors();
}
/**
 * Returns the nature manager for this workspace.
 */
public NatureManager getNatureManager() {
	return natureManager;
}
public NotificationManager getNotificationManager() {
	return notificationManager;
}
/**
 * @see org.eclipse.core.resources.IWorkspace#getPathVariableManager()
 */
public IPathVariableManager getPathVariableManager() {
	return pathVariableManager;
} 
public PropertyManager getPropertyManager() {
	return propertyManager;
}
/**
 * Returns the resource info for the identified resource.
 * null is returned if no such resource can be found.
 * If the phantom flag is true, phantom resources are considered.
 * If the mutable flag is true, the info is opened for change.
 *
 * This method DOES NOT throw an exception if the resource is not found.
 */
public ResourceInfo getResourceInfo(IPath path, boolean phantom, boolean mutable) {
	try {
		if (path.segmentCount() == 0) {
			ResourceInfo info = (ResourceInfo)tree.getTreeData();
			Assert.isNotNull(info, "Tree root info must never be null"); //$NON-NLS-1$
			return info;
		}
		ResourceInfo result = null;
		if (!tree.includes(path))
			return null;
		if (mutable)
			result = (ResourceInfo) tree.openElementData(path);
		else
			result = (ResourceInfo) tree.getElementData(path);
		if (result != null && (!phantom && result.isSet(M_PHANTOM)))
			return null;
		return result;
	} catch (IllegalArgumentException e) {
		return null;
	}
}
/**
 * @see IWorkspace#getRoot
 */
public IWorkspaceRoot getRoot() {
	return defaultRoot;
}
public SaveManager getSaveManager() {
	return saveManager;
}
/**
 * @see IWorkspace#getSynchronizer
 */
public ISynchronizer getSynchronizer() {
	return synchronizer;
}
/**
 * Returns the installed team hook.  Never returns null.
 */
protected TeamHook getTeamHook() {
	if (teamHook == null)
		initializeTeamHook();
	return teamHook;
}
/**
 * We should not have direct references to this field. All references should go through
 * this method.
 */
public WorkManager getWorkManager() throws CoreException {
	if (workManager == null) {
		String message = Policy.bind("resources.shutdown"); //$NON-NLS-1$
		throw new ResourceException(new ResourceStatus(IResourceStatus.INTERNAL_ERROR, null, message));
	}
	return workManager;
}
/**
 * A file modification validator hasn't been initialized. Check the extension point and 
 * try to create a new validator if a user has one defined as an extension.
 */
protected void initializeValidator() {
	shouldValidate = false;
	IConfigurationElement[] configs = Platform.getPluginRegistry().getConfigurationElementsFor(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_FILE_MODIFICATION_VALIDATOR);
	// no-one is plugged into the extension point so disable validation
	if (configs == null || configs.length == 0) {
		return;
	}
	// can only have one defined at a time. log a warning, disable validation, but continue with
	// the #setContents (e.g. don't throw an exception)
	if (configs.length > 1) {
		//XXX: shoud provide a meaningful status code
		IStatus status = new ResourceStatus(IResourceStatus.ERROR, 1, null, Policy.bind("resources.oneValidator"), null); //$NON-NLS-1$
		ResourcesPlugin.getPlugin().getLog().log(status);
		return;
	}
	// otherwise we have exactly one validator extension. Try to create a new instance 
	// from the user-specified class.
	try {
		IConfigurationElement config = configs[0];
		validator = (IFileModificationValidator) config.createExecutableExtension("class"); //$NON-NLS-1$
		shouldValidate = true;
	} catch (CoreException e) {
		//XXX: shoud provide a meaningful status code
		IStatus status = new ResourceStatus(IResourceStatus.ERROR, 1, null, Policy.bind("resources.initValidator"), e); //$NON-NLS-1$
		ResourcesPlugin.getPlugin().getLog().log(status);
	}
}
/**
 * A move/delete hook hasn't been initialized. Check the extension point and 
 * try to create a new hook if a user has one defined as an extension. Otherwise
 * use the Core's implementation as the default.
 */
protected void initializeMoveDeleteHook() {
	try {
		IConfigurationElement[] configs = Platform.getPluginRegistry().getConfigurationElementsFor(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_MOVE_DELETE_HOOK);
		// no-one is plugged into the extension point so disable validation
		if (configs == null || configs.length == 0) {
			return;
		}
		// can only have one defined at a time. log a warning
		if (configs.length > 1) {
			//XXX: shoud provide a meaningful status code
			IStatus status = new ResourceStatus(IResourceStatus.ERROR, 1, null, Policy.bind("resources.oneHook"), null); //$NON-NLS-1$
			ResourcesPlugin.getPlugin().getLog().log(status);
			return;
		}
		// otherwise we have exactly one hook extension. Try to create a new instance 
		// from the user-specified class.
		try {
			IConfigurationElement config = configs[0];
			moveDeleteHook = (IMoveDeleteHook) config.createExecutableExtension("class"); //$NON-NLS-1$
		} catch (CoreException e) {
			//XXX: shoud provide a meaningful status code
			IStatus status = new ResourceStatus(IResourceStatus.ERROR, 1, null, Policy.bind("resources.initHook"), e); //$NON-NLS-1$
			ResourcesPlugin.getPlugin().getLog().log(status);
		}
	} finally {
		// for now just use Core's implementation
		if (moveDeleteHook == null)
			moveDeleteHook = new MoveDeleteHook();
	}
}
/**
 * A team hook hasn't been initialized. Check the extension point and 
 * try to create a new hook if a user has one defined as an extension. 
 * Otherwise use the Core's implementation as the default.
 */
protected void initializeTeamHook() {
	try {
		IConfigurationElement[] configs = Platform.getPluginRegistry().getConfigurationElementsFor(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PT_TEAM_HOOK);
		// no-one is plugged into the extension point so disable validation
		if (configs == null || configs.length == 0) {
			return;
		}
		// can only have one defined at a time. log a warning
		if (configs.length > 1) {
			//XXX: shoud provide a meaningful status code
			IStatus status = new ResourceStatus(IResourceStatus.ERROR, 1, null, Policy.bind("resources.oneTeamHook"), null); //$NON-NLS-1$
			ResourcesPlugin.getPlugin().getLog().log(status);
			return;
		}
		// otherwise we have exactly one hook extension. Try to create a new instance 
		// from the user-specified class.
		try {
			IConfigurationElement config = configs[0];
			teamHook = (TeamHook) config.createExecutableExtension("class"); //$NON-NLS-1$
		} catch (CoreException e) {
			//XXX: shoud provide a meaningful status code
			IStatus status = new ResourceStatus(IResourceStatus.ERROR, 1, null, Policy.bind("resources.initTeamHook"), e); //$NON-NLS-1$
			ResourcesPlugin.getPlugin().getLog().log(status);
		}
	} finally {
		// default to use Core's implementation
		if (teamHook == null)
			teamHook = new TeamHook();
	}
}
public WorkspaceDescription internalGetDescription() {
	return description;
}
/**
 * @see IWorkspace
 */
public boolean isAutoBuilding() {
	return description.isAutoBuilding();
}
/**
 * Returns true if the object at the specified position has any
 * other copy in the given array.
 */
private static boolean isDuplicate(Object[] array, int position) {
	if (array == null || position >= array.length)
		return false;
	for (int j = position - 1; j >= 0; j--)
		if (array[j].equals(array[position]))
			return true;
	return false;
}
/**
 * @see IWorkspace#isOpen
 */
public boolean isOpen() {
	return openFlag;
}
/**
 * Returns true if the given file system locations overlap (they are the same,
 * or one is a proper prefix of the other), and false otherwise.  
 * Does the right thing with respect to case insensitive platforms.
 */
protected boolean isOverlapping(IPath location1, IPath location2) {
	IPath one = location1;
	IPath two = location2;
	// If we are on a case-insensitive file system then convert to all lowercase.
	if (!CoreFileSystemLibrary.isCaseSensitive()) {
		one = new Path(location1.toOSString().toLowerCase());
		two = new Path(location2.toOSString().toLowerCase());
	}
	return one.isPrefixOf(two) || two.isPrefixOf(one);
}
public boolean isTreeLocked() {
	return treeLocked;
}
/**
 * Link the given tree into the receiver's tree at the specified resource.
 */
protected void linkTrees(IPath path, ElementTree[] newTrees) throws CoreException {
	tree = tree.mergeDeltaChain(path, newTrees);
}
/**
 * @see IWorkspace#loadProjectDescription
 * @since 2.0
 */
public IProjectDescription loadProjectDescription(IPath path) throws CoreException {
	IProjectDescription result = null;
	IOException e = null;
	try {
		result = (IProjectDescription) new ModelObjectReader().read(path);
		if (result != null) {
			// check to see if we are using in the default area or not. use java.io.File for
			// testing equality because it knows better w.r.t. drives and case sensitivity
			IPath user = path.removeLastSegments(1);
			IPath platform = Platform.getLocation().append(result.getName());
			if (!user.toFile().equals(platform.toFile()))
				result.setLocation(user);
		}
	} catch (IOException ex) {
		e = ex;
	}
	if (result == null || e != null) {
		String message = Policy.bind("resources.errorReadProject", path.toOSString());//$NON-NLS1 //$NON-NLS-1$
		IStatus status = new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_READ_METADATA, message, e);
		throw new ResourceException(status);
	}
	return result;
} 


/*
 * @see IWorkspace#move
 */
public IStatus move(IResource[] resources, IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
	monitor = Policy.monitorFor(monitor);
	try {
		int opWork = Math.max(resources.length, 1);
		int totalWork = Policy.totalWork * opWork / Policy.opWork;
		String message = Policy.bind("resources.moving.0"); //$NON-NLS-1$
		monitor.beginTask(message, totalWork);
		Assert.isLegal(resources != null);
		if (resources.length == 0)
			return ResourceStatus.OK_STATUS;
		resources = (IResource[]) resources.clone(); // to avoid concurrent changes to this array
		IPath parentPath = null;
		message = Policy.bind("resources.moveProblem"); //$NON-NLS-1$
		MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, message, null);
		try {
			prepareOperation();
			beginOperation(true);
			for (int i = 0; i < resources.length; i++) {
				Policy.checkCanceled(monitor);
				Resource resource = (Resource) resources[i];
				if (resource == null || isDuplicate(resources, i)) {
					monitor.worked(1);
					continue;
				}
				// test siblings
				if (parentPath == null)
					parentPath = resource.getFullPath().removeLastSegments(1);
				if (parentPath.equals(resource.getFullPath().removeLastSegments(1))) {
					// test move requirements
					try {
						IStatus requirements = resource.checkMoveRequirements(destination.append(resource.getName()), resource.getType(), updateFlags);
						if (requirements.isOK()) {
							try {
								resource.move(destination.append(resource.getName()), updateFlags, Policy.subMonitorFor(monitor, 1));
							} catch (CoreException e) {
								status.merge(e.getStatus());
							}
						} else {
							monitor.worked(1);
							status.merge(requirements);
						}
					} catch (CoreException e) {
						monitor.worked(1);
						status.merge(e.getStatus());
					}
				} else {
					monitor.worked(1);
					message = Policy.bind("resources.notChild", resource.getFullPath().toString(), parentPath.toString()); //$NON-NLS-1$
					status.merge(new ResourceStatus(IResourceStatus.OPERATION_FAILED, resource.getFullPath(), message));
				}
			}
		} catch (OperationCanceledException e) {
			getWorkManager().operationCanceled();
			throw e;
		} finally {
			endOperation(true, Policy.subMonitorFor(monitor, totalWork - opWork));
		}
		if (status.matches(IStatus.ERROR))
			throw new ResourceException(status);
		return status.isOK() ? (IStatus) ResourceStatus.OK_STATUS : (IStatus) status;
	} finally {
		monitor.done();
	}
}

/**
 * @see IWorkspace#move
 */
public IStatus move(IResource[] resources, IPath destination, boolean force, IProgressMonitor monitor) throws CoreException {
	int updateFlags = force ? IResource.FORCE : IResource.NONE;
	updateFlags |= IResource.KEEP_HISTORY;
	return move(resources, destination, updateFlags, monitor);
}

/* package */ void move(Resource source, IPath destination, int depth, boolean overwrite) throws CoreException {
	move(source, destination, depth, overwrite, false);
}
/**
 * Moves this resource's subtree to the destination. This operation should only be
 * used by move methods. Destination must be a valid destination for this resource.
 * The keepSyncInfo boolean is used to indicated whether or not the sync info should
 * be moved from the source to the destination.
 */

/* package */ void move(Resource source, IPath destination, int depth, boolean overwrite, boolean keepSyncInfo) throws CoreException {
	// overlay the tree at the destination path, preserving any important info
	// in any already existing resource infos
	copyTree(source, destination, depth, false, overwrite, keepSyncInfo);
	source.fixupAfterMoveSource();
}
/**
 * Notify the relevant infrastructure pieces that the given project or linked
 * resource is being moved.
 */
protected void moving(IResource source, IResource destination, int updateFlags) {
	//most infrastructure only cares about project deletion
	if (source.getType() == IResource.PROJECT) {
		IProject project = (IProject)source;
		buildManager.deleting(project);
		natureManager.deleting(project);
		notificationManager.deleting(project);
		propertyManager.deleting(project);
		markerManager.deleting(project);
	}
	aliasManager.moving(source, destination, updateFlags);
}

/**
 * Create and return a new tree element of the given type.
 */
protected ResourceInfo newElement(int type) {
	ResourceInfo result = null;
	switch (type) {
		case IResource.FILE :
		case IResource.FOLDER :
			result = new ResourceInfo();
			break;
		case IResource.PROJECT :
			result = new ProjectInfo();
			break;
		case IResource.ROOT :
			result = new RootInfo();
			break;
	}
	result.setNodeId(nextNodeId());
	result.setModificationStamp(nextModificationStamp());
	result.setType(type);
	return result;
}
/**
 * @see IWorkspace#newProjectDescription
 */
public IProjectDescription newProjectDescription(String projectName) {
	IProjectDescription result = new ProjectDescription();
	result.setName(projectName);
	return result;
}
public Resource newResource(IPath path, int type) {
	String message;
	switch (type) {
		case IResource.FOLDER :
			message = "Path must include project and resource name."; //$NON-NLS-1$
			Assert.isLegal(path.segmentCount() >= ICoreConstants.MINIMUM_FOLDER_SEGMENT_LENGTH , message);
			return new Folder(path.makeAbsolute(), this);
		case IResource.FILE :
			message = "Path must include project and resource name."; //$NON-NLS-1$
			Assert.isLegal(path.segmentCount() >= ICoreConstants.MINIMUM_FILE_SEGMENT_LENGTH, message);
			return new File(path.makeAbsolute(), this);
		case IResource.PROJECT :
			return (Resource) getRoot().getProject(path.lastSegment());
		case IResource.ROOT :
			return (Resource) getRoot();
	}
	Assert.isLegal(false);
	// will never get here because of assertion.
	return null;
}
/**
 * Opens a new mutable element tree layer, thus allowing 
 * modifications to the tree.
 */
public ElementTree newWorkingTree() {
	tree = tree.newEmptyDelta();
	return tree;
}
/**
 * Returns the next, previously unassigned, marker id.
 */
protected long nextMarkerId() {
	return nextMarkerId++;
}
public long nextModificationStamp() {
	return nextModificationStamp++;
}
public long nextNodeId() {
	return nextNodeId++;
}
/**
 * Opens this workspace using the data at its location in the local file system.
 * This workspace must not be open.
 * If the operation succeeds, the result will detail any serious
 * (but non-fatal) problems encountered while opening the workspace.
 * The status code will be <code>OK</code> if there were no problems.
 * An exception is thrown if there are fatal problems opening the workspace,
 * in which case the workspace is left closed.
 * <p>
 * This method is long-running; progress and cancellation are provided
 * by the given progress monitor.
 * </p>
 *
 * @param monitor a progress monitor, or <code>null</code> if progress
 *    reporting and cancellation are not desired
 * @return status with code <code>OK</code> if no problems;
 *     otherwise status describing any serious but non-fatal problems.
 *     
 * @exception CoreException if the workspace could not be opened.
 * Reasons include:
 * <ul>
 * <li> There is no valid workspace structure at the given location
 *      in the local file system.</li>
 * <li> The workspace structure on disk appears to be hopelessly corrupt.</li>
 * </ul>
 * @see IWorkspace#getLocation
 * @see ResourcePlugin#containsWorkspace
 */
public IStatus open(IProgressMonitor monitor) throws CoreException {
	// This method is not inside an operation because it is the one responsible for
	// creating the WorkManager object (who takes care of operations).
	String message = Policy.bind("resources.workspaceOpen"); //$NON-NLS-1$
	Assert.isTrue(!isOpen(), message);
	description = getMetaArea().readWorkspace();
	if (description == null) {
		message = Policy.bind("resources.readWorkspaceMeta"); //$NON-NLS-1$
		throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, Platform.getLocation(), message, null);
	}

	// create root location
	localMetaArea.locationFor(getRoot()).toFile().mkdirs();
		
	// turn off autobuilding while we open the workspace.  This is in
	// case an operation is triggered.  We don't want to do an autobuild
	// just yet. Any changes will be reported the next time we build.
	boolean oldBuildFlag = description.isAutoBuilding();
	try {
		description.setAutoBuilding(false);
		IProgressMonitor nullMonitor = Policy.monitorFor(null);
		startup(nullMonitor);
		//restart the notification manager so it is initialized with the right tree
		notificationManager.startup(null);
		openFlag = true;
		if (crashed || refreshRequested()) {
			try {
				getRoot().refreshLocal(IResource.DEPTH_INFINITE, null);
			} catch (CoreException e) {
				//don't fail entire open if refresh failed, just report as minor warning
				return e.getStatus();
			}
		}
		return ResourceStatus.OK_STATUS;
	} finally {
		description.setAutoBuilding(oldBuildFlag);
	}
}
/**
 * Notify the relevant infrastructure pieces that the given project is being
 * opened. 
 */
protected void opening(IProject project) throws CoreException {
	buildManager.opening(project);
	natureManager.opening(project);
	notificationManager.opening(project);
	propertyManager.opening(project);
	markerManager.opening(project);
	aliasManager.opening(project);
}
/**
 * Called before checking the pre-conditions of an operation.
 */
public void prepareOperation() throws CoreException {
	getWorkManager().checkIn();
	if (!isOpen()) {
		String message = Policy.bind("resources.workspaceClosed"); //$NON-NLS-1$
		throw new ResourceException(IResourceStatus.OPERATION_FAILED, null, message, null);
	}
}

protected boolean refreshRequested() {
	String[] args = Platform.getCommandLineArgs();
	for (int i = 0; i < args.length; i++) 
		if (args[i].equalsIgnoreCase(REFRESH_ON_STARTUP))
			return true;
	return false;
}
/**
 * @see IWorkspace
 */
public void removeResourceChangeListener(IResourceChangeListener listener) {
	notificationManager.removeListener(listener);
}
/**
 * @see IWorkspace
 */
public void removeSaveParticipant(Plugin plugin) {
	Assert.isNotNull(plugin, "Plugin must not be null"); //$NON-NLS-1$
	saveManager.removeParticipant(plugin);
}
/**
 * @see IWorkspace#run
 */
public void run(IWorkspaceRunnable job, IProgressMonitor monitor) throws CoreException {
	monitor = Policy.monitorFor(monitor);
	try {
		monitor.beginTask(null, Policy.totalWork);
		try {
			prepareOperation();
			beginOperation(true);
			job.run(Policy.subMonitorFor(monitor, Policy.opWork, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
		} catch (OperationCanceledException e) {
			getWorkManager().operationCanceled();
			throw e;
		} finally {
			endOperation(false, Policy.subMonitorFor(monitor, Policy.buildWork));
		}
	} finally {
		monitor.done();
	}
}
/** 
 * @see IWorkspace
 */
public IStatus save(boolean full, IProgressMonitor monitor) throws CoreException {
	String message;
	// if a full save was requested, and this is a top-level op, try the save.  Otherwise
	// fail the operation.
	if (full) {
		// If the workmanager thread is null or is different than this thread
		// it is OK to start the save because it will wait until the other thread
		// is finished. Otherwise, someone in this thread has tried to do a save
		// inside of an operation (which is not allowed by the spec).
		if (getWorkManager().getCurrentOperationThread() == Thread.currentThread()) {
			message = Policy.bind("resources.saveOp"); //$NON-NLS-1$
			throw new ResourceException(IResourceStatus.OPERATION_FAILED, null, message, null);
		} 
		return saveManager.save(ISaveContext.FULL_SAVE, null, monitor);
	}
	// A snapshot was requested.  Start an operation (if not already started) and 
	// signal that a snapshot should be done at the end.
	try {
		prepareOperation();
		beginOperation(false);
		saveManager.requestSnapshot();
		message = Policy.bind("resources.snapRequest"); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.OK, message);
	} finally {
		endOperation(false, null);
	}
}
public void setCrashed(boolean value) {
	crashed = value;
}
/**
 * @see IWorkspace
 */
public void setDescription(IWorkspaceDescription value) throws CoreException {
	// if both the old and new description's build orders are null, leave the
	// workspace's build order slot because it is caching the computed order.
	// Otherwise, set the slot to null to force recomputation or building from the description.
	String[] newOrder = ((WorkspaceDescription) value).getBuildOrder(false);
	if (description.getBuildOrder(false) != null || newOrder != null)
		buildOrder = null;
	description = (WorkspaceDescription) ((WorkspaceDescription) value).clone();
	Policy.setupAutoBuildProgress(description.isAutoBuilding());
	localMetaArea.write(description);
}
public void setTreeLocked(boolean locked) {
	treeLocked = locked;
}
public void setWorkspaceLock(WorkspaceLock lock) {
	workManager.setWorkspaceLock(lock);
}

private boolean shouldBuild() throws CoreException {
	return getWorkManager().shouldBuild() && ElementTree.hasChanges(tree, operationTree, ResourceComparator.getComparator(false), true);
}
protected void shutdown(IProgressMonitor monitor) throws CoreException {
	monitor = Policy.monitorFor(monitor);
	try {
		IManager[] managers = { buildManager, notificationManager, propertyManager, pathVariableManager, fileSystemManager, markerManager, saveManager, workManager };
		monitor.beginTask(null, managers.length);
		String message = Policy.bind("resources.shutdownProblems"); //$NON-NLS-1$
		MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, message, null);
		// best effort to shutdown every object and free resources
		for (int i = 0; i < managers.length; i++) {
			IManager manager = managers[i];
			if (manager == null)
				monitor.worked(1);
			else {
				try {
					manager.shutdown(Policy.subMonitorFor(monitor, 1));
				} catch (Exception e) {
					message = Policy.bind("resources.shutdownProblems"); //$NON-NLS-1$
					status.add(new Status(Status.ERROR, ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, message, e));
				}
			}
		}
		buildManager = null;
		notificationManager = null;
		propertyManager = null;
		pathVariableManager = null;
		fileSystemManager = null;
		markerManager = null;
		synchronizer = null;
		saveManager = null;
		workManager = null;
		if (!status.isOK())
			throw new CoreException(status);
	} finally {
		monitor.done();
	}
}
/**
 * @see IWorkspace#sortNatureSet(String[])
 */
public String[] sortNatureSet(String[] natureIds) {
	return natureManager.sortNatureSet(natureIds);
}
protected void startup(IProgressMonitor monitor) throws CoreException {
	// ensure the tree is locked during the startup notification
	workManager = new WorkManager(this);
	workManager.startup(null);
	fileSystemManager = new FileSystemResourceManager(this);
	fileSystemManager.startup(monitor);
	propertyManager = new PropertyManager(this);
	propertyManager.startup(monitor);
	pathVariableManager = new PathVariableManager(this);
	pathVariableManager.startup(null);
	natureManager = new NatureManager();
	natureManager.startup(null);
	buildManager = new BuildManager(this);
	buildManager.startup(null);
	notificationManager = new NotificationManager(this);
	notificationManager.startup(null);
	markerManager = new MarkerManager(this);
	markerManager.startup(null);
	synchronizer = new Synchronizer(this);
	saveManager = new SaveManager(this);
	saveManager.startup(null);
	//must start after save manager, because (read) access to tree is needed
	aliasManager = new AliasManager(this);
	aliasManager.startup(null);
	
	treeLocked = false; // unlock the tree.
}
/** 
 * Returns a string representation of this working state's
 * structure suitable for debug purposes.
 */
public String toDebugString() {
	final StringBuffer buffer = new StringBuffer("\nDump of " + toString() + ":\n"); //$NON-NLS-1$ //$NON-NLS-2$
	buffer.append("  parent: " + tree.getParent()); //$NON-NLS-1$
	ElementTreeIterator iterator = new ElementTreeIterator();
	IElementContentVisitor visitor = new IElementContentVisitor() {
		public void visitElement(ElementTree tree, IPath path, Object elementContents) {
			buffer.append("\n  " + path + ": " + elementContents); //$NON-NLS-1$ //$NON-NLS-2$
		}
	};
	iterator.iterate(tree, visitor);
	return buffer.toString();
}
public void updateModificationStamp(ResourceInfo info) {
	info.setModificationStamp(nextModificationStamp());
}
/* (non-javadoc)
 * Method declared on IWorkspace.
 */
public IStatus validateEdit(final IFile[] files, final Object context) {
	// if validation is turned off then just return
	if (!shouldValidate) {
		String message = Policy.bind("resources.readOnly2"); //$NON-NLS-1$
		MultiStatus result = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.OK, message, null);
		for (int i=0; i<files.length; i++) {
			if (files[i].isReadOnly()) {
				IPath filePath = files[i].getFullPath();
				message = Policy.bind("resources.readOnly", filePath.toString()); //$NON-NLS-1$
				result.add(new ResourceStatus(IResourceStatus.FAILED_WRITE_LOCAL, filePath, message));
			}
		}
		return result.isOK() ? ResourceStatus.OK_STATUS : (IStatus) result;
	}
	// first time through the validator hasn't been initialized so try and create it
	if (validator == null) 
		initializeValidator();
	// we were unable to initialize the validator. Validation has been turned off and 
	// a warning has already been logged so just return.
	if (validator == null)
		return ResourceStatus.OK_STATUS;
	// otherwise call the API and throw an exception if appropriate
	final IStatus[] status = new IStatus[1];
	ISafeRunnable body = new ISafeRunnable() {
		public void run() throws Exception {
			status[0] = validator.validateEdit(files, context);
		}
		public void handleException(Throwable exception) {
			status[0]  = new ResourceStatus(IResourceStatus.ERROR, null, Policy.bind("resources.errorValidator"), exception); //$NON-NLS-1$
		}
	};
	Platform.run(body);
	return status[0];
}
/* (non-javadoc)
 * Method declared on IWorkspace.
 */
public IStatus validateLinkLocation(IResource resource, IPath location) {
	//check the standard path name restrictions
	int segmentCount = location.segmentCount();
	for (int i = 0; i < segmentCount; i++) {
		IStatus result = validateName(location.segment(i), resource.getType());
		if (!result.isOK())
			return result;
	}
	//if the location doesn't have a device, see if the OS will assign one
	if (location.getDevice() == null)
		location = new Path(location.toFile().getAbsolutePath());
	// test if the given location overlaps the platform metadata location
	IPath testLocation = getMetaArea().getLocation();
	String message;
	if (isOverlapping(location, testLocation)) {
		message = Policy.bind("links.invalidLocation", location.toString()); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}
	//test if the given path overlaps the location of the given project
	testLocation = resource.getProject().getLocation();
	if (isOverlapping(location, testLocation)) {
		message = Policy.bind("links.locationOverlapsProject", location.toString()); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}
	// Iterate over each known project and ensure that the location does not
	// conflict with any project locations or linked resource locations
	IProject[] projects = getRoot().getProjects();
	for (int i = 0; i < projects.length; i++) {
		IProject project = (IProject) projects[i];
		// since we are iterating over the project in the workspace, we
		// know that they have been created before and must have a description
		IProjectDescription desc  = ((Project) project).internalGetDescription();
		testLocation = desc.getLocation();
		// if the project uses the default location then continue
		if (testLocation == null)
			continue;
		if (isOverlapping(location, testLocation)) {
			message = Policy.bind("links.overlappingResource", location.toString()); //$NON-NLS-1$
			return new ResourceStatus(IResourceStatus.OVERLAPPING_LOCATION, null, message);
		}
		//iterate over linked resources and check for overlap
		if (!project.isOpen())
			continue;
		IResource[] children = null;
		try {
			children = project.members();
		} catch (CoreException e) {
			//ignore projects that cannot be accessed
		}
		if (children == null)
			continue;
		for (int j = 0; j < children.length; j++) {
			if (children[j].isLinked()) {
				testLocation = children[j].getLocation();
				if (isOverlapping(location, testLocation)) {
					message = Policy.bind("links.overlappingResource", location.toString()); //$NON-NLS-1$
					return new ResourceStatus(IResourceStatus.OVERLAPPING_LOCATION, null, message);
				}
			}				
		}
	}
	return ResourceStatus.OK_STATUS;
}
/**
 * @see IWorkspace#validateName
 */
public IStatus validateName(String segment, int type) {
	String message;

	/* segment must not be null */
	if (segment == null) {
		message = Policy.bind("resources.nameNull"); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}

	// cannot be an empty string
	if (segment.length() == 0) {
		message = Policy.bind("resources.nameEmpty"); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}

	/* segment must not begin or end with a whitespace */
	if (Character.isWhitespace(segment.charAt(0)) || Character.isWhitespace(segment.charAt(segment.length() - 1))) {
		message = Policy.bind("resources.invalidWhitespace",segment); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}

	/* segment must not end with a dot */
	if (segment.endsWith(".")) { //$NON-NLS-1$
		message = Policy.bind("resources.invalidDot", segment); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}

	/* test invalid characters */
	char[] chars = OS.INVALID_RESOURCE_CHARACTERS;
	for (int i = 0; i < chars.length; i++)
		if (segment.indexOf(chars[i]) != -1) {
			message = Policy.bind("resources.invalidCharInName", String.valueOf(chars[i]), segment); //$NON-NLS-1$
			return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
		}

	/* test invalid OS names */
	if (!OS.isNameValid(segment)) {
		message = Policy.bind("resources.invalidName", segment); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}
	return ResourceStatus.OK_STATUS;
}
/**
 * @see IWorkspace#validateNatureSet(String[])
 */
public IStatus validateNatureSet(String[] natureIds) {
	return natureManager.validateNatureSet(natureIds);
}
/**
 * @see IWorkspace#validatePath
 */
public IStatus validatePath(String path, int type) {
	String message;

	/* path must not be null */
	if (path == null) {
		message = Policy.bind("resources.pathNull"); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}

	/* path must not have a device separator */
	if (path.indexOf(IPath.DEVICE_SEPARATOR) != -1) {
		message = Policy.bind("resources.invalidCharInPath", String.valueOf(IPath.DEVICE_SEPARATOR), path); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}

	/* path must not be the root path */
	IPath testPath = new Path(path);
	if (testPath.isRoot()) {
		message = Policy.bind("resources.invalidRoot"); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}

	/* path must be absolute */
	if (!testPath.isAbsolute()) {
		message = Policy.bind("resources.mustBeAbsolute", path); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}

	/* validate segments */
	int numberOfSegments = testPath.segmentCount();
	if ((type & IResource.PROJECT) != 0) {
		if (numberOfSegments == ICoreConstants.PROJECT_SEGMENT_LENGTH) {
			return validateName(testPath.segment(0), IResource.PROJECT);
		} else
			if (type == IResource.PROJECT) {
				message = Policy.bind("resources.projectPath",path); //$NON-NLS-1$
				return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
			}
	}
	if ((type & (IResource.FILE | IResource.FOLDER)) != 0)
		if (numberOfSegments >= ICoreConstants.MINIMUM_FILE_SEGMENT_LENGTH) {
			IStatus status = validateName(testPath.segment(0), IResource.PROJECT);
			if (!status.isOK())
				return status;
			int fileFolderType = type &= ~IResource.PROJECT;
			int segmentCount = testPath.segmentCount();
			// ignore first segment (the project)
			for (int i = 1; i < segmentCount; i++) {
				status = validateName(testPath.segment(i), fileFolderType);
				if (!status.isOK())
					return status;
			}
			return ResourceStatus.OK_STATUS;
		} else {
			message = Policy.bind("resources.resourcePath",path); //$NON-NLS-1$
			return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
		}
	message = Policy.bind("resources.invalidPath", path); //$NON-NLS-1$
	return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
}
/**
 * @see IWorkspace#validateProjectLocation
 */
public IStatus validateProjectLocation(IProject context, IPath location) {
	String message;
	// the default default is ok for all projects
	if (location == null) {
		message = Policy.bind("resources.validLocation"); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.OK, message);
	}
	//check the standard path name restrictions
	int segmentCount = location.segmentCount();
	for (int i = 0; i < segmentCount; i++) {
		IStatus result = validateName(location.segment(i), IResource.PROJECT);
		if (!result.isOK())
			return result;
	}
	//if the location doesn't have a device, see if the OS will assign one
	if (location.getDevice() == null)
		location = new Path(location.toFile().getAbsolutePath());
	// test if the given location overlaps the default default location
	IPath defaultDefaultLocation = Platform.getLocation();
	if (isOverlapping(location, defaultDefaultLocation)) {
		message = Policy.bind("resources.overlapLocal", location.toString(), defaultDefaultLocation.toString()); //$NON-NLS-1$
		return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
	}
	// Iterate over each known project and ensure that the location does not
	// conflict with any of their already defined locations.
	IProject[] projects = getRoot().getProjects();
	for (int j = 0; j < projects.length; j++) {
		IProject project = (IProject) projects[j];
		// since we are iterating over the project in the workspace, we
		// know that they have been created before and must have a description
		IProjectDescription desc  = ((Project) project).internalGetDescription();
		IPath definedLocalLocation = desc.getLocation();
		// if the project uses the default location then continue
		if (definedLocalLocation == null)
			continue;
		//tolerate locations being the same if this is the project being tested
		if (project.equals(context) && definedLocalLocation.equals(location))
			continue;
		if (isOverlapping(location, definedLocalLocation)) {
			message = Policy.bind("resources.overlapLocal", location.toString(), definedLocalLocation.toString()); //$NON-NLS-1$
			return new ResourceStatus(IResourceStatus.INVALID_VALUE, null, message);
		}
	}
	message = Policy.bind("resources.validLocation"); //$NON-NLS-1$
	return new ResourceStatus(IResourceStatus.OK, message);
}
/**
 * Internal method. To be called only from the following methods:
 * <ul>
 * <li><code>IFile#appendContents</code></li>
 * <li><code>IFile#setContents(InputStream, boolean, boolean, IProgressMonitor)</code></li>
 * <li><code>IFile#setContents(IFileState, boolean, boolean, IProgressMonitor)</code></li>
 * </ul>
 * 
 * @see IFileModificationValidator#validateSave
 */
protected void validateSave(final IFile file) throws CoreException {
	// if validation is turned off then just return
	if (!shouldValidate)
		return;
	// first time through the validator hasn't been initialized so try and create it
	if (validator == null) 
		initializeValidator();
	// we were unable to initialize the validator. Validation has been turned off and 
	// a warning has already been logged so just return.
	if (validator == null)
		return;
	// otherwise call the API and throw an exception if appropriate
	final IStatus[] status = new IStatus[1];
	ISafeRunnable body = new ISafeRunnable() {
		public void run() throws Exception {
			status[0] = validator.validateSave(file);
		}
		public void handleException(Throwable exception) {
			status[0]  = new ResourceStatus(IResourceStatus.ERROR, null, Policy.bind("resources.errorValidator"), exception); //$NON-NLS-1$
		}
	};
	Platform.run(body);
	if (!status[0].isOK())
		throw new ResourceException(status[0]);
}



}
