package org.eclipse.core.internal.resources;
import java.net.URI;
import java.util.*;
import org.eclipse.core.filesystem.*;
import org.eclipse.core.internal.events.LifecycleEvent;
import org.eclipse.core.internal.utils.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.team.IMoveDeleteHook;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentTypeMatcher;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
public class Project extends Container implements IProject {
public static final int SNAPSHOT_SET_AUTOLOAD = 2;
protected Project(IPath path, Workspace container) {
super(path, container);
}
protected void assertCreateRequirements(IProjectDescription description) throws CoreException {
checkDoesNotExist();
checkDescription(this, description, false);
URI location = description.getLocationURI();
if (location != null)
return;
if (!Workspace.caseSensitive) {
IFileStore store = getStore();
IFileInfo localInfo = store.fetchInfo();
if (localInfo.exists()) {
String name = getLocalManager().getLocalName(store);
if (name != null && !store.getName().equals(name)) {
String msg = NLS.bind(Messages.resources_existsLocalDifferentCase, new Path(store.toString()).removeLastSegments(1).append(name).toOSString());
throw new ResourceException(IResourceStatus.CASE_VARIANT_EXISTS, getFullPath(), msg, null);
}
}
}
}
protected MultiStatus basicSetDescription(ProjectDescription description, int updateFlags) {
String message = Messages.resources_projectDesc;
MultiStatus result = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_WRITE_METADATA, message, null);
ProjectDescription current = internalGetDescription();
current.setComment(description.getComment());
current.setSnapshotLocationURI(description.getSnapshotLocationURI());
current.setBuildSpec(description.getBuildSpec(true));
boolean flushOrder = false;
IProject[] oldReferences = current.getReferencedProjects();
IProject[] newReferences = description.getReferencedProjects();
if (!Arrays.equals(oldReferences, newReferences)) {
current.setReferencedProjects(newReferences);
flushOrder = true;
}
flushOrder |= current.updateDynamicState(description);
if (flushOrder)
workspace.flushBuildOrder();
if ((updateFlags & IResource.AVOID_NATURE_CONFIG) == 0)
workspace.getNatureManager().configureNatures(this, current, description, result);
else
current.setNatureIds(description.getNatureIds(false));
return result;
}
@Override
public void build(int trigger, IProgressMonitor monitor) throws CoreException {
if (!isAccessible())
return;
internalBuild(getActiveBuildConfig(), trigger, null, null, monitor);
}
@Override
public void build(int trigger, String builderName, Map<String, String> args, IProgressMonitor monitor) throws CoreException {
Assert.isNotNull(builderName);
if (!isAccessible())
return;
internalBuild(getActiveBuildConfig(), trigger, builderName, args, monitor);
}
@Override
public void build(IBuildConfiguration config, int trigger, IProgressMonitor monitor) throws CoreException {
Assert.isNotNull(config);
if (!isAccessible() || !hasBuildConfig(config.getName()))
return;
internalBuild(config, trigger, null, null, monitor);
}
@Override
public void checkAccessible(int flags) throws CoreException {
super.checkAccessible(flags);
if (!isOpen(flags)) {
String message = NLS.bind(Messages.resources_mustBeOpen, getName());
throw new ResourceException(IResourceStatus.PROJECT_NOT_OPEN, getFullPath(), message, null);
}
}
protected void checkDescription(IProject project, IProjectDescription desc, boolean moving) throws CoreException {
URI location = desc.getLocationURI();
String message = Messages.resources_invalidProjDesc;
MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INVALID_VALUE, message, null);
status.merge(workspace.validateName(desc.getName(), IResource.PROJECT));
if (moving) {
URI sourceLocation = internalGetDescription().getLocationURI();
if (sourceLocation == null || !sourceLocation.equals(location))
status.merge(workspace.validateProjectLocationURI(project, location));
} else
status.merge(workspace.validateProjectLocationURI(project, location));
if (!status.isOK())
throw new ResourceException(status);
}
@Override
public void close(IProgressMonitor monitor) throws CoreException {
String msg = NLS.bind(Messages.resources_closing_1, getName());
SubMonitor subMonitor = SubMonitor.convert(monitor, msg, 100);
final ISchedulingRule rule = workspace.getRuleFactory().modifyRule(this);
try {
workspace.prepareOperation(rule, subMonitor.newChild(1));
ResourceInfo info = getResourceInfo(false, false);
int flags = getFlags(info);
checkExists(flags, true);
subMonitor.subTask(msg);
if (!isOpen(flags))
return;
workspace.beginOperation(true);
workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_CLOSE, this));
workspace.flushBuildOrder();
IProgressMonitor sub = subMonitor.newChild(49, SubMonitor.SUPPRESS_SUBTASK);
IStatus saveStatus = workspace.getSaveManager().save(ISaveContext.PROJECT_SAVE, this, sub);
internalClose(subMonitor.newChild(49));
if (saveStatus != null && !saveStatus.isOK())
throw new ResourceException(saveStatus);
} catch (OperationCanceledException e) {
workspace.getWorkManager().operationCanceled();
throw e;
} finally {
subMonitor.done();
workspace.endOperation(rule, true);
}
}
@Override
public void copy(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
monitor = Policy.monitorFor(monitor);
if (destination.segmentCount() == 1) {
String projectName = destination.segment(0);
IProjectDescription desc = getDescription();
desc.setName(projectName);
desc.setLocation(null);
((ProjectDescription) desc).setSnapshotLocationURI(null);
internalCopy(desc, updateFlags, monitor);
} else {
checkCopyRequirements(destination, IResource.PROJECT, updateFlags);
}
}
@Override
public void copy(IProjectDescription destination, int updateFlags, IProgressMonitor monitor) throws CoreException {
Assert.isNotNull(destination);
internalCopy(destination, updateFlags, monitor);
}
protected void copyMetaArea(IProject source, IProject destination, IProgressMonitor monitor) throws CoreException {
IFileStore oldMetaArea = EFS.getFileSystem(EFS.SCHEME_FILE).getStore(workspace.getMetaArea().locationFor(source));
IFileStore newMetaArea = EFS.getFileSystem(EFS.SCHEME_FILE).getStore(workspace.getMetaArea().locationFor(destination));
oldMetaArea.copy(newMetaArea, EFS.NONE, monitor);
}
@Override
public void create(IProgressMonitor monitor) throws CoreException {
create(null, monitor);
}
@Override
public void create(IProjectDescription description, IProgressMonitor monitor) throws CoreException {
create(description, IResource.NONE, monitor);
}
@Override
public void create(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {
SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.resources_create, 100);
checkValidPath(path, PROJECT, false);
final ISchedulingRule rule = workspace.getRuleFactory().createRule(this);
try {
workspace.prepareOperation(rule, subMonitor);
if (description == null) {
description = new ProjectDescription();
description.setName(getName());
}
assertCreateRequirements(description);
workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_CREATE, this));
workspace.beginOperation(true);
workspace.createResource(this, updateFlags);
workspace.getMetaArea().create(this);
ProjectInfo info = (ProjectInfo) getResourceInfo(false, true);
ProjectDescription desc = (ProjectDescription) ((ProjectDescription) description).clone();
desc.setLocationURI(FileUtil.canonicalURI(description.getLocationURI()));
desc.setName(getName());
internalSetDescription(desc, false);
final boolean hasSavedDescription = getLocalManager().hasSavedDescription(this);
boolean hasContent = hasSavedDescription;
if (!hasSavedDescription)
hasContent = getLocalManager().hasSavedContent(this);
try {
if (hasSavedDescription) {
updateDescription();
workspace.getMetaArea().writePrivateDescription(this);
} else {
writeDescription(IResource.FORCE);
}
} catch (CoreException e) {
workspace.deleteResource(this);
throw e;
}
info.clearModificationStamp();
if (hasContent)
info.set(ICoreConstants.M_CHILDREN_UNKNOWN);
workspace.getSaveManager().requestSnapshot();
} catch (OperationCanceledException e) {
workspace.getWorkManager().operationCanceled();
throw e;
} finally {
subMonitor.done();
workspace.endOperation(rule, true);
}
}
@Override
public void delete(boolean deleteContent, boolean force, IProgressMonitor monitor) throws CoreException {
int updateFlags = force ? IResource.FORCE : IResource.NONE;
updateFlags |= deleteContent ? IResource.ALWAYS_DELETE_PROJECT_CONTENT : IResource.NEVER_DELETE_PROJECT_CONTENT;
delete(updateFlags, monitor);
}
@Override
public void delete(boolean force, IProgressMonitor monitor) throws CoreException {
int updateFlags = force ? IResource.FORCE : IResource.NONE;
delete(updateFlags, monitor);
}
@Override
public void deleteResource(boolean convertToPhantom, MultiStatus status) throws CoreException {
super.deleteResource(convertToPhantom, status);
clearHistory(null);
workspace.getMetaArea().delete(this);
}
@Override
protected void fixupAfterMoveSource() throws CoreException {
workspace.deleteResource(this);
ProjectPreferences.deleted(this);
}
@Override
public IBuildConfiguration getActiveBuildConfig() throws CoreException {
ResourceInfo info = getResourceInfo(false, false);
int flags = getFlags(info);
checkAccessible(flags);
return internalGetActiveBuildConfig();
}
@Override
public IBuildConfiguration getBuildConfig(String configName) throws CoreException {
if (configName == null)
return getActiveBuildConfig();
ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
checkAccessible(getFlags(info));
IBuildConfiguration[] configs = internalGetBuildConfigs(false);
for (IBuildConfiguration config : configs) {
if (config.getName().equals(configName)) {
return config;
}
}
throw new ResourceException(IResourceStatus.BUILD_CONFIGURATION_NOT_FOUND, getFullPath(), null, null);
}
@Override
public IBuildConfiguration[] getBuildConfigs() throws CoreException {
ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
checkAccessible(getFlags(info));
return internalGetBuildConfigs(true);
}
@Override
public IContentTypeMatcher getContentTypeMatcher() throws CoreException {
return workspace.getContentDescriptionManager().getContentTypeMatcher(this);
}
@Override
public String getDefaultCharset(boolean checkImplicit) {
if (!exists())
return checkImplicit ? ResourcesPlugin.getEncoding() : null;
return workspace.getCharsetManager().getCharsetFor(getFullPath(), checkImplicit);
}
@Override
public IProjectDescription getDescription() throws CoreException {
ResourceInfo info = getResourceInfo(false, false);
checkAccessible(getFlags(info));
ProjectDescription description = ((ProjectInfo) info).getDescription();
if (description == null)
checkAccessible(NULL_FLAG);
return (IProjectDescription) description.clone();
}
@Override
public IProjectNature getNature(String natureID) throws CoreException {
ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
checkAccessible(getFlags(info));
IProjectNature nature = info.getNature(natureID);
if (nature == null) {
if (!hasNature(natureID))
return null;
nature = workspace.getNatureManager().createNature(this, natureID);
info.setNature(natureID, nature);
}
return nature;
}
@Override
public IContainer getParent() {
return workspace.getRoot();
}
@Override
public IProject getProject() {
return this;
}
@Override
public IPath getProjectRelativePath() {
return Path.EMPTY;
}
@Override
public IPath getRawLocation() {
ProjectDescription description = internalGetDescription();
return description == null ? null : description.getLocation();
}
@Override
public URI getRawLocationURI() {
ProjectDescription description = internalGetDescription();
return description == null ? null : description.getLocationURI();
}
@Override
public IBuildConfiguration[] getReferencedBuildConfigs(String configName, boolean includeMissing) throws CoreException {
ResourceInfo info = getResourceInfo(false, false);
checkAccessible(getFlags(info));
ProjectDescription description = ((ProjectInfo) info).getDescription();
if (description == null)
checkAccessible(NULL_FLAG);
if (!hasBuildConfig(configName))
throw new ResourceException(IResourceStatus.BUILD_CONFIGURATION_NOT_FOUND, getFullPath(), null, null);
return internalGetReferencedBuildConfigs(configName, includeMissing);
}
@Override
public IProject[] getReferencedProjects() throws CoreException {
ResourceInfo info = getResourceInfo(false, false);
checkAccessible(getFlags(info));
ProjectDescription description = ((ProjectInfo) info).getDescription();
if (description == null)
checkAccessible(NULL_FLAG);
return description.getAllReferences(this, true);
}
@Override
public void clearCachedDynamicReferences() {
ResourceInfo info = getResourceInfo(false, false);
if (info == null) {
return;
}
ProjectDescription description = ((ProjectInfo) info).getDescription();
if (description == null) {
return;
}
description.clearCachedDynamicReferences(null);
}
@Override
public IProject[] getReferencingProjects() {
IProject[] projects = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
List<IProject> result = new ArrayList<>(projects.length);
for (IProject p : projects) {
Project project = (Project) p;
if (!project.isAccessible())
continue;
ProjectDescription description = project.internalGetDescription();
if (description == null)
continue;
IProject[] references = description.getAllReferences(project, false);
for (IProject reference : references)
if (reference.equals(this)) {
result.add(project);
break;
}
}
return result.toArray(new IProject[result.size()]);
}
@Override
public int getType() {
return PROJECT;
}
@Override
public IPath getWorkingLocation(String id) {
if (id == null || !exists())
return null;
IPath result = workspace.getMetaArea().getWorkingLocation(this, id);
result.toFile().mkdirs();
return result;
}
@Override
public boolean hasBuildConfig(String configName) throws CoreException {
ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
checkAccessible(getFlags(info));
return internalHasBuildConfig(configName);
}
@Override
public boolean hasNature(String natureID) throws CoreException {
checkAccessible(getFlags(getResourceInfo(false, false)));
IProjectDescription desc = internalGetDescription();
if (desc == null)
checkAccessible(NULL_FLAG);
return desc.hasNature(natureID);
}
protected void internalBuild(final IBuildConfiguration config, final int trigger, final String builderName, final Map<String, String> args, IProgressMonitor monitor) throws CoreException {
ICoreRunnable buildRunnable = new ICoreRunnable() {
@Override
public void run(IProgressMonitor innerMonitor) throws CoreException {
final ISchedulingRule projectBuildRule = workspace.getBuildManager().getRule(config, trigger,
builderName, args);
final boolean relaxed = Job.getJobManager().currentRule() == null && workspace.isRelaxedRule(projectBuildRule);
final ISchedulingRule notificationsRule = relaxed ? null : workspace.getRoot();
SubMonitor subMonitor = SubMonitor.convert(innerMonitor, 100);
try {
try {
workspace.prepareOperation(notificationsRule, innerMonitor);
if (!shouldBuild())
return;
workspace.beginOperation(true);
workspace.aboutToBuild(Project.this, trigger);
} finally {
workspace.endOperation(notificationsRule, false);
}
try {
IStatus result;
workspace.prepareOperation(projectBuildRule, innerMonitor);
workspace.beginOperation(false);
result = workspace.getBuildManager().build(config, trigger, builderName, args,
subMonitor.split(100));
if (!result.isOK())
throw new ResourceException(result);
} finally {
workspace.endOperation(projectBuildRule, false);
try {
workspace.prepareOperation(notificationsRule, innerMonitor);
workspace.beginOperation(false);
workspace.broadcastBuildEvent(Project.this, IResourceChangeEvent.POST_BUILD, trigger);
if (workspace.getElementTree().isImmutable())
workspace.newWorkingTree();
} finally {
workspace.endOperation(notificationsRule, false);
}
}
} finally {
subMonitor.done();
}
}
private boolean shouldBuild() {
ResourceInfo info = getResourceInfo(false, false);
int flags = getFlags(info);
if (!exists(flags, true) || !isOpen(flags)) {
return false;
}
return true;
}
};
workspace.run(buildRunnable, null, IWorkspace.AVOID_UPDATE, monitor);
}
protected void internalClose(IProgressMonitor monitor) throws CoreException {
SubMonitor subMonitor = SubMonitor.convert(monitor, 2);
workspace.flushBuildOrder();
getMarkerManager().removeMarkers(this, IResource.DEPTH_INFINITE);
subMonitor.worked(1);
IResource[] members = members(IContainer.INCLUDE_PHANTOMS | IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN);
subMonitor.setWorkRemaining(members.length);
for (IResource member2 : members) {
Resource member = (Resource) member2;
workspace.deleteResource(member);
subMonitor.worked(1);
}
ResourceInfo info = getResourceInfo(false, true);
info.clear(M_OPEN);
info.clearSessionProperties();
info.clearModificationStamp();
info.clearCharsetGenerationCount();
info.setSyncInfo(null);
}
protected void internalCopy(IProjectDescription destDesc, int updateFlags, IProgressMonitor monitor) throws CoreException {
monitor = Policy.monitorFor(monitor);
try {
String message = NLS.bind(Messages.resources_copying, getFullPath());
monitor.beginTask(message, Policy.totalWork);
String destName = destDesc.getName();
IPath destPath = new Path(destName).makeAbsolute();
Project destination = (Project) workspace.getRoot().getProject(destName);
final ISchedulingRule rule = workspace.getRuleFactory().copyRule(this, destination);
try {
workspace.prepareOperation(rule, monitor);
assertCopyRequirements(destPath, IResource.PROJECT, updateFlags);
checkDescription(destination, destDesc, false);
workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_COPY, this, destination, updateFlags));
workspace.beginOperation(true);
getLocalManager().refresh(this, DEPTH_INFINITE, true, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100));
getPropertyManager().closePropertyStore(this);
getLocalManager().getHistoryStore().closeHistoryStore(this);
copyMetaArea(this, destination, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));
internalCopyProjectOnly(destination, destDesc, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));
destination.internalSetDescription(destDesc, false);
destination.getStore().mkdir(EFS.NONE, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));
message = Messages.resources_copyProblem;
MultiStatus problems = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, message, null);
IResource[] children = members(IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN);
final int childCount = children.length;
final int childWork = childCount > 1 ? Policy.opWork * 50 / 100 / (childCount - 1) : 0;
for (int i = 0; i < childCount; i++) {
IResource child = children[i];
if (!isProjectDescriptionFile(child)) {
try {
child.copy(destPath.append(child.getName()), updateFlags, Policy.subMonitorFor(monitor, childWork));
} catch (CoreException e) {
problems.merge(e.getStatus());
}
}
}
try {
destination.writeDescription(IResource.FORCE);
} catch (CoreException e) {
try {
destination.delete((updateFlags & IResource.FORCE) != 0, null);
} catch (CoreException e2) {
}
throw e;
}
monitor.worked(Policy.opWork * 5 / 100);
monitor.subTask(Messages.resources_updating);
getLocalManager().refresh(destination, DEPTH_INFINITE, true, Policy.subMonitorFor(monitor, Policy.opWork * 10 / 100));
if (!problems.isOK())
throw new ResourceException(problems);
} catch (OperationCanceledException e) {
workspace.getWorkManager().operationCanceled();
throw e;
} finally {
workspace.endOperation(rule, true);
}
} finally {
monitor.done();
}
}
protected void internalCopyProjectOnly(IResource destination, IProjectDescription destDesc, IProgressMonitor monitor) throws CoreException {
getPropertyManager().closePropertyStore(this);
getLocalManager().getHistoryStore().closeHistoryStore(this);
workspace.copyTree(this, destination.getFullPath(), IResource.DEPTH_ZERO, IResource.NONE, false);
getPropertyManager().copy(this, destination, IResource.DEPTH_ZERO);
ProjectInfo info = (ProjectInfo) ((Resource) destination).getResourceInfo(false, true);
ProjectDescription projectDesc = (ProjectDescription) destDesc;
ProjectDescription internalDesc = ((Project) destination.getProject()).internalGetDescription();
projectDesc.setLinkDescriptions(internalDesc.getLinks());
projectDesc.setFilterDescriptions(internalDesc.getFilters());
projectDesc.setVariableDescriptions(internalDesc.getVariables());
info.description = null;
info.natures = null;
info.setMarkers(null);
info.clearSessionProperties();
}
IBuildConfiguration internalGetActiveBuildConfig() {
String configName = internalGetDescription().activeConfiguration;
try {
if (configName != null)
return getBuildConfig(configName);
} catch (CoreException e) {
}
return internalGetBuildConfigs(false)[0];
}
public IBuildConfiguration[] internalGetBuildConfigs(boolean makeCopy) {
ProjectDescription desc = internalGetDescription();
if (desc == null)
return new IBuildConfiguration[] {new BuildConfiguration(this, IBuildConfiguration.DEFAULT_CONFIG_NAME)};
return desc.getBuildConfigs(this, makeCopy);
}
public ProjectDescription internalGetDescription() {
ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
if (info == null)
return null;
return info.getDescription();
}
public IBuildConfiguration[] internalGetReferencedBuildConfigs(String configName, boolean includeMissing) {
ProjectDescription description = internalGetDescription();
IBuildConfiguration[] refs = description.getAllBuildConfigReferences(this, configName, false);
Collection<IBuildConfiguration> configs = new LinkedHashSet<>(refs.length);
for (IBuildConfiguration ref : refs) {
try {
configs.add((((BuildConfiguration) ref).getBuildConfig()));
} catch (CoreException e) {
if (includeMissing)
configs.add(ref);
}
}
return configs.toArray(new IBuildConfiguration[configs.size()]);
}
boolean internalHasBuildConfig(String configName) {
return internalGetDescription().hasBuildConfig(configName);
}
void internalSetDescription(IProjectDescription value, boolean incrementContentId) {
workspace.flushBuildOrder();
ProjectInfo info = (ProjectInfo) getResourceInfo(false, true);
info.setDescription((ProjectDescription) value);
getLocalManager().setLocation(this, info, value.getLocationURI());
if (incrementContentId) {
info.incrementContentId();
if (info.getModificationStamp() != NULL_STAMP)
workspace.updateModificationStamp(info);
}
}
@Override
public void internalSetLocal(boolean flag, int depth) throws CoreException {
if (depth == IResource.DEPTH_ZERO)
return;
if (depth == IResource.DEPTH_ONE)
depth = IResource.DEPTH_ZERO;
IResource[] children = getChildren(IResource.NONE);
for (IResource element : children)
((Resource) element).internalSetLocal(flag, depth);
}
@Override
public boolean isAccessible() {
return isOpen();
}
@Override
public boolean isDerived(int options) {
return false;
}
@Override
public boolean isLinked(int options) {
return false;
}
@Override
public boolean isVirtual() {
return false;
}
@Override
public boolean isTeamPrivateMember(int options) {
return false;
}
@Deprecated
@Override
public boolean isLocal(int depth) {
return isLocal(-1, depth);
}
@Deprecated
@Override
public boolean isLocal(int flags, int depth) {
if (depth == DEPTH_ZERO)
return true;
if (depth == DEPTH_ONE)
depth = DEPTH_ZERO;
IResource[] children = getChildren(IResource.NONE);
for (IResource element : children)
if (!element.isLocal(depth))
return false;
return true;
}
@Override
public boolean isNatureEnabled(String natureId) throws CoreException {
checkAccessible(getFlags(getResourceInfo(false, false)));
return workspace.getNatureManager().isNatureEnabled(this, natureId);
}
@Override
public boolean isOpen() {
ResourceInfo info = getResourceInfo(false, false);
return isOpen(getFlags(info));
}
public boolean isOpen(int flags) {
return flags != NULL_FLAG && ResourceInfo.isSet(flags, M_OPEN);
}
protected boolean isProjectDescriptionFile(IResource resource) {
return resource.getType() == IResource.FILE && resource.getFullPath().segmentCount() == 2 && resource.getName().equals(IProjectDescription.DESCRIPTION_FILE_NAME);
}
@Override
public void loadSnapshot(int options, URI snapshotLocation, IProgressMonitor monitor) throws CoreException {
if (isOpen()) {
String message = Messages.resources_projectMustNotBeOpen;
MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, null);
throw new CoreException(status);
}
internalLoadSnapshot(options, snapshotLocation, monitor);
}
private void internalLoadSnapshot(int options, URI snapshotLocation, IProgressMonitor monitor) throws CoreException {
if ((options & SNAPSHOT_TREE) != 0) {
snapshotLocation = workspace.getPathVariableManager().resolveURI(snapshotLocation);
if (!snapshotLocation.isAbsolute()) {
String message = NLS.bind(Messages.projRead_badSnapshotLocation, snapshotLocation.toString());
throw new CoreException(new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, message, null));
}
IPath snapshotPath = workspace.getMetaArea().getRefreshLocationFor(this);
IFileStore snapshotFileStore = EFS.getStore(org.eclipse.core.filesystem.URIUtil.toURI(snapshotPath));
EFS.getStore(snapshotLocation).copy(snapshotFileStore, EFS.OVERWRITE, monitor);
}
}
@Override
public void move(IProjectDescription destination, boolean force, IProgressMonitor monitor) throws CoreException {
Assert.isNotNull(destination);
move(destination, force ? IResource.FORCE : IResource.NONE, monitor);
}
@Override
public void move(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {
Assert.isNotNull(description);
monitor = Policy.monitorFor(monitor);
try {
String message = NLS.bind(Messages.resources_moving, getFullPath());
monitor.beginTask(message, Policy.totalWork);
IProject destination = workspace.getRoot().getProject(description.getName());
final ISchedulingRule rule = workspace.getRuleFactory().moveRule(this, destination);
try {
workspace.prepareOperation(rule, monitor);
if (!getName().equals(description.getName())) {
IPath destPath = Path.ROOT.append(description.getName());
assertMoveRequirements(destPath, IResource.PROJECT, updateFlags);
}
checkDescription(destination, description, true);
workspace.beginOperation(true);
message = Messages.resources_moveProblem;
MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.ERROR, message, null);
WorkManager workManager = workspace.getWorkManager();
ResourceTree tree = new ResourceTree(getLocalManager(), workManager.getLock(), status, updateFlags);
IMoveDeleteHook hook = workspace.getMoveDeleteHook();
workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_MOVE, this, destination, updateFlags));
int depth = 0;
try {
depth = workManager.beginUnprotected();
if (!hook.moveProject(tree, this, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork / 2)))
tree.standardMoveProject(this, description, updateFlags, Policy.subMonitorFor(monitor, Policy.opWork / 2));
} finally {
workManager.endUnprotected(depth);
}
tree.makeInvalid();
if (!tree.getStatus().isOK())
throw new ResourceException(tree.getStatus());
workspace.getSaveManager().requestSnapshot();
} catch (OperationCanceledException e) {
workspace.getWorkManager().operationCanceled();
throw e;
} finally {
workspace.endOperation(rule, true);
}
} finally {
monitor.done();
}
}
@Override
public void open(int updateFlags, IProgressMonitor monitor) throws CoreException {
monitor = Policy.monitorFor(monitor);
try {
String msg = NLS.bind(Messages.resources_opening_1, getName());
monitor.beginTask(msg, Policy.totalWork);
monitor.subTask(msg);
final ISchedulingRule rule = workspace.getRuleFactory().modifyRule(this);
try {
workspace.prepareOperation(rule, monitor);
ProjectInfo info = (ProjectInfo) getResourceInfo(false, false);
int flags = getFlags(info);
checkExists(flags, true);
if (isOpen(flags))
return;
workspace.beginOperation(true);
workspace.flushBuildOrder();
info = (ProjectInfo) getResourceInfo(false, true);
info.set(M_OPEN);
boolean unknownChildren = info.isSet(M_CHILDREN_UNKNOWN);
if (unknownChildren)
info.clear(M_CHILDREN_UNKNOWN);
boolean used = info.isSet(M_USED);
boolean snapshotLoaded = false;
if (!used && !workspace.getMetaArea().getRefreshLocationFor(this).toFile().exists()) {
final boolean hasSavedDescription = getLocalManager().hasSavedDescription(this);
if (hasSavedDescription) {
ProjectDescription updatedDesc = info.getDescription();
if (updatedDesc != null) {
URI autoloadURI = updatedDesc.getSnapshotLocationURI();
if (autoloadURI != null) {
try {
autoloadURI = getPathVariableManager().resolveURI(autoloadURI);
internalLoadSnapshot(SNAPSHOT_TREE, autoloadURI, Policy.subMonitorFor(monitor, Policy.opWork * 5 / 100));
snapshotLoaded = true;
} catch (CoreException ce) {
String msgerr = NLS.bind(Messages.projRead_cannotReadSnapshot, getName(), ce.getLocalizedMessage());
Policy.log(new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, msgerr));
}
}
}
}
}
boolean minorIssuesDuringRestore = false;
if (used) {
minorIssuesDuringRestore = workspace.getSaveManager().restore(this, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100));
} else {
info.set(M_USED);
IStatus result = reconcileLinksAndGroups(info.getDescription());
if (!result.isOK())
throw new CoreException(result);
workspace.updateModificationStamp(info);
monitor.worked(Policy.opWork * (snapshotLoaded ? 15 : 20) / 100);
}
startup();
if ((!used && unknownChildren) || !minorIssuesDuringRestore) {
boolean refreshed = false;
if (!used) {
refreshed = workspace.getSaveManager().restoreFromRefreshSnapshot(this, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100));
if (refreshed) {
monitor.worked(Policy.opWork * 60 / 100);
}
}
if (!refreshed) {
if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
workspace.refreshManager.refresh(this);
monitor.worked(Policy.opWork * 60 / 100);
} else {
refreshLocal(IResource.DEPTH_INFINITE, Policy.subMonitorFor(monitor, Policy.opWork * 60 / 100));
}
}
} else {
if ((updateFlags & IResource.BACKGROUND_REFRESH) != 0) {
workspace.refreshManager.refresh(this);
monitor.worked(Policy.opWork * 60 / 100);
}
}
workspace.getAliasManager().updateAliases(this, getStore(), IResource.DEPTH_INFINITE, monitor);
} catch (OperationCanceledException e) {
workspace.getWorkManager().operationCanceled();
throw e;
} finally {
workspace.endOperation(rule, true);
}
} finally {
monitor.done();
}
}
@Override
public void open(IProgressMonitor monitor) throws CoreException {
open(IResource.NONE, monitor);
}
public IStatus reconcileLinksAndGroups(ProjectDescription newDescription) {
String msg = Messages.links_errorLinkReconcile;
HashMap<IPath, LinkDescription> newLinks = newDescription.getLinks();
MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.OPERATION_FAILED, msg, null);
ProjectDescription oldDescription = internalGetDescription();
if (oldDescription != null) {
HashMap<IPath, LinkDescription> oldLinks = oldDescription.getLinks();
if (oldLinks != null) {
for (LinkDescription oldLink : oldLinks.values()) {
Resource oldLinkResource = (Resource) findMember(oldLink.getProjectRelativePath());
if (oldLinkResource == null || !oldLinkResource.isLinked())
continue;
LinkDescription newLink = null;
if (newLinks != null)
newLink = newLinks.get(oldLink.getProjectRelativePath());
if (newLink == null || !newLink.getLocationURI().equals(oldLinkResource.getRawLocationURI()) || newLink.getType() != oldLinkResource.getType()) {
try {
oldLinkResource.delete(IResource.NONE, null);
oldLinkResource.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
status.merge(e.getStatus());
}
}
}
}
}
if (newLinks == null)
return status;
TreeSet<LinkDescription> newLinksAndGroups = new TreeSet<>((arg0, arg1) -> {
int numberOfSegments0 = arg0.getProjectRelativePath().segmentCount();
int numberOfSegments1 = arg1.getProjectRelativePath().segmentCount();
if (numberOfSegments0 != numberOfSegments1)
return numberOfSegments0 - numberOfSegments1;
else if (arg0.equals(arg1))
return 0;
return -1;
});
if (newLinks != null)
newLinksAndGroups.addAll(newLinks.values());
for (LinkDescription newLink : newLinksAndGroups) {
try {
Resource toLink = workspace.newResource(getFullPath().append(newLink.getProjectRelativePath()), newLink.getType());
IContainer parent = toLink.getParent();
if (parent != null && !parent.exists() && parent.getType() == FOLDER)
((Folder) parent).ensureExists(Policy.monitorFor(null));
if (!toLink.exists() || !toLink.isLinked()) {
if (newLink.isGroup())
((Folder) toLink).create(IResource.REPLACE | IResource.VIRTUAL, true, null);
else
toLink.createLink(newLink.getLocationURI(), IResource.REPLACE | IResource.ALLOW_MISSING_LOCAL, null);
}
} catch (CoreException e) {
status.merge(e.getStatus());
}
}
return status;
}
@Override
public void saveSnapshot(int options, URI snapshotLocation, IProgressMonitor monitor) throws CoreException {
monitor = Policy.monitorFor(monitor);
try {
monitor.beginTask("", Policy.totalWork);
checkAccessible(getFlags(getResourceInfo(false, false)));
URI resolvedSnapshotLocation = getPathVariableManager().resolveURI(snapshotLocation);
if (resolvedSnapshotLocation == null || !resolvedSnapshotLocation.isAbsolute()) {
String message = NLS.bind(Messages.projRead_badSnapshotLocation, resolvedSnapshotLocation);
throw new CoreException(new Status(IStatus.ERROR, ResourcesPlugin.PI_RESOURCES, message, null));
}
if ((options & SNAPSHOT_TREE) != 0) {
try {
IProgressMonitor sub = Policy.subMonitorFor(monitor, Policy.opWork / 2);
workspace.getSaveManager().saveRefreshSnapshot(this, resolvedSnapshotLocation, sub);
} catch (OperationCanceledException e) {
throw e;
}
}
if ((options & SNAPSHOT_SET_AUTOLOAD) != 0) {
IProgressMonitor sub = Policy.subMonitorFor(monitor, Policy.opWork / 2);
if (snapshotLocation != null && snapshotLocation.isAbsolute()) {
snapshotLocation = getPathVariableManager().convertToRelative(snapshotLocation, false, "PROJECT_LOC");
}
IProjectDescription desc = getDescription();
((ProjectDescription) desc).setSnapshotLocationURI(snapshotLocation);
setDescription(desc, IResource.KEEP_HISTORY | IResource.AVOID_NATURE_CONFIG, sub);
}
} finally {
monitor.done();
}
}
@Override
public void setDescription(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException {
monitor = Policy.monitorFor(monitor);
try {
monitor.beginTask(Messages.resources_setDesc, Policy.totalWork);
ISchedulingRule rule = null;
if ((updateFlags & IResource.AVOID_NATURE_CONFIG) != 0)
rule = workspace.getRuleFactory().modifyRule(this);
else
rule = workspace.getRoot();
try {
workspace.prepareOperation(rule, monitor);
ResourceInfo info = getResourceInfo(false, false);
checkAccessible(getFlags(info));
ProjectDescription oldDescription = internalGetDescription();
ProjectDescription newDescription = (ProjectDescription) description;
boolean hasPublicChanges = oldDescription.hasPublicChanges(newDescription);
boolean hasPrivateChanges = oldDescription.hasPrivateChanges(newDescription);
if (!hasPublicChanges && !hasPrivateChanges)
return;
checkDescription(this, newDescription, false);
boolean hadSavedDescription = true;
if (((updateFlags & IResource.FORCE) == 0)) {
hadSavedDescription = getLocalManager().hasSavedDescription(this);
if (hadSavedDescription && !getLocalManager().isDescriptionSynchronized(this)) {
String message = NLS.bind(Messages.resources_projectDescSync, getName());
throw new ResourceException(IResourceStatus.OUT_OF_SYNC_LOCAL, getFullPath(), message, null);
}
}
if (!hadSavedDescription)
hadSavedDescription = workspace.getMetaArea().hasSavedProject(this);
workspace.beginOperation(true);
MultiStatus status = basicSetDescription(newDescription, updateFlags);
if (hadSavedDescription && !status.isOK())
throw new CoreException(status);
writeDescription(oldDescription, updateFlags, hasPublicChanges, hasPrivateChanges);
info = getResourceInfo(false, true);
info.incrementContentId();
workspace.updateModificationStamp(info);
if (!hadSavedDescription) {
String msg = NLS.bind(Messages.resources_missingProjectMetaRepaired, getName());
status.merge(new ResourceStatus(IResourceStatus.MISSING_DESCRIPTION_REPAIRED, getFullPath(), msg));
}
if (!status.isOK())
throw new CoreException(status);
} finally {
workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.POST_PROJECT_CHANGE, this));
workspace.endOperation(rule, true);
}
} finally {
monitor.done();
}
}
@Override
public void setDescription(IProjectDescription description, IProgressMonitor monitor) throws CoreException {
setDescription(description, IResource.KEEP_HISTORY, monitor);
}
protected void startup() throws CoreException {
if (!isOpen())
return;
workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.PRE_PROJECT_OPEN, this));
}
@Override
public void touch(IProgressMonitor monitor) throws CoreException {
monitor = Policy.monitorFor(monitor);
try {
String message = NLS.bind(Messages.resources_touch, getFullPath());
monitor.beginTask(message, Policy.totalWork);
final ISchedulingRule rule = workspace.getRuleFactory().modifyRule(this);
try {
workspace.prepareOperation(rule, monitor);
workspace.beginOperation(true);
super.touch(Policy.subMonitorFor(monitor, Policy.opWork));
} catch (OperationCanceledException e) {
workspace.getWorkManager().operationCanceled();
throw e;
} finally {
workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.POST_PROJECT_CHANGE, this));
workspace.endOperation(rule, true);
}
} finally {
monitor.done();
}
}
protected void updateDescription() throws CoreException {
if (ProjectDescription.isWriting)
return;
ProjectDescription.isReading = true;
try {
ProjectDescription description = getLocalManager().read(this, false);
IStatus result = null;
if (isOpen())
result = reconcileLinksAndGroups(description);
internalSetDescription(description, true);
if (result != null && !result.isOK())
throw new CoreException(result);
} finally {
workspace.broadcastEvent(LifecycleEvent.newEvent(LifecycleEvent.POST_PROJECT_CHANGE, this));
ProjectDescription.isReading = false;
}
}
public void writeDescription(int updateFlags) throws CoreException {
writeDescription(internalGetDescription(), updateFlags, true, true);
}
public void writeDescription(IProjectDescription description, int updateFlags, boolean hasPublicChanges, boolean hasPrivateChanges) throws CoreException {
if (ProjectDescription.isReading)
return;
ProjectDescription.isWriting = true;
try {
getLocalManager().internalWrite(this, description, updateFlags, hasPublicChanges, hasPrivateChanges);
} finally {
ProjectDescription.isWriting = false;
}
}
}