[14982] | 1 | /*
|
---|
| 2 | * Copyright 2000-2004 The Apache Software Foundation
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
---|
| 5 | * you may not use this file except in compliance with the License.
|
---|
| 6 | * You may obtain a copy of the License at
|
---|
| 7 | *
|
---|
| 8 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
| 9 | *
|
---|
| 10 | * Unless required by applicable law or agreed to in writing, software
|
---|
| 11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
| 13 | * See the License for the specific language governing permissions and
|
---|
| 14 | * limitations under the License.
|
---|
| 15 | *
|
---|
| 16 | */
|
---|
| 17 |
|
---|
| 18 | package org.apache.tools.ant.types;
|
---|
| 19 |
|
---|
| 20 | import java.io.File;
|
---|
| 21 | import java.util.StringTokenizer;
|
---|
| 22 | import java.util.Vector;
|
---|
| 23 | import java.util.ArrayList;
|
---|
| 24 | import java.util.List;
|
---|
| 25 | import java.util.ListIterator;
|
---|
| 26 | import java.util.LinkedList;
|
---|
| 27 |
|
---|
| 28 | import org.apache.tools.ant.BuildException;
|
---|
| 29 | import org.apache.tools.ant.ProjectComponent;
|
---|
| 30 | import org.apache.tools.ant.util.StringUtils;
|
---|
| 31 |
|
---|
| 32 |
|
---|
| 33 | /**
|
---|
| 34 | * Commandline objects help handling command lines specifying processes to
|
---|
| 35 | * execute.
|
---|
| 36 | *
|
---|
| 37 | * The class can be used to define a command line as nested elements or as a
|
---|
| 38 | * helper to define a command line by an application.
|
---|
| 39 | * <p>
|
---|
| 40 | * <code>
|
---|
| 41 | * <someelement><br>
|
---|
| 42 | * <acommandline executable="/executable/to/run"><br>
|
---|
| 43 | * <argument value="argument 1" /><br>
|
---|
| 44 | * <argument line="argument_1 argument_2 argument_3" /><br>
|
---|
| 45 | * <argument value="argument 4" /><br>
|
---|
| 46 | * </acommandline><br>
|
---|
| 47 | * </someelement><br>
|
---|
| 48 | * </code>
|
---|
| 49 | * The element <code>someelement</code> must provide a method
|
---|
| 50 | * <code>createAcommandline</code> which returns an instance of this class.
|
---|
| 51 | *
|
---|
| 52 | */
|
---|
| 53 | public class Commandline implements Cloneable {
|
---|
| 54 |
|
---|
| 55 | /**
|
---|
| 56 | * The arguments of the command
|
---|
| 57 | */
|
---|
| 58 | private Vector arguments = new Vector();
|
---|
| 59 |
|
---|
| 60 | /**
|
---|
| 61 | * the program to execute
|
---|
| 62 | */
|
---|
| 63 | private String executable = null;
|
---|
| 64 |
|
---|
| 65 | protected static final String DISCLAIMER =
|
---|
| 66 | StringUtils.LINE_SEP
|
---|
| 67 | + "The \' characters around the executable and arguments are"
|
---|
| 68 | + StringUtils.LINE_SEP
|
---|
| 69 | + "not part of the command."
|
---|
| 70 | + StringUtils.LINE_SEP;
|
---|
| 71 |
|
---|
| 72 | /**
|
---|
| 73 | * create a command line from a string
|
---|
| 74 | * @param toProcess the line: the first element becomes the executable, the rest
|
---|
| 75 | * the arguments
|
---|
| 76 | */
|
---|
| 77 | public Commandline(String toProcess) {
|
---|
| 78 | super();
|
---|
| 79 | String[] tmp = translateCommandline(toProcess);
|
---|
| 80 | if (tmp != null && tmp.length > 0) {
|
---|
| 81 | setExecutable(tmp[0]);
|
---|
| 82 | for (int i = 1; i < tmp.length; i++) {
|
---|
| 83 | createArgument().setValue(tmp[i]);
|
---|
| 84 | }
|
---|
| 85 | }
|
---|
| 86 | }
|
---|
| 87 |
|
---|
| 88 | /**
|
---|
| 89 | * Create an empty command line
|
---|
| 90 | */
|
---|
| 91 | public Commandline() {
|
---|
| 92 | super();
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 | /**
|
---|
| 96 | * Used for nested xml command line definitions.
|
---|
| 97 | */
|
---|
| 98 | public static class Argument extends ProjectComponent {
|
---|
| 99 |
|
---|
| 100 | private String[] parts;
|
---|
| 101 |
|
---|
| 102 | /**
|
---|
| 103 | * Sets a single commandline argument.
|
---|
| 104 | *
|
---|
| 105 | * @param value a single commandline argument.
|
---|
| 106 | */
|
---|
| 107 | public void setValue(String value) {
|
---|
| 108 | parts = new String[] {value};
|
---|
| 109 | }
|
---|
| 110 |
|
---|
| 111 | /**
|
---|
| 112 | * Line to split into several commandline arguments.
|
---|
| 113 | *
|
---|
| 114 | * @param line line to split into several commandline arguments
|
---|
| 115 | */
|
---|
| 116 | public void setLine(String line) {
|
---|
| 117 | if (line == null) {
|
---|
| 118 | return;
|
---|
| 119 | }
|
---|
| 120 | parts = translateCommandline(line);
|
---|
| 121 | }
|
---|
| 122 |
|
---|
| 123 | /**
|
---|
| 124 | * Sets a single commandline argument and treats it like a
|
---|
| 125 | * PATH - ensures the right separator for the local platform
|
---|
| 126 | * is used.
|
---|
| 127 | *
|
---|
| 128 | * @param value a single commandline argument.
|
---|
| 129 | */
|
---|
| 130 | public void setPath(Path value) {
|
---|
| 131 | parts = new String[] {value.toString()};
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | /**
|
---|
| 135 | * Sets a single commandline argument from a reference to a
|
---|
| 136 | * path - ensures the right separator for the local platform
|
---|
| 137 | * is used.
|
---|
| 138 | *
|
---|
| 139 | * @param value a single commandline argument.
|
---|
| 140 | */
|
---|
| 141 | public void setPathref(Reference value) {
|
---|
| 142 | Path p = new Path(getProject());
|
---|
| 143 | p.setRefid(value);
|
---|
| 144 | parts = new String[] {p.toString()};
|
---|
| 145 | }
|
---|
| 146 |
|
---|
| 147 | /**
|
---|
| 148 | * Sets a single commandline argument to the absolute filename
|
---|
| 149 | * of the given file.
|
---|
| 150 | *
|
---|
| 151 | * @param value a single commandline argument.
|
---|
| 152 | */
|
---|
| 153 | public void setFile(File value) {
|
---|
| 154 | parts = new String[] {value.getAbsolutePath()};
|
---|
| 155 | }
|
---|
| 156 |
|
---|
| 157 | /**
|
---|
| 158 | * Returns the parts this Argument consists of.
|
---|
| 159 | */
|
---|
| 160 | public String[] getParts() {
|
---|
| 161 | return parts;
|
---|
| 162 | }
|
---|
| 163 | }
|
---|
| 164 |
|
---|
| 165 | /**
|
---|
| 166 | * Class to keep track of the position of an Argument.
|
---|
| 167 | <p>This class is there to support the srcfile and targetfile
|
---|
| 168 | elements of <execon> and <transform> - don't know
|
---|
| 169 | whether there might be additional use cases.</p> --SB
|
---|
| 170 | */
|
---|
| 171 | public class Marker {
|
---|
| 172 |
|
---|
| 173 | private int position;
|
---|
| 174 | private int realPos = -1;
|
---|
| 175 |
|
---|
| 176 | Marker(int position) {
|
---|
| 177 | this.position = position;
|
---|
| 178 | }
|
---|
| 179 |
|
---|
| 180 | /**
|
---|
| 181 | * Return the number of arguments that preceeded this marker.
|
---|
| 182 | *
|
---|
| 183 | * <p>The name of the executable - if set - is counted as the
|
---|
| 184 | * very first argument.</p>
|
---|
| 185 | */
|
---|
| 186 | public int getPosition() {
|
---|
| 187 | if (realPos == -1) {
|
---|
| 188 | realPos = (executable == null ? 0 : 1);
|
---|
| 189 | for (int i = 0; i < position; i++) {
|
---|
| 190 | Argument arg = (Argument) arguments.elementAt(i);
|
---|
| 191 | realPos += arg.getParts().length;
|
---|
| 192 | }
|
---|
| 193 | }
|
---|
| 194 | return realPos;
|
---|
| 195 | }
|
---|
| 196 | }
|
---|
| 197 |
|
---|
| 198 | /**
|
---|
| 199 | * Creates an argument object.
|
---|
| 200 | *
|
---|
| 201 | * <p>Each commandline object has at most one instance of the
|
---|
| 202 | * argument class. This method calls
|
---|
| 203 | * <code>this.createArgument(false)</code>.</p>
|
---|
| 204 | *
|
---|
| 205 | * @see #createArgument(boolean)
|
---|
| 206 | * @return the argument object.
|
---|
| 207 | */
|
---|
| 208 | public Argument createArgument() {
|
---|
| 209 | return this.createArgument(false);
|
---|
| 210 | }
|
---|
| 211 |
|
---|
| 212 | /**
|
---|
| 213 | * Creates an argument object and adds it to our list of args.
|
---|
| 214 | *
|
---|
| 215 | * <p>Each commandline object has at most one instance of the
|
---|
| 216 | * argument class.</p>
|
---|
| 217 | *
|
---|
| 218 | * @param insertAtStart if true, the argument is inserted at the
|
---|
| 219 | * beginning of the list of args, otherwise it is appended.
|
---|
| 220 | */
|
---|
| 221 | public Argument createArgument(boolean insertAtStart) {
|
---|
| 222 | Argument argument = new Argument();
|
---|
| 223 | if (insertAtStart) {
|
---|
| 224 | arguments.insertElementAt(argument, 0);
|
---|
| 225 | } else {
|
---|
| 226 | arguments.addElement(argument);
|
---|
| 227 | }
|
---|
| 228 | return argument;
|
---|
| 229 | }
|
---|
| 230 |
|
---|
| 231 | /**
|
---|
| 232 | * Sets the executable to run. All file separators in the string
|
---|
| 233 | * are converted to the platform specific value
|
---|
| 234 | */
|
---|
| 235 | public void setExecutable(String executable) {
|
---|
| 236 | if (executable == null || executable.length() == 0) {
|
---|
| 237 | return;
|
---|
| 238 | }
|
---|
| 239 | this.executable = executable.replace('/', File.separatorChar)
|
---|
| 240 | .replace('\\', File.separatorChar);
|
---|
| 241 | }
|
---|
| 242 |
|
---|
| 243 |
|
---|
| 244 | /**
|
---|
| 245 | * get the executable
|
---|
| 246 | * @return the program to run -null if not yet set
|
---|
| 247 | */
|
---|
| 248 | public String getExecutable() {
|
---|
| 249 | return executable;
|
---|
| 250 | }
|
---|
| 251 |
|
---|
| 252 |
|
---|
| 253 | /**
|
---|
| 254 | * append the arguments to the existing command
|
---|
| 255 | * @param line an array of arguments to append
|
---|
| 256 | */
|
---|
| 257 | public void addArguments(String[] line) {
|
---|
| 258 | for (int i = 0; i < line.length; i++) {
|
---|
| 259 | createArgument().setValue(line[i]);
|
---|
| 260 | }
|
---|
| 261 | }
|
---|
| 262 |
|
---|
| 263 | /**
|
---|
| 264 | * Returns the executable and all defined arguments.
|
---|
| 265 | */
|
---|
| 266 | public String[] getCommandline() {
|
---|
| 267 | List commands = new LinkedList();
|
---|
| 268 | ListIterator list = commands.listIterator();
|
---|
| 269 | addCommandToList(list);
|
---|
| 270 | final String[] result = new String[commands.size()];
|
---|
| 271 | return (String[]) commands.toArray(result);
|
---|
| 272 | }
|
---|
| 273 |
|
---|
| 274 | /**
|
---|
| 275 | * add the entire command, including (optional) executable to a list
|
---|
| 276 | * @param list
|
---|
| 277 | * @since Ant 1.6
|
---|
| 278 | */
|
---|
| 279 | public void addCommandToList(ListIterator list) {
|
---|
| 280 | if (executable != null) {
|
---|
| 281 | list.add(executable);
|
---|
| 282 | }
|
---|
| 283 | addArgumentsToList(list);
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 |
|
---|
| 287 | /**
|
---|
| 288 | * Returns all arguments defined by <code>addLine</code>,
|
---|
| 289 | * <code>addValue</code> or the argument object.
|
---|
| 290 | */
|
---|
| 291 | public String[] getArguments() {
|
---|
| 292 | List result = new ArrayList(arguments.size() * 2);
|
---|
| 293 | addArgumentsToList(result.listIterator());
|
---|
| 294 | String [] res = new String[result.size()];
|
---|
| 295 | return (String[]) result.toArray(res);
|
---|
| 296 | }
|
---|
| 297 |
|
---|
| 298 | /**
|
---|
| 299 | * append all the arguments to the tail of a supplied list
|
---|
| 300 | * @param list
|
---|
| 301 | * @since Ant 1.6
|
---|
| 302 | */
|
---|
| 303 | public void addArgumentsToList(ListIterator list) {
|
---|
| 304 | for (int i = 0; i < arguments.size(); i++) {
|
---|
| 305 | Argument arg = (Argument) arguments.elementAt(i);
|
---|
| 306 | String[] s = arg.getParts();
|
---|
| 307 | if (s != null) {
|
---|
| 308 | for (int j = 0; j < s.length; j++) {
|
---|
| 309 | list.add(s[j]);
|
---|
| 310 | }
|
---|
| 311 | }
|
---|
| 312 | }
|
---|
| 313 | }
|
---|
| 314 |
|
---|
| 315 |
|
---|
| 316 | /**
|
---|
| 317 | * stringify operator returns the command line as a string
|
---|
| 318 | * @return the command line
|
---|
| 319 | */
|
---|
| 320 | public String toString() {
|
---|
| 321 | return toString(getCommandline());
|
---|
| 322 | }
|
---|
| 323 |
|
---|
| 324 | /**
|
---|
| 325 | * Put quotes around the given String if necessary.
|
---|
| 326 | *
|
---|
| 327 | * <p>If the argument doesn't include spaces or quotes, return it
|
---|
| 328 | * as is. If it contains double quotes, use single quotes - else
|
---|
| 329 | * surround the argument by double quotes.</p>
|
---|
| 330 | *
|
---|
| 331 | * @exception BuildException if the argument contains both, single
|
---|
| 332 | * and double quotes.
|
---|
| 333 | */
|
---|
| 334 | public static String quoteArgument(String argument) {
|
---|
| 335 | if (argument.indexOf("\"") > -1) {
|
---|
| 336 | if (argument.indexOf("\'") > -1) {
|
---|
| 337 | throw new BuildException("Can\'t handle single and double"
|
---|
| 338 | + " quotes in same argument");
|
---|
| 339 | } else {
|
---|
| 340 | return '\'' + argument + '\'';
|
---|
| 341 | }
|
---|
| 342 | } else if (argument.indexOf("\'") > -1 || argument.indexOf(" ") > -1) {
|
---|
| 343 | return '\"' + argument + '\"';
|
---|
| 344 | } else {
|
---|
| 345 | return argument;
|
---|
| 346 | }
|
---|
| 347 | }
|
---|
| 348 |
|
---|
| 349 | /**
|
---|
| 350 | * Quotes the parts of the given array in way that makes them
|
---|
| 351 | * usable as command line arguments.
|
---|
| 352 | * @return empty string for null or no command, else every argument split
|
---|
| 353 | * by spaces and quoted by quoting rules
|
---|
| 354 | */
|
---|
| 355 | public static String toString(String [] line) {
|
---|
| 356 | // empty path return empty string
|
---|
| 357 | if (line == null || line.length == 0) {
|
---|
| 358 | return "";
|
---|
| 359 | }
|
---|
| 360 |
|
---|
| 361 | // path containing one or more elements
|
---|
| 362 | final StringBuffer result = new StringBuffer();
|
---|
| 363 | for (int i = 0; i < line.length; i++) {
|
---|
| 364 | if (i > 0) {
|
---|
| 365 | result.append(' ');
|
---|
| 366 | }
|
---|
| 367 | result.append(quoteArgument(line[i]));
|
---|
| 368 | }
|
---|
| 369 | return result.toString();
|
---|
| 370 | }
|
---|
| 371 |
|
---|
| 372 | /**
|
---|
| 373 | * crack a command line
|
---|
| 374 | * @param toProcess the command line to process
|
---|
| 375 | * @return the command line broken into strings.
|
---|
| 376 | * An empty or null toProcess parameter results in a zero sized array
|
---|
| 377 | */
|
---|
| 378 | public static String[] translateCommandline(String toProcess) {
|
---|
| 379 | if (toProcess == null || toProcess.length() == 0) {
|
---|
| 380 | //no command? no string
|
---|
| 381 | return new String[0];
|
---|
| 382 | }
|
---|
| 383 |
|
---|
| 384 | // parse with a simple finite state machine
|
---|
| 385 |
|
---|
| 386 | final int normal = 0;
|
---|
| 387 | final int inQuote = 1;
|
---|
| 388 | final int inDoubleQuote = 2;
|
---|
| 389 | int state = normal;
|
---|
| 390 | StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
|
---|
| 391 | Vector v = new Vector();
|
---|
| 392 | StringBuffer current = new StringBuffer();
|
---|
| 393 | boolean lastTokenHasBeenQuoted = false;
|
---|
| 394 |
|
---|
| 395 | while (tok.hasMoreTokens()) {
|
---|
| 396 | String nextTok = tok.nextToken();
|
---|
| 397 | switch (state) {
|
---|
| 398 | case inQuote:
|
---|
| 399 | if ("\'".equals(nextTok)) {
|
---|
| 400 | lastTokenHasBeenQuoted = true;
|
---|
| 401 | state = normal;
|
---|
| 402 | } else {
|
---|
| 403 | current.append(nextTok);
|
---|
| 404 | }
|
---|
| 405 | break;
|
---|
| 406 | case inDoubleQuote:
|
---|
| 407 | if ("\"".equals(nextTok)) {
|
---|
| 408 | lastTokenHasBeenQuoted = true;
|
---|
| 409 | state = normal;
|
---|
| 410 | } else {
|
---|
| 411 | current.append(nextTok);
|
---|
| 412 | }
|
---|
| 413 | break;
|
---|
| 414 | default:
|
---|
| 415 | if ("\'".equals(nextTok)) {
|
---|
| 416 | state = inQuote;
|
---|
| 417 | } else if ("\"".equals(nextTok)) {
|
---|
| 418 | state = inDoubleQuote;
|
---|
| 419 | } else if (" ".equals(nextTok)) {
|
---|
| 420 | if (lastTokenHasBeenQuoted || current.length() != 0) {
|
---|
| 421 | v.addElement(current.toString());
|
---|
| 422 | current = new StringBuffer();
|
---|
| 423 | }
|
---|
| 424 | } else {
|
---|
| 425 | current.append(nextTok);
|
---|
| 426 | }
|
---|
| 427 | lastTokenHasBeenQuoted = false;
|
---|
| 428 | break;
|
---|
| 429 | }
|
---|
| 430 | }
|
---|
| 431 |
|
---|
| 432 | if (lastTokenHasBeenQuoted || current.length() != 0) {
|
---|
| 433 | v.addElement(current.toString());
|
---|
| 434 | }
|
---|
| 435 |
|
---|
| 436 | if (state == inQuote || state == inDoubleQuote) {
|
---|
| 437 | throw new BuildException("unbalanced quotes in " + toProcess);
|
---|
| 438 | }
|
---|
| 439 |
|
---|
| 440 | String[] args = new String[v.size()];
|
---|
| 441 | v.copyInto(args);
|
---|
| 442 | return args;
|
---|
| 443 | }
|
---|
| 444 |
|
---|
| 445 | /**
|
---|
| 446 | * size operator. This actually creates the command line, so it is not
|
---|
| 447 | * a zero cost operation.
|
---|
| 448 | * @return number of elements in the command, including the executable
|
---|
| 449 | */
|
---|
| 450 | public int size() {
|
---|
| 451 | return getCommandline().length;
|
---|
| 452 | }
|
---|
| 453 |
|
---|
| 454 | /**
|
---|
| 455 | * Generate a deep clone of the contained object.
|
---|
| 456 | * @return a clone of the contained object
|
---|
| 457 | */
|
---|
| 458 | public Object clone() {
|
---|
| 459 | try {
|
---|
| 460 | Commandline c = (Commandline) super.clone();
|
---|
| 461 | c.arguments = (Vector) arguments.clone();
|
---|
| 462 | return c;
|
---|
| 463 | } catch (CloneNotSupportedException e) {
|
---|
| 464 | throw new BuildException(e);
|
---|
| 465 | }
|
---|
| 466 | }
|
---|
| 467 |
|
---|
| 468 | /**
|
---|
| 469 | * Clear out the whole command line. */
|
---|
| 470 | public void clear() {
|
---|
| 471 | executable = null;
|
---|
| 472 | arguments.removeAllElements();
|
---|
| 473 | }
|
---|
| 474 |
|
---|
| 475 | /**
|
---|
| 476 | * Clear out the arguments but leave the executable in place for
|
---|
| 477 | * another operation.
|
---|
| 478 | */
|
---|
| 479 | public void clearArgs() {
|
---|
| 480 | arguments.removeAllElements();
|
---|
| 481 | }
|
---|
| 482 |
|
---|
| 483 | /**
|
---|
| 484 | * Return a marker.
|
---|
| 485 | *
|
---|
| 486 | * <p>This marker can be used to locate a position on the
|
---|
| 487 | * commandline - to insert something for example - when all
|
---|
| 488 | * parameters have been set.</p>
|
---|
| 489 | */
|
---|
| 490 | public Marker createMarker() {
|
---|
| 491 | return new Marker(arguments.size());
|
---|
| 492 | }
|
---|
| 493 |
|
---|
| 494 | /**
|
---|
| 495 | * Returns a String that describes the command and arguments
|
---|
| 496 | * suitable for verbose output before a call to
|
---|
| 497 | * <code>Runtime.exec(String[])<code>
|
---|
| 498 | *
|
---|
| 499 | * @since Ant 1.5
|
---|
| 500 | */
|
---|
| 501 | public String describeCommand() {
|
---|
| 502 | return describeCommand(this);
|
---|
| 503 | }
|
---|
| 504 |
|
---|
| 505 | /**
|
---|
| 506 | * Returns a String that describes the arguments suitable for
|
---|
| 507 | * verbose output before a call to
|
---|
| 508 | * <code>Runtime.exec(String[])<code>
|
---|
| 509 | *
|
---|
| 510 | * @since Ant 1.5
|
---|
| 511 | */
|
---|
| 512 | public String describeArguments() {
|
---|
| 513 | return describeArguments(this);
|
---|
| 514 | }
|
---|
| 515 |
|
---|
| 516 | /**
|
---|
| 517 | * Returns a String that describes the command and arguments
|
---|
| 518 | * suitable for verbose output before a call to
|
---|
| 519 | * <code>Runtime.exec(String[])<code>
|
---|
| 520 | *
|
---|
| 521 | * @since Ant 1.5
|
---|
| 522 | */
|
---|
| 523 | public static String describeCommand(Commandline line) {
|
---|
| 524 | return describeCommand(line.getCommandline());
|
---|
| 525 | }
|
---|
| 526 |
|
---|
| 527 | /**
|
---|
| 528 | * Returns a String that describes the arguments suitable for
|
---|
| 529 | * verbose output before a call to
|
---|
| 530 | * <code>Runtime.exec(String[])<code>
|
---|
| 531 | *
|
---|
| 532 | * @since Ant 1.5
|
---|
| 533 | */
|
---|
| 534 | public static String describeArguments(Commandline line) {
|
---|
| 535 | return describeArguments(line.getArguments());
|
---|
| 536 | }
|
---|
| 537 |
|
---|
| 538 | /**
|
---|
| 539 | * Returns a String that describes the command and arguments
|
---|
| 540 | * suitable for verbose output before a call to
|
---|
| 541 | * <code>Runtime.exec(String[])<code>.
|
---|
| 542 | *
|
---|
| 543 | * <p>This method assumes that the first entry in the array is the
|
---|
| 544 | * executable to run.</p>
|
---|
| 545 | *
|
---|
| 546 | * @since Ant 1.5
|
---|
| 547 | */
|
---|
| 548 | public static String describeCommand(String[] args) {
|
---|
| 549 | if (args == null || args.length == 0) {
|
---|
| 550 | return "";
|
---|
| 551 | }
|
---|
| 552 |
|
---|
| 553 | StringBuffer buf = new StringBuffer("Executing \'");
|
---|
| 554 | buf.append(args[0]);
|
---|
| 555 | buf.append("\'");
|
---|
| 556 | if (args.length > 0) {
|
---|
| 557 | buf.append(" with ");
|
---|
| 558 | buf.append(describeArguments(args, 1));
|
---|
| 559 | } else {
|
---|
| 560 | buf.append(DISCLAIMER);
|
---|
| 561 | }
|
---|
| 562 | return buf.toString();
|
---|
| 563 | }
|
---|
| 564 |
|
---|
| 565 | /**
|
---|
| 566 | * Returns a String that describes the arguments suitable for
|
---|
| 567 | * verbose output before a call to
|
---|
| 568 | * <code>Runtime.exec(String[])<code>
|
---|
| 569 | *
|
---|
| 570 | * @since Ant 1.5
|
---|
| 571 | */
|
---|
| 572 | public static String describeArguments(String[] args) {
|
---|
| 573 | return describeArguments(args, 0);
|
---|
| 574 | }
|
---|
| 575 |
|
---|
| 576 | /**
|
---|
| 577 | * Returns a String that describes the arguments suitable for
|
---|
| 578 | * verbose output before a call to
|
---|
| 579 | * <code>Runtime.exec(String[])<code>
|
---|
| 580 | *
|
---|
| 581 | * @param offset ignore entries before this index
|
---|
| 582 | *
|
---|
| 583 | * @since Ant 1.5
|
---|
| 584 | */
|
---|
| 585 | protected static String describeArguments(String[] args, int offset) {
|
---|
| 586 | if (args == null || args.length <= offset) {
|
---|
| 587 | return "";
|
---|
| 588 | }
|
---|
| 589 |
|
---|
| 590 | StringBuffer buf = new StringBuffer("argument");
|
---|
| 591 | if (args.length > offset) {
|
---|
| 592 | buf.append("s");
|
---|
| 593 | }
|
---|
| 594 | buf.append(":").append(StringUtils.LINE_SEP);
|
---|
| 595 | for (int i = offset; i < args.length; i++) {
|
---|
| 596 | buf.append("\'").append(args[i]).append("\'")
|
---|
| 597 | .append(StringUtils.LINE_SEP);
|
---|
| 598 | }
|
---|
| 599 | buf.append(DISCLAIMER);
|
---|
| 600 | return buf.toString();
|
---|
| 601 | }
|
---|
| 602 | }
|
---|