1 /* 2 Licensed to the Apache Software Foundation (ASF) under one or more 3 contributor license agreements. See the NOTICE file distributed with 4 this work for additional information regarding copyright ownership. 5 The ASF licenses this file to You under the Apache License, Version 2.0 6 (the "License"); you may not use this file except in compliance with 7 the License. You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11 Unless required by applicable law or agreed to in writing, software 12 distributed under the License is distributed on an "AS IS" BASIS, 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 See the License for the specific language governing permissions and 15 limitations under the License. 16 */ 17 18 package org.apache.commons.cli; 19 20 import static org.apache.commons.cli.Util.EMPTY_STRING_ARRAY; 21 22 import java.io.Serializable; 23 import java.util.ArrayList; 24 import java.util.Iterator; 25 import java.util.LinkedList; 26 import java.util.List; 27 import java.util.Properties; 28 29 /** 30 * Represents list of arguments parsed against a {@link Options} descriptor. 31 * <p> 32 * It allows querying of a boolean {@link #hasOption(String opt)}, in addition to retrieving the 33 * {@link #getOptionValue(String opt)} for options requiring arguments. 34 * <p> 35 * Additionally, any left-over or unrecognized arguments, are available for further processing. 36 */ 37 public class CommandLine implements Serializable { 38 39 /** 40 * A nested builder class to create {@code CommandLine} instance using descriptive methods. 41 * 42 * @since 1.4 43 */ 44 public static final class Builder { 45 46 /** 47 * CommandLine that is being build by this Builder. 48 */ 49 private final CommandLine commandLine = new CommandLine(); 50 51 /** 52 * Adds left-over unrecognized option/argument. 53 * 54 * @param arg the unrecognized option/argument. 55 * 56 * @return this Builder instance for method chaining. 57 */ 58 public Builder addArg(final String arg) { 59 commandLine.addArg(arg); 60 return this; 61 } 62 63 /** 64 * Adds an option to the command line. The values of the option are stored. 65 * 66 * @param opt the processed option. 67 * 68 * @return this Builder instance for method chaining. 69 */ 70 public Builder addOption(final Option opt) { 71 commandLine.addOption(opt); 72 return this; 73 } 74 75 /** 76 * Returns the new instance. 77 * 78 * @return the new instance. 79 */ 80 public CommandLine build() { 81 return commandLine; 82 } 83 } 84 85 /** The serial version UID. */ 86 private static final long serialVersionUID = 1L; 87 88 /** The unrecognized options/arguments */ 89 private final List<String> args = new LinkedList<>(); 90 91 /** The processed options */ 92 private final List<Option> options = new ArrayList<>(); 93 94 /** 95 * Creates a command line. 96 */ 97 protected CommandLine() { 98 // nothing to do 99 } 100 101 /** 102 * Adds left-over unrecognized option/argument. 103 * 104 * @param arg the unrecognized option/argument. 105 */ 106 protected void addArg(final String arg) { 107 if (arg != null) { 108 args.add(arg); 109 } 110 } 111 112 /** 113 * Adds an option to the command line. The values of the option are stored. 114 * 115 * @param opt the processed option. 116 */ 117 protected void addOption(final Option opt) { 118 if (opt != null) { 119 options.add(opt); 120 } 121 } 122 123 /** 124 * Gets any left-over non-recognized options and arguments 125 * 126 * @return remaining items passed in but not parsed as a {@code List}. 127 */ 128 public List<String> getArgList() { 129 return args; 130 } 131 132 /** 133 * Gets any left-over non-recognized options and arguments 134 * 135 * @return remaining items passed in but not parsed as an array. 136 */ 137 public String[] getArgs() { 138 return args.toArray(Util.EMPTY_STRING_ARRAY); 139 } 140 141 /** 142 * Gets the {@code Object} type of this {@code Option}. 143 * 144 * @deprecated due to System.err message. Instead use getParsedOptionValue(char) 145 * @param opt the name of the option. 146 * @return the type of opt. 147 */ 148 @Deprecated 149 public Object getOptionObject(final char opt) { 150 return getOptionObject(String.valueOf(opt)); 151 } 152 153 /** 154 * Gets the {@code Object} type of this {@code Option}. 155 * 156 * @param opt the name of the option. 157 * @return the type of this {@code Option}. 158 * @deprecated due to System.err message. Instead use getParsedOptionValue(String) 159 */ 160 @Deprecated 161 public Object getOptionObject(final String opt) { 162 try { 163 return getParsedOptionValue(opt); 164 } catch (final ParseException pe) { 165 System.err.println("Exception found converting " + opt + " to desired type: " + pe.getMessage()); 166 return null; 167 } 168 } 169 170 /** 171 * Gets the map of values associated to the option. This is convenient for options specifying Java properties like 172 * <code>-Dparam1=value1 173 * -Dparam2=value2</code>. The first argument of the option is the key, and the 2nd argument is the value. If the option 174 * has only one argument ({@code -Dfoo}) it is considered as a boolean flag and the value is {@code "true"}. 175 * 176 * @param option name of the option. 177 * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists. 178 * @since 1.5.0 179 */ 180 public Properties getOptionProperties(final Option option) { 181 final Properties props = new Properties(); 182 183 for (final Option processedOption : options) { 184 if (processedOption.equals(option)) { 185 final List<String> values = processedOption.getValuesList(); 186 if (values.size() >= 2) { 187 // use the first 2 arguments as the key/value pair 188 props.put(values.get(0), values.get(1)); 189 } else if (values.size() == 1) { 190 // no explicit value, handle it as a boolean 191 props.put(values.get(0), "true"); 192 } 193 } 194 } 195 196 return props; 197 } 198 199 /** 200 * Gets the map of values associated to the option. This is convenient for options specifying Java properties like 201 * <code>-Dparam1=value1 202 * -Dparam2=value2</code>. The first argument of the option is the key, and the 2nd argument is the value. If the option 203 * has only one argument ({@code -Dfoo}) it is considered as a boolean flag and the value is {@code "true"}. 204 * 205 * @param opt name of the option. 206 * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists. 207 * @since 1.2 208 */ 209 public Properties getOptionProperties(final String opt) { 210 final Properties props = new Properties(); 211 212 for (final Option option : options) { 213 if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt())) { 214 final List<String> values = option.getValuesList(); 215 if (values.size() >= 2) { 216 // use the first 2 arguments as the key/value pair 217 props.put(values.get(0), values.get(1)); 218 } else if (values.size() == 1) { 219 // no explicit value, handle it as a boolean 220 props.put(values.get(0), "true"); 221 } 222 } 223 } 224 225 return props; 226 } 227 228 /** 229 * Gets an array of the processed {@link Option}s. 230 * 231 * @return an array of the processed {@link Option}s. 232 */ 233 public Option[] getOptions() { 234 return options.toArray(Option.EMPTY_ARRAY); 235 } 236 237 /** 238 * Gets the first argument, if any, of this option. 239 * 240 * @param opt the character name of the option. 241 * @return Value of the argument if option is set, and has an argument, otherwise null. 242 */ 243 public String getOptionValue(final char opt) { 244 return getOptionValue(String.valueOf(opt)); 245 } 246 247 /** 248 * Gets the argument, if any, of an option. 249 * 250 * @param opt character name of the option 251 * @param defaultValue is the default value to be returned if the option is not specified. 252 * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}. 253 */ 254 public String getOptionValue(final char opt, final String defaultValue) { 255 return getOptionValue(String.valueOf(opt), defaultValue); 256 } 257 258 /** 259 * Gets the first argument, if any, of this option. 260 * 261 * @param option the name of the option. 262 * @return Value of the argument if option is set, and has an argument, otherwise null. 263 * @since 1.5.0 264 */ 265 public String getOptionValue(final Option option) { 266 if (option == null) { 267 return null; 268 } 269 final String[] values = getOptionValues(option); 270 return values == null ? null : values[0]; 271 } 272 273 /** 274 * Gets the first argument, if any, of an option. 275 * 276 * @param option name of the option. 277 * @param defaultValue is the default value to be returned if the option is not specified. 278 * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}. 279 * @since 1.5.0 280 */ 281 public String getOptionValue(final Option option, final String defaultValue) { 282 final String answer = getOptionValue(option); 283 return answer != null ? answer : defaultValue; 284 } 285 286 /** 287 * Gets the first argument, if any, of this option. 288 * 289 * @param opt the name of the option. 290 * @return Value of the argument if option is set, and has an argument, otherwise null. 291 */ 292 public String getOptionValue(final String opt) { 293 return getOptionValue(resolveOption(opt)); 294 } 295 296 /** 297 * Gets the first argument, if any, of an option. 298 * 299 * @param opt name of the option. 300 * @param defaultValue is the default value to be returned if the option is not specified. 301 * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}. 302 */ 303 public String getOptionValue(final String opt, final String defaultValue) { 304 return getOptionValue(resolveOption(opt), defaultValue); 305 } 306 307 /** 308 * Gets the array of values, if any, of an option. 309 * 310 * @param opt character name of the option. 311 * @return Values of the argument if option is set, and has an argument, otherwise null. 312 */ 313 public String[] getOptionValues(final char opt) { 314 return getOptionValues(String.valueOf(opt)); 315 } 316 317 /** 318 * Gets the array of values, if any, of an option. 319 * 320 * @param option string name of the option. 321 * @return Values of the argument if option is set, and has an argument, otherwise null. 322 * @since 1.5.0 323 */ 324 public String[] getOptionValues(final Option option) { 325 final List<String> values = new ArrayList<>(); 326 327 for (final Option processedOption : options) { 328 if (processedOption.equals(option)) { 329 values.addAll(processedOption.getValuesList()); 330 } 331 } 332 333 return values.isEmpty() ? null : values.toArray(EMPTY_STRING_ARRAY); 334 } 335 336 /** 337 * Gets the array of values, if any, of an option. 338 * 339 * @param opt string name of the option. 340 * @return Values of the argument if option is set, and has an argument, otherwise null. 341 */ 342 public String[] getOptionValues(final String opt) { 343 return getOptionValues(resolveOption(opt)); 344 } 345 346 /** 347 * Gets a version of this {@code Option} converted to a particular type. 348 * 349 * @param opt the name of the option. 350 * @return the value parsed into a particular object. 351 * @throws ParseException if there are problems turning the option value into the desired type 352 * @see PatternOptionBuilder 353 * @since 1.5.0 354 */ 355 public Object getParsedOptionValue(final char opt) throws ParseException { 356 return getParsedOptionValue(String.valueOf(opt)); 357 } 358 359 /** 360 * Gets a version of this {@code Option} converted to a particular type. 361 * 362 * @param option the name of the option. 363 * @return the value parsed into a particular object. 364 * @throws ParseException if there are problems turning the option value into the desired type 365 * @see PatternOptionBuilder 366 * @since 1.5.0 367 */ 368 public Object getParsedOptionValue(final Option option) throws ParseException { 369 if (option == null) { 370 return null; 371 } 372 final String res = getOptionValue(option); 373 if (res == null) { 374 return null; 375 } 376 return TypeHandler.createValue(res, option.getType()); 377 } 378 379 /** 380 * Gets a version of this {@code Option} converted to a particular type. 381 * 382 * @param opt the name of the option. 383 * @return the value parsed into a particular object. 384 * @throws ParseException if there are problems turning the option value into the desired type 385 * @see PatternOptionBuilder 386 * @since 1.2 387 */ 388 public Object getParsedOptionValue(final String opt) throws ParseException { 389 return getParsedOptionValue(resolveOption(opt)); 390 } 391 392 /** 393 * jkeyes - commented out until it is implemented properly 394 * <p> 395 * Dump state, suitable for debugging. 396 * </p> 397 * 398 * @return Stringified form of this object. 399 */ 400 401 /* 402 * public String toString() { StringBuilder buf = new StringBuilder(); 403 * 404 * buf.append("[ CommandLine: [ options: "); buf.append(options.toString()); buf.append(" ] [ args: "); 405 * buf.append(args.toString()); buf.append(" ] ]"); 406 * 407 * return buf.toString(); } 408 */ 409 410 /** 411 * Tests to see if an option has been set. 412 * 413 * @param opt character name of the option. 414 * @return true if set, false if not. 415 */ 416 public boolean hasOption(final char opt) { 417 return hasOption(String.valueOf(opt)); 418 } 419 420 /** 421 * Tests to see if an option has been set. 422 * 423 * @param opt the option to check. 424 * @return true if set, false if not. 425 * @since 1.5.0 426 */ 427 public boolean hasOption(final Option opt) { 428 return options.contains(opt); 429 } 430 431 /** 432 * Tests to see if an option has been set. 433 * 434 * @param opt Short name of the option. 435 * @return true if set, false if not. 436 */ 437 public boolean hasOption(final String opt) { 438 return hasOption(resolveOption(opt)); 439 } 440 441 /** 442 * Returns an iterator over the Option members of CommandLine. 443 * 444 * @return an {@code Iterator} over the processed {@link Option} members of this {@link CommandLine}. 445 */ 446 public Iterator<Option> iterator() { 447 return options.iterator(); 448 } 449 450 /** 451 * Retrieves the option object given the long or short option as a String 452 * 453 * @param opt short or long name of the option, may be null. 454 * @return Canonicalized option. 455 */ 456 private Option resolveOption(final String opt) { 457 final String actual = Util.stripLeadingHyphens(opt); 458 if (actual != null) { 459 for (final Option option : options) { 460 if (actual.equals(option.getOpt()) || actual.equals(option.getLongOpt())) { 461 return option; 462 } 463 } 464 } 465 return null; 466 } 467 }