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 net.sourceforge.phpdt.externaltools.internal.model.ExternalToolsModelMessages;
15 import net.sourceforge.phpdt.externaltools.internal.registry.ArgumentVariable;
16 import net.sourceforge.phpdt.externaltools.internal.registry.ArgumentVariableRegistry;
17 import net.sourceforge.phpdt.externaltools.internal.registry.PathLocationVariable;
18 import net.sourceforge.phpdt.externaltools.internal.registry.PathLocationVariableRegistry;
19 import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
20 import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
22 import org.eclipse.core.runtime.IPath;
23 import org.eclipse.core.runtime.MultiStatus;
26 * General utility class dealing with external tools
28 public final class ToolUtil {
30 * Argument parsing constants
32 private static final char ARG_DELIMITER = ' '; //$NON-NLS-1$
34 private static final char ARG_DBL_QUOTE = '"'; //$NON-NLS-1$
37 * Variable tag indentifiers
39 private static final char VAR_TAG_START_CHAR1 = '$'; //$NON-NLS-1$
41 private static final char VAR_TAG_START_CHAR2 = '{'; //$NON-NLS-1$
43 private static final char VAR_TAG_END_CHAR1 = '}'; //$NON-NLS-1$
45 private static final String VAR_TAG_START = "${"; //$NON-NLS-1$
47 private static final String VAR_TAG_END = "}"; //$NON-NLS-1$
49 private static final String VAR_TAG_SEP = ":"; //$NON-NLS-1$
52 * No instances allowed
59 * Builds a variable tag that will be auto-expanded before the tool is run.
62 * the name of a known variable (one of the VAR_* constants for
65 * an optional argument for the variable, <code>null</code> if
68 public static String buildVariableTag(String varName, String varArgument) {
69 StringBuffer buf = new StringBuffer();
70 buildVariableTag(varName, varArgument, buf);
71 return buf.toString();
75 * Builds a variable tag that will be auto-expanded before the tool is run.
78 * the name of a known variable (one of the VAR_* constants for
81 * an optional argument for the variable, <code>null</code> if
84 * the buffer to write the constructed variable tag
86 public static void buildVariableTag(String varName, String varArgument,
87 StringBuffer buffer) {
88 buffer.append(VAR_TAG_START);
89 buffer.append(varName);
90 if (varArgument != null && varArgument.length() > 0) {
91 buffer.append(VAR_TAG_SEP);
92 buffer.append(varArgument);
94 buffer.append(VAR_TAG_END);
98 * Expands all the variables found in an individual argument text.
101 * one of the argument text in the list of arguments
103 * the context to use for expanding variables
105 * multi status to report any problems expanding variables
106 * @return the argument text with all variables expanded, or
107 * <code>null</code> if not possible
109 public static String expandArgument(String argument,
110 ExpandVariableContext context, MultiStatus status) {
111 StringBuffer buffer = new StringBuffer();
115 VariableDefinition varDef = extractVariableTag(argument, start);
117 // No more variables found...
118 if (varDef.start == -1) {
120 buffer.append(argument);
122 buffer.append(argument.substring(start));
126 // Invalid variable format
127 if (varDef.end == -1 || varDef.name == null
128 || varDef.name.length() == 0) {
129 String msg = ExternalToolsModelMessages
130 .getString("ToolUtil.argumentVarFormatWrong"); //$NON-NLS-1$
131 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
135 // Copy text between start and variable.
136 if (varDef.start > start)
137 buffer.append(argument.substring(start, varDef.start));
140 // Lookup the variable if it exist
141 ArgumentVariableRegistry registry;
142 registry = ExternalToolsPlugin.getDefault()
143 .getArgumentVariableRegistry();
144 ArgumentVariable variable = registry
145 .getArgumentVariable(varDef.name);
146 if (variable == null) {
147 String msg = ExternalToolsModelMessages
149 "ToolUtil.argumentVarMissing", new Object[] { varDef.name }); //$NON-NLS-1$
150 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
154 // Expand the variable as text if possible
155 String text = variable.getExpander().getText(varDef.name,
156 varDef.argument, context);
158 String msg = ExternalToolsModelMessages
160 "ToolUtil.argumentVarExpandFailed", new Object[] { varDef.name }); //$NON-NLS-1$
161 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
167 return buffer.toString();
171 * Returns a list of individual arguments where all variables have been
175 * the arguments with leading and trailing spaces already
178 * the context used to expand the variable(s)
180 * multi status to report any problems expanding variables
181 * @return the list of individual arguments where some elements in the list
182 * maybe <code>null</code> if problems expanding variable(s).
184 public static String[] expandArguments(String arguments,
185 ExpandVariableContext context, MultiStatus status) {
186 if (arguments == null || arguments.length() == 0)
187 return new String[0];
189 String[] argList = parseArgumentsIntoList(arguments);
190 for (int i = 0; i < argList.length; i++)
191 argList[i] = expandArgument(argList[i], context, status);
197 * Returns the expanded directory location if represented by a directory
198 * variable. Otherwise, the directory location given is return unless an
199 * unknown variable was detected.
202 * a directory location either as a path or a variable with
203 * leading and trailing spaces already removed.
205 * the context used to expand the variable
207 * multi status to report any problems expanding variables
208 * @return the directory location as a string or <code>null</code> if not
211 public static String expandDirectoryLocation(String dirLocation,
212 ExpandVariableContext context, MultiStatus status) {
213 if (dirLocation == null || dirLocation.length() == 0)
214 return ""; //$NON-NLS-1$
216 VariableDefinition varDef = extractVariableTag(dirLocation, 0);
217 // Return if no variable found
218 if (varDef.start < 0)
221 // Disallow text before/after variable
222 if (varDef.start != 0
223 || (varDef.end < dirLocation.length() && varDef.end != -1)) {
224 String msg = ExternalToolsModelMessages
225 .getString("ToolUtil.dirLocVarBetweenText"); //$NON-NLS-1$
226 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
230 // Invalid variable format
231 if (varDef.name == null || varDef.name.length() == 0
232 || varDef.end == -1) {
233 String msg = ExternalToolsModelMessages
234 .getString("ToolUtil.dirLocVarFormatWrong"); //$NON-NLS-1$
235 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
239 // Lookup the variable if it exist
240 PathLocationVariableRegistry registry;
241 registry = ExternalToolsPlugin.getDefault()
242 .getDirectoryLocationVariableRegistry();
243 PathLocationVariable variable = registry
244 .getPathLocationVariable(varDef.name);
245 if (variable == null) {
246 String msg = ExternalToolsModelMessages.format(
247 "ToolUtil.dirLocVarMissing", new Object[] { varDef.name }); //$NON-NLS-1$
248 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
252 // Expand the variable into a IPath if possible
253 IPath path = variable.getExpander().getPath(varDef.name,
254 varDef.argument, context);
256 String msg = ExternalToolsModelMessages
258 "ToolUtil.dirLocVarExpandFailed", new Object[] { varDef.name }); //$NON-NLS-1$
259 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
263 return path.toOSString();
267 * Returns the expanded file location if represented by a file variable.
268 * Otherwise, the file location given is return unless an unknown variable
271 * @param fileLocation
272 * a file location either as a path or a variable with leading
273 * and trailing spaces already removed.
275 * the context used to expand the variable
277 * multi status to report any problems expanding variables
278 * @return the file location as a string or <code>null</code> if not
281 public static String expandFileLocation(String fileLocation,
282 ExpandVariableContext context, MultiStatus status) {
283 if (fileLocation == null || fileLocation.length() == 0)
284 return ""; //$NON-NLS-1$
286 VariableDefinition varDef = extractVariableTag(fileLocation, 0);
287 // Return if no variable found
288 if (varDef.start < 0)
291 // Disallow text before/after variable
292 if (varDef.start != 0
293 || (varDef.end < fileLocation.length() && varDef.end != -1)) {
294 String msg = ExternalToolsModelMessages
295 .getString("ToolUtil.fileLocVarBetweenText"); //$NON-NLS-1$
296 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
300 // Invalid variable format
301 if (varDef.name == null || varDef.name.length() == 0
302 || varDef.end == -1) {
303 String msg = ExternalToolsModelMessages
304 .getString("ToolUtil.fileLocVarFormatWrong"); //$NON-NLS-1$
305 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
309 // Lookup the variable if it exist
310 PathLocationVariableRegistry registry;
311 registry = ExternalToolsPlugin.getDefault()
312 .getFileLocationVariableRegistry();
313 PathLocationVariable variable = registry
314 .getPathLocationVariable(varDef.name);
315 if (variable == null) {
316 String msg = ExternalToolsModelMessages.format(
317 "ToolUtil.fileLocVarMissing", new Object[] { varDef.name }); //$NON-NLS-1$
318 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
322 // Expand the variable into a IPath if possible
323 IPath path = variable.getExpander().getPath(varDef.name,
324 varDef.argument, context);
326 String msg = ExternalToolsModelMessages
328 "The variable {0} with argument {1} could not be expanded to a valid path.",
329 new Object[] { varDef.name, varDef.argument });
330 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
334 return path.toString();
338 * Extracts from the source text the variable tag's name and argument.
341 * the source text to parse for a variable tag
343 * the index in the string to start the search
344 * @return the variable definition
346 public static VariableDefinition extractVariableTag(String text, int start) {
347 VariableDefinition varDef = new VariableDefinition();
349 varDef.start = text.indexOf(VAR_TAG_START, start);
350 if (varDef.start < 0)
352 start = varDef.start + VAR_TAG_START.length();
354 int end = text.indexOf(VAR_TAG_END, start);
357 varDef.end = end + VAR_TAG_END.length();
361 int mid = text.indexOf(VAR_TAG_SEP, start);
362 if (mid < 0 || mid > end) {
363 varDef.name = text.substring(start, end);
366 varDef.name = text.substring(start, mid);
367 mid = mid + VAR_TAG_SEP.length();
369 varDef.argument = text.substring(mid, end);
376 * Parses the argument text into an array of individual arguments using the
377 * space character as the delimiter. An individual argument containing
378 * spaces must have a double quote (") at the start and end. Two double
379 * quotes together is taken to mean an embedded double quote in the argument
380 * text. Variables are treated as a single unit and therefore spaces and
381 * double quotes inside a variable are copied as is and not parsed.
384 * the arguments as one string
385 * @return the array of arguments
387 public static String[] parseArgumentsIntoList(String arguments) {
388 if (arguments == null || arguments.length() == 0)
389 return new String[0];
391 ArrayList list = new ArrayList(10);
392 boolean inQuotes = false;
393 boolean inVar = false;
395 int end = arguments.length();
396 StringBuffer buffer = new StringBuffer(end);
398 while (start < end) {
399 char ch = arguments.charAt(start);
404 if (inQuotes || inVar) {
407 if (buffer.length() > 0) {
408 list.add(buffer.toString());
419 if (arguments.charAt(start) == ARG_DBL_QUOTE) {
420 // Two quotes together represents one quote
424 inQuotes = !inQuotes;
427 // A lone quote at the end, just drop it.
433 case VAR_TAG_START_CHAR1:
435 if (!inVar && start < end) {
436 if (arguments.charAt(start) == VAR_TAG_START_CHAR2) {
437 buffer.append(VAR_TAG_START_CHAR2);
444 case VAR_TAG_END_CHAR1:
456 if (buffer.length() > 0)
457 list.add(buffer.toString());
459 String[] results = new String[list.size()];
460 list.toArray(results);
465 * Structure to represent a variable definition within a source string.
467 public static final class VariableDefinition {
469 * Index in the source text where the variable started or
470 * <code>-1</code> if no valid variable start tag identifier found.
472 public int start = -1;
475 * Index in the source text of the character following the end of the
476 * variable or <code>-1</code> if no valid variable end tag found.
481 * The variable's name found in the source text, or <code>null</code>
482 * if no valid variable found.
484 public String name = null;
487 * The variable's argument found in the source text, or
488 * <code>null</code> if no valid variable found or if the variable did
489 * not specify an argument
491 public String argument = null;
494 * Create an initialized variable definition.
496 private VariableDefinition() {
501 * Create an initialized variable definition.
503 private VariableDefinition(int start, int end) {