| /******************************************************************************* |
| * 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.net.MalformedURLException; |
| import java.net.URL; |
| |
| import org.eclipse.core.internal.localstore.*; |
| import org.eclipse.core.internal.properties.PropertyManager; |
| import org.eclipse.core.internal.utils.Assert; |
| import org.eclipse.core.internal.utils.Policy; |
| import org.eclipse.core.resources.*; |
| import org.eclipse.core.resources.team.IMoveDeleteHook; |
| import org.eclipse.core.runtime.*; |
| |
| public abstract class Resource extends PlatformObject implements IResource, ICoreConstants, Cloneable { |
| /* package */ IPath path; |
| /* package */ Workspace workspace; |
| protected Resource(IPath path, Workspace workspace) { |
| this.path = path.removeTrailingSeparator(); |
| this.workspace = workspace; |
| } |
| |
| /** |
| * @see IResource#accept(IResourceVisitor) |
| */ |
| public void accept(IResourceVisitor visitor) throws CoreException { |
| // forward to central method |
| accept(visitor, IResource.DEPTH_INFINITE, 0); |
| } |
| |
| /** |
| * @see IResource#accept(IResourceVisitor, int, boolean) |
| */ |
| public void accept(IResourceVisitor visitor, int depth, boolean includePhantoms) throws CoreException { |
| // forward to central method |
| accept(visitor, depth, includePhantoms ? IContainer.INCLUDE_PHANTOMS : 0); |
| } |
| |
| /* |
| * @see IResource#accept |
| */ |
| public void accept(IResourceVisitor visitor, int depth, int memberFlags) throws CoreException { |
| final boolean includePhantoms = (memberFlags & IContainer.INCLUDE_PHANTOMS) != 0; |
| ResourceInfo info = getResourceInfo(includePhantoms, false); |
| checkExists(getFlags(info), true); |
| if (!visitor.visit(this) || depth == DEPTH_ZERO) |
| return; |
| // get the info again because it might have been changed by the visitor |
| info = getResourceInfo(includePhantoms, false); |
| if (info == null) |
| return; |
| // thread safety: (cache the type to avoid changes -- we might not be inside an operation) |
| int type = info.getType(); |
| if (type == FILE) |
| return; |
| if (depth == DEPTH_ONE) |
| depth = DEPTH_ZERO; |
| // if we had a gender change we need to fix up the resource before asking for its members |
| IContainer resource = getType() != type ? (IContainer) workspace.newResource(getFullPath(), type) : (IContainer) this; |
| IResource[] members = resource.members(memberFlags); |
| for (int i = 0; i < members.length; i++) |
| members[i].accept(visitor, depth, memberFlags); |
| } |
| |
| protected void assertCopyRequirements(IPath destination, int destinationType, int updateFlags) throws CoreException { |
| IStatus status = checkCopyRequirements(destination, destinationType, updateFlags); |
| if (!status.isOK()) { |
| // this assert is ok because the error cases generated by the |
| // check method above indicate assertion conditions. |
| Assert.isTrue(false, status.getChildren()[0].getMessage()); |
| } |
| } |
| protected void assertLinkRequirements(IPath localLocation, int updateFlags) throws CoreException { |
| checkDoesNotExist(getFlags(getResourceInfo(false, false)), true); |
| Container parent = (Container) getParent(); |
| if (parent == null || parent.getType() != IResource.PROJECT) { |
| String msg = Policy.bind("links.parentNotProject", getFullPath().toString());//$NON-NLS-1$ |
| Assert.isLegal(false, msg); |
| } |
| parent.checkAccessible(getFlags(parent.getResourceInfo(false, false))); |
| boolean allowMissingLocal = (updateFlags & IResource.ALLOW_MISSING_LOCAL) != 0; |
| if (localLocation.isAbsolute()) { |
| java.io.File localFile = localLocation.toFile(); |
| boolean localExists = localFile.exists(); |
| if (!allowMissingLocal && !localExists) { |
| String msg = Policy.bind("links.localDoesNotExist", localFile.toString());//$NON-NLS-1$ |
| throw new ResourceException(IResourceStatus.NOT_FOUND_LOCAL, getFullPath(), msg, null); |
| } |
| //resource type and file system type must match |
| if (localExists && ((getType() == IResource.FOLDER) != localFile.isDirectory())) { |
| String msg = Policy.bind("links.wrongLocalType", getFullPath().toString());//$NON-NLS-1$ |
| throw new ResourceException(IResourceStatus.WRONG_TYPE_LOCAL, getFullPath(), msg, null); |
| } |
| } else { |
| //relative paths are considered to be variable-relative paths |
| if (!allowMissingLocal) { |
| String msg = Policy.bind("links.pathNotAbsolute", getFullPath().toString());//$NON-NLS-1$ |
| throw new ResourceException(IResourceStatus.VARIABLE_NOT_DEFINED, getFullPath(), msg, null); |
| } |
| } |
| //check nature veto |
| String[] natureIds = ((Project)getProject()).internalGetDescription().getNatureIds(); |
| IStatus result = workspace.getNatureManager().validateLinkCreation(natureIds); |
| if (!result.isOK()) |
| throw new ResourceException(result); |
| //check team provider veto |
| if (getType() == IResource.FILE) |
| result = workspace.getTeamHook().validateCreateLink((IFile)this, updateFlags, localLocation); |
| else |
| result = workspace.getTeamHook().validateCreateLink((IFolder)this, updateFlags, localLocation); |
| if (!result.isOK()) |
| throw new ResourceException(result); |
| } |
| protected void assertMoveRequirements(IPath destination, int destinationType, int updateFlags) throws CoreException { |
| IStatus status = checkMoveRequirements(destination, destinationType, updateFlags); |
| if (!status.isOK()) { |
| // this assert is ok because the error cases generated by the |
| // check method above indicate assertion conditions. |
| Assert.isTrue(false, status.getChildren()[0].getMessage()); |
| } |
| } |
| public void checkAccessible(int flags) throws CoreException { |
| checkExists(flags, true); |
| } |
| /** |
| * This method reports errors in two different ways. It can throw a |
| * CoreException or log a status. CoreExceptions are used according |
| * to the specification of the copy method. Programming errors, that |
| * would usually be prevented by using an "Assert" code, are reported as |
| * an IStatus. |
| * We're doing this way because we have two different methods to copy |
| * resources: IResource#copy and IWorkspace#copy. The first one gets |
| * the error and throws its message in an AssertionFailureException. The |
| * second one just throws a CoreException using the status returned |
| * by this method. |
| * |
| * @see IResource#copy |
| */ |
| public IStatus checkCopyRequirements(IPath destination, int destinationType, int updateFlags) throws CoreException { |
| String message = Policy.bind("resources.copyNotMet"); //$NON-NLS-1$ |
| MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INVALID_VALUE, message, null); |
| if (destination == null) { |
| message = Policy.bind("resources.destNotNull"); //$NON-NLS-1$ |
| return new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message); |
| } |
| destination = makePathAbsolute(destination); |
| if (getFullPath().isPrefixOf(destination)) { |
| message = Policy.bind("resources.destNotSub"); //$NON-NLS-1$ |
| status.add(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message)); |
| } |
| checkValidPath(destination, destinationType); |
| |
| ResourceInfo info = getResourceInfo(false, false); |
| int flags = getFlags(info); |
| checkAccessible(flags); |
| checkLocal(flags, DEPTH_INFINITE); |
| |
| Resource dest = (Resource) workspace.newResource(destination, destinationType); |
| dest.checkDoesNotExist(); |
| |
| // ensure we aren't trying to copy a file to a project |
| if (getType() == IResource.FILE && destinationType == IResource.PROJECT) { |
| message = Policy.bind("resources.fileToProj"); //$NON-NLS-1$ |
| throw new ResourceException(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message)); |
| } |
| |
| // ensure we aren't trying to copy a linked resource into a folder |
| Container parent = (Container)dest.getParent(); |
| boolean isDeepCopy = (updateFlags & IResource.SHALLOW) == 0; |
| if (isLinked() && !isDeepCopy && (parent == null || parent.getType() != IResource.PROJECT)) { |
| message = Policy.bind("links.copyNotProject", getFullPath().toString(), destination.toString()); //$NON-NLS-1$ |
| throw new ResourceException(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message)); |
| } |
| |
| // we can't copy into a closed project |
| if (destinationType != IResource.PROJECT) { |
| Project project = (Project) dest.getProject(); |
| info = project.getResourceInfo(false, false); |
| project.checkAccessible(getFlags(info)); |
| |
| if (!parent.equals(project)) { |
| info = parent.getResourceInfo(false, false); |
| parent.checkExists(getFlags(info), true); |
| } |
| } |
| |
| return status.isOK() ? (IStatus) new ResourceStatus(IResourceStatus.OK, Policy.bind("resources.copyMet")) : (IStatus) status; //$NON-NLS-1$ |
| } |
| /** |
| * Helper method that considers case insensitive file systems. |
| */ |
| protected void checkDoesNotExist() throws CoreException { |
| // should consider getting the ResourceInfo as a paramenter to reduce tree lookups |
| |
| //first check the tree for an exact case match |
| checkDoesNotExist(getFlags(getResourceInfo(false, false)), false); |
| if (CoreFileSystemLibrary.isCaseSensitive()) { |
| return; |
| } |
| //now look for a matching case variant in the tree |
| IResource variant = findExistingResourceVariant(getFullPath()); |
| if (variant == null) |
| return; |
| String msg = Policy.bind("resources.existsDifferentCase", variant.getFullPath().toString()); //$NON-NLS-1$ |
| throw new ResourceException(IResourceStatus.CASE_VARIANT_EXISTS, variant.getFullPath(), msg, null); |
| } |
| /** |
| * Checks that this resource does not exist. |
| * |
| * @exception CoreException if this resource exists |
| */ |
| public void checkDoesNotExist(int flags, boolean checkType) throws CoreException { |
| // See if there is any resource at all. If none then we are happy. |
| if (!exists(flags, false)) |
| return; |
| // We know there is something in the tree at this path. |
| // If we are checking type then go ahead and check the type. |
| // If there is nothing there of this resource's type, then return. |
| if ((checkType && !exists(flags, checkType))) |
| return; |
| String message = Policy.bind("resources.mustNotExist", getFullPath().toString()); //$NON-NLS-1$ |
| throw new ResourceException(checkType ? IResourceStatus.RESOURCE_EXISTS : IResourceStatus.PATH_OCCUPIED, getFullPath(), message, null); |
| } |
| /** |
| * Checks that this resource exists. |
| * If checkType is true, the type of this resource and the one in the tree must match. |
| * |
| * @exception CoreException if this resource does not exist |
| */ |
| public void checkExists(int flags, boolean checkType) throws CoreException { |
| if (!exists(flags, checkType)) { |
| String message = Policy.bind("resources.mustExist", getFullPath().toString()); //$NON-NLS-1$ |
| throw new ResourceException(IResourceStatus.RESOURCE_NOT_FOUND, getFullPath(), message, null); |
| } |
| } |
| /** |
| * Checks that this resource is local to the given depth. |
| * |
| * @exception CoreException if this resource is not local |
| */ |
| public void checkLocal(int flags, int depth) throws CoreException { |
| if (!isLocal(flags, depth)) { |
| String message = Policy.bind("resources.mustBeLocal", getFullPath().toString()); //$NON-NLS-1$ |
| throw new ResourceException(IResourceStatus.RESOURCE_NOT_LOCAL, getFullPath(), message, null); |
| } |
| } |
| /** |
| * This method reports errors in two different ways. It can throw a |
| * CoreException or log a status. CoreExceptions are used according |
| * to the specification of the move method. Programming errors, that |
| * would usually be prevented by using an "Assert" code, are reported as |
| * an IStatus. |
| * We're doing this way because we have two different methods to move |
| * resources: IResource#move and IWorkspace#move. The first one gets |
| * the error and throws its message in an AssertionFailureException. The |
| * second one just throws a CoreException using the status returned |
| * by this method. |
| * |
| * @see IResource#move |
| */ |
| protected IStatus checkMoveRequirements(IPath destination, int destinationType, int updateFlags) throws CoreException { |
| String message = Policy.bind("resources.moveNotMet"); //$NON-NLS-1$ |
| MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INVALID_VALUE, message, null); |
| if (destination == null) { |
| message = Policy.bind("resources.destNotNull"); //$NON-NLS-1$ |
| return new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message); |
| } |
| destination = makePathAbsolute(destination); |
| if (getFullPath().isPrefixOf(destination)) { |
| message = Policy.bind("resources.destNotSub"); //$NON-NLS-1$ |
| status.add(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message)); |
| } |
| checkValidPath(destination, destinationType); |
| |
| ResourceInfo info = getResourceInfo(false, false); |
| int flags = getFlags(info); |
| checkAccessible(flags); |
| checkLocal(flags, DEPTH_INFINITE); |
| |
| Resource dest = (Resource) workspace.newResource(destination, destinationType); |
| |
| // check if we are only changing case |
| IResource variant = CoreFileSystemLibrary.isCaseSensitive() ? null : findExistingResourceVariant(destination); |
| if (variant == null || !this.equals(variant)) |
| dest.checkDoesNotExist(); |
| |
| // ensure we aren't trying to move a file to a project |
| if (getType() == IResource.FILE && dest.getType() == IResource.PROJECT) { |
| message = Policy.bind("resources.fileToProj"); //$NON-NLS-1$ |
| throw new ResourceException(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message)); |
| } |
| |
| // ensure we aren't trying to shallow move a linked resource into a folder |
| Container parent = (Container)dest.getParent(); |
| boolean isDeepMove = (updateFlags & IResource.SHALLOW) == 0; |
| if (!isDeepMove && isLinked() && (parent == null || parent.getType() != IResource.PROJECT)) { |
| message = Policy.bind("links.moveNotProject", getFullPath().toString(), destination.toString()); //$NON-NLS-1$ |
| throw new ResourceException(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message)); |
| } |
| |
| // we can't move into a closed project |
| if (destinationType != IResource.PROJECT) { |
| Project project = (Project) dest.getProject(); |
| info = project.getResourceInfo(false, false); |
| project.checkAccessible(getFlags(info)); |
| |
| if (!parent.equals(project)) { |
| info = parent.getResourceInfo(false, false); |
| parent.checkExists(getFlags(info), true); |
| } |
| } |
| return status.isOK() ? (IStatus) new ResourceStatus(IResourceStatus.OK, Policy.bind("resources.moveMet")) : (IStatus) status; //$NON-NLS-1$ |
| } |
| /** |
| * Checks that the supplied path is valid according to Workspace.validatePath(). |
| * |
| * @exception CoreException if the path is not valid |
| */ |
| public void checkValidPath(IPath path, int type) throws CoreException { |
| IStatus result = workspace.validatePath(path.toString(), type); |
| if (!result.isOK()) |
| throw new ResourceException(result); |
| } |
| /** |
| * @see IResource |
| */ |
| public void clearHistory(IProgressMonitor monitor) throws CoreException { |
| getLocalManager().getHistoryStore().removeAll(this); |
| } |
| public void convertToPhantom() throws CoreException { |
| ResourceInfo info = getResourceInfo(false, true); |
| if (info == null || isPhantom(getFlags(info))) |
| return; |
| info.clearSessionProperties(); |
| info.set(M_PHANTOM); |
| getLocalManager().updateLocalSync(info, I_NULL_SYNC_INFO); |
| info.setModificationStamp(IResource.NULL_STAMP); |
| // should already be done by the #deleteResource call but left in |
| // just to be safe and for code clarity. |
| info.setMarkers(null); |
| } |
| |
| /* |
| * Used when a folder is to be copied to a project. |
| * @see IResource#copy |
| */ |
| public void copy(IProjectDescription destDesc, int updateFlags, IProgressMonitor monitor) throws CoreException { |
| // FIXME - funnel through a central method |
| // FIXME - ensure source is a project |
| Assert.isNotNull(destDesc); |
| monitor = Policy.monitorFor(monitor); |
| try { |
| String message = Policy.bind("resources.copying", getFullPath().toString()); //$NON-NLS-1$ |
| monitor.beginTask(message, Policy.totalWork); |
| try { |
| workspace.prepareOperation(); |
| // The following assert method throws CoreExceptions as stated in the IResource.copy API |
| // and assert for programming errors. See checkCopyRequirements for more information. |
| IPath destPath = new Path(destDesc.getName()).makeAbsolute(); |
| assertCopyRequirements(destPath, getType(), updateFlags); |
| Project destProject = (Project) workspace.getRoot().getProject(destPath.lastSegment()); |
| workspace.beginOperation(true); |
| |
| // create and open the new project |
| destProject.create(destDesc, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100)); |
| destProject.open(Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100)); |
| |
| // copy the children |
| // FIXME: fix the progress monitor here...create a sub monitor and do a worked(1) after each child instead |
| IResource[] children = ((IContainer) this).members(IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS); |
| for (int i = 0; i < children.length; i++) { |
| Resource child = (Resource) children[i]; |
| child.copy(destPath.append(child.getName()), updateFlags, Policy.subMonitorFor(monitor, Policy.opWork * 60 / 100 / children.length)); |
| } |
| |
| // copy over the properties |
| getPropertyManager().copy(this, destProject, DEPTH_ZERO); |
| monitor.worked(Policy.opWork * 15 / 100); |
| |
| } catch (OperationCanceledException e) { |
| workspace.getWorkManager().operationCanceled(); |
| throw e; |
| } finally { |
| workspace.endOperation(true, Policy.subMonitorFor(monitor, Policy.buildWork)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /* |
| * @see IResource#copy |
| */ |
| public void copy(IProjectDescription destDesc, boolean force, IProgressMonitor monitor) throws CoreException { |
| int updateFlags = force ? IResource.FORCE : IResource.NONE; |
| copy(destDesc, updateFlags, monitor); |
| } |
| |
| /** |
| * @see IResource#copy |
| */ |
| public void copy(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException { |
| try { |
| monitor = Policy.monitorFor(monitor); |
| String message = Policy.bind("resources.copying", getFullPath().toString()); //$NON-NLS-1$ |
| monitor.beginTask(message, Policy.totalWork); |
| try { |
| workspace.prepareOperation(); |
| // The following assert method throws CoreExceptions as stated in the IResource.copy API |
| // and assert for programming errors. See checkCopyRequirements for more information. |
| assertCopyRequirements(destination, getType(), updateFlags); |
| |
| workspace.beginOperation(true); |
| Resource destResource = workspace.newResource(makePathAbsolute(destination), getType()); |
| getLocalManager().copy(this, destResource, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork)); |
| } catch (OperationCanceledException e) { |
| workspace.getWorkManager().operationCanceled(); |
| throw e; |
| } finally { |
| workspace.endOperation(true, Policy.subMonitorFor(monitor, Policy.buildWork)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * @see IResource#copy |
| */ |
| public void copy(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException { |
| int updateFlags = force ? IResource.FORCE : IResource.NONE; |
| copy(destination, updateFlags, monitor); |
| } |
| |
| /** |
| * Count the number of resources in the tree from this container to the |
| * specified depth. Include this resource. Include phantoms if |
| * the phantom boolean is true. |
| */ |
| public int countResources(int depth, boolean phantom) throws CoreException { |
| return workspace.countResources(path, depth, phantom); |
| } |
| /** |
| * @see org.eclipse.core.resources.IFolder#createLink(IPath, int, IProgressMonitor) |
| * @see org.eclipse.core.resources.IFile#createLink(IPath, int, IProgressMonitor) |
| */ |
| public void createLink(IPath localLocation, int updateFlags, IProgressMonitor monitor) throws CoreException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| String message = Policy.bind("resources.creatingLink", getFullPath().toString()); //$NON-NLS-1$ |
| monitor.beginTask(message, Policy.totalWork); |
| checkValidPath(path, FOLDER); |
| try { |
| workspace.prepareOperation(); |
| // resolve any variables used in the location path |
| IPath resolvedLocation = workspace.getPathVariableManager().resolvePath(localLocation); |
| assertLinkRequirements(resolvedLocation, updateFlags); |
| workspace.beginOperation(true); |
| ResourceInfo info = workspace.createResource(this, false); |
| info.set(M_LINK); |
| getLocalManager().link(this, resolvedLocation); |
| monitor.worked(Policy.opWork * 5 / 100); |
| //save the location in the project description |
| Project project = (Project)getProject(); |
| project.internalGetDescription().setLinkLocation(getName(), |
| new LinkDescription(this,localLocation)); |
| project.writeDescription(IResource.NONE); |
| monitor.worked(Policy.opWork * 5 / 100); |
| //notify internal infrastructure that link has been created |
| workspace.creating(this); |
| //refresh to discover any new resources below this linked location |
| if (getType() != IResource.FILE) |
| refreshLocal(DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 90 / 100)); |
| else |
| monitor.worked(Policy.opWork * 90 / 100); |
| } catch (OperationCanceledException e) { |
| workspace.getWorkManager().operationCanceled(); |
| throw e; |
| } finally { |
| workspace.endOperation(true, Policy.subMonitorFor(monitor, Policy.buildWork)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| /** |
| * @see IResource |
| */ |
| public IMarker createMarker(String type) throws CoreException { |
| Assert.isNotNull(type); |
| try { |
| workspace.prepareOperation(); |
| ResourceInfo resourceInfo = getResourceInfo(false, false); |
| checkAccessible(getFlags(resourceInfo)); |
| |
| workspace.beginOperation(true); |
| MarkerInfo info = new MarkerInfo(); |
| info.setType(type); |
| info.setCreationTime(System.currentTimeMillis()); |
| workspace.getMarkerManager().add(this, new MarkerInfo[] { info }); |
| return new Marker(this, info.getId()); |
| } finally { |
| workspace.endOperation(false, null); |
| } |
| } |
| |
| /** |
| * @see IResource |
| */ |
| public void delete(boolean force, IProgressMonitor monitor) throws CoreException { |
| delete(force ? IResource.FORCE : IResource.NONE , monitor); |
| } |
| |
| /** |
| * @see IResource |
| */ |
| public void delete(int updateFlags, IProgressMonitor monitor) throws CoreException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| String message = Policy.bind("resources.deleting", getFullPath().toString()); //$NON-NLS-1$ |
| monitor.beginTask(message, Policy.totalWork*1000); |
| try { |
| workspace.prepareOperation(); |
| /* if there is no such resource (including type check) then there is nothing |
| to delete so just return. */ |
| if (!exists()) |
| return; |
| |
| workspace.beginOperation(true); |
| message = Policy.bind("resources.deleteProblem"); //$NON-NLS-1$ |
| MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, null); |
| ResourceTree tree = new ResourceTree(status); |
| IMoveDeleteHook hook = workspace.getMoveDeleteHook(); |
| switch (getType()) { |
| case IResource.FILE: |
| if (!hook.deleteFile(tree, (IFile) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork*1000/2))) |
| tree.standardDeleteFile((IFile) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork*1000/2)); |
| break; |
| case IResource.FOLDER: |
| if (!hook.deleteFolder(tree, (IFolder) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork*1000/2))) |
| tree.standardDeleteFolder((IFolder) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork*1000/2)); |
| break; |
| case IResource.PROJECT: |
| workspace.deleting((IProject) this); |
| if (!hook.deleteProject(tree, (IProject) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork*1000/2))) |
| tree.standardDeleteProject((IProject) this, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork*1000/2)); |
| break; |
| case IResource.ROOT: |
| IProject[] projects = ((IWorkspaceRoot) this).getProjects(); |
| for (int i = 0; i < projects.length; i++) { |
| workspace.deleting(projects[i]); |
| if (!hook.deleteProject(tree, projects[i], updateFlags, Policy.subMonitorFor(monitor, Policy.opWork*1000/projects.length/2))) |
| tree.standardDeleteProject(projects[i], updateFlags, Policy.subMonitorFor(monitor, Policy.opWork*1000/projects.length/2)); |
| } |
| // need to clear out the root info |
| workspace.getMarkerManager().removeMarkers(this, IResource.DEPTH_ZERO); |
| getPropertyManager().deleteProperties(this, IResource.DEPTH_ZERO); |
| getResourceInfo(false, false).clearSessionProperties(); |
| break; |
| } |
| // Invalidate the tree for further use by clients. |
| tree.makeInvalid(); |
| if (!tree.getStatus().isOK()) |
| throw new ResourceException(tree.getStatus()); |
| } catch (OperationCanceledException e) { |
| workspace.getWorkManager().operationCanceled(); |
| throw e; |
| } finally { |
| workspace.endOperation(true, Policy.subMonitorFor(monitor, Policy.buildWork*1000)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * @see IProject and IWorkspaceRoot -- N.B. This is not an IResource method! |
| */ |
| public void delete(boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { |
| int updateFlags = force ? IResource.FORCE : IResource.NONE; |
| updateFlags |= keepHistory ? IResource.KEEP_HISTORY : IResource.NONE; |
| delete(updateFlags, monitor); |
| } |
| /** |
| * @see IResource |
| */ |
| public void deleteMarkers(String type, boolean includeSubtypes, int depth) throws CoreException { |
| try { |
| workspace.prepareOperation(); |
| ResourceInfo info = getResourceInfo(false, false); |
| checkAccessible(getFlags(info)); |
| |
| workspace.beginOperation(true); |
| workspace.getMarkerManager().removeMarkers(this, type, includeSubtypes, depth); |
| } finally { |
| workspace.endOperation(false, null); |
| } |
| } |
| /** |
| * This method should be called to delete a resource from the tree because it will also |
| * delete its properties and markers. If a status object is provided, minor exceptions are |
| * added, otherwise they are thrown. If major exceptions occur, they are always thrown. |
| */ |
| public void deleteResource(boolean convertToPhantom, MultiStatus status) throws CoreException { |
| // delete properties |
| CoreException err = null; |
| try { |
| getPropertyManager().deleteProperties(this, IResource.DEPTH_INFINITE); |
| } catch (CoreException e) { |
| if (status != null) |
| status.add(e.getStatus()); |
| else |
| err = e; |
| } |
| // remove markers on this resource and its descendents |
| if (exists()) |
| getMarkerManager().removeMarkers(this, IResource.DEPTH_INFINITE); |
| // if this is a linked resource, remove the entry from the project description |
| if (isLinked()) { |
| //pre-delete notification to internal infrastructure |
| workspace.deleting(this); |
| Project project = (Project)getProject(); |
| ProjectDescription description = project.internalGetDescription(); |
| description.setLinkLocation(getName(), null); |
| project.internalSetDescription(description, true); |
| project.writeDescription(IResource.FORCE); |
| } |
| |
| /* if we are synchronizing, do not delete the resource. Convert it |
| into a phantom. Actual deletion will happen when we refresh or push. */ |
| if (convertToPhantom && getType() != PROJECT && synchronizing(getResourceInfo(true, false))) |
| convertToPhantom(); |
| else |
| workspace.deleteResource(this); |
| if (err != null) |
| throw err; |
| } |
| /** |
| * @see IResource#equals |
| */ |
| public boolean equals(Object target) { |
| if (this == target) |
| return true; |
| if (!(target instanceof Resource)) |
| return false; |
| Resource resource = (Resource) target; |
| return getType() == resource.getType() && path.equals(resource.path) && workspace.equals(resource.workspace); |
| } |
| /** |
| * @see IResource#exists |
| */ |
| public boolean exists() { |
| ResourceInfo info = getResourceInfo(false, false); |
| return exists(getFlags(info), true); |
| } |
| public boolean exists(int flags, boolean checkType) { |
| return flags != NULL_FLAG && !(checkType && ResourceInfo.getType(flags) != getType()); |
| } |
| /** |
| * @see IResource#findMarker |
| */ |
| public IMarker findMarker(long id) throws CoreException { |
| return workspace.getMarkerManager().findMarker(this, id); |
| } |
| /** |
| * @see IResource#findMarkers |
| */ |
| public IMarker[] findMarkers(String type, boolean includeSubtypes, int depth) throws CoreException { |
| ResourceInfo info = getResourceInfo(false, false); |
| checkAccessible(getFlags(info)); |
| // It might happen that from this point the resource is not accessible anymore. |
| // But markers have the #exists method that callers can use to check if it is |
| // still valid. |
| return workspace.getMarkerManager().findMarkers(this, type, includeSubtypes, depth); |
| } |
| protected void fixupAfterMoveSource() throws CoreException { |
| ResourceInfo info = getResourceInfo(true, true); |
| //if a linked resource is moved, we need to remove the location info from the .project |
| if (isLinked()) { |
| Project project = (Project)getProject(); |
| project.internalGetDescription().setLinkLocation(getName(), null); |
| project.writeDescription(IResource.NONE); |
| } |
| |
| if (!synchronizing(info)) { |
| workspace.deleteResource(this); |
| return; |
| } |
| info.clearSessionProperties(); |
| info.clear(M_LOCAL_EXISTS); |
| info.setLocalSyncInfo(I_NULL_SYNC_INFO); |
| info.set(M_PHANTOM); |
| info.setModificationStamp(IResource.NULL_STAMP); |
| info.setMarkers(null); |
| } |
| /** |
| * @see IResource#getFileExtension |
| */ |
| public String getFileExtension() { |
| String name = getName(); |
| int index = name.lastIndexOf('.'); |
| if (index == -1) |
| return null; |
| if (index == (name.length() - 1)) |
| return ""; //$NON-NLS-1$ |
| return name.substring(index + 1); |
| } |
| public int getFlags(ResourceInfo info) { |
| return (info == null) ? NULL_FLAG : info.getFlags(); |
| } |
| /** |
| * @see IResource#getFullPath |
| */ |
| public IPath getFullPath() { |
| return path; |
| } |
| public FileSystemResourceManager getLocalManager() { |
| return workspace.getFileSystemManager(); |
| } |
| /** |
| * @see IResource#getLocation |
| */ |
| public IPath getLocation() { |
| IProject project = getProject(); |
| if (project != null && !project.exists()) |
| return null; |
| return getLocalManager().locationFor(this); |
| } |
| |
| /** |
| * @see IResource#getLocationURL |
| */ |
| public URL getLocationURL() { |
| IProject project = getProject(); |
| if (project != null && !project.exists()) |
| return null; |
| try { |
| return new URL("platform:/resource" + getFullPath()); //$NON-NLS-1$ |
| } catch (MalformedURLException e) { |
| return null; |
| } |
| } |
| /** |
| * @see IResource |
| */ |
| public IMarker getMarker(long id) { |
| return new Marker(this, id); |
| } |
| protected MarkerManager getMarkerManager() { |
| return workspace.getMarkerManager(); |
| } |
| /** |
| * @see IResource |
| */ |
| public long getModificationStamp() { |
| ResourceInfo info = getResourceInfo(false, false); |
| return info == null ? IResource.NULL_STAMP : info.getModificationStamp(); |
| } |
| /** |
| * @see IResource#getName |
| */ |
| public String getName() { |
| return path.lastSegment(); |
| } |
| /** |
| * @see IResource#getParent |
| */ |
| public IContainer getParent() { |
| IPath parent = path.removeLastSegments(1); |
| if (parent.isRoot() || parent.isEmpty()) |
| return null; |
| if (parent.segmentCount() == 1) |
| return workspace.getRoot().getProject(parent.lastSegment()); |
| else |
| return workspace.getRoot().getFolder(parent); |
| } |
| /** |
| * @see IResource |
| */ |
| public String getPersistentProperty(QualifiedName key) throws CoreException { |
| ResourceInfo info = getResourceInfo(false, false); |
| int flags = getFlags(info); |
| checkAccessible(flags); |
| checkLocal(flags, DEPTH_ZERO); |
| return getPropertyManager().getProperty(this, key); |
| } |
| /** |
| * @see IResource#getProject |
| */ |
| public IProject getProject() { |
| return workspace.getRoot().getProject(path.segment(0)); |
| } |
| /** |
| * @see IResource#getProjectRelativePath |
| */ |
| public IPath getProjectRelativePath() { |
| return getFullPath().removeFirstSegments(ICoreConstants.PROJECT_SEGMENT_LENGTH); |
| } |
| public PropertyManager getPropertyManager() { |
| return workspace.getPropertyManager(); |
| } |
| /** |
| * @see IResource#getRawLocation |
| */ |
| public IPath getRawLocation() { |
| if (isLinked()) |
| return ((Project)getProject()).internalGetDescription().getLinkLocation(getName()); |
| return getLocation(); |
| } |
| /** |
| * Returns the resource info. Returns null if the resource doesn't exist. |
| * If the phantom flag is true, phantom resources are considered. |
| * If the mutable flag is true, a mutable info is returned. |
| */ |
| public ResourceInfo getResourceInfo(boolean phantom, boolean mutable) { |
| return workspace.getResourceInfo(getFullPath(), phantom, mutable); |
| } |
| /** |
| * @see IResource |
| */ |
| public Object getSessionProperty(QualifiedName key) throws CoreException { |
| ResourceInfo info = getResourceInfo(false, false); |
| int flags = getFlags(info); |
| checkAccessible(flags); |
| checkLocal(flags, DEPTH_ZERO); |
| return info.getSessionProperty(key); |
| } |
| /** |
| * @see IResource#getType |
| */ |
| public abstract int getType(); |
| public String getTypeString() { |
| switch (getType()) { |
| case FILE : |
| return "L"; //$NON-NLS-1$ |
| case FOLDER : |
| return "F"; //$NON-NLS-1$ |
| case PROJECT : |
| return "P"; //$NON-NLS-1$ |
| case ROOT: |
| return "R"; //$NON-NLS-1$ |
| } |
| return ""; //$NON-NLS-1$ |
| } |
| /** |
| * @see IResource#getWorkspace |
| */ |
| public IWorkspace getWorkspace() { |
| return workspace; |
| } |
| public int hashCode() { |
| // the container may be null if the identified resource |
| // does not exist so don't bother with it in the hash |
| return getFullPath().hashCode(); |
| } |
| /** |
| * Sets the M_LOCAL_EXISTS flag. Is internal so we don't have |
| * to begin an operation. |
| */ |
| protected void internalSetLocal(boolean flag, int depth) throws CoreException { |
| ResourceInfo info = getResourceInfo(true, true); |
| //only make the change if it's not already in desired state |
| if (info.isSet(M_LOCAL_EXISTS) != flag) { |
| if (flag && !isPhantom(getFlags(info))) { |
| info.set(M_LOCAL_EXISTS); |
| workspace.updateModificationStamp(info); |
| } else { |
| info.clear(M_LOCAL_EXISTS); |
| info.setModificationStamp(IResource.NULL_STAMP); |
| } |
| } |
| if (getType() == IResource.FILE || depth == IResource.DEPTH_ZERO) |
| return; |
| if (depth == IResource.DEPTH_ONE) |
| depth = IResource.DEPTH_ZERO; |
| IResource[] children = ((IContainer) this).members(); |
| for (int i = 0; i < children.length; i++) |
| ((Resource) children[i]).internalSetLocal(flag, depth); |
| } |
| /** |
| * @see IResource |
| */ |
| public boolean isAccessible() { |
| return exists(); |
| } |
| /** |
| * @see IResource |
| */ |
| public boolean isLocal(int depth) { |
| ResourceInfo info = getResourceInfo(false, false); |
| return isLocal(getFlags(info), depth); |
| } |
| public boolean isLocal(int flags, int depth) { |
| if (getType() == PROJECT) |
| return flags != NULL_FLAG; // exists |
| else |
| return flags != NULL_FLAG && ResourceInfo.isSet(flags, M_LOCAL_EXISTS); |
| } |
| |
| /** |
| * @see IResource |
| */ |
| public boolean isPhantom() { |
| ResourceInfo info = getResourceInfo(true, false); |
| return isPhantom(getFlags(info)); |
| } |
| public boolean isPhantom(int flags) { |
| return flags != NULL_FLAG && ResourceInfo.isSet(flags, M_PHANTOM); |
| } |
| /** |
| * @see IResource |
| */ |
| public boolean isReadOnly() { |
| IPath location = getLocation(); |
| if (location == null) |
| return false; |
| return CoreFileSystemLibrary.isReadOnly(location.toOSString()); |
| } |
| /** |
| * @see IResource#isSynchronized(int) |
| */ |
| public boolean isSynchronized(int depth) { |
| return getLocalManager().isSynchronized(this, depth); |
| } |
| protected IPath makePathAbsolute(IPath target) { |
| if (target.isAbsolute()) |
| return target; |
| return getParent().getFullPath().append(target); |
| } |
| |
| |
| /* |
| * @see IResource#move |
| */ |
| public void move(IProjectDescription description, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { |
| int updateFlags = force ? IResource.FORCE : IResource.NONE; |
| updateFlags |= keepHistory ? IResource.KEEP_HISTORY : IResource.NONE; |
| move(description, updateFlags, monitor); |
| } |
| |
| /* |
| * Used when a folder is to be moved to a project. |
| * @see IResource#move |
| */ |
| public void move(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException { |
| Assert.isNotNull(description); |
| monitor = Policy.monitorFor(monitor); |
| try { |
| String message = Policy.bind("resources.moving", getFullPath().toString()); //$NON-NLS-1$ |
| monitor.beginTask(message, Policy.totalWork); |
| try { |
| workspace.prepareOperation(); |
| // The following assert method throws CoreExceptions as stated in the IResource.move API |
| // and assert for programming errors. See checkCopyRequirements for more information. |
| if (!getName().equals(description.getName())) { |
| IPath path = Path.ROOT.append(description.getName()); |
| assertMoveRequirements(path, IResource.PROJECT, updateFlags); |
| } |
| workspace.beginOperation(true); |
| message = Policy.bind("resources.moveProblem"); //$NON-NLS-1$ |
| MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, null); |
| ResourceTree tree = new ResourceTree(status); |
| IMoveDeleteHook hook = workspace.getMoveDeleteHook(); |
| // if there is a name change then we are deleting the source so notify |
| IProject project = (IProject) this; |
| if (!getName().equals(description.getName())) { |
| workspace.changing(project); |
| workspace.deleting(project); |
| } |
| if (!hook.moveProject(tree, project, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork/2))) |
| tree.standardMoveProject(project, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork/2)); |
| // Invalidate the tree for further use by clients. |
| tree.makeInvalid(); |
| if (!tree.getStatus().isOK()) |
| throw new ResourceException(tree.getStatus()); |
| } catch (OperationCanceledException e) { |
| workspace.getWorkManager().operationCanceled(); |
| throw e; |
| } finally { |
| workspace.endOperation(true, Policy.subMonitorFor(monitor, Policy.buildWork)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * @see IFolder#move and IFile#move |
| */ |
| public void move(IPath destination, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { |
| int updateFlags = force ? IResource.FORCE : IResource.NONE; |
| updateFlags |= keepHistory ? IResource.KEEP_HISTORY : IResource.NONE; |
| move(destination, updateFlags, monitor); |
| } |
| /** |
| * @see IResource#move |
| */ |
| public void move(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException { |
| move(destination, force ? IResource.FORCE : IResource.NONE, monitor); |
| } |
| |
| /** |
| * @see IResource#move |
| */ |
| public void move(IPath path, int updateFlags, IProgressMonitor monitor) throws CoreException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| String message = Policy.bind("resources.moving", getFullPath().toString()); //$NON-NLS-1$ |
| monitor.beginTask(message, Policy.totalWork); |
| try { |
| workspace.prepareOperation(); |
| // The following assert method throws CoreExceptions as stated in the IResource.move API |
| // and assert for programming errors. See checkMoveRequirements for more information. |
| assertMoveRequirements(path, getType(), updateFlags); |
| path = makePathAbsolute(path); |
| workspace.beginOperation(true); |
| message = Policy.bind("resources.moveProblem"); //$NON-NLS-1$ |
| MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, null); |
| ResourceTree tree = new ResourceTree(status); |
| IMoveDeleteHook hook = workspace.getMoveDeleteHook(); |
| switch (getType()) { |
| case IResource.FILE: |
| IResource destination = workspace.getRoot().getFile(path); |
| if (!hook.moveFile(tree, (IFile) this, (IFile) destination, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork/2))) |
| tree.standardMoveFile((IFile) this, (IFile) destination, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork/2)); |
| break; |
| case IResource.FOLDER: |
| destination = workspace.getRoot().getFolder(path); |
| if (!hook.moveFolder(tree, (IFolder) this, (IFolder) destination, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork/2))) |
| tree.standardMoveFolder((IFolder) this, (IFolder) destination, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork/2)); |
| break; |
| case IResource.PROJECT: |
| IProject project = (IProject) this; |
| // if there is no change in name, there is nothing to do so return. |
| if (getName().equals(path.lastSegment())) { |
| return; |
| } |
| //we are deleting the source project so notify. |
| workspace.changing(project); |
| workspace.deleting(project); |
| IProjectDescription description = project.getDescription(); |
| description.setName(path.lastSegment()); |
| if (!hook.moveProject(tree, project, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork/2))) |
| tree.standardMoveProject(project, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork/2)); |
| break; |
| case IResource.ROOT: |
| message = Policy.bind("resources.moveRoot"); //$NON-NLS-1$ |
| throw new ResourceException(new ResourceStatus(IResourceStatus.INVALID_VALUE, getFullPath(), message)); |
| } |
| // Invalidate the tree for further use by clients. |
| tree.makeInvalid(); |
| if (!tree.getStatus().isOK()) |
| throw new ResourceException(tree.getStatus()); |
| } catch (OperationCanceledException e) { |
| workspace.getWorkManager().operationCanceled(); |
| throw e; |
| } finally { |
| workspace.endOperation(true, Policy.subMonitorFor(monitor, Policy.buildWork)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * @see IResource#refreshLocal |
| */ |
| public void refreshLocal(int depth, IProgressMonitor monitor) throws CoreException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| String message = (getType() == ROOT) |
| ? Policy.bind("resources.refreshingRoot") //$NON-NLS-1$ |
| : Policy.bind("resources.refreshing", getFullPath().toString()); //$NON-NLS-1$ |
| monitor.beginTask(message, Policy.totalWork); |
| boolean build = false; |
| try { |
| workspace.prepareOperation(); |
| if (getType() != ROOT && !getProject().isAccessible()) |
| return; |
| workspace.beginOperation(true); |
| build = getLocalManager().refresh(this, depth, Policy.subMonitorFor(monitor, Policy.opWork)); |
| } catch (OperationCanceledException e) { |
| workspace.getWorkManager().operationCanceled(); |
| throw e; |
| } finally { |
| workspace.endOperation(build, Policy.subMonitorFor(monitor, Policy.buildWork)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| /** |
| * @see IResource |
| */ |
| public void setLocal(boolean flag, int depth, IProgressMonitor monitor) throws CoreException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| String message = Policy.bind("resources.setLocal"); //$NON-NLS-1$ |
| monitor.beginTask(message, Policy.totalWork); |
| try { |
| workspace.prepareOperation(); |
| workspace.beginOperation(true); |
| internalSetLocal(flag, depth); |
| monitor.worked(Policy.opWork); |
| } finally { |
| workspace.endOperation(true, Policy.subMonitorFor(monitor, Policy.buildWork)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| /** |
| * @see IResource |
| */ |
| public void setPersistentProperty(QualifiedName key, String value) throws CoreException { |
| ResourceInfo info = getResourceInfo(false, false); |
| int flags = getFlags(info); |
| checkAccessible(flags); |
| checkLocal(flags, DEPTH_ZERO); |
| getPropertyManager().setProperty(this, key, value); |
| } |
| /** |
| * @see IResource |
| */ |
| public void setReadOnly(boolean readonly) { |
| CoreFileSystemLibrary.setReadOnly(getLocation().toOSString(), readonly); |
| } |
| /** |
| * @see IResource |
| */ |
| public void setSessionProperty(QualifiedName key, Object value) throws CoreException { |
| // fetch the info but don't bother making it mutable even though we are going |
| // to modify it. We don't know whether or not the tree is open and it really doesn't |
| // matter as the change we are doing does not show up in deltas. |
| ResourceInfo info = getResourceInfo(false, false); |
| int flags = getFlags(info); |
| checkAccessible(flags); |
| checkLocal(flags, DEPTH_ZERO); |
| info.setSessionProperty(key, value); |
| } |
| /** |
| * Returns true if this resource has the potential to be |
| * (or have been) synchronized. |
| */ |
| public boolean synchronizing(ResourceInfo info) { |
| return info != null && info.getSyncInfo(false) != null; |
| } |
| public String toString() { |
| return getTypeString() + getFullPath().toString(); |
| } |
| /** |
| * @see IResource |
| */ |
| public void touch(IProgressMonitor monitor) throws CoreException { |
| monitor = Policy.monitorFor(monitor); |
| try { |
| String message = Policy.bind("resources.touch", getFullPath().toString()); //$NON-NLS-1$ |
| monitor.beginTask(message, Policy.totalWork); |
| try { |
| workspace.prepareOperation(); |
| ResourceInfo info = getResourceInfo(false, false); |
| int flags = getFlags(info); |
| checkAccessible(flags); |
| checkLocal(flags, DEPTH_ZERO); |
| |
| workspace.beginOperation(true); |
| // fake a change by incrementing the content ID |
| info = getResourceInfo(false, true); |
| info.incrementContentId(); |
| workspace.updateModificationStamp(info); |
| monitor.worked(Policy.opWork); |
| } catch (OperationCanceledException e) { |
| workspace.getWorkManager().operationCanceled(); |
| throw e; |
| } finally { |
| workspace.endOperation(true, Policy.subMonitorFor(monitor, Policy.buildWork)); |
| } |
| } finally { |
| monitor.done(); |
| } |
| } |
| |
| /** |
| * Helper method for case insensitive file systems. Returns |
| * an existing resource whose path differs only in case from |
| * the given path, or null if no such resource exists. |
| */ |
| public IResource findExistingResourceVariant(IPath target) { |
| IPath result = Path.ROOT; |
| int segmentCount = target.segmentCount(); |
| for (int i = 0; i < segmentCount; i++) { |
| String[] childNames = workspace.tree.getNamesOfChildren(result); |
| String name = findVariant(target.segment(i), childNames); |
| if (name == null) |
| return null; |
| result = result.append(name); |
| } |
| return workspace.getRoot().findMember(result); |
| } |
| /** |
| * Searches for a variant of the given target in the list, |
| * that differs only in case. Returns the variant from |
| * the list if one is found, otherwise returns null. |
| */ |
| private String findVariant(String target, String[] list) { |
| for (int i = 0; i < list.length; i++) { |
| if (target.equalsIgnoreCase(list[i])) |
| return list[i]; |
| } |
| return null; |
| } |
| |
| /* |
| * @see IResource |
| */ |
| public boolean isDerived() { |
| ResourceInfo info = getResourceInfo(false, false); |
| return isDerived(getFlags(info)); |
| } |
| |
| /** |
| * Returns whether the derived flag is set in the given resource info flags. |
| * |
| * @param flags resource info flags (bitwuise or of M_* constants) |
| * @return <code>true</code> if the derived flag is set, and <code>false</code> |
| * if the derived flag is not set or if the flags are <code>NULL_FLAG</code> |
| */ |
| public boolean isDerived(int flags) { |
| return flags != NULL_FLAG && ResourceInfo.isSet(flags, ICoreConstants.M_DERIVED); |
| } |
| /** |
| * @see IResource#isLinked() |
| */ |
| public boolean isLinked() { |
| ResourceInfo info = getResourceInfo(false, false); |
| return info != null && info.isSet(M_LINK); |
| }/* |
| * @see IResource |
| */ |
| public void setDerived(boolean isDerived) throws CoreException { |
| // fetch the info but don't bother making it mutable even though we are going |
| // to modify it. We don't know whether or not the tree is open and it really doesn't |
| // matter as the change we are doing does not show up in deltas. |
| ResourceInfo info = getResourceInfo(false, false); |
| int flags = getFlags(info); |
| checkAccessible(flags); |
| // ignore attempts to set derived flag on anything except files and folders |
| if (info.getType() == FILE || info.getType() == FOLDER) { |
| if (isDerived) { |
| info.set(ICoreConstants.M_DERIVED); |
| } else { |
| info.clear(ICoreConstants.M_DERIVED); |
| } |
| } |
| } |
| |
| /* |
| * @see IResource |
| */ |
| public boolean isTeamPrivateMember() { |
| ResourceInfo info = getResourceInfo(false, false); |
| return isTeamPrivateMember(getFlags(info)); |
| } |
| |
| /** |
| * Returns whether the team private member flag is set in the given resource info flags. |
| * |
| * @param flags resource info flags (bitwise or of M_* constants) |
| * @return <code>true</code> if the team private member flag is set, and |
| * <code>false</code> if the flag is not set or if the flags are <code>NULL_FLAG</code> |
| */ |
| public boolean isTeamPrivateMember(int flags) { |
| return flags != NULL_FLAG && ResourceInfo.isSet(flags, ICoreConstants.M_TEAM_PRIVATE_MEMBER); |
| }/* |
| * @see IResource |
| */ |
| public void setTeamPrivateMember(boolean isTeamPrivate) throws CoreException { |
| // fetch the info but don't bother making it mutable even though we are going |
| // to modify it. We don't know whether or not the tree is open and it really doesn't |
| // matter as the change we are doing does not show up in deltas. |
| ResourceInfo info = getResourceInfo(false, false); |
| int flags = getFlags(info); |
| checkAccessible(flags); |
| // ignore attempts to set team private member flag on anything except files and folders |
| if (info.getType() == FILE || info.getType() == FOLDER) { |
| if (isTeamPrivate) { |
| info.set(ICoreConstants.M_TEAM_PRIVATE_MEMBER); |
| } else { |
| info.clear(ICoreConstants.M_TEAM_PRIVATE_MEMBER); |
| } |
| } |
| } |
| } |