Copyright (c) 2000, 2010 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * 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$ } }