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.ExternalToolsPlugin;
15 import net.sourceforge.phpdt.externaltools.internal.model.ToolMessages;
16 import net.sourceforge.phpdt.externaltools.internal.registry.ArgumentVariable;
17 import net.sourceforge.phpdt.externaltools.internal.registry.ArgumentVariableRegistry;
18 import net.sourceforge.phpdt.externaltools.internal.registry.PathLocationVariable;
19 import net.sourceforge.phpdt.externaltools.internal.registry.PathLocationVariableRegistry;
20 import net.sourceforge.phpdt.externaltools.variable.ExpandVariableContext;
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$
33 private static final char ARG_DBL_QUOTE = '"'; //$NON-NLS-1$
36 * Variable tag indentifiers
38 private static final char VAR_TAG_START_CHAR1 = '$'; //$NON-NLS-1$
39 private static final char VAR_TAG_START_CHAR2 = '{'; //$NON-NLS-1$
40 private static final char VAR_TAG_END_CHAR1 = '}'; //$NON-NLS-1$
41 private static final String VAR_TAG_START = "${"; //$NON-NLS-1$
42 private static final String VAR_TAG_END = "}"; //$NON-NLS-1$
43 private static final String VAR_TAG_SEP = ":"; //$NON-NLS-1$
46 * No instances allowed
53 * Builds a variable tag that will be auto-expanded before
56 * @param varName the name of a known variable (one of the VAR_* constants for instance)
57 * @param varArgument an optional argument for the variable, <code>null</code> if none
59 public static String buildVariableTag(String varName, String varArgument) {
60 StringBuffer buf = new StringBuffer();
61 buildVariableTag(varName,varArgument, buf);
62 return buf.toString();
66 * Builds a variable tag that will be auto-expanded before
69 * @param varName the name of a known variable (one of the VAR_* constants for instance)
70 * @param varArgument an optional argument for the variable, <code>null</code> if none
71 * @param buffer the buffer to write the constructed variable tag
73 public static void buildVariableTag(String varName, String varArgument, StringBuffer buffer) {
74 buffer.append(VAR_TAG_START);
75 buffer.append(varName);
76 if (varArgument != null && varArgument.length() > 0) {
77 buffer.append(VAR_TAG_SEP);
78 buffer.append(varArgument);
80 buffer.append(VAR_TAG_END);
84 * Expands all the variables found in an individual
87 * @param argument one of the argument text in the list of arguments
88 * @param context the context to use for expanding variables
89 * @param status multi status to report any problems expanding variables
90 * @return the argument text with all variables expanded, or <code>null</code> if not possible
92 public static String expandArgument(String argument, ExpandVariableContext context, MultiStatus status) {
93 StringBuffer buffer = new StringBuffer();
97 VariableDefinition varDef = extractVariableTag(argument, start);
99 // No more variables found...
100 if (varDef.start == -1) {
102 buffer.append(argument);
104 buffer.append(argument.substring(start));
108 // Invalid variable format
109 if (varDef.end == -1 || varDef.name == null || varDef.name.length() == 0) {
110 String msg = ToolMessages.getString("ToolUtil.argumentVarFormatWrong"); //$NON-NLS-1$
111 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
115 // Copy text between start and variable.
116 if (varDef.start > start)
117 buffer.append(argument.substring(start, varDef.start));
120 // Lookup the variable if it exist
121 ArgumentVariableRegistry registry;
122 registry = ExternalToolsPlugin.getDefault().getArgumentVariableRegistry();
123 ArgumentVariable variable = registry.getArgumentVariable(varDef.name);
124 if (variable == null) {
125 String msg = ToolMessages.format("ToolUtil.argumentVarMissing", new Object[] {varDef.name}); //$NON-NLS-1$
126 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
130 // Expand the variable as text if possible
131 String text = variable.getExpander().getText(varDef.name, varDef.argument, context);
133 String msg = ToolMessages.format("ToolUtil.argumentVarExpandFailed", new Object[] {varDef.name}); //$NON-NLS-1$
134 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
140 return buffer.toString();
144 * Returns a list of individual arguments where all
145 * variables have been expanded.
147 * @param arguments the arguments with leading and trailing
148 * spaces already removed.
149 * @param context the context used to expand the variable(s)
150 * @param status multi status to report any problems expanding variables
151 * @return the list of individual arguments where some elements in the
152 * list maybe <code>null</code> if problems expanding variable(s).
154 public static String[] expandArguments(String arguments, ExpandVariableContext context, MultiStatus status) {
155 if (arguments == null || arguments.length() == 0)
156 return new String[0];
158 String[] argList = parseArgumentsIntoList(arguments);
159 for (int i = 0; i < argList.length; i++)
160 argList[i] = expandArgument(argList[i], context, status);
166 * Returns the expanded directory location if represented by a
167 * directory variable. Otherwise, the directory location given is
168 * return unless an unknown variable was detected.
170 * @param dirLocation a directory location either as a path or a variable
171 * with leading and trailing spaces already removed.
172 * @param context the context used to expand the variable
173 * @param status multi status to report any problems expanding variables
174 * @return the directory location as a string or <code>null</code> if not possible
176 public static String expandDirectoryLocation(String dirLocation, ExpandVariableContext context, MultiStatus status) {
177 if (dirLocation == null || dirLocation.length() == 0)
178 return ""; //$NON-NLS-1$
180 VariableDefinition varDef = extractVariableTag(dirLocation, 0);
181 // Return if no variable found
182 if (varDef.start < 0)
185 // Disallow text before/after variable
186 if (varDef.start != 0 || (varDef.end < dirLocation.length() && varDef.end != -1)) {
187 String msg = ToolMessages.getString("ToolUtil.dirLocVarBetweenText"); //$NON-NLS-1$
188 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
192 // Invalid variable format
193 if (varDef.name == null || varDef.name.length() == 0 || varDef.end == -1) {
194 String msg = ToolMessages.getString("ToolUtil.dirLocVarFormatWrong"); //$NON-NLS-1$
195 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
199 // Lookup the variable if it exist
200 PathLocationVariableRegistry registry;
201 registry = ExternalToolsPlugin.getDefault().getDirectoryLocationVariableRegistry();
202 PathLocationVariable variable = registry.getPathLocationVariable(varDef.name);
203 if (variable == null) {
204 String msg = ToolMessages.format("ToolUtil.dirLocVarMissing", new Object[] {varDef.name}); //$NON-NLS-1$
205 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
209 // Expand the variable into a IPath if possible
210 IPath path = variable.getExpander().getPath(varDef.name, varDef.argument, context);
212 String msg = ToolMessages.format("ToolUtil.dirLocVarExpandFailed", new Object[] {varDef.name}); //$NON-NLS-1$
213 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
217 return path.toOSString();
221 * Returns the expanded file location if represented by a
222 * file variable. Otherwise, the file location given is
223 * return unless an unknown variable was detected.
225 * @param fileLocation a file location either as a path or a variable
226 * with leading and trailing spaces already removed.
227 * @param context the context used to expand the variable
228 * @param status multi status to report any problems expanding variables
229 * @return the file location as a string or <code>null</code> if not possible
231 public static String expandFileLocation(String fileLocation, ExpandVariableContext context, MultiStatus status) {
232 if (fileLocation == null || fileLocation.length() == 0)
233 return ""; //$NON-NLS-1$
235 VariableDefinition varDef = extractVariableTag(fileLocation, 0);
236 // Return if no variable found
237 if (varDef.start < 0)
240 // Disallow text before/after variable
241 if (varDef.start != 0 || (varDef.end < fileLocation.length() && varDef.end != -1)) {
242 String msg = ToolMessages.getString("ToolUtil.fileLocVarBetweenText"); //$NON-NLS-1$
243 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
247 // Invalid variable format
248 if (varDef.name == null || varDef.name.length() == 0 || varDef.end == -1) {
249 String msg = ToolMessages.getString("ToolUtil.fileLocVarFormatWrong"); //$NON-NLS-1$
250 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
254 // Lookup the variable if it exist
255 PathLocationVariableRegistry registry;
256 registry = ExternalToolsPlugin.getDefault().getFileLocationVariableRegistry();
257 PathLocationVariable variable = registry.getPathLocationVariable(varDef.name);
258 if (variable == null) {
259 String msg = ToolMessages.format("ToolUtil.fileLocVarMissing", new Object[] {varDef.name}); //$NON-NLS-1$
260 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
264 // Expand the variable into a IPath if possible
265 IPath path = variable.getExpander().getPath(varDef.name, varDef.argument, context);
267 String msg = ToolMessages.format("The variable {0} with argument {1} could not be expanded to a valid path.", new Object[] {varDef.name, varDef.argument});
268 status.merge(ExternalToolsPlugin.newErrorStatus(msg, null));
272 return path.toString();
276 * Extracts from the source text the variable tag's name
279 * @param text the source text to parse for a variable tag
280 * @param start the index in the string to start the search
281 * @return the variable definition
283 public static VariableDefinition extractVariableTag(String text, int start) {
284 VariableDefinition varDef = new VariableDefinition();
286 varDef.start = text.indexOf(VAR_TAG_START, start);
287 if (varDef.start < 0)
289 start = varDef.start + VAR_TAG_START.length();
291 int end = text.indexOf(VAR_TAG_END, start);
294 varDef.end = end + VAR_TAG_END.length();
298 int mid = text.indexOf(VAR_TAG_SEP, start);
299 if (mid < 0 || mid > end) {
300 varDef.name = text.substring(start, end);
303 varDef.name = text.substring(start, mid);
304 mid = mid + VAR_TAG_SEP.length();
306 varDef.argument = text.substring(mid, end);
313 * Parses the argument text into an array of individual
314 * arguments using the space character as the delimiter.
315 * An individual argument containing spaces must have a
316 * double quote (") at the start and end. Two double
317 * quotes together is taken to mean an embedded double
318 * quote in the argument text. Variables are treated as
319 * a single unit and therefore spaces and double quotes
320 * inside a variable are copied as is and not parsed.
322 * @param arguments the arguments as one string
323 * @return the array of arguments
325 public static String[] parseArgumentsIntoList(String arguments) {
326 if (arguments == null || arguments.length() == 0)
327 return new String[0];
329 ArrayList list = new ArrayList(10);
330 boolean inQuotes = false;
331 boolean inVar = false;
333 int end = arguments.length();
334 StringBuffer buffer = new StringBuffer(end);
336 while (start < end) {
337 char ch = arguments.charAt(start);
342 if (inQuotes || inVar) {
345 if (buffer.length() > 0) {
346 list.add(buffer.toString());
357 if (arguments.charAt(start) == ARG_DBL_QUOTE) {
358 // Two quotes together represents one quote
362 inQuotes = !inQuotes;
365 // A lone quote at the end, just drop it.
371 case VAR_TAG_START_CHAR1 :
373 if (!inVar && start < end) {
374 if (arguments.charAt(start) == VAR_TAG_START_CHAR2) {
375 buffer.append(VAR_TAG_START_CHAR2);
382 case VAR_TAG_END_CHAR1 :
394 if (buffer.length() > 0)
395 list.add(buffer.toString());
397 String[] results = new String[list.size()];
398 list.toArray(results);
404 * Structure to represent a variable definition within a
407 public static final class VariableDefinition {
409 * Index in the source text where the variable started
410 * or <code>-1</code> if no valid variable start tag
413 public int start = -1;
416 * Index in the source text of the character following
417 * the end of the variable or <code>-1</code> if no
418 * valid variable end tag found.
423 * The variable's name found in the source text, or
424 * <code>null</code> if no valid variable found.
426 public String name = null;
429 * The variable's argument found in the source text, or
430 * <code>null</code> if no valid variable found or if
431 * the variable did not specify an argument
433 public String argument = null;
436 * Create an initialized variable definition.
438 private VariableDefinition() {
443 * Create an initialized variable definition.
445 private VariableDefinition(int start, int end) {