blob: f01322e53d3fa877dfc95ccc143f162dd05cce39 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.dltk.internal.core;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.dltk.core.IBuildpathContainer;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.internal.core.util.Util;
public class SetContainerOperation extends ChangeBuildpathOperation {
final IPath containerPath;
final IScriptProject[] affectedProjects;
final IBuildpathContainer[] respectiveContainers;
public SetContainerOperation(IPath containerPath,
IScriptProject[] affectedProjects,
IBuildpathContainer[] respectiveContainers) {
super(
new IModelElement[] { ModelManager.getModelManager().getModel() },
!ResourcesPlugin.getWorkspace().isTreeLocked());
this.containerPath = containerPath;
this.affectedProjects = affectedProjects;
this.respectiveContainers = respectiveContainers;
}
@Override
protected void executeOperation() throws ModelException {
checkCanceled();
try {
beginTask("", 1); //$NON-NLS-1$
if (ModelManager.BP_RESOLVE_VERBOSE) {
verboseSetContainer();
verboseSetContainer_Trace();
}
final ModelManager manager = ModelManager.getModelManager();
if (manager.containerPutIfInitializingWithSameEntries(
containerPath, affectedProjects, respectiveContainers))
return;
final int projectLength = affectedProjects.length;
final IScriptProject[] modifiedProjects;
System.arraycopy(affectedProjects, 0,
modifiedProjects = new IScriptProject[projectLength], 0,
projectLength);
// filter out unmodified project containers
int remaining = 0;
for (int i = 0; i < projectLength; i++) {
if (isCanceled())
return;
ScriptProject affectedProject = (ScriptProject) affectedProjects[i];
IBuildpathContainer newContainer = respectiveContainers[i];
if (newContainer == null)
newContainer = ModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS; // 30920
// -
// prevent
// infinite
// loop
boolean found = false;
if (ScriptProject.hasScriptNature(affectedProject.getProject())) {
IBuildpathEntry[] rawClasspath = affectedProject
.getRawBuildpath();
for (int j = 0, cpLength = rawClasspath.length; j < cpLength; j++) {
IBuildpathEntry entry = rawClasspath[j];
if (entry.getEntryKind() == IBuildpathEntry.BPE_CONTAINER
&& entry.getPath().equals(containerPath)) {
found = true;
break;
}
}
}
if (!found) {
modifiedProjects[i] = null; // filter out this project -
// does
// not reference the container path,
// or isnt't yet script project
manager.containerPut(affectedProject, containerPath,
newContainer);
continue;
}
IBuildpathContainer oldContainer = manager.containerGet(
affectedProject, containerPath);
if (oldContainer == ModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) {
oldContainer = null;
}
if ((oldContainer != null && oldContainer
.equals(respectiveContainers[i]))
|| (oldContainer == this.respectiveContainers[i]) /*
* handle
* case
* where
* old
* and
* new
* containers
* are
* null
* (see
* bug
* 149043
*/
) {
modifiedProjects[i] = null; // filter out this project -
// container did not change
continue;
}
remaining++;
manager.containerPut(affectedProject, containerPath,
newContainer);
}
if (remaining == 0)
return;
// trigger model refresh
try {
for (int i = 0; i < projectLength; i++) {
if (isCanceled())
return;
ScriptProject affectedProject = (ScriptProject) modifiedProjects[i];
if (affectedProject == null)
continue; // was filtered out
if (ModelManager.BP_RESOLVE_VERBOSE) {
verboseUpdateProject(affectedProject);
}
// force resolved buildpath to be recomputed
BuildpathChange buildpathChange = affectedProject
.getPerProjectInfo().resetResolvedBuildpath();
// if needed, generate delta, update project ref, create
// markers, ...
buildpathChanged(buildpathChange);
if (this.canChangeResources) {
// touch project to force a build if needed
try {
affectedProject.getProject().touch(
this.progressMonitor);
} catch (CoreException e) {
// see
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=148970
if (!ExternalScriptProject.EXTERNAL_PROJECT_NAME
.equals(affectedProject.getElementName()))
throw e;
}
}
}
} catch (CoreException e) {
if (ModelManager.BP_RESOLVE_VERBOSE) {
verboseFailure(e);
}
ModelException.propagate(e);
} finally {
for (int i = 0; i < projectLength; i++) {
if (respectiveContainers[i] == null) {
manager.containerPut(affectedProjects[i],
containerPath, null); // reset init in progress
// marker
}
}
}
} finally {
done();
}
}
private void verboseFailure(CoreException e) {
Util.verbose("CPContainer SET - FAILED DUE TO EXCEPTION\n" + //$NON-NLS-1$
" container path: " + containerPath, //$NON-NLS-1$
System.err);
e.printStackTrace();
}
private void verboseUpdateProject(ScriptProject affectedProject) {
Util.verbose("BPContainer SET - updating affected project due to setting container\n" + //$NON-NLS-1$
" project: " //$NON-NLS-1$
+ affectedProject.getElementName()
+ '\n'
+ " container path: " + containerPath); //$NON-NLS-1$
}
private void verboseSetContainer_Trace() {
new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
}
private void verboseSetContainer() {
Util.verbose("BPContainer SET - setting container\n" + //$NON-NLS-1$
" container path: " //$NON-NLS-1$
+ containerPath + '\n' + " projects: {" //$NON-NLS-1$
+ Util.toString(affectedProjects, new Util.Displayable() {
@Override
public String displayString(Object o) {
return ((IScriptProject) o).getElementName();
}
}) + "}\n values: {\n" + //$NON-NLS-1$
Util.toString(respectiveContainers, new Util.Displayable() {
@Override
public String displayString(Object o) {
StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
if (o == null) {
buffer.append("<null>"); //$NON-NLS-1$
return buffer.toString();
}
IBuildpathContainer container = (IBuildpathContainer) o;
buffer.append(container.getDescription());
buffer.append(" {\n"); //$NON-NLS-1$
IBuildpathEntry[] entries = container
.getBuildpathEntries();
if (entries != null) {
for (int i = 0; i < entries.length; i++) {
buffer.append(" "); //$NON-NLS-1$
buffer.append(entries[i]);
buffer.append('\n');
}
}
buffer.append(" }"); //$NON-NLS-1$
return buffer.toString();
}
}) + "\n }\n invocation stack trace:"); //$NON-NLS-1$
}
}