1 package net.sourceforge.phpdt.externaltools.model;
3 /**********************************************************************
4 Copyright (c) 2002 IBM Corp. and others. All rights reserved.
5 This file is made available under the terms of the Common Public License v1.0
6 which accompanies this distribution, and is available at
7 http://www.eclipse.org/legal/cpl-v10.html
10 **********************************************************************/
12 import java.util.ArrayList;
14 import org.eclipse.core.runtime.IPath;
15 import org.eclipse.core.runtime.MultiStatus;
16 import net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsPlugin;
17 import net.sourceforge.phpdt.externaltools.internal.model.ToolMessages;
18 import net.sourceforge.phpdt.externaltools.internal.registry.ArgumentVariable;
19 import net.sourceforge.phpdt.externaltools.internal.registry.ArgumentVariableRegistry;
20 import net.sourceforge.phpdt.externaltools.internal.registry.PathLocationVariable;
21 import net.sourceforge.phpdt.externaltools.internal.registry.PathLocationVariableRegistry;
22 import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
25 * General utility class dealing with external tools
27 public final class ToolUtil {
29 * Argument parsing constants
31 private static final char ARG_DELIMITER = ' '; //$NON-NLS-1$
32 private static final char ARG_DBL_QUOTE = '"'; //$NON-NLS-1$
35 * Variable tag indentifiers
37 private static final char VAR_TAG_START_CHAR1 = '$'; //$NON-NLS-1$
38 private static final char VAR_TAG_START_CHAR2 = '{'; //$NON-NLS-1$
39 private static final char VAR_TAG_END_CHAR1 = '}'; //$NON-NLS-1$
40 private static final String VAR_TAG_START = "${"; //$NON-NLS-1$
41 private static final String VAR_TAG_END = "}"; //$NON-NLS-1$
42 private static final String VAR_TAG_SEP = ":"; //$NON-NLS-1$
45 * No instances allowed
52 * Builds a variable tag that will be auto-expanded before
55 * @param varName the name of a known variable (one of the VAR_* constants for instance)
56 * @param varArgument an optional argument for the variable, <code>null</code> if none
58 public static String buildVariableTag(String varName, String varArgument) {
59 StringBuffer buf = new StringBuffer();
60 buildVariableTag(varName,varArgument, buf);
61 return buf.toString();
65 * Builds a variable tag that will be auto-expanded before
68 * @param varName the name of a known variable (one of the VAR_* constants for instance)
69 * @param varArgument an optional argument for the variable, <code>null</code> if none
70 * @param buffer the buffer to write the constructed variable tag
72 public static void buildVariableTag(String varName, String varArgument, StringBuffer buffer) {
73 buffer.append(VAR_TAG_START);
74 buffer.append(varName);
75 if (varArgument != null && varArgument.length() > 0) {
76 buffer.append(VAR_TAG_SEP);
77 buffer.append(varArgument);
79 buffer.append(VAR_TAG_END);
83 * Expands all the variables found in an individual
86 * @param argument one of the argument text in the list of arguments
87 * @param context the context to use for expanding variables
88 * @param status multi status to report any problems expanding variables
89 * @return the argument text with all variables expanded, or <code>null</code> if not possible
91 public static String expandArgument(String argument, ExpandVariableContext context, MultiStatus status) {
92 StringBuffer buffer = new StringBuffer();
96 VariableDefinition varDef = extractVariableTag(argument, start);
98 // No more variables found...
99 if (varDef.start == -1) {
101 buffer.append(argument);
103 buffer.append(argument.substring(start));
107 // Invalid variable format
108 if (varDef.end == -1 || varDef.name == null || varDef.name.length() == 0) {
109 String msg = ToolMessages.getString("ToolUtil.argumentVarFormatWrong"); //$NON-NLS-1$
110 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
114 // Copy text between start and variable.
115 if (varDef.start > start)
116 buffer.append(argument.substring(start, varDef.start));
119 // Lookup the variable if it exist
120 ArgumentVariableRegistry registry;
121 registry = ExternalToolsPlugin.getDefault().getArgumentVariableRegistry();
122 ArgumentVariable variable = registry.getArgumentVariable(varDef.name);
123 if (variable == null) {
124 String msg = ToolMessages.format("ToolUtil.argumentVarMissing", new Object[] {varDef.name}); //$NON-NLS-1$
125 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
129 // Expand the variable as text if possible
130 String text = variable.getExpander().getText(varDef.name, varDef.argument, context);
132 String msg = ToolMessages.format("ToolUtil.argumentVarExpandFailed", new Object[] {varDef.name}); //$NON-NLS-1$
133 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
139 return buffer.toString();
143 * Returns a list of individual arguments where all
144 * variables have been expanded.
146 * @param arguments the arguments with leading and trailing
147 * spaces already removed.
148 * @param context the context used to expand the variable(s)
149 * @param status multi status to report any problems expanding variables
150 * @return the list of individual arguments where some elements in the
151 * list maybe <code>null</code> if problems expanding variable(s).
153 public static String[] expandArguments(String arguments, ExpandVariableContext context, MultiStatus status) {
154 if (arguments == null || arguments.length() == 0)
155 return new String[0];
157 String[] argList = parseArgumentsIntoList(arguments);
158 for (int i = 0; i < argList.length; i++)
159 argList[i] = expandArgument(argList[i], context, status);
165 * Returns the expanded directory location if represented by a
166 * directory variable. Otherwise, the directory location given is
167 * return unless an unknown variable was detected.
169 * @param dirLocation a directory location either as a path or a variable
170 * with leading and trailing spaces already removed.
171 * @param context the context used to expand the variable
172 * @param status multi status to report any problems expanding variables
173 * @return the directory location as a string or <code>null</code> if not possible
175 public static String expandDirectoryLocation(String dirLocation, ExpandVariableContext context, MultiStatus status) {
176 if (dirLocation == null || dirLocation.length() == 0)
177 return ""; //$NON-NLS-1$
179 VariableDefinition varDef = extractVariableTag(dirLocation, 0);
180 // Return if no variable found
181 if (varDef.start < 0)
184 // Disallow text before/after variable
185 if (varDef.start != 0 || (varDef.end < dirLocation.length() && varDef.end != -1)) {
186 String msg = ToolMessages.getString("ToolUtil.dirLocVarBetweenText"); //$NON-NLS-1$
187 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
191 // Invalid variable format
192 if (varDef.name == null || varDef.name.length() == 0 || varDef.end == -1) {
193 String msg = ToolMessages.getString("ToolUtil.dirLocVarFormatWrong"); //$NON-NLS-1$
194 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
198 // Lookup the variable if it exist
199 PathLocationVariableRegistry registry;
200 registry = ExternalToolsPlugin.getDefault().getDirectoryLocationVariableRegistry();
201 PathLocationVariable variable = registry.getPathLocationVariable(varDef.name);
202 if (variable == null) {
203 String msg = ToolMessages.format("ToolUtil.dirLocVarMissing", new Object[] {varDef.name}); //$NON-NLS-1$
204 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
208 // Expand the variable into a IPath if possible
209 IPath path = variable.getExpander().getPath(varDef.name, varDef.argument, context);
211 String msg = ToolMessages.format("ToolUtil.dirLocVarExpandFailed", new Object[] {varDef.name}); //$NON-NLS-1$
212 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
216 return path.toOSString();
220 * Returns the expanded file location if represented by a
221 * file variable. Otherwise, the file location given is
222 * return unless an unknown variable was detected.
224 * @param fileLocation a file location either as a path or a variable
225 * with leading and trailing spaces already removed.
226 * @param context the context used to expand the variable
227 * @param status multi status to report any problems expanding variables
228 * @return the file location as a string or <code>null</code> if not possible
230 public static String expandFileLocation(String fileLocation, ExpandVariableContext context, MultiStatus status) {
231 if (fileLocation == null || fileLocation.length() == 0)
232 return ""; //$NON-NLS-1$
234 VariableDefinition varDef = extractVariableTag(fileLocation, 0);
235 // Return if no variable found
236 if (varDef.start < 0)
239 // Disallow text before/after variable
240 if (varDef.start != 0 || (varDef.end < fileLocation.length() && varDef.end != -1)) {
241 String msg = ToolMessages.getString("ToolUtil.fileLocVarBetweenText"); //$NON-NLS-1$
242 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
246 // Invalid variable format
247 if (varDef.name == null || varDef.name.length() == 0 || varDef.end == -1) {
248 String msg = ToolMessages.getString("ToolUtil.fileLocVarFormatWrong"); //$NON-NLS-1$
249 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
253 // Lookup the variable if it exist
254 PathLocationVariableRegistry registry;
255 registry = ExternalToolsPlugin.getDefault().getFileLocationVariableRegistry();
256 PathLocationVariable variable = registry.getPathLocationVariable(varDef.name);
257 if (variable == null) {
258 String msg = ToolMessages.format("ToolUtil.fileLocVarMissing", new Object[] {varDef.name}); //$NON-NLS-1$
259 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
263 // Expand the variable into a IPath if possible
264 IPath path = variable.getExpander().getPath(varDef.name, varDef.argument, context);
266 String msg = ToolMessages.format("The variable {0} with argument {1} could not be expanded to a valid path.", new Object[] {varDef.name, varDef.argument});
267 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
271 return path.toString();
275 * Extracts from the source text the variable tag's name
278 * @param text the source text to parse for a variable tag
279 * @param start the index in the string to start the search
280 * @return the variable definition
282 public static VariableDefinition extractVariableTag(String text, int start) {
283 VariableDefinition varDef = new VariableDefinition();
285 varDef.start = text.indexOf(VAR_TAG_START, start);
286 if (varDef.start < 0)
288 start = varDef.start + VAR_TAG_START.length();
290 int end = text.indexOf(VAR_TAG_END, start);
293 varDef.end = end + VAR_TAG_END.length();
297 int mid = text.indexOf(VAR_TAG_SEP, start);
298 if (mid < 0 || mid > end) {
299 varDef.name = text.substring(start, end);
302 varDef.name = text.substring(start, mid);
303 mid = mid + VAR_TAG_SEP.length();
305 varDef.argument = text.substring(mid, end);
312 * Parses the argument text into an array of individual
313 * arguments using the space character as the delimiter.
314 * An individual argument containing spaces must have a
315 * double quote (") at the start and end. Two double
316 * quotes together is taken to mean an embedded double
317 * quote in the argument text. Variables are treated as
318 * a single unit and therefore spaces and double quotes
319 * inside a variable are copied as is and not parsed.
321 * @param arguments the arguments as one string
322 * @return the array of arguments
324 public static String[] parseArgumentsIntoList(String arguments) {
325 if (arguments == null || arguments.length() == 0)
326 return new String[0];
328 ArrayList list = new ArrayList(10);
329 boolean inQuotes = false;
330 boolean inVar = false;
332 int end = arguments.length();
333 StringBuffer buffer = new StringBuffer(end);
335 while (start < end) {
336 char ch = arguments.charAt(start);
341 if (inQuotes || inVar) {
344 if (buffer.length() > 0) {
345 list.add(buffer.toString());
356 if (arguments.charAt(start) == ARG_DBL_QUOTE) {
357 // Two quotes together represents one quote
361 inQuotes = !inQuotes;
364 // A lone quote at the end, just drop it.
370 case VAR_TAG_START_CHAR1 :
372 if (!inVar && start < end) {
373 if (arguments.charAt(start) == VAR_TAG_START_CHAR2) {
374 buffer.append(VAR_TAG_START_CHAR2);
381 case VAR_TAG_END_CHAR1 :
393 if (buffer.length() > 0)
394 list.add(buffer.toString());
396 String[] results = new String[list.size()];
397 list.toArray(results);
403 * Structure to represent a variable definition within a
406 public static final class VariableDefinition {
408 * Index in the source text where the variable started
409 * or <code>-1</code> if no valid variable start tag
412 public int start = -1;
415 * Index in the source text of the character following
416 * the end of the variable or <code>-1</code> if no
417 * valid variable end tag found.
422 * The variable's name found in the source text, or
423 * <code>null</code> if no valid variable found.
425 public String name = null;
428 * The variable's argument found in the source text, or
429 * <code>null</code> if no valid variable found or if
430 * the variable did not specify an argument
432 public String argument = null;
435 * Create an initialized variable definition.
437 private VariableDefinition() {
442 * Create an initialized variable definition.
444 private VariableDefinition(int start, int end) {