/******************************************************************************* * 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$ } }