| /******************************************************************************* |
| * 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; |
| } |
| |
| 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++){ |
| 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); |
| } 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(){ |
| 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(){ |
| 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$ |
| } |
| |
| } |