/******************************************************************************* * Copyright (c) 2000, 2013 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 -1 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 -1 if no * valid variable end tag found. */ public int end = -1; /** * The variable's name found in the source text, or * null if no valid variable found. */ public String name = null; /** * The variable's argument found in the source text, or * null 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 antBuildType). */ 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 * null 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 * null 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 args) { String version = args.get(TAG_VERSION); if (VERSION_21.equals(version)) { return configFrom21ArgumentMap(args); } return configFrom20ArgumentMap(args); } public static ILaunchConfigurationWorkingCopy configFrom21ArgumentMap(Map 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 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 targets = new ArrayList(); StringBuffer buffer = new StringBuffer(); 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 null 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 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; } }