| /******************************************************************************* |
| * Copyright (c) 2000, 2008 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); |
| |
| 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$ |
| } |
| |
| } |