001/* 002 Licensed to the Apache Software Foundation (ASF) under one or more 003 contributor license agreements. See the NOTICE file distributed with 004 this work for additional information regarding copyright ownership. 005 The ASF licenses this file to You under the Apache License, Version 2.0 006 (the "License"); you may not use this file except in compliance with 007 the License. You may obtain a copy of the License at 008 009 http://www.apache.org/licenses/LICENSE-2.0 010 011 Unless required by applicable law or agreed to in writing, software 012 distributed under the License is distributed on an "AS IS" BASIS, 013 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 See the License for the specific language governing permissions and 015 limitations under the License. 016 */ 017 018package org.apache.commons.cli; 019 020import java.io.Serializable; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Iterator; 024import java.util.LinkedList; 025import java.util.List; 026import java.util.Properties; 027 028/** 029 * Represents list of arguments parsed against a {@link Options} descriptor. 030 * <p> 031 * It allows querying of a boolean {@link #hasOption(String opt)}, in addition to retrieving the 032 * {@link #getOptionValue(String opt)} for options requiring arguments. 033 * <p> 034 * Additionally, any left-over or unrecognized arguments, are available for further processing. 035 */ 036public class CommandLine implements Serializable { 037 /** 038 * A nested builder class to create {@code CommandLine} instance using descriptive methods. 039 * 040 * @since 1.4 041 */ 042 public static final class Builder { 043 /** 044 * CommandLine that is being build by this Builder. 045 */ 046 private final CommandLine commandLine = new CommandLine(); 047 048 /** 049 * Add left-over unrecognized option/argument. 050 * 051 * @param arg the unrecognized option/argument. 052 * 053 * @return this Builder instance for method chaining. 054 */ 055 public Builder addArg(final String arg) { 056 commandLine.addArg(arg); 057 return this; 058 } 059 060 /** 061 * Add an option to the command line. The values of the option are stored. 062 * 063 * @param opt the processed option. 064 * 065 * @return this Builder instance for method chaining. 066 */ 067 public Builder addOption(final Option opt) { 068 commandLine.addOption(opt); 069 return this; 070 } 071 072 public CommandLine build() { 073 return commandLine; 074 } 075 } 076 077 /** The serial version UID. */ 078 private static final long serialVersionUID = 1L; 079 080 /** The unrecognized options/arguments */ 081 private final List<String> args = new LinkedList<>(); 082 083 /** The processed options */ 084 private final List<Option> options = new ArrayList<>(); 085 086 /** 087 * Creates a command line. 088 */ 089 protected CommandLine() { 090 // nothing to do 091 } 092 093 /** 094 * Add left-over unrecognized option/argument. 095 * 096 * @param arg the unrecognized option/argument. 097 */ 098 protected void addArg(final String arg) { 099 args.add(arg); 100 } 101 102 /** 103 * Add an option to the command line. The values of the option are stored. 104 * 105 * @param opt the processed option. 106 */ 107 protected void addOption(final Option opt) { 108 options.add(opt); 109 } 110 111 /** 112 * Retrieve any left-over non-recognized options and arguments 113 * 114 * @return remaining items passed in but not parsed as a {@code List}. 115 */ 116 public List<String> getArgList() { 117 return args; 118 } 119 120 /** 121 * Retrieve any left-over non-recognized options and arguments 122 * 123 * @return remaining items passed in but not parsed as an array. 124 */ 125 public String[] getArgs() { 126 final String[] answer = new String[args.size()]; 127 128 args.toArray(answer); 129 130 return answer; 131 } 132 133 /** 134 * Return the {@code Object} type of this {@code Option}. 135 * 136 * @deprecated due to System.err message. Instead use getParsedOptionValue(char) 137 * @param opt the name of the option. 138 * @return the type of opt. 139 */ 140 @Deprecated 141 public Object getOptionObject(final char opt) { 142 return getOptionObject(String.valueOf(opt)); 143 } 144 145 /** 146 * Return the {@code Object} type of this {@code Option}. 147 * 148 * @param opt the name of the option. 149 * @return the type of this {@code Option}. 150 * @deprecated due to System.err message. Instead use getParsedOptionValue(String) 151 */ 152 @Deprecated 153 public Object getOptionObject(final String opt) { 154 try { 155 return getParsedOptionValue(opt); 156 } catch (final ParseException pe) { 157 System.err.println("Exception found converting " + opt + " to desired type: " + pe.getMessage()); 158 return null; 159 } 160 } 161 162 /** 163 * Retrieve the map of values associated to the option. This is convenient for options specifying Java properties like 164 * <code>-Dparam1=value1 165 * -Dparam2=value2</code>. The first argument of the option is the key, and the 2nd argument is the value. If the option 166 * has only one argument ({@code -Dfoo}) it is considered as a boolean flag and the value is {@code "true"}. 167 * 168 * @param option name of the option. 169 * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists. 170 * @since 1.5.0 171 */ 172 public Properties getOptionProperties(final Option option) { 173 final Properties props = new Properties(); 174 175 for (final Option processedOption : options) { 176 if (processedOption.equals(option)) { 177 final List<String> values = processedOption.getValuesList(); 178 if (values.size() >= 2) { 179 // use the first 2 arguments as the key/value pair 180 props.put(values.get(0), values.get(1)); 181 } else if (values.size() == 1) { 182 // no explicit value, handle it as a boolean 183 props.put(values.get(0), "true"); 184 } 185 } 186 } 187 188 return props; 189 } 190 191 /** 192 * Retrieve the map of values associated to the option. This is convenient for options specifying Java properties like 193 * <code>-Dparam1=value1 194 * -Dparam2=value2</code>. The first argument of the option is the key, and the 2nd argument is the value. If the option 195 * has only one argument ({@code -Dfoo}) it is considered as a boolean flag and the value is {@code "true"}. 196 * 197 * @param opt name of the option. 198 * @return The Properties mapped by the option, never {@code null} even if the option doesn't exists. 199 * @since 1.2 200 */ 201 public Properties getOptionProperties(final String opt) { 202 final Properties props = new Properties(); 203 204 for (final Option option : options) { 205 if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt())) { 206 final List<String> values = option.getValuesList(); 207 if (values.size() >= 2) { 208 // use the first 2 arguments as the key/value pair 209 props.put(values.get(0), values.get(1)); 210 } else if (values.size() == 1) { 211 // no explicit value, handle it as a boolean 212 props.put(values.get(0), "true"); 213 } 214 } 215 } 216 217 return props; 218 } 219 220 /** 221 * Gets an array of the processed {@link Option}s. 222 * 223 * @return an array of the processed {@link Option}s. 224 */ 225 public Option[] getOptions() { 226 final Collection<Option> processed = options; 227 228 // reinitialize array 229 final Option[] optionsArray = new Option[processed.size()]; 230 231 // return the array 232 return processed.toArray(optionsArray); 233 } 234 235 /** 236 * Retrieve the first argument, if any, of this option. 237 * 238 * @param opt the character name of the option. 239 * @return Value of the argument if option is set, and has an argument, otherwise null. 240 */ 241 public String getOptionValue(final char opt) { 242 return getOptionValue(String.valueOf(opt)); 243 } 244 245 /** 246 * Retrieve the argument, if any, of an option. 247 * 248 * @param opt character name of the option 249 * @param defaultValue is the default value to be returned if the option is not specified. 250 * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}. 251 */ 252 public String getOptionValue(final char opt, final String defaultValue) { 253 return getOptionValue(String.valueOf(opt), defaultValue); 254 } 255 256 /** 257 * Retrieve the first argument, if any, of this option. 258 * 259 * @param option the name of the option. 260 * @return Value of the argument if option is set, and has an argument, otherwise null. 261 * @since 1.5.0 262 */ 263 public String getOptionValue(final Option option) { 264 if (option == null) { 265 return null; 266 } 267 final String[] values = getOptionValues(option); 268 return values == null ? null : values[0]; 269 } 270 271 /** 272 * Retrieve the first argument, if any, of an option. 273 * 274 * @param option name of the option. 275 * @param defaultValue is the default value to be returned if the option is not specified. 276 * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}. 277 * @since 1.5.0 278 */ 279 public String getOptionValue(final Option option, final String defaultValue) { 280 final String answer = getOptionValue(option); 281 return answer != null ? answer : defaultValue; 282 } 283 284 /** 285 * Retrieve the first argument, if any, of this option. 286 * 287 * @param opt the name of the option. 288 * @return Value of the argument if option is set, and has an argument, otherwise null. 289 */ 290 public String getOptionValue(final String opt) { 291 return getOptionValue(resolveOption(opt)); 292 } 293 294 /** 295 * Retrieve the first argument, if any, of an option. 296 * 297 * @param opt name of the option. 298 * @param defaultValue is the default value to be returned if the option is not specified. 299 * @return Value of the argument if option is set, and has an argument, otherwise {@code defaultValue}. 300 */ 301 public String getOptionValue(final String opt, final String defaultValue) { 302 return getOptionValue(resolveOption(opt), defaultValue); 303 } 304 305 /** 306 * Retrieves the array of values, if any, of an option. 307 * 308 * @param opt character name of the option. 309 * @return Values of the argument if option is set, and has an argument, otherwise null. 310 */ 311 public String[] getOptionValues(final char opt) { 312 return getOptionValues(String.valueOf(opt)); 313 } 314 315 /** 316 * Retrieves the array of values, if any, of an option. 317 * 318 * @param option string name of the option. 319 * @return Values of the argument if option is set, and has an argument, otherwise null. 320 * @since 1.5.0 321 */ 322 public String[] getOptionValues(final Option option) { 323 final List<String> values = new ArrayList<>(); 324 325 for (final Option processedOption : options) { 326 if (processedOption.equals(option)) { 327 values.addAll(processedOption.getValuesList()); 328 } 329 } 330 331 return values.isEmpty() ? null : values.toArray(new String[values.size()]); 332 } 333 334 /** 335 * Retrieves the array of values, if any, of an option. 336 * 337 * @param opt string name of the option. 338 * @return Values of the argument if option is set, and has an argument, otherwise null. 339 */ 340 public String[] getOptionValues(final String opt) { 341 return getOptionValues(resolveOption(opt)); 342 } 343 344 /** 345 * Return a version of this {@code Option} converted to a particular type. 346 * 347 * @param opt the name of the option. 348 * @return the value parsed into a particular object. 349 * @throws ParseException if there are problems turning the option value into the desired type 350 * @see PatternOptionBuilder 351 * @since 1.5.0 352 */ 353 public Object getParsedOptionValue(final char opt) throws ParseException { 354 return getParsedOptionValue(String.valueOf(opt)); 355 } 356 357 /** 358 * Return a version of this {@code Option} converted to a particular type. 359 * 360 * @param option the name of the option. 361 * @return the value parsed into a particular object. 362 * @throws ParseException if there are problems turning the option value into the desired type 363 * @see PatternOptionBuilder 364 * @since 1.5.0 365 */ 366 public Object getParsedOptionValue(final Option option) throws ParseException { 367 if (option == null) { 368 return null; 369 } 370 final String res = getOptionValue(option); 371 if (res == null) { 372 return null; 373 } 374 return TypeHandler.createValue(res, option.getType()); 375 } 376 377 /** 378 * Return a version of this {@code Option} converted to a particular type. 379 * 380 * @param opt the name of the option. 381 * @return the value parsed into a particular object. 382 * @throws ParseException if there are problems turning the option value into the desired type 383 * @see PatternOptionBuilder 384 * @since 1.2 385 */ 386 public Object getParsedOptionValue(final String opt) throws ParseException { 387 return getParsedOptionValue(resolveOption(opt)); 388 } 389 390 /** 391 * jkeyes - commented out until it is implemented properly 392 * <p> 393 * Dump state, suitable for debugging. 394 * </p> 395 * 396 * @return Stringified form of this object. 397 */ 398 399 /* 400 * public String toString() { StringBuilder buf = new StringBuilder(); 401 * 402 * buf.append("[ CommandLine: [ options: "); buf.append(options.toString()); buf.append(" ] [ args: "); 403 * buf.append(args.toString()); buf.append(" ] ]"); 404 * 405 * return buf.toString(); } 406 */ 407 408 /** 409 * Tests to see if an option has been set. 410 * 411 * @param opt character name of the option. 412 * @return true if set, false if not. 413 */ 414 public boolean hasOption(final char opt) { 415 return hasOption(String.valueOf(opt)); 416 } 417 418 /** 419 * Tests to see if an option has been set. 420 * 421 * @param opt the option to check. 422 * @return true if set, false if not. 423 * @since 1.5.0 424 */ 425 public boolean hasOption(final Option opt) { 426 return options.contains(opt); 427 } 428 429 /** 430 * Tests to see if an option has been set. 431 * 432 * @param opt Short name of the option. 433 * @return true if set, false if not. 434 */ 435 public boolean hasOption(final String opt) { 436 return hasOption(resolveOption(opt)); 437 } 438 439 /** 440 * Returns an iterator over the Option members of CommandLine. 441 * 442 * @return an {@code Iterator} over the processed {@link Option} members of this {@link CommandLine}. 443 */ 444 public Iterator<Option> iterator() { 445 return options.iterator(); 446 } 447 448 /** 449 * Retrieves the option object given the long or short option as a String 450 * 451 * @param opt short or long name of the option. 452 * @return Canonicalized option. 453 */ 454 private Option resolveOption(String opt) { 455 opt = Util.stripLeadingHyphens(opt); 456 for (final Option option : options) { 457 if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt())) { 458 return option; 459 } 460 461 } 462 return null; 463 } 464}