| /******************************************************************************* |
| * Copyright (c) 2000, 2018 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.core.externaltools.internal.registry; |
| |
| |
| import java.util.ArrayList; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| |
| import org.eclipse.core.externaltools.internal.ExternalToolsCore; |
| import org.eclipse.core.externaltools.internal.IExternalToolConstants; |
| import org.eclipse.core.runtime.CoreException; |
| 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.core.RefreshUtil; |
| |
| |
| /** |
| * Responsible reading an old external tool format and creating |
| * and migrating it to create a new external tool. |
| */ |
| public final class ExternalToolMigration { |
| /** |
| * Structure to represent a variable definition within a |
| * source string. |
| */ |
| public static final class VariableDefinition { |
| /** |
| * Index in the source text where the variable started |
| * or <code>-1</code> if no valid variable start tag |
| * identifier found. |
| */ |
| public int start = -1; |
| |
| /** |
| * Index in the source text of the character following |
| * the end of the variable or <code>-1</code> if no |
| * valid variable end tag found. |
| */ |
| public int end = -1; |
| |
| /** |
| * The variable's name found in the source text, or |
| * <code>null</code> if no valid variable found. |
| */ |
| public String name = null; |
| |
| /** |
| * The variable's argument found in the source text, or |
| * <code>null</code> if no valid variable found or if |
| * the variable did not specify an argument |
| */ |
| public String argument = null; |
| |
| /** |
| * Create an initialized variable definition. |
| */ |
| private VariableDefinition() { |
| super(); |
| } |
| } |
| |
| /** |
| * Variable tag indentifiers |
| */ |
| private static final String VAR_TAG_START = "${"; //$NON-NLS-1$ |
| private static final String VAR_TAG_END = "}"; //$NON-NLS-1$ |
| private static final String VAR_TAG_SEP = ":"; //$NON-NLS-1$ |
| |
| /** |
| * External tool type for Ant build files (value <code>antBuildType</code>). |
| */ |
| public static final String TOOL_TYPE_ANT_BUILD = "antBuildType"; //$NON-NLS-1$; |
| /** |
| * Ant builder launch configuration type identifier. Ant project builders |
| * are of this type. |
| */ |
| public static final String ID_ANT_BUILDER_LAUNCH_CONFIGURATION_TYPE = "org.eclipse.ant.AntBuilderLaunchConfigurationType"; //$NON-NLS-1$ |
| |
| public static final String RUN_TARGETS_ATTRIBUTE = TOOL_TYPE_ANT_BUILD + ".runTargets"; //$NON-NLS-1$; |
| |
| /** |
| * String attribute indicating the Ant targets to execute. Default value is |
| * <code>null</code> which indicates that the default target is to be |
| * executed. Format is a comma separated listing of targets. |
| * NOTE: This value is copied here from org.eclipse.ant.ui.internal.IAntLaunchConfigurationConstants. |
| * Ant no longer resides in External Tools and this plug-in. This value is kept here only |
| * for migration. |
| */ |
| public static final String ATTR_ANT_TARGETS = IExternalToolConstants.UI_PLUGIN_ID + ".ATTR_ANT_TARGETS"; //$NON-NLS-1$ |
| |
| /* |
| * 2.0 External Tool Tags |
| */ |
| public static final String TAG_TOOL_TYPE = "!{tool_type}"; //$NON-NLS-1$ |
| public static final String TAG_TOOL_NAME = "!{tool_name}"; //$NON-NLS-1$ |
| public static final String TAG_TOOL_LOCATION = "!{tool_loc}"; //$NON-NLS-1$ |
| public static final String TAG_TOOL_ARGUMENTS = "!{tool_args}"; //$NON-NLS-1$ |
| public static final String TAG_TOOL_DIRECTORY = "!{tool_dir}"; //$NON-NLS-1$ |
| public static final String TAG_TOOL_REFRESH = "!{tool_refresh}"; //$NON-NLS-1$ |
| public static final String TAG_TOOL_SHOW_LOG = "!{tool_show_log}"; //$NON-NLS-1$ |
| public static final String TAG_TOOL_BUILD_TYPES = "!{tool_build_types}"; //$NON-NLS-1$ |
| public static final String TAG_TOOL_BLOCK = "!{tool_block}"; //$NON-NLS-1$ |
| |
| // Known kind of tools |
| private static final String TOOL_TYPE_ANT = "org.eclipse.ui.externaltools.type.ant"; //$NON-NLS-1$ |
| private static final String TOOL_TYPE_PROGRAM = "org.eclipse.ui.externaltools.type.program"; //$NON-NLS-1$ |
| |
| /* |
| * 2.1 External Tool Keys |
| */ |
| public static final String TAG_TYPE = "type"; //$NON-NLS-1$ |
| public static final String TAG_NAME = "name"; //$NON-NLS-1$ |
| public static final String TAG_LOCATION = "location"; //$NON-NLS-1$ |
| public static final String TAG_WORK_DIR = "workDirectory"; //$NON-NLS-1$ |
| public static final String TAG_CAPTURE_OUTPUT = "captureOutput"; //$NON-NLS-1$ |
| public static final String TAG_SHOW_CONSOLE = "showConsole"; //$NON-NLS-1$ |
| public static final String TAG_RUN_BKGRND = "runInBackground"; //$NON-NLS-1$ |
| public static final String TAG_PROMPT_ARGS = "promptForArguments"; //$NON-NLS-1$ |
| public static final String TAG_ARGS = "arguments"; //$NON-NLS-1$ |
| public static final String TAG_REFRESH_SCOPE = "refreshScope"; //$NON-NLS-1$ |
| public static final String TAG_REFRESH_RECURSIVE = "refreshRecursive"; //$NON-NLS-1$ |
| public static final String TAG_RUN_BUILD_KINDS = "runForBuildKinds"; //$NON-NLS-1$ |
| public static final String TAG_EXTRA_ATTR = "extraAttribute"; //$NON-NLS-1$ |
| public static final String TAG_VERSION = "version"; //$NON-NLS-1$ |
| |
| private static final String EXTRA_ATTR_SEPARATOR = "="; //$NON-NLS-1$ |
| |
| private static final String VERSION_21 = "2.1"; //$NON-NLS-1$; |
| |
| private static final String TRUE = "true"; //$NON-NLS-1$ |
| private static final String FALSE = "false"; //$NON-NLS-1$ |
| |
| /** |
| * Allows no instances. |
| */ |
| private ExternalToolMigration() { |
| super(); |
| } |
| |
| /** |
| * Returns a launch configuration working copy from the argument map or |
| * <code>null</code> if the given map cannot be interpreted as a 2.0 or 2.1 |
| * branch external tool. The returned working copy will be unsaved and its |
| * location will be set to the metadata area. |
| */ |
| public static ILaunchConfigurationWorkingCopy configFromArgumentMap(Map<String, String> args) { |
| String version = args.get(TAG_VERSION); |
| if (VERSION_21.equals(version)) { |
| return configFrom21ArgumentMap(args); |
| } |
| return configFrom20ArgumentMap(args); |
| } |
| |
| public static ILaunchConfigurationWorkingCopy configFrom21ArgumentMap(Map<String, String> commandArgs) { |
| String name = commandArgs.get(TAG_NAME); |
| String type = commandArgs.get(TAG_TYPE); |
| |
| ILaunchConfigurationWorkingCopy config = newConfig(type, name); |
| if (config == null) { |
| return null; |
| } |
| |
| config.setAttribute(IExternalToolConstants.ATTR_LOCATION, commandArgs.get(TAG_LOCATION)); |
| config.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, commandArgs.get(TAG_WORK_DIR)); |
| config.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, TRUE.equals(commandArgs.get(TAG_CAPTURE_OUTPUT))); |
| config.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, TRUE.equals(commandArgs.get(TAG_SHOW_CONSOLE))); |
| config.setAttribute(IExternalToolConstants.ATTR_LAUNCH_IN_BACKGROUND, TRUE.equals(commandArgs.get(TAG_RUN_BKGRND))); |
| config.setAttribute(IExternalToolConstants.ATTR_PROMPT_FOR_ARGUMENTS, TRUE.equals(commandArgs.get(TAG_PROMPT_ARGS))); |
| config.setAttribute(RefreshUtil.ATTR_REFRESH_SCOPE, commandArgs.get(TAG_REFRESH_SCOPE)); |
| config.setAttribute(RefreshUtil.ATTR_REFRESH_RECURSIVE, TRUE.equals(commandArgs.get(TAG_REFRESH_RECURSIVE))); |
| |
| config.setAttribute(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, commandArgs.get(TAG_RUN_BUILD_KINDS)); |
| |
| String args = commandArgs.get(TAG_ARGS); |
| if (args != null) { |
| config.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, args); |
| } |
| |
| String extraAttributes = commandArgs.get(TAG_EXTRA_ATTR); |
| if (extraAttributes != null) { |
| StringTokenizer tokenizer = new StringTokenizer(extraAttributes, EXTRA_ATTR_SEPARATOR); |
| while (tokenizer.hasMoreTokens()) { |
| String key = tokenizer.nextToken(); |
| if (!tokenizer.hasMoreTokens()) { |
| break; |
| } |
| String value = tokenizer.nextToken(); |
| if (key.equals(RUN_TARGETS_ATTRIBUTE)) { |
| // 2.1 implementation only defined 1 "extra attribute" |
| config.setAttribute(ATTR_ANT_TARGETS, value); |
| } |
| } |
| } |
| return config; |
| } |
| |
| /** |
| * Creates an external tool from the map. |
| */ |
| public static ILaunchConfigurationWorkingCopy configFrom20ArgumentMap(Map<String, String> args) { |
| // Update the type... |
| String type = args.get(TAG_TOOL_TYPE); |
| if (TOOL_TYPE_ANT.equals(type)) { |
| type = TOOL_TYPE_ANT_BUILD; |
| } else if (TOOL_TYPE_PROGRAM.equals(type)){ |
| type = IExternalToolConstants.TOOL_TYPE_PROGRAM; |
| } else { |
| return null; |
| } |
| |
| String name = args.get(TAG_TOOL_NAME); |
| |
| ILaunchConfigurationWorkingCopy config = newConfig(type, name); |
| if (config == null) { |
| return null; |
| } |
| |
| // Update the location... |
| String location = args.get(TAG_TOOL_LOCATION); |
| config.setAttribute(IExternalToolConstants.ATTR_LOCATION, location); |
| |
| // Update the refresh scope... |
| String refresh = args.get(TAG_TOOL_REFRESH); |
| if (refresh != null) { |
| VariableDefinition varDef = extractVariableDefinition(refresh, 0); |
| if ("none".equals(varDef.name)) { //$NON-NLS-1$ |
| refresh = null; |
| } |
| config.setAttribute(RefreshUtil.ATTR_REFRESH_SCOPE, refresh); |
| } |
| |
| // Update the arguments |
| String arguments = args.get(TAG_TOOL_ARGUMENTS); |
| if (type.equals(TOOL_TYPE_ANT_BUILD)) { |
| String targetNames = null; |
| if (arguments != null) { |
| int start = 0; |
| ArrayList<String> targets = new ArrayList<>(); |
| StringBuilder buffer = new StringBuilder(); |
| VariableDefinition varDef = extractVariableDefinition(arguments, start); |
| while (varDef.end != -1) { |
| if ("ant_target".equals(varDef.name) && varDef.argument != null) { //$NON-NLS-1$ |
| targets.add(varDef.argument); |
| buffer.append(arguments.substring(start, varDef.start)); |
| } else { |
| buffer.append(arguments.substring(start, varDef.end)); |
| } |
| start = varDef.end; |
| varDef = extractVariableDefinition(arguments, start); |
| } |
| buffer.append(arguments.substring(start, arguments.length())); |
| arguments = buffer.toString(); |
| |
| buffer.setLength(0); |
| for (int i = 0; i < targets.size(); i++) { |
| String target = targets.get(i); |
| if (target != null && target.length() > 0) { |
| buffer.append(target); |
| buffer.append(","); //$NON-NLS-1$ |
| } |
| } |
| targetNames = buffer.toString(); |
| } |
| if (targetNames != null && targetNames.length() > 0) { |
| config.setAttribute(ATTR_ANT_TARGETS, targetNames); |
| } |
| } |
| config.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, arguments); |
| |
| // Collect the rest of the information |
| config.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, TRUE.equals(args.get(TAG_TOOL_SHOW_LOG))); |
| config.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, TRUE.equals(args.get(TAG_TOOL_SHOW_LOG))); |
| config.setAttribute(IExternalToolConstants.ATTR_LAUNCH_IN_BACKGROUND, FALSE.equals(args.get(TAG_TOOL_BLOCK))); |
| String buildKinds= args.get(TAG_TOOL_BUILD_TYPES); |
| if (buildKinds != null) { |
| buildKinds= buildKinds.replace(';', ','); // Replace the old separator with the new |
| } |
| config.setAttribute(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, buildKinds); |
| config.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, args.get(TAG_TOOL_DIRECTORY)); |
| return config; |
| } |
| |
| /** |
| * Returns a new working copy with the given external tool name and external |
| * tool type or <code>null</code> if no config could be created. |
| */ |
| private static ILaunchConfigurationWorkingCopy newConfig(String type, String name) { |
| if (type == null || name == null) { |
| return null; |
| } |
| ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); |
| ILaunchConfigurationType configType; |
| if (TOOL_TYPE_ANT_BUILD.equals(type)) { |
| configType = manager.getLaunchConfigurationType(ID_ANT_BUILDER_LAUNCH_CONFIGURATION_TYPE); |
| } else if (IExternalToolConstants.TOOL_TYPE_PROGRAM.equals(type)) { |
| configType = manager.getLaunchConfigurationType(IExternalToolConstants.ID_PROGRAM_BUILDER_LAUNCH_CONFIGURATION_TYPE); |
| } else { |
| return null; |
| } |
| try { |
| if (configType != null) { |
| return configType.newInstance(null, name); |
| } |
| } catch (CoreException e) { |
| ExternalToolsCore.log(e); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the tool name extracted from the given command argument map. |
| * Extraction is attempted using 2.0 and 2.1 external tool formats. |
| */ |
| public static String getNameFromCommandArgs(Map<String, String> commandArgs) { |
| String name= commandArgs.get(TAG_NAME); |
| if (name == null) { |
| name= commandArgs.get(TAG_TOOL_NAME); |
| } |
| return name; |
| } |
| |
| /** |
| * Migrate the old RUN_IN_BACKGROUND launch config attribute to the new |
| * LAUNCH_IN_BACKGROUND attribute provided by the debug ui plugin. |
| * |
| * @param config the config to migrate |
| * @return the migrated config |
| */ |
| public static ILaunchConfiguration migrateRunInBackground(ILaunchConfiguration config) { |
| String noValueFlag= "NoValue"; //$NON-NLS-1$ |
| String attr= null; |
| try { |
| attr = config.getAttribute(IExternalToolConstants.ATTR_LAUNCH_IN_BACKGROUND, noValueFlag); |
| } catch (CoreException e) { |
| // Exception will occur if the attribute is already set because the attribute is actually a boolean. |
| // No migration necessary. |
| return config; |
| } |
| if (noValueFlag.equals(attr)) { |
| //the old constant |
| String ATTR_RUN_IN_BACKGROUND= IExternalToolConstants.UI_PLUGIN_ID + ".ATTR_RUN_IN_BACKGROUND"; //$NON-NLS-1$ |
| boolean runInBackground= false; |
| try { |
| runInBackground = config.getAttribute(ATTR_RUN_IN_BACKGROUND, runInBackground); |
| } catch (CoreException e) { |
| ExternalToolsCore.log(ExternalToolsMigrationMessages.ExternalToolMigration_37, e); |
| } |
| try { |
| ILaunchConfigurationWorkingCopy workingCopy= config.getWorkingCopy(); |
| workingCopy.setAttribute(IExternalToolConstants.ATTR_LAUNCH_IN_BACKGROUND, runInBackground); |
| return workingCopy.doSave(); |
| } catch (CoreException e) { |
| ExternalToolsCore.log(ExternalToolsMigrationMessages.ExternalToolMigration_38, e); |
| } |
| } |
| return config; |
| } |
| |
| /** |
| * Extracts a variable name and argument from the given string. |
| * |
| * @param text the source text to parse for a variable tag |
| * @param start the index in the string to start the search |
| * @return the variable definition |
| */ |
| public static VariableDefinition extractVariableDefinition(String text, int start) { |
| VariableDefinition varDef = new VariableDefinition(); |
| int strt = start; |
| varDef.start = text.indexOf(VAR_TAG_START, strt); |
| if (varDef.start < 0){ |
| return varDef; |
| } |
| strt = varDef.start + VAR_TAG_START.length(); |
| |
| int end = text.indexOf(VAR_TAG_END, strt); |
| if (end < 0) { |
| return varDef; |
| } |
| varDef.end = end + VAR_TAG_END.length(); |
| if (end == strt) { |
| return varDef; |
| } |
| |
| int mid = text.indexOf(VAR_TAG_SEP, strt); |
| if (mid < 0 || mid > end) { |
| varDef.name = text.substring(strt, end); |
| } else { |
| if (mid > strt) { |
| varDef.name = text.substring(strt, mid); |
| } |
| mid = mid + VAR_TAG_SEP.length(); |
| if (mid < end) { |
| varDef.argument = text.substring(mid, end); |
| } |
| } |
| |
| return varDef; |
| } |
| } |