blob: e202049bda425ff1a5489844516c2a397347d25a [file] [log] [blame]
/*******************************************************************************
* 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.jdt.internal.core;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.util.Util;
public class SetContainerOperation extends ChangeClasspathOperation {
IPath containerPath;
IJavaProject[] affectedProjects;
IClasspathContainer[] respectiveContainers;
/*
* Creates a new SetContainerOperation.
*/
public SetContainerOperation(IPath containerPath, IJavaProject[] affectedProjects, IClasspathContainer[] respectiveContainers) {
super(new IJavaElement[] {JavaModelManager.getJavaModelManager().getJavaModel()}, !ResourcesPlugin.getWorkspace().isTreeLocked());
this.containerPath = containerPath;
this.affectedProjects = affectedProjects;
this.respectiveContainers = respectiveContainers;
}
@Override
protected void executeOperation() throws JavaModelException {
checkCanceled();
try {
beginTask("", 1); //$NON-NLS-1$
if (JavaModelManager.CP_RESOLVE_VERBOSE)
verbose_set_container();
if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
verbose_set_container_invocation_trace();
JavaModelManager manager = JavaModelManager.getJavaModelManager();
if (manager.containerPutIfInitializingWithSameEntries(this.containerPath, this.affectedProjects, this.respectiveContainers))
return;
final int projectLength = this.affectedProjects.length;
final IJavaProject[] modifiedProjects;
System.arraycopy(this.affectedProjects, 0, modifiedProjects = new IJavaProject[projectLength], 0, projectLength);
// filter out unmodified project containers
int remaining = 0;
for (int i = 0; i < projectLength; i++){
if (isCanceled())
return;
JavaProject affectedProject = (JavaProject) this.affectedProjects[i];
IClasspathContainer newContainer = this.respectiveContainers[i];
if (newContainer == null) newContainer = JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS; // 30920 - prevent infinite loop
boolean found = false;
if (JavaProject.hasJavaNature(affectedProject.getProject())){
IClasspathEntry[] rawClasspath = affectedProject.getRawClasspath();
for (int j = 0, cpLength = rawClasspath.length; j <cpLength; j++) {
IClasspathEntry entry = rawClasspath[j];
if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER && entry.getPath().equals(this.containerPath)){
found = true;
break;
}
}
}
if (!found) {
modifiedProjects[i] = null; // filter out this project - does not reference the container path, or isnt't yet Java project
manager.containerPut(affectedProject, this.containerPath, newContainer);
continue;
}
IClasspathContainer oldContainer = manager.containerGet(affectedProject, this.containerPath);
if (oldContainer == JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) {
oldContainer = null;
}
if ((oldContainer != null && oldContainer.equals(this.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, this.containerPath, newContainer);
}
if (remaining == 0) return;
// trigger model refresh
try {
for(int i = 0; i < projectLength; i++){
this.progressMonitor.setWorkRemaining(projectLength - i);
if (isCanceled())
return;
JavaProject affectedProject = (JavaProject)modifiedProjects[i];
if (affectedProject == null) continue; // was filtered out
if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
verbose_update_project(affectedProject);
// force resolved classpath to be recomputed
ClasspathChange classpathChange = affectedProject.getPerProjectInfo().resetResolvedClasspath();
// if needed, generate delta, update project ref, create markers, ...
classpathChanged(classpathChange, i==0/*refresh external linked folder only once*/);
if (this.canChangeResources) {
// touch project to force a build if needed
try {
affectedProject.getProject().touch(this.progressMonitor.split(1));
} catch (CoreException e) {
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=148970
if (!ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(affectedProject.getElementName()))
throw e;
}
}
}
} catch(CoreException e) {
if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE)
verbose_failure(e);
if (e instanceof JavaModelException) {
throw (JavaModelException)e;
} else {
throw new JavaModelException(e);
}
} finally {
for (int i = 0; i < projectLength; i++) {
if (this.respectiveContainers[i] == null) {
manager.containerPut(this.affectedProjects[i], this.containerPath, null); // reset init in progress marker
}
}
}
} finally {
done();
}
}
private void verbose_failure(CoreException e) {
Util.verbose(
"CPContainer SET - FAILED DUE TO EXCEPTION\n" + //$NON-NLS-1$
" container path: " + this.containerPath, //$NON-NLS-1$
System.err);
e.printStackTrace();
}
private void verbose_update_project(JavaProject affectedProject) {
Util.verbose(
"CPContainer SET - updating affected project due to setting container\n" + //$NON-NLS-1$
" project: " + affectedProject.getElementName() + '\n' + //$NON-NLS-1$
" container path: " + this.containerPath); //$NON-NLS-1$
}
private void verbose_set_container() {
Util.verbose(
"CPContainer SET - setting container\n" + //$NON-NLS-1$
" container path: " + this.containerPath + '\n' + //$NON-NLS-1$
" projects: {" +//$NON-NLS-1$
org.eclipse.jdt.internal.compiler.util.Util.toString(
this.affectedProjects,
new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
@Override
public String displayString(Object o) { return ((IJavaProject) o).getElementName(); }
}) +
"}\n values: {\n" +//$NON-NLS-1$
org.eclipse.jdt.internal.compiler.util.Util.toString(
this.respectiveContainers,
new org.eclipse.jdt.internal.compiler.util.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();
}
IClasspathContainer container = (IClasspathContainer) o;
buffer.append(container.getDescription());
buffer.append(" {\n"); //$NON-NLS-1$
IClasspathEntry[] entries = container.getClasspathEntries();
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 }");//$NON-NLS-1$
}
private void verbose_set_container_invocation_trace() {
Util.verbose(
"CPContainer SET - setting container\n" + //$NON-NLS-1$
" invocation stack trace:"); //$NON-NLS-1$
new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
}
}