| /******************************************************************************* |
| * Copyright (c) 2000, 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Tomasz Stanczak - Fix for Bug 29504 |
| *******************************************************************************/ |
| |
| package org.eclipse.ui.externaltools.internal.model; |
| |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.MultiStatus; |
| import org.eclipse.ui.externaltools.internal.registry.ExternalToolVariable; |
| import org.eclipse.ui.externaltools.internal.registry.ExternalToolVariableRegistry; |
| import org.eclipse.ui.externaltools.internal.variable.ExpandVariableContext; |
| |
| /** |
| * General utility class dealing with external tools |
| */ |
| public final class ToolUtil { |
| /** |
| * Argument parsing constants |
| */ |
| private static final char ARG_DELIMITER = ' '; //$NON-NLS-1$ |
| private static final char ARG_DBL_QUOTE = '"'; //$NON-NLS-1$ |
| |
| /** |
| * Variable tag indentifiers |
| */ |
| private static final char VAR_TAG_START_CHAR1 = '$'; //$NON-NLS-1$ |
| private static final char VAR_TAG_START_CHAR2 = '{'; //$NON-NLS-1$ |
| private static final char VAR_TAG_END_CHAR1 = '}'; //$NON-NLS-1$ |
| 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$ |
| |
| /** |
| * No instances allowed |
| */ |
| private ToolUtil() { |
| super(); |
| } |
| |
| /** |
| * Builds a variable tag that will be auto-expanded before |
| * the tool is run. |
| * |
| * @param varName the name of a known variable (one of the VAR_* constants for instance) |
| * @param varArgument an optional argument for the variable, <code>null</code> if none |
| */ |
| public static String buildVariableTag(String varName, String varArgument) { |
| StringBuffer buf = new StringBuffer(); |
| buildVariableTag(varName,varArgument, buf); |
| return buf.toString(); |
| } |
| |
| /** |
| * Builds a variable tag that will be auto-expanded before |
| * the tool is run. |
| * |
| * @param varName the name of a known variable (one of the VAR_* constants for instance) |
| * @param varArgument an optional argument for the variable, <code>null</code> if none |
| * @param buffer the buffer to write the constructed variable tag |
| */ |
| public static void buildVariableTag(String varName, String varArgument, StringBuffer buffer) { |
| buffer.append(VAR_TAG_START); |
| buffer.append(varName); |
| if (varArgument != null && varArgument.length() > 0) { |
| buffer.append(VAR_TAG_SEP); |
| buffer.append(varArgument); |
| } |
| buffer.append(VAR_TAG_END); |
| } |
| |
| /** |
| * Expands all the variables found in an individual |
| * argument text. |
| * |
| * @param argument one of the argument text in the list of arguments |
| * @param context the context to use for expanding variables |
| * @param status multi status to report any problems expanding variables |
| * @return the argument text with all variables expanded, or <code>null</code> if not possible |
| */ |
| public static String expandArgument(String argument, ExpandVariableContext context, MultiStatus status) { |
| StringBuffer buffer = new StringBuffer(); |
| |
| int start = 0; |
| while (true) { |
| VariableDefinition varDef = extractVariableTag(argument, start); |
| |
| // No more variables found... |
| if (varDef.start == -1) { |
| if (start == 0) |
| buffer.append(argument); |
| else |
| buffer.append(argument.substring(start)); |
| break; |
| } |
| |
| // Invalid variable format |
| if (varDef.end == -1 || varDef.name == null || varDef.name.length() == 0) { |
| String msg = ExternalToolsModelMessages.getString("ToolUtil.argumentVarFormatWrong"); //$NON-NLS-1$ |
| status.merge(ExternalToolsPlugin.newErrorStatus(msg, null)); |
| return null; |
| } |
| |
| // Copy text between start and variable. |
| if (varDef.start > start) |
| buffer.append(argument.substring(start, varDef.start)); |
| start = varDef.end; |
| |
| // Lookup the variable if it exist |
| ExternalToolVariableRegistry registry; |
| registry = ExternalToolsPlugin.getDefault().getToolVariableRegistry(); |
| ExternalToolVariable variable = registry.getVariable(varDef.name); |
| if (variable == null) { |
| String msg = MessageFormat.format(ExternalToolsModelMessages.getString("ToolUtil.argumentVarMissing"), new Object[] {varDef.name}); //$NON-NLS-1$ |
| status.merge(ExternalToolsPlugin.newErrorStatus(msg, null)); |
| return null; |
| } |
| |
| // Expand the variable as text if possible |
| String text = null; |
| try { |
| text= variable.getExpander().getText(varDef.name, varDef.argument, context); |
| } catch (CoreException exception) { |
| status.merge(exception.getStatus()); |
| return null; |
| } |
| buffer.append(text); |
| } |
| |
| return buffer.toString(); |
| } |
| |
| /** |
| * Returns a list of individual arguments where all |
| * variables have been expanded. |
| * |
| * @param arguments the arguments with leading and trailing |
| * spaces already removed. |
| * @param context the context used to expand the variable(s) |
| * @param status multi status to report any problems expanding variables |
| * @return the list of individual arguments where some elements in the |
| * list maybe <code>null</code> if problems expanding variable(s). |
| */ |
| public static String[] expandArguments(String arguments, ExpandVariableContext context, MultiStatus status) { |
| if (arguments == null || arguments.length() == 0) |
| return new String[0]; |
| |
| String[] argList = parseArgumentsIntoList(arguments); |
| for (int i = 0; i < argList.length; i++) |
| argList[i] = expandArgument(argList[i], context, status); |
| |
| return argList; |
| } |
| |
| /** |
| * Returns the expanded directory location if represented by a |
| * directory variable. Otherwise, the directory location given is |
| * return unless an unknown variable was detected. |
| * |
| * @param dirLocation a directory location either as a path or a variable |
| * with leading and trailing spaces already removed. |
| * @param context the context used to expand the variable |
| * @param status multi status to report any problems expanding variables |
| * @return the directory location as a string or <code>null</code> if not possible |
| */ |
| public static String expandDirectoryLocation(String dirLocation, ExpandVariableContext context, MultiStatus status) { |
| if (dirLocation == null || dirLocation.length() == 0) |
| return ""; //$NON-NLS-1$ |
| |
| VariableDefinition varDef = extractVariableTag(dirLocation, 0); |
| // Return if no variable found |
| if (varDef.start < 0) { |
| return dirLocation; |
| } |
| |
| StringBuffer buffer= new StringBuffer(); |
| int start= 0; |
| while (varDef.start >= 0) { |
| // Invalid variable format |
| if (varDef.name == null || varDef.name.length() == 0 || varDef.end == -1) { |
| String msg = ExternalToolsModelMessages.getString("ToolUtil.dirLocVarFormatWrong"); //$NON-NLS-1$ |
| status.merge(ExternalToolsPlugin.newErrorStatus(msg, null)); |
| return null; |
| } |
| |
| // Append text before the variable |
| buffer.append(dirLocation.substring(start, varDef.start)); |
| |
| // Lookup the variable if it exist |
| ExternalToolVariableRegistry registry; |
| registry = ExternalToolsPlugin.getDefault().getToolVariableRegistry(); |
| ExternalToolVariable variable = registry.getVariable(varDef.name); |
| if (variable == null) { |
| String msg = MessageFormat.format(ExternalToolsModelMessages.getString("ToolUtil.dirLocVarMissing"), new Object[] {varDef.name}); //$NON-NLS-1$ |
| status.merge(ExternalToolsPlugin.newErrorStatus(msg, null)); |
| return null; |
| } |
| |
| // Expand the variable into a IPath if possible |
| IPath path= null; |
| try { |
| path= variable.getExpander().getPath(varDef.name, varDef.argument, context); |
| } catch (CoreException exception) { |
| status.merge(exception.getStatus()); |
| return null; |
| } |
| buffer.append(path.toOSString()); |
| start= varDef.end; |
| varDef= extractVariableTag(dirLocation, start); |
| } |
| // Append text remaining after the variables |
| buffer.append(dirLocation.substring(start)); |
| return buffer.toString(); |
| } |
| |
| /** |
| * Returns the expanded file location if represented by a |
| * file variable. Otherwise, the file location given is |
| * return unless an unknown variable was detected. |
| * |
| * @param fileLocation a file location either as a path or a variable |
| * with leading and trailing spaces already removed. |
| * @param context the context used to expand the variable |
| * @param status multi status to report any problems expanding variables |
| * @return the file location as a string or <code>null</code> if not possible |
| */ |
| public static String expandFileLocation(String fileLocation, ExpandVariableContext context, MultiStatus status) { |
| if (fileLocation == null || fileLocation.length() == 0) |
| return ""; //$NON-NLS-1$ |
| |
| VariableDefinition varDef = extractVariableTag(fileLocation, 0); |
| // Return if no variable found |
| if (varDef.start < 0) { |
| return fileLocation; |
| } |
| |
| StringBuffer buffer= new StringBuffer(); |
| int start= 0; |
| while (varDef.start >= 0) { |
| // Invalid variable format |
| if (varDef.name == null || varDef.name.length() == 0 || varDef.end == -1) { |
| String msg = ExternalToolsModelMessages.getString("ToolUtil.fileLocVarFormatWrong"); //$NON-NLS-1$ |
| status.merge(ExternalToolsPlugin.newErrorStatus(msg, null)); |
| return null; |
| } |
| |
| // Append text before the variable |
| buffer.append(fileLocation.substring(start, varDef.start)); |
| |
| // Lookup the variable if it exist |
| ExternalToolVariableRegistry registry; |
| registry = ExternalToolsPlugin.getDefault().getToolVariableRegistry(); |
| ExternalToolVariable variable = registry.getVariable(varDef.name); |
| if (variable == null) { |
| String msg = MessageFormat.format(ExternalToolsModelMessages.getString("ToolUtil.fileLocVarMissing"), new Object[] {varDef.name}); //$NON-NLS-1$ |
| status.merge(ExternalToolsPlugin.newErrorStatus(msg, null)); |
| return null; |
| } |
| |
| // Expand the variable into a IPath if possible |
| IPath path = null; |
| try { |
| path= variable.getExpander().getPath(varDef.name, varDef.argument, context); |
| } catch (CoreException exception) { |
| status.merge(exception.getStatus()); |
| return null; |
| } |
| buffer.append(path.toOSString()); |
| start= varDef.end; |
| varDef= extractVariableTag(fileLocation, start); |
| } |
| // Append text remaining after the variables |
| buffer.append(fileLocation.substring(start)); |
| return buffer.toString(); |
| |
| |
| } |
| |
| /** |
| * Extracts from the source text the variable tag's name |
| * and argument. |
| * |
| * @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 extractVariableTag(String text, int start) { |
| VariableDefinition varDef = new VariableDefinition(); |
| |
| varDef.start = text.indexOf(VAR_TAG_START, start); |
| if (varDef.start < 0) |
| return varDef; |
| start = varDef.start + VAR_TAG_START.length(); |
| |
| int end = text.indexOf(VAR_TAG_END, start); |
| if (end < 0) |
| return varDef; |
| varDef.end = end + VAR_TAG_END.length(); |
| if (end == start) |
| return varDef; |
| |
| int mid = text.indexOf(VAR_TAG_SEP, start); |
| if (mid < 0 || mid > end) { |
| varDef.name = text.substring(start, end); |
| } else { |
| if (mid > start) |
| varDef.name = text.substring(start, mid); |
| mid = mid + VAR_TAG_SEP.length(); |
| if (mid < end) |
| varDef.argument = text.substring(mid, end); |
| } |
| |
| return varDef; |
| } |
| |
| /** |
| * Parses the argument text into an array of individual |
| * arguments using the space character as the delimiter. |
| * An individual argument containing spaces must have a |
| * double quote (") at the start and end. Two double |
| * quotes together is taken to mean an embedded double |
| * quote in the argument text. Variables are treated as |
| * a single unit and therefore spaces and double quotes |
| * inside a variable are copied as is and not parsed. |
| * |
| * @param arguments the arguments as one string |
| * @return the array of arguments |
| */ |
| public static String[] parseArgumentsIntoList(String arguments) { |
| if (arguments == null || arguments.length() == 0) |
| return new String[0]; |
| |
| ArrayList list = new ArrayList(10); |
| boolean inQuotes = false; |
| boolean inVar = false; |
| int start = 0; |
| int end = arguments.length(); |
| StringBuffer buffer = new StringBuffer(end); |
| |
| while (start < end) { |
| char ch = arguments.charAt(start); |
| start++; |
| |
| switch (ch) { |
| case ARG_DELIMITER : |
| if (inQuotes || inVar) { |
| buffer.append(ch); |
| } else { |
| if (buffer.length() > 0) { |
| list.add(buffer.toString()); |
| buffer.setLength(0); |
| } |
| } |
| break; |
| |
| case ARG_DBL_QUOTE : |
| if (inVar) { |
| buffer.append(ch); |
| } else { |
| if (start < end) { |
| if (arguments.charAt(start) == ARG_DBL_QUOTE) { |
| // Two quotes together represents one quote |
| buffer.append(ch); |
| start++; |
| } else { |
| inQuotes = !inQuotes; |
| } |
| } else { |
| // A lone quote at the end, just drop it. |
| inQuotes = false; |
| } |
| } |
| break; |
| |
| case VAR_TAG_START_CHAR1 : |
| buffer.append(ch); |
| if (!inVar && start < end) { |
| if (arguments.charAt(start) == VAR_TAG_START_CHAR2) { |
| buffer.append(VAR_TAG_START_CHAR2); |
| inVar = true; |
| start++; |
| } |
| } |
| break; |
| |
| case VAR_TAG_END_CHAR1 : |
| buffer.append(ch); |
| inVar = false; |
| break; |
| |
| default : |
| buffer.append(ch); |
| break; |
| } |
| |
| } |
| |
| if (buffer.length() > 0) |
| list.add(buffer.toString()); |
| |
| String[] results = new String[list.size()]; |
| list.toArray(results); |
| return results; |
| } |
| |
| |
| /** |
| * 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(); |
| } |
| } |
| } |