| /******************************************************************************* |
| * Copyright (c) 2000, 2007 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 |
| * John-Mason P. Shackelford - bug 34548 |
| *******************************************************************************/ |
| package org.eclipse.ant.internal.ui.launchConfigurations; |
| |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.ant.internal.ui.AntUIPlugin; |
| import org.eclipse.ant.internal.ui.AntUtil; |
| import org.eclipse.ant.internal.ui.IAntUIConstants; |
| import org.eclipse.ant.internal.ui.IAntUIPreferenceConstants; |
| import org.eclipse.ant.internal.ui.model.AntElementNode; |
| import org.eclipse.ant.internal.ui.model.AntProjectNode; |
| import org.eclipse.ant.internal.ui.model.AntTargetNode; |
| import org.eclipse.ant.internal.ui.model.AntTaskNode; |
| 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.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| 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.debug.ui.CommonTab; |
| import org.eclipse.debug.ui.DebugUITools; |
| import org.eclipse.debug.ui.IDebugUIConstants; |
| import org.eclipse.debug.ui.ILaunchShortcut; |
| import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; |
| import org.eclipse.jface.dialogs.ErrorDialog; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.viewers.ILabelProvider; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.dialogs.ElementListSelectionDialog; |
| import org.eclipse.ui.editors.text.ILocationProvider; |
| import org.eclipse.ui.externaltools.internal.launchConfigurations.ExternalToolsUtil; |
| import org.eclipse.ui.externaltools.internal.model.IExternalToolConstants; |
| |
| import com.ibm.icu.text.MessageFormat; |
| |
| |
| public class AntLaunchShortcut implements ILaunchShortcut { |
| |
| private boolean fShowDialog= false; |
| private static final int MAX_TARGET_APPEND_LENGTH = 30; |
| |
| /** |
| * Constructor for AntLaunchShortcut. |
| */ |
| public AntLaunchShortcut() { |
| super(); |
| } |
| |
| /** |
| * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.jface.viewers.ISelection, java.lang.String) |
| */ |
| public void launch(ISelection selection, String mode) { |
| if (selection instanceof IStructuredSelection) { |
| IStructuredSelection structuredSelection = (IStructuredSelection)selection; |
| Object object = structuredSelection.getFirstElement(); |
| if (object instanceof IAdaptable) { |
| IResource resource = (IResource)((IAdaptable)object).getAdapter(IResource.class); |
| if (resource != null) { |
| launch(resource, mode); |
| return; |
| } else if (object instanceof AntElementNode){ |
| launch((AntElementNode) object, mode); |
| return; |
| } |
| } |
| } |
| antFileNotFound(); |
| } |
| |
| /** |
| * Launches the given Ant node. |
| * <ul><li>AntProjectNodes: the default target is executed</li> |
| * <li>AntTargetNodes: that target is executed</li> |
| * <li>AntTaskNodes: the owning target is executed</li> |
| * </ul> |
| * @param node the Ant node to use as the context for the launch |
| * @param mode the mode of the launch |
| */ |
| public void launch(AntElementNode node, String mode) { |
| String selectedTargetName= null; |
| if (node instanceof AntTargetNode) { |
| AntTargetNode targetNode= (AntTargetNode) node; |
| if (targetNode.isDefaultTarget()) { |
| selectedTargetName= ""; //$NON-NLS-1$ |
| } else { |
| selectedTargetName= targetNode.getTarget().getName(); |
| } |
| } else if (node instanceof AntProjectNode) { |
| selectedTargetName = ""; //$NON-NLS-1$ |
| } else if (node instanceof AntTaskNode) { |
| AntTaskNode taskNode= (AntTaskNode) node; |
| selectedTargetName= taskNode.getTask().getOwningTarget().getName(); |
| } |
| |
| if (selectedTargetName == null) { |
| return; |
| } |
| IFile file= node.getBuildFileResource(); |
| if (file != null) { |
| launch(file, mode, selectedTargetName); |
| return; |
| } |
| //external buildfile |
| IPath filePath= getExternalBuildFilePath(); |
| if (filePath != null) { |
| launch(filePath, mode, selectedTargetName); |
| return; |
| } |
| |
| antFileNotFound(); |
| } |
| |
| private IPath getExternalBuildFilePath() { |
| IWorkbenchPage page= AntUIPlugin.getActiveWorkbenchWindow().getActivePage(); |
| IPath filePath= null; |
| IEditorPart editor= page.getActiveEditor(); |
| if (editor != null) { |
| IEditorInput editorInput= editor.getEditorInput(); |
| ILocationProvider locationProvider= (ILocationProvider)editorInput.getAdapter(ILocationProvider.class); |
| if (locationProvider != null) { |
| filePath= locationProvider.getPath(editorInput); |
| } |
| } |
| return filePath; |
| } |
| |
| /** |
| * Inform the user that an ant file was not found to run. |
| */ |
| private void antFileNotFound() { |
| reportError(AntLaunchConfigurationMessages.AntLaunchShortcut_Unable, null); |
| } |
| |
| /** |
| * Launch the given file in the specified mode. |
| * |
| * @param resource either a build file (*.xml file) to execute or a resource |
| * from whose location a build file should be searched for. If the given |
| * resource is a file that does not end in ".xml", a search will begin at |
| * the resource's enclosing folder. The given resource must be of type IFile |
| * or IContainer. |
| * @param mode the mode in which the build file should be executed |
| */ |
| protected void launch(IResource resource, String mode) { |
| if (!("xml".equalsIgnoreCase(resource.getFileExtension()))) { //$NON-NLS-1$ |
| if (resource.getType() == IResource.FILE) { |
| resource= resource.getParent(); |
| } |
| resource= findBuildFile((IContainer)resource); |
| } |
| if (resource != null) { |
| launch((IFile)resource, mode, null); |
| } else { |
| antFileNotFound(); |
| } |
| } |
| |
| /** |
| * Launch the given targets in the given build file. The targets are |
| * launched in the given mode. |
| * |
| * @param file the build file to launch |
| * @param mode the mode in which the build file should be executed |
| * @param targetAttribute the targets to launch, in the form of the launch |
| * configuration targets attribute. |
| */ |
| public void launch(IFile file, String mode, String targetAttribute) { |
| ILaunchConfiguration configuration= null; |
| |
| List configurations = findExistingLaunchConfigurations(file); |
| if (configurations.isEmpty()) { |
| configuration = createDefaultLaunchConfiguration(file); |
| } else { |
| if (configurations.size() == 1) { |
| configuration= (ILaunchConfiguration)configurations.get(0); |
| } else { |
| configuration= chooseConfig(configurations); |
| if (configuration == null) { |
| // User cancelled selection |
| return; |
| } |
| } |
| } |
| |
| if (configuration == null) { |
| antFileNotFound(); |
| } |
| // ensure that the targets are selected in the launch configuration |
| try { |
| if (targetAttribute != null && ! targetAttribute.equals(configuration.getAttribute(IAntLaunchConfigurationConstants.ATTR_ANT_TARGETS, ""))) { //$NON-NLS-1$ |
| String projectName= null; |
| try { |
| projectName= configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null); |
| } catch (CoreException e) { |
| } |
| String newName= getNewLaunchConfigurationName(file.getFullPath(), projectName, targetAttribute); |
| configuration= configuration.copy(newName); |
| ((ILaunchConfigurationWorkingCopy) configuration).setAttribute(IAntLaunchConfigurationConstants.ATTR_ANT_TARGETS, targetAttribute); |
| if (fShowDialog) { |
| configuration= ((ILaunchConfigurationWorkingCopy) configuration).doSave(); |
| } |
| } |
| } catch (CoreException exception) { |
| reportError(MessageFormat.format(AntLaunchConfigurationMessages.AntLaunchShortcut_Exception_launching, new String[] {file.getName()}), exception); |
| return; |
| } |
| launch(mode, configuration); |
| } |
| |
| /** |
| * Returns a unique name for a copy of the given launch configuration with the given |
| * targets. The name seed is the same as the name for a new launch configuration with |
| * " [targetList]" appended to the end. |
| * @param filePath the path to the buildfile |
| * @param projectName the name of the project containing the buildfile or <code>null</code> if no project is known |
| * @param targetAttribute the listing of targets to execute or <code>null</code> for default target execution |
| * @return a unique name for the copy |
| */ |
| public static String getNewLaunchConfigurationName(IPath filePath, String projectName, String targetAttribute) { |
| StringBuffer buffer = new StringBuffer(); |
| if (projectName != null) { |
| buffer.append(projectName); |
| buffer.append(' '); |
| buffer.append(filePath.lastSegment()); |
| } else { |
| buffer.append(filePath.lastSegment()); |
| } |
| |
| if (targetAttribute != null) { |
| buffer.append(" ["); //$NON-NLS-1$ |
| if (targetAttribute.length() > MAX_TARGET_APPEND_LENGTH + 3) { |
| // The target attribute can potentially be a long, comma-separated list |
| // of target. Make sure the generated name isn't extremely long. |
| buffer.append(targetAttribute.substring(0, MAX_TARGET_APPEND_LENGTH)); |
| buffer.append("..."); //$NON-NLS-1$ |
| } else { |
| buffer.append(targetAttribute); |
| } |
| buffer.append(']'); |
| } |
| |
| String name= DebugPlugin.getDefault().getLaunchManager().generateUniqueLaunchConfigurationNameFrom(buffer.toString()); |
| return name; |
| } |
| |
| /** |
| * Launch the given targets in the given build file. The targets are |
| * launched in the given mode. |
| * |
| * @param filePath the path to the build file to launch |
| * @param mode the mode in which the build file should be executed |
| * @param targetAttribute the targets to launch, in the form of the launch |
| * configuration targets attribute. |
| */ |
| public void launch(IPath filePath, String mode, String targetAttribute) { |
| ILaunchConfiguration configuration= null; |
| |
| List configurations = findExistingLaunchConfigurations(filePath); |
| if (configurations.isEmpty()) { |
| configuration = createDefaultLaunchConfiguration(filePath, null); |
| } else { |
| if (configurations.size() == 1) { |
| configuration= (ILaunchConfiguration)configurations.get(0); |
| } else { |
| configuration= chooseConfig(configurations); |
| if (configuration == null) { |
| // User cancelled selection |
| return; |
| } |
| } |
| } |
| |
| if (configuration == null) { |
| antFileNotFound(); |
| } |
| // ensure that the targets are selected in the launch configuration |
| try { |
| if (targetAttribute != null && ! targetAttribute.equals(configuration.getAttribute(IAntLaunchConfigurationConstants.ATTR_ANT_TARGETS, ""))) { //$NON-NLS-1$ |
| String projectName= null; |
| try { |
| projectName= configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null); |
| } catch (CoreException e) { |
| } |
| String newName= getNewLaunchConfigurationName(filePath, projectName, targetAttribute); |
| configuration= configuration.copy(newName); |
| ((ILaunchConfigurationWorkingCopy) configuration).setAttribute(IAntLaunchConfigurationConstants.ATTR_ANT_TARGETS, targetAttribute); |
| if (fShowDialog) { |
| configuration= ((ILaunchConfigurationWorkingCopy) configuration).doSave(); |
| } |
| } |
| } catch (CoreException exception) { |
| reportError(MessageFormat.format(AntLaunchConfigurationMessages.AntLaunchShortcut_Exception_launching, new String[] {filePath.toFile().getName()}), exception); |
| return; |
| } |
| launch(mode, configuration); |
| } |
| |
| private void launch(String mode, ILaunchConfiguration configuration) { |
| if (fShowDialog) { |
| // Offer to save dirty editors before opening the dialog as the contents |
| // of an Ant editor often affect the contents of the dialog. |
| if (!DebugUITools.saveBeforeLaunch()) { |
| return; |
| } |
| IStatus status = new Status(IStatus.INFO, IAntUIConstants.PLUGIN_ID, IAntUIConstants.STATUS_INIT_RUN_ANT, "", null); //$NON-NLS-1$ |
| String groupId; |
| if (mode.equals(ILaunchManager.DEBUG_MODE)) { |
| groupId= IDebugUIConstants.ID_DEBUG_LAUNCH_GROUP; |
| } else { |
| groupId= IExternalToolConstants.ID_EXTERNAL_TOOLS_LAUNCH_GROUP; |
| } |
| DebugUITools.openLaunchConfigurationDialog(AntUIPlugin.getActiveWorkbenchWindow().getShell(), configuration, groupId, status); |
| } else { |
| DebugUITools.launch(configuration, mode); |
| } |
| } |
| |
| /** |
| * Walks the file hierarchy looking for a build file. |
| * Returns the first build file found that matches the |
| * search criteria. |
| */ |
| private IFile findBuildFile(IContainer parent) { |
| String[] names= getBuildFileNames(); |
| if (names == null) { |
| return null; |
| } |
| IResource file= null; |
| while (file == null || file.getType() != IResource.FILE) { |
| for (int i = 0; i < names.length; i++) { |
| String string = names[i]; |
| file= parent.findMember(string); |
| if (file != null && file.getType() == IResource.FILE) { |
| break; |
| } |
| } |
| parent = parent.getParent(); |
| if (parent == null) { |
| return null; |
| } |
| } |
| return (IFile)file; |
| } |
| |
| private String[] getBuildFileNames() { |
| IPreferenceStore prefs= AntUIPlugin.getDefault().getPreferenceStore(); |
| String buildFileNames= prefs.getString(IAntUIPreferenceConstants.ANT_FIND_BUILD_FILE_NAMES); |
| if (buildFileNames.length() == 0) { |
| //the user has not specified any names to look for |
| return null; |
| } |
| return AntUtil.parseString(buildFileNames, ","); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Creates and returns a default launch configuration for the given file. |
| * |
| * @param file |
| * @return default launch configuration |
| */ |
| public static ILaunchConfiguration createDefaultLaunchConfiguration(IFile file) { |
| return createDefaultLaunchConfiguration(file.getFullPath(), file.getProject()); |
| } |
| |
| /** |
| * Creates and returns a default launch configuration for the given file path |
| * and project. |
| * |
| * @param filePath the path to the buildfile |
| * @param project the project containing the buildfile or <code>null</code> if the |
| * buildfile is not contained in a project (is external). |
| * @return default launch configuration or <code>null</code> if one could not be created |
| */ |
| public static ILaunchConfiguration createDefaultLaunchConfiguration(IPath filePath, IProject project) { |
| ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); |
| ILaunchConfigurationType type = manager.getLaunchConfigurationType(IAntLaunchConfigurationConstants.ID_ANT_LAUNCH_CONFIGURATION_TYPE); |
| |
| String projectName= project != null ? project.getName() : null; |
| String name = getNewLaunchConfigurationName(filePath, projectName, null); |
| try { |
| ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null, name); |
| if (project != null) { |
| workingCopy.setAttribute(IExternalToolConstants.ATTR_LOCATION, |
| VariablesPlugin.getDefault().getStringVariableManager().generateVariableExpression("workspace_loc", filePath.toString())); //$NON-NLS-1$ |
| } else { |
| workingCopy.setAttribute(IExternalToolConstants.ATTR_LOCATION, filePath.toString()); |
| } |
| workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH_PROVIDER, "org.eclipse.ant.ui.AntClasspathProvider"); //$NON-NLS-1$ |
| // set default for common settings |
| CommonTab tab = new CommonTab(); |
| tab.setDefaults(workingCopy); |
| tab.dispose(); |
| |
| //set the project name so that the correct default VM install can be determined |
| if (project != null) { |
| workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getName()); |
| } |
| AntJRETab jreTab = new AntJRETab(); |
| jreTab.setDefaults(workingCopy); |
| jreTab.dispose(); |
| |
| IFile file= AntUtil.getFileForLocation(filePath.toString(), null); |
| workingCopy.setMappedResources(new IResource[] {file}); |
| |
| return workingCopy.doSave(); |
| } catch (CoreException e) { |
| reportError(MessageFormat.format(AntLaunchConfigurationMessages.AntLaunchShortcut_2, new String[]{filePath.toString()}), e); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns a list of existing launch configuration for the given file. |
| * |
| * @param file the buildfile resource |
| * @return list of launch configurations |
| */ |
| public static List findExistingLaunchConfigurations(IFile file) { |
| IPath filePath = file.getLocation(); |
| return findExistingLaunchConfigurations(filePath); |
| } |
| |
| /** |
| * Returns a list of existing launch configuration for the given file. |
| * |
| * @param filePath the fully qualified path for the buildfile |
| * @return list of launch configurations |
| */ |
| public static List findExistingLaunchConfigurations(IPath filePath) { |
| ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); |
| ILaunchConfigurationType type = manager.getLaunchConfigurationType(IAntLaunchConfigurationConstants.ID_ANT_LAUNCH_CONFIGURATION_TYPE); |
| List validConfigs= new ArrayList(); |
| if (type != null) { |
| ILaunchConfiguration[] configs = null; |
| try { |
| configs = manager.getLaunchConfigurations(type); |
| } catch (CoreException e) { |
| reportError(AntLaunchConfigurationMessages.AntLaunchShortcut_3, e); |
| } |
| if (configs != null && configs.length > 0) { |
| if (filePath == null) { |
| reportError(AntLaunchConfigurationMessages.AntLaunchShortcut_0, null); |
| } else { |
| for (int i = 0; i < configs.length; i++) { |
| ILaunchConfiguration configuration = configs[i]; |
| IPath location; |
| try { |
| location = ExternalToolsUtil.getLocation(configuration); |
| if (filePath.equals(location)) { |
| validConfigs.add(configuration); |
| } |
| } catch (CoreException e) { |
| // error occurred in variable expand - ignore |
| } |
| } |
| } |
| } |
| } |
| return validConfigs; |
| } |
| |
| /** |
| * Prompts the user to choose from the list of given launch configurations |
| * and returns the config the user choose or <code>null</code> if the user |
| * pressed Cancel or if the given list is empty. |
| */ |
| public static ILaunchConfiguration chooseConfig(List configs) { |
| if (configs.isEmpty()) { |
| return null; |
| } |
| ILabelProvider labelProvider = DebugUITools.newDebugModelPresentation(); |
| ElementListSelectionDialog dialog= new ElementListSelectionDialog(Display.getDefault().getActiveShell(), labelProvider); |
| dialog.setElements(configs.toArray(new ILaunchConfiguration[configs.size()])); |
| dialog.setTitle(AntLaunchConfigurationMessages.AntLaunchShortcut_4); |
| dialog.setMessage(AntLaunchConfigurationMessages.AntLaunchShortcut_5); |
| dialog.setMultipleSelection(false); |
| int result = dialog.open(); |
| labelProvider.dispose(); |
| if (result == Window.OK) { |
| return (ILaunchConfiguration) dialog.getFirstResult(); |
| } |
| return null; |
| } |
| |
| /** |
| * @see org.eclipse.debug.ui.ILaunchShortcut#launch(org.eclipse.ui.IEditorPart, java.lang.String) |
| */ |
| public void launch(IEditorPart editor, String mode) { |
| IEditorInput input = editor.getEditorInput(); |
| IFile file = (IFile)input.getAdapter(IFile.class); |
| if (file != null) { |
| launch(file, mode); |
| return; |
| } |
| ILocationProvider locationProvider= (ILocationProvider)input.getAdapter(ILocationProvider.class); |
| if (locationProvider != null) { |
| IPath filePath= locationProvider.getPath(input); |
| if ("xml".equals(filePath.getFileExtension())) { //$NON-NLS-1$ |
| launch(filePath, mode, null); |
| return; |
| } |
| } |
| |
| antFileNotFound(); |
| } |
| |
| protected static void reportError(String message, Throwable throwable) { |
| IStatus status = null; |
| if (throwable instanceof CoreException) { |
| status = ((CoreException)throwable).getStatus(); |
| } else { |
| status = new Status(IStatus.ERROR, IAntUIConstants.PLUGIN_ID, 0, message, throwable); |
| } |
| ErrorDialog.openError(AntUIPlugin.getActiveWorkbenchWindow().getShell(), AntLaunchConfigurationMessages.AntLaunchShortcut_Error_7, AntLaunchConfigurationMessages.AntLaunchShortcut_Build_Failed_2, status); |
| } |
| |
| /** |
| * Sets whether to show the external tools launch configuration dialog |
| * |
| * @param showDialog If true the launch configuration dialog will always be |
| * shown |
| */ |
| public void setShowDialog(boolean showDialog) { |
| fShowDialog = showDialog; |
| } |
| } |