| /******************************************************************************* |
| * Copyright (c) 2003, 2013 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.ant.internal.ui.refactoring; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.ant.core.AntCorePlugin; |
| import org.eclipse.ant.internal.core.IAntCoreConstants; |
| import org.eclipse.ant.internal.ui.AntUtil; |
| import org.eclipse.ant.launching.IAntLaunchConstants; |
| import org.eclipse.core.externaltools.internal.IExternalToolConstants; |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.IWorkspaceRoot; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.content.IContentDescription; |
| import org.eclipse.core.runtime.content.IContentType; |
| import org.eclipse.core.variables.IStringVariableManager; |
| import org.eclipse.core.variables.VariablesPlugin; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationType; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.core.ILaunchManager; |
| import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.CompositeChange; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| |
| import com.ibm.icu.text.MessageFormat; |
| |
| public class LaunchConfigurationBuildfileChange extends Change { |
| |
| private ILaunchConfiguration fLaunchConfiguration; |
| private String fNewBuildfileLocation; |
| private String fNewProjectName; |
| private String fNewLaunchConfigurationName; |
| private String fOldBuildfileLocation; |
| private String fOldProjectName; |
| private ILaunchConfigurationWorkingCopy fNewLaunchConfiguration; |
| private String fNewConfigContainerName; |
| |
| /** |
| * Create a change for each launch configuration which needs to be updated for this IJavaProject rename. |
| * |
| * @since 3.5 |
| */ |
| public static Change createChangesForProjectRename(IProject project, String newProjectName) throws CoreException { |
| String projectName = project.getDescription().getName(); |
| ILaunchConfiguration[] configs = getAntLaunchConfigurations(); |
| List<Change> changes = createChangesForProjectRename(configs, projectName, newProjectName); |
| return createChangeFromList(changes, RefactoringMessages.LaunchConfigurationBuildfileChange_7); |
| } |
| |
| /** |
| * Create a change for each launch configuration which needs to be updated for this buildfile rename. |
| */ |
| public static Change createChangesForBuildfileRename(IFile file, String newBuildfileName) throws CoreException { |
| IContentDescription description = null; |
| try { |
| description = file.getContentDescription(); |
| } |
| catch (CoreException e) { |
| // missing file |
| return null; |
| } |
| if (description == null) { |
| return null; |
| } |
| IContentType contentType = description.getContentType(); |
| if (contentType == null || !AntCorePlugin.ANT_BUILDFILE_CONTENT_TYPE.equals(contentType.getId())) { |
| return null; // not an Ant buildfile |
| } |
| ILaunchConfiguration[] configs = getAntLaunchConfigurations(); |
| List<Change> changes = createChangesForBuildfileRename(file, configs, file.getProject().getName(), newBuildfileName); |
| return createChangeFromList(changes, RefactoringMessages.LaunchConfigurationBuildfileChange_7); |
| } |
| |
| private static ILaunchConfiguration[] getAntLaunchConfigurations() throws CoreException { |
| ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); |
| // Ant launch configurations |
| ILaunchConfigurationType configurationType = manager.getLaunchConfigurationType(IAntLaunchConstants.ID_ANT_LAUNCH_CONFIGURATION_TYPE); |
| ILaunchConfiguration[] configs = manager.getLaunchConfigurations(configurationType); |
| return configs; |
| } |
| |
| /** |
| * Take a list of Changes, and return a unique Change, a CompositeChange, or null. |
| */ |
| private static Change createChangeFromList(List<Change> changes, String changeLabel) { |
| int nbChanges = changes.size(); |
| if (nbChanges == 0) { |
| return null; |
| } else if (nbChanges == 1) { |
| return changes.get(0); |
| } else { |
| return new CompositeChange(changeLabel, changes.toArray(new Change[changes.size()])); |
| } |
| } |
| |
| /** |
| * Create a change for each launch configuration from the given list which needs to be updated for this IProject rename. |
| */ |
| private static List<Change> createChangesForProjectRename(ILaunchConfiguration[] configs, String projectName, String newProjectName) throws CoreException { |
| List<Change> changes = new ArrayList<>(); |
| for (int i = 0; i < configs.length; i++) { |
| ILaunchConfiguration launchConfiguration = configs[i]; |
| String launchConfigurationProjectName = launchConfiguration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null); |
| if (projectName.equals(launchConfigurationProjectName)) { |
| LaunchConfigurationBuildfileChange change = new LaunchConfigurationBuildfileChange(launchConfiguration, null, null, newProjectName, false); |
| String newContainerName = computeNewContainerName(launchConfiguration); |
| if (newContainerName != null) { |
| change.setNewContainerName(newContainerName); |
| } |
| |
| changes.add(change); |
| } |
| } |
| return changes; |
| } |
| |
| /** |
| * Create a change for each launch configuration from the given list which needs to be updated for this buildfile rename. |
| */ |
| private static List<Change> createChangesForBuildfileRename(IFile buildfile, ILaunchConfiguration[] configs, String projectName, String newBuildfileName) throws CoreException { |
| List<Change> changes = new ArrayList<>(); |
| for (int i = 0; i < configs.length; i++) { |
| ILaunchConfiguration launchConfiguration = configs[i]; |
| String launchConfigurationProjectName = launchConfiguration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null); |
| if (projectName.equals(launchConfigurationProjectName)) { |
| LaunchConfigurationBuildfileChange change = new LaunchConfigurationBuildfileChange(launchConfiguration, buildfile.getName(), newBuildfileName, null, false); |
| changes.add(change); |
| } |
| } |
| return changes; |
| } |
| |
| protected void setNewContainerName(String newContainerName) { |
| fNewConfigContainerName = newContainerName; |
| } |
| |
| /** |
| * Creates a new container name for the given configuration |
| * |
| * @param launchConfiguration |
| * @return the new container name |
| * @since 3.5 |
| */ |
| private static String computeNewContainerName(ILaunchConfiguration launchConfiguration) { |
| IFile file = launchConfiguration.getFile(); |
| if (file != null) { |
| return file.getParent().getProjectRelativePath().toString(); |
| } |
| return null; |
| } |
| |
| protected LaunchConfigurationBuildfileChange(ILaunchConfiguration launchConfiguration, String oldBuildFileName, String newBuildfileName, String newProjectName, boolean undo) throws CoreException { |
| fLaunchConfiguration = launchConfiguration; |
| fNewLaunchConfiguration = launchConfiguration.getWorkingCopy(); |
| fNewBuildfileLocation = newBuildfileName; |
| fNewProjectName = newProjectName; |
| fOldBuildfileLocation = oldBuildFileName; |
| fOldProjectName = fLaunchConfiguration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null); |
| if (fNewBuildfileLocation != null) { |
| // generate the new configuration name |
| String launchConfigurationName = fLaunchConfiguration.getName(); |
| fNewLaunchConfigurationName = launchConfigurationName.replaceAll(oldBuildFileName, newBuildfileName); |
| if (launchConfigurationName.equals(fNewLaunchConfigurationName) |
| || (!undo && DebugPlugin.getDefault().getLaunchManager().isExistingLaunchConfigurationName(fNewLaunchConfigurationName))) { |
| fNewLaunchConfigurationName = null; |
| } |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ltk.core.refactoring.Change#getName() |
| */ |
| @Override |
| public String getName() { |
| if (fNewLaunchConfigurationName != null) { |
| return MessageFormat.format(RefactoringMessages.LaunchConfigurationBuildfileChange_0, new Object[] { fLaunchConfiguration.getName(), |
| fNewLaunchConfigurationName }); |
| } |
| if (fNewProjectName == null) { |
| return MessageFormat.format(RefactoringMessages.LaunchConfigurationBuildfileChange_1, new Object[] { fLaunchConfiguration.getName() }); |
| } |
| return MessageFormat.format(RefactoringMessages.LaunchConfigurationBuildfileChange_2, new Object[] { fLaunchConfiguration.getName() }); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ltk.core.refactoring.Change#initializeValidationData(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| @Override |
| public void initializeValidationData(IProgressMonitor pm) { |
| // do nothing |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ltk.core.refactoring.Change#isValid(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| @Override |
| public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException, OperationCanceledException { |
| if (fLaunchConfiguration.exists()) { |
| String buildFileLocation = fLaunchConfiguration.getAttribute(IExternalToolConstants.ATTR_LOCATION, IAntCoreConstants.EMPTY_STRING); |
| if (fOldBuildfileLocation == null |
| || (buildFileLocation.endsWith(fOldBuildfileLocation + '}') || buildFileLocation.endsWith(fOldBuildfileLocation))) { |
| String projectName = fLaunchConfiguration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null); |
| if (fOldProjectName.equals(projectName)) { |
| return new RefactoringStatus(); |
| } |
| return RefactoringStatus.createWarningStatus(MessageFormat.format(RefactoringMessages.LaunchConfigurationBuildfileChange_4, new Object[] { |
| fLaunchConfiguration.getName(), fOldProjectName })); |
| } |
| return RefactoringStatus.createWarningStatus(MessageFormat.format(RefactoringMessages.LaunchConfigurationBuildfileChange_5, new Object[] { |
| fLaunchConfiguration.getName(), fOldBuildfileLocation })); |
| } |
| return RefactoringStatus.createFatalErrorStatus(MessageFormat.format(RefactoringMessages.LaunchConfigurationBuildfileChange_6, new Object[] { fLaunchConfiguration.getName() })); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ltk.core.refactoring.Change#perform(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| @Override |
| public Change perform(IProgressMonitor pm) throws CoreException { |
| if (fNewConfigContainerName != null) { |
| IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| IWorkspaceRoot root = workspace.getRoot(); |
| IProject project = root.getProject(fNewProjectName); |
| IContainer container = (IContainer) project.findMember(fNewConfigContainerName); |
| fNewLaunchConfiguration.setContainer(container); |
| } |
| |
| String oldBuildfileLocation = fNewLaunchConfiguration.getAttribute(IExternalToolConstants.ATTR_LOCATION, IAntCoreConstants.EMPTY_STRING); |
| String oldProjectName; |
| if (fNewBuildfileLocation != null) { |
| String newBuildFileLocation = oldBuildfileLocation.replaceFirst(fOldBuildfileLocation, fNewBuildfileLocation); |
| fNewLaunchConfiguration.setAttribute(IExternalToolConstants.ATTR_LOCATION, newBuildFileLocation); |
| fNewLaunchConfiguration.setMappedResources(new IResource[] { getAssociatedFile(newBuildFileLocation) }); |
| } |
| if (fNewProjectName != null) { |
| oldProjectName = fOldProjectName; |
| fNewLaunchConfiguration.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, fNewProjectName); |
| String newBuildFileLocation = oldBuildfileLocation.replaceFirst(oldProjectName, fNewProjectName); |
| fNewLaunchConfiguration.setAttribute(IExternalToolConstants.ATTR_LOCATION, newBuildFileLocation); |
| fNewLaunchConfiguration.setMappedResources(new IResource[] { getAssociatedFile(newBuildFileLocation) }); |
| String launchConfigurationName = fLaunchConfiguration.getName(); |
| fNewLaunchConfigurationName = launchConfigurationName.replaceFirst(oldProjectName, fNewProjectName); |
| if (launchConfigurationName.equals(fNewLaunchConfigurationName) |
| || DebugPlugin.getDefault().getLaunchManager().isExistingLaunchConfigurationName(fNewLaunchConfigurationName)) { |
| fNewLaunchConfigurationName = null; |
| } |
| } else { |
| oldProjectName = null; |
| } |
| if (fNewLaunchConfigurationName != null) { |
| fNewLaunchConfiguration.rename(fNewLaunchConfigurationName); |
| } |
| |
| fNewLaunchConfiguration.doSave(); |
| |
| // create the undo change |
| return new LaunchConfigurationBuildfileChange(fNewLaunchConfiguration, fNewBuildfileLocation, fOldBuildfileLocation, oldProjectName, true); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ltk.core.refactoring.Change#getModifiedElement() |
| */ |
| @Override |
| public Object getModifiedElement() { |
| return fLaunchConfiguration; |
| } |
| |
| private IFile getAssociatedFile(String location) { |
| IFile file = null; |
| IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager(); |
| try { |
| String expandedLocation = manager.performStringSubstitution(location); |
| if (expandedLocation != null) { |
| file = AntUtil.getFileForLocation(expandedLocation, null); |
| } |
| } |
| catch (CoreException e) { |
| // do nothing |
| } |
| return file; |
| } |
| } |