/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.core.internal.resources; import java.util.*; import org.eclipse.core.internal.events.LifecycleEvent; import org.eclipse.core.internal.localstore.IHistoryStore; import org.eclipse.core.internal.utils.*; import org.eclipse.core.internal.watson.*; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.osgi.util.NLS; public abstract class Container extends Resource implements IContainer { protected Container(IPath path, Workspace container) { super(path, container); } /** * Converts this resource and all its children into phantoms by modifying their resource infos * in-place. */ public void convertToPhantom() throws CoreException { if (isPhantom()) return; super.convertToPhantom(); IResource[] members= members(IContainer.INCLUDE_PHANTOMS | IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN); for (int i= 0; i < members.length; i++) ((Resource)members[i]).convertToPhantom(); } /** * @see IContainer#createFilter(int, FileInfoMatcherDescription, int, IProgressMonitor) */ public IResourceFilterDescription createFilter(int type, FileInfoMatcherDescription matcherDescription, int updateFlags, IProgressMonitor monitor) throws CoreException { Assert.isNotNull(getProject()); monitor= Policy.monitorFor(monitor); FilterDescription filter= null; try { String message= NLS.bind(Messages.links_creating, getFullPath()); monitor.beginTask(message, Policy.totalWork); Policy.checkCanceled(monitor); checkValidPath(path, FOLDER | PROJECT, true); final ISchedulingRule rule= workspace.getRuleFactory().createRule(this); try { workspace.prepareOperation(rule, monitor); workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_FILTER_ADD, this)); workspace.beginOperation(true); monitor.worked(Policy.opWork * 5 / 100); //save the filter in the project description filter= new FilterDescription(this, type, matcherDescription); filter.setId(System.currentTimeMillis()); Project project= (Project)getProject(); project.internalGetDescription().addFilter(getProjectRelativePath(), filter); project.writeDescription(IResource.NONE); monitor.worked(Policy.opWork * 5 / 100); //refresh to discover any new resources below this folder if (getType() != IResource.FILE) { //refresh either in background or foreground if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) { workspace.refreshManager.refresh(this); monitor.worked(Policy.opWork * 90 / 100); } else { 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(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork)); } } finally { monitor.done(); } return filter; } /* (non-Javadoc) * @see IContainer#exists(IPath) */ public boolean exists(IPath childPath) { return workspace.getResourceInfo(getFullPath().append(childPath), false, false) != null; } /* (non-Javadoc) * @see IContainer#findMember(String) */ public IResource findMember(String name) { return findMember(name, false); } /* (non-Javadoc) * @see IContainer#findMember(String, boolean) */ public IResource findMember(String name, boolean phantom) { IPath childPath= getFullPath().append(name); ResourceInfo info= workspace.getResourceInfo(childPath, phantom, false); return info == null ? null : workspace.newResource(childPath, info.getType()); } /* (non-Javadoc) * @see IContainer#findMember(IPath) */ public IResource findMember(IPath childPath) { return findMember(childPath, false); } /* (non-Javadoc) * @see IContainer#findMember(IPath) */ public IResource findMember(IPath childPath, boolean phantom) { childPath= getFullPath().append(childPath); ResourceInfo info= workspace.getResourceInfo(childPath, phantom, false); return (info == null) ? null : workspace.newResource(childPath, info.getType()); } protected void fixupAfterMoveSource() throws CoreException { super.fixupAfterMoveSource(); if (!synchronizing(getResourceInfo(true, false))) return; IResource[] members= members(IContainer.INCLUDE_PHANTOMS | IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN); for (int i= 0; i < members.length; i++) ((Resource)members[i]).fixupAfterMoveSource(); } protected IResource[] getChildren(int memberFlags) { IPath[] children= null; try { children= workspace.tree.getChildren(path); } catch (IllegalArgumentException e) { //concurrency problem: the container has been deleted by another //thread during this call. Just return empty children set } if (children == null || children.length == 0) return ICoreConstants.EMPTY_RESOURCE_ARRAY; Resource[] result= new Resource[children.length]; int found= 0; for (int i= 0; i < children.length; i++) { ResourceInfo info= workspace.getResourceInfo(children[i], true, false); if (info != null && isMember(info.getFlags(), memberFlags)) result[found++]= workspace.newResource(children[i], info.getType()); } if (found == result.length) return result; Resource[] trimmedResult= new Resource[found]; System.arraycopy(result, 0, trimmedResult, 0, found); return trimmedResult; } /* (non-Javadoc) * @see IFolder#getFile(String) and IProject#getFile(String) */ public IFile getFile(String name) { return (IFile)workspace.newResource(getFullPath().append(name), FILE); } /* (non-Javadoc) * @see org.eclipse.core.resources.IContainer#getFilters() */ public IResourceFilterDescription[] getFilters() throws CoreException { IResourceFilterDescription[] results= null; checkValidPath(path, FOLDER | PROJECT, true); Project project= (Project)getProject(); ProjectDescription desc= project.internalGetDescription(); if (desc != null) { LinkedList/*<FilterDescription>*/list= desc.getFilter(getProjectRelativePath()); if (list != null) { results= new IResourceFilterDescription[list.size()]; for (int i= 0; i < list.size(); i++) { results[i]= (FilterDescription)list.get(i); } return results; } } return new IResourceFilterDescription[0]; } public boolean hasFilters() { IProject project= getProject(); if (project == null) return false; ProjectDescription desc= ((Project)project).internalGetDescription(); if (desc == null) return false; LinkedList/*<FilterDescription>*/filters= desc.getFilter(getProjectRelativePath()); if ((filters != null) && (filters.size() > 0)) return true; return false; } /* (non-Javadoc) * @see IContainer#getFile(IPath) */ public IFile getFile(IPath childPath) { return (IFile)workspace.newResource(getFullPath().append(childPath), FILE); } /* (non-Javadoc) * @see IFolder#getFolder(String) and IProject#getFolder(String) */ public IFolder getFolder(String name) { return (IFolder)workspace.newResource(getFullPath().append(name), FOLDER); } /* (non-Javadoc) * @see IContainer#getFolder(IPath) */ public IFolder getFolder(IPath childPath) { return (IFolder)workspace.newResource(getFullPath().append(childPath), FOLDER); } /** * @deprecated */ public boolean isLocal(int flags, int depth) { if (!super.isLocal(flags, depth)) return false; if (depth == DEPTH_ZERO) return true; if (depth == DEPTH_ONE) depth= DEPTH_ZERO; // get the children via the workspace since we know that this // resource exists (it is local). IResource[] children= getChildren(IResource.NONE); for (int i= 0; i < children.length; i++) if (!children[i].isLocal(depth)) return false; return true; } /* (non-Javadoc) * @see IContainer#members() */ public IResource[] members() throws CoreException { // forward to central method return members(IResource.NONE); } /* (non-Javadoc) * @see IContainer#members(boolean) */ public IResource[] members(boolean phantom) throws CoreException { // forward to central method return members(phantom ? INCLUDE_PHANTOMS : IResource.NONE); } /* (non-Javadoc) * @see IContainer#members(int) */ public IResource[] members(int memberFlags) throws CoreException { final boolean phantom= (memberFlags & INCLUDE_PHANTOMS) != 0; ResourceInfo info= getResourceInfo(phantom, false); checkAccessible(getFlags(info)); //if children are currently unknown, ask for immediate refresh if (info.isSet(ICoreConstants.M_CHILDREN_UNKNOWN)) workspace.refreshManager.refresh(this); return getChildren(memberFlags); } public void removeFilter(IResourceFilterDescription filterDescription, int updateFlags, IProgressMonitor monitor) throws CoreException { monitor= Policy.monitorFor(monitor); try { String message= NLS.bind(Messages.links_creating, getFullPath()); monitor.beginTask(message, Policy.totalWork); Policy.checkCanceled(monitor); checkValidPath(path, FOLDER | PROJECT, true); final ISchedulingRule rule= workspace.getRuleFactory().createRule(this); try { workspace.prepareOperation(rule, monitor); workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_FILTER_REMOVE, this)); workspace.beginOperation(true); monitor.worked(Policy.opWork * 5 / 100); //save the filter in the project description Project project= (Project)getProject(); project.internalGetDescription().removeFilter(getProjectRelativePath(), (FilterDescription)filterDescription); project.writeDescription(IResource.NONE); monitor.worked(Policy.opWork * 5 / 100); //refresh to discover any new resources below this linked location if (getType() != IResource.FILE) { //refresh either in background or foreground if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) { workspace.refreshManager.refresh(this); monitor.worked(Policy.opWork * 90 / 100); } else { 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(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork)); } } finally { monitor.done(); } } /* (non-Javadoc) * @see IContainer#getDefaultCharset() */ public String getDefaultCharset() throws CoreException { return getDefaultCharset(true); } /* (non-Javadoc) * @see IContainer#findDeletedMembersWithHistory(int, IProgressMonitor) */ public IFile[] findDeletedMembersWithHistory(int depth, IProgressMonitor monitor) { IHistoryStore historyStore= getLocalManager().getHistoryStore(); IPath basePath= getFullPath(); IWorkspaceRoot root= getWorkspace().getRoot(); Set deletedFiles= new HashSet(); if (depth == IResource.DEPTH_ZERO) { // this folder might have been a file in a past life if (historyStore.getStates(basePath, monitor).length > 0) { IFile file= root.getFile(basePath); if (!file.exists()) { deletedFiles.add(file); } } } else { Set allFilePaths= historyStore.allFiles(basePath, depth, monitor); // convert IPaths to IFiles keeping only files that no longer exist for (Iterator it= allFilePaths.iterator(); it.hasNext();) { IPath filePath= (IPath)it.next(); IFile file= root.getFile(filePath); if (!file.exists()) { deletedFiles.add(file); } } } return (IFile[])deletedFiles.toArray(new IFile[deletedFiles.size()]); } /** * (non-Javadoc) * * @see IContainer#setDefaultCharset(String) * @deprecated Replaced by {@link #setDefaultCharset(String, IProgressMonitor)} which is a * workspace operation and reports changes in resource deltas. */ public void setDefaultCharset(String charset) throws CoreException { ResourceInfo info= getResourceInfo(false, false); checkAccessible(getFlags(info)); workspace.getCharsetManager().setCharsetFor(getFullPath(), charset); } /* (non-Javadoc) * @see IContainer#setDefaultCharset(String, IProgressMonitor) */ public void setDefaultCharset(String newCharset, IProgressMonitor monitor) throws CoreException { monitor= Policy.monitorFor(monitor); try { String message= NLS.bind(Messages.resources_settingDefaultCharsetContainer, getFullPath()); monitor.beginTask(message, Policy.totalWork); // need to get the project as a scheduling rule because we might be // creating a new folder/file to hold the project settings final ISchedulingRule rule= workspace.getRuleFactory().charsetRule(this); try { workspace.prepareOperation(rule, monitor); checkAccessible(getFlags(getResourceInfo(false, false))); workspace.beginOperation(true); workspace.getCharsetManager().setCharsetFor(getFullPath(), newCharset); // now propagate the changes to all children inheriting their setting from this container IElementContentVisitor visitor= new IElementContentVisitor() { boolean visitedRoot= false; public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) { if (elementContents == null) return false; IPath nodePath= requestor.requestPath(); // we will always generate an event at least for the root of the sub tree // (skip visiting the root because we already have set the charset above and // that is the condition we are checking later) if (!visitedRoot) { visitedRoot= true; ResourceInfo info= workspace.getResourceInfo(nodePath, false, true); if (info == null) return false; info.incrementCharsetGenerationCount(); return true; } // does it already have an encoding explicitly set? if (workspace.getCharsetManager().getCharsetFor(nodePath, false) != null) return false; ResourceInfo info= workspace.getResourceInfo(nodePath, false, true); if (info == null) return false; info.incrementCharsetGenerationCount(); return true; } }; try { new ElementTreeIterator(workspace.getElementTree(), getFullPath()).iterate(visitor); } catch (WrappedRuntimeException e) { throw (CoreException)e.getTargetException(); } monitor.worked(Policy.opWork); } catch (OperationCanceledException e) { workspace.getWorkManager().operationCanceled(); throw e; } finally { workspace.endOperation(rule, true, Policy.subMonitorFor(monitor, Policy.endOpWork)); } } finally { monitor.done(); } } }