/******************************************************************************* * 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 java.util.HashMap; import java.util.Iterator; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaModel; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.core.util.Util; public class SetVariablesOperation extends ChangeClasspathOperation { String[] variableNames; IPath[] variablePaths; boolean updatePreferences; /* * Creates a new SetVariablesOperation for the given variable values (null path meaning removal), allowing to change multiple variable values at once. */ public SetVariablesOperation(String[] variableNames, IPath[] variablePaths, boolean updatePreferences) { super(new IJavaElement[] { JavaModelManager.getJavaModelManager().getJavaModel() }, !ResourcesPlugin.getWorkspace().isTreeLocked()); this.variableNames= variableNames; this.variablePaths= variablePaths; this.updatePreferences= updatePreferences; } protected void executeOperation() throws JavaModelException { checkCanceled(); try { beginTask("", 1); //$NON-NLS-1$ if (JavaModelManager.CP_RESOLVE_VERBOSE) verbose_set_variables(); JavaModelManager manager= JavaModelManager.getJavaModelManager(); if (manager.variablePutIfInitializingWithSameValue(this.variableNames, this.variablePaths)) return; int varLength= this.variableNames.length; // gather classpath information for updating final HashMap affectedProjectClasspaths= new HashMap(5); IJavaModel model= getJavaModel(); // filter out unmodified variables int discardCount= 0; for (int i= 0; i < varLength; i++) { String variableName= this.variableNames[i]; IPath oldPath= manager.variableGet(variableName); // if reentering will provide previous session value if (oldPath == JavaModelManager.VARIABLE_INITIALIZATION_IN_PROGRESS) { oldPath= null; //33695 - cannot filter out restored variable, must update affected project to reset cached CP } if (oldPath != null && oldPath.equals(this.variablePaths[i])) { this.variableNames[i]= null; discardCount++; } } if (discardCount > 0) { if (discardCount == varLength) return; int changedLength= varLength - discardCount; String[] changedVariableNames= new String[changedLength]; IPath[] changedVariablePaths= new IPath[changedLength]; for (int i= 0, index= 0; i < varLength; i++) { if (this.variableNames[i] != null) { changedVariableNames[index]= this.variableNames[i]; changedVariablePaths[index]= this.variablePaths[i]; index++; } } this.variableNames= changedVariableNames; this.variablePaths= changedVariablePaths; varLength= changedLength; } if (isCanceled()) return; IJavaProject[] projects= model.getJavaProjects(); nextProject: for (int i= 0, projectLength= projects.length; i < projectLength; i++) { JavaProject project= (JavaProject)projects[i]; // check to see if any of the modified variables is present on the classpath IClasspathEntry[] classpath= project.getRawClasspath(); for (int j= 0, cpLength= classpath.length; j < cpLength; j++) { IClasspathEntry entry= classpath[j]; for (int k= 0; k < varLength; k++) { String variableName= this.variableNames[k]; if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE) { if (variableName.equals(entry.getPath().segment(0))) { affectedProjectClasspaths.put(project, project.getResolvedClasspath()); continue nextProject; } IPath sourcePath, sourceRootPath; if (((sourcePath= entry.getSourceAttachmentPath()) != null && variableName.equals(sourcePath.segment(0))) || ((sourceRootPath= entry.getSourceAttachmentRootPath()) != null && variableName.equals(sourceRootPath.segment(0)))) { affectedProjectClasspaths.put(project, project.getResolvedClasspath()); continue nextProject; } } } } } // update variables for (int i= 0; i < varLength; i++) { manager.variablePut(this.variableNames[i], this.variablePaths[i]); if (this.updatePreferences) manager.variablePreferencesPut(this.variableNames[i], this.variablePaths[i]); } // update affected project classpaths if (!affectedProjectClasspaths.isEmpty()) { String[] dbgVariableNames= this.variableNames; try { // propagate classpath change Iterator projectsToUpdate= affectedProjectClasspaths.keySet().iterator(); while (projectsToUpdate.hasNext()) { if (this.progressMonitor != null && this.progressMonitor.isCanceled()) return; JavaProject affectedProject= (JavaProject)projectsToUpdate.next(); // force resolved classpath to be recomputed if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED) verbose_update_project(dbgVariableNames, affectedProject); ClasspathChange classpathChange= affectedProject.getPerProjectInfo().resetResolvedClasspath(); // if needed, generate delta, update project ref, create markers, ... classpathChanged(classpathChange, true/*refresh if external linked folder already exists*/); if (this.canChangeResources) { // touch project to force a build if needed affectedProject.getProject().touch(this.progressMonitor); } } } catch (CoreException e) { if (JavaModelManager.CP_RESOLVE_VERBOSE || JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { verbose_failure(dbgVariableNames); e.printStackTrace(); } if (e instanceof JavaModelException) { throw (JavaModelException)e; } else { throw new JavaModelException(e); } } } } finally { done(); } } private void verbose_failure(String[] dbgVariableNames) { Util.verbose( "CPVariable SET - FAILED DUE TO EXCEPTION\n" + //$NON-NLS-1$ " variables: " + org.eclipse.jdt.internal.compiler.util.Util.toString(dbgVariableNames), //$NON-NLS-1$ System.err); } private void verbose_update_project(String[] dbgVariableNames, JavaProject affectedProject) { Util.verbose( "CPVariable SET - updating affected project due to setting variables\n" + //$NON-NLS-1$ " project: " + affectedProject.getElementName() + '\n' + //$NON-NLS-1$ " variables: " + org.eclipse.jdt.internal.compiler.util.Util.toString(dbgVariableNames)); //$NON-NLS-1$ } private void verbose_set_variables() { Util.verbose( "CPVariable SET - setting variables\n" + //$NON-NLS-1$ " variables: " + org.eclipse.jdt.internal.compiler.util.Util.toString(this.variableNames) + '\n' + //$NON-NLS-1$ " values: " + org.eclipse.jdt.internal.compiler.util.Util.toString(this.variablePaths)); //$NON-NLS-1$ } }