View Javadoc
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 java.io.Serializable;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Iterator;
24  import java.util.LinkedList;
25  import java.util.List;
26  import java.util.Properties;
27  
28  /**
29   * Represents list of arguments parsed against a {@link Options} descriptor.
30   * <p>
31   * It allows querying of a boolean {@link #hasOption(String opt)},
32   * in addition to retrieving the {@link #getOptionValue(String opt)}
33   * for options requiring arguments.
34   * <p>
35   * Additionally, any left-over or unrecognized arguments,
36   * are available for further processing.
37   */
38  public class CommandLine implements Serializable
39  {
40      /** The serial version UID. */
41      private static final long serialVersionUID = 1L;
42  
43      /** the unrecognized options/arguments */
44      private final List<String> args = new LinkedList<String>();
45  
46      /** the processed options */
47      private final List<Option> options = new ArrayList<Option>();
48  
49      /**
50       * Creates a command line.
51       */
52      protected CommandLine()
53      {
54          // nothing to do
55      }
56  
57      /**
58       * Query to see if an option has been set.
59       *
60       * @param opt the option to check.
61       * @return true if set, false if not.
62       * @since 1.5
63       */
64      public boolean hasOption(final Option opt)
65      {
66          return options.contains(opt);
67      }
68  
69      /**
70       * Query to see if an option has been set.
71       *
72       * @param opt Short name of the option.
73       * @return true if set, false if not.
74       */
75      public boolean hasOption(final String opt)
76      {
77          return hasOption(resolveOption(opt));
78      }
79  
80      /**
81       * Query to see if an option has been set.
82       *
83       * @param opt character name of the option.
84       * @return true if set, false if not.
85       */
86      public boolean hasOption(final char opt)
87      {
88          return hasOption(String.valueOf(opt));
89      }
90  
91      /**
92       * Return the <code>Object</code> type of this <code>Option</code>.
93       *
94       * @param opt the name of the option.
95       * @return the type of this <code>Option</code>.
96       * @deprecated due to System.err message. Instead use getParsedOptionValue(String)
97       */
98      @Deprecated
99      public Object getOptionObject(final String opt)
100     {
101         try
102         {
103             return getParsedOptionValue(opt);
104         }
105         catch (final ParseException pe)
106         {
107             System.err.println("Exception found converting " + opt + " to desired type: " + pe.getMessage());
108             return null;
109         }
110     }
111 
112     /**
113      * Return a version of this <code>Option</code> converted to a particular type.
114      *
115      * @param option the name of the option.
116      * @return the value parsed into a particular object.
117      * @throws ParseException if there are problems turning the option value into the desired type
118      * @see PatternOptionBuilder
119      * @since 1.5
120      */
121     public Object getParsedOptionValue(final Option option) throws ParseException
122     {
123         if (option == null)
124         {
125             return null;
126         }
127         final String res = getOptionValue(option);
128         if (res == null)
129         {
130             return null;
131         }
132         return TypeHandler.createValue(res, option.getType());
133     }
134 
135     /**
136      * Return a version of this <code>Option</code> converted to a particular type.
137      *
138      * @param opt the name of the option.
139      * @return the value parsed into a particular object.
140      * @throws ParseException if there are problems turning the option value into the desired type
141      * @see PatternOptionBuilder
142      * @since 1.2
143      */
144     public Object getParsedOptionValue(final String opt) throws ParseException
145     {
146         return getParsedOptionValue(resolveOption(opt));
147     }
148 
149     /**
150      * Return a version of this <code>Option</code> converted to a particular type.
151      *
152      * @param opt the name of the option.
153      * @return the value parsed into a particular object.
154      * @throws ParseException if there are problems turning the option value into the desired type
155      * @see PatternOptionBuilder
156      * @since 1.5
157      */
158     public Object getParsedOptionValue(final char opt) throws ParseException
159     {
160         return getParsedOptionValue(String.valueOf(opt));
161     }
162 
163     /**
164      * Return the <code>Object</code> type of this <code>Option</code>.
165      *
166      * @deprecated due to System.err message. Instead use getParsedOptionValue(char)
167      * @param opt the name of the option.
168      * @return the type of opt.
169      */
170     public Object getOptionObject(final char opt)
171     {
172         return getOptionObject(String.valueOf(opt));
173     }
174 
175     /**
176      * Retrieve the first argument, if any, of this option.
177      *
178      * @param option the name of the option.
179      * @return Value of the argument if option is set, and has an argument,
180      * otherwise null.
181      * @since 1.5
182      */
183     public String getOptionValue(final Option option)
184     {
185         if (option == null)
186         {
187             return null;
188         }
189         final String[] values = getOptionValues(option);
190         return (values == null) ? null : values[0];
191     }
192 
193     /**
194      * Retrieve the first argument, if any, of this option.
195      *
196      * @param opt the name of the option.
197      * @return Value of the argument if option is set, and has an argument,
198      * otherwise null.
199      */
200     public String getOptionValue(final String opt)
201     {
202         return getOptionValue(resolveOption(opt));
203     }
204 
205     /**
206      * Retrieve the first argument, if any, of this option.
207      *
208      * @param opt the character name of the option.
209      * @return Value of the argument if option is set, and has an argument,
210      * otherwise null.
211      */
212     public String getOptionValue(final char opt)
213     {
214         return getOptionValue(String.valueOf(opt));
215     }
216 
217     /**
218      * Retrieves the array of values, if any, of an option.
219      *
220      * @param option string name of the option.
221      * @return Values of the argument if option is set, and has an argument,
222      * otherwise null.
223      * @since 1.5
224      */
225     public String[] getOptionValues(final Option option)
226     {
227         final List<String> values = new ArrayList<String>();
228 
229         for (final Option processedOption : options)
230         {
231             if (processedOption.equals(option))
232             {
233                 values.addAll(processedOption.getValuesList());
234             }
235         }
236 
237         return values.isEmpty() ? null : values.toArray(new String[values.size()]);
238     }
239 
240     /**
241      * Retrieves the array of values, if any, of an option.
242      *
243      * @param opt string name of the option.
244      * @return Values of the argument if option is set, and has an argument,
245      * otherwise null.
246      */
247     public String[] getOptionValues(final String opt)
248     {
249         return getOptionValues(resolveOption(opt));
250     }
251 
252     /**
253      * Retrieves the option object given the long or short option as a String
254      *
255      * @param opt short or long name of the option.
256      * @return Canonicalized option.
257      */
258     private Option resolveOption(String opt)
259     {
260         opt = Util.stripLeadingHyphens(opt);
261         for (final Option option : options)
262         {
263             if (opt.equals(option.getOpt()))
264             {
265                 return option;
266             }
267 
268             if (opt.equals(option.getLongOpt()))
269             {
270                 return option;
271             }
272 
273         }
274         return null;
275     }
276 
277     /**
278      * Retrieves the array of values, if any, of an option.
279      *
280      * @param opt character name of the option.
281      * @return Values of the argument if option is set, and has an argument,
282      * otherwise null.
283      */
284     public String[] getOptionValues(final char opt)
285     {
286         return getOptionValues(String.valueOf(opt));
287     }
288 
289     /**
290      * Retrieve the first argument, if any, of an option.
291      *
292      * @param option name of the option.
293      * @param defaultValue is the default value to be returned if the option
294      * is not specified.
295      * @return Value of the argument if option is set, and has an argument,
296      * otherwise <code>defaultValue</code>.
297      * @since 1.5
298      */
299     public String getOptionValue(final Option option, final String defaultValue)
300     {
301         final String answer = getOptionValue(option);
302         return (answer != null) ? answer : defaultValue;
303     }
304 
305     /**
306      * Retrieve the first argument, if any, of an option.
307      *
308      * @param opt name of the option.
309      * @param defaultValue is the default value to be returned if the option
310      * is not specified.
311      * @return Value of the argument if option is set, and has an argument,
312      * otherwise <code>defaultValue</code>.
313      */
314     public String getOptionValue(final String opt, final String defaultValue)
315     {
316         return getOptionValue(resolveOption(opt), defaultValue);
317     }
318 
319     /**
320      * Retrieve the argument, if any, of an option.
321      *
322      * @param opt character name of the option
323      * @param defaultValue is the default value to be returned if the option
324      * is not specified.
325      * @return Value of the argument if option is set, and has an argument,
326      * otherwise <code>defaultValue</code>.
327      */
328     public String getOptionValue(final char opt, final String defaultValue)
329     {
330         return getOptionValue(String.valueOf(opt), defaultValue);
331     }
332 
333     /**
334      * Retrieve the map of values associated to the option. This is convenient
335      * for options specifying Java properties like <code>-Dparam1=value1
336      * -Dparam2=value2</code>. The first argument of the option is the key, and
337      * the 2nd argument is the value. If the option has only one argument
338      * (<code>-Dfoo</code>) it is considered as a boolean flag and the value is
339      * <code>"true"</code>.
340      *
341      * @param option name of the option.
342      * @return The Properties mapped by the option, never <code>null</code>
343      *         even if the option doesn't exists.
344      * @since 1.5
345      */
346     public Properties getOptionProperties(final Option option)
347     {
348         final Properties props = new Properties();
349 
350         for (final Option processedOption : options)
351         {
352             if (processedOption.equals(option))
353             {
354                 final List<String> values = processedOption.getValuesList();
355                 if (values.size() >= 2)
356                 {
357                     // use the first 2 arguments as the key/value pair
358                     props.put(values.get(0), values.get(1));
359                 }
360                 else if (values.size() == 1)
361                 {
362                     // no explicit value, handle it as a boolean
363                     props.put(values.get(0), "true");
364                 }
365             }
366         }
367 
368         return props;
369     }
370 
371     /**
372      * Retrieve the map of values associated to the option. This is convenient
373      * for options specifying Java properties like <code>-Dparam1=value1
374      * -Dparam2=value2</code>. The first argument of the option is the key, and
375      * the 2nd argument is the value. If the option has only one argument
376      * (<code>-Dfoo</code>) it is considered as a boolean flag and the value is
377      * <code>"true"</code>.
378      *
379      * @param opt name of the option.
380      * @return The Properties mapped by the option, never <code>null</code>
381      *         even if the option doesn't exists.
382      * @since 1.2
383      */
384     public Properties getOptionProperties(final String opt)
385     {
386         final Properties props = new Properties();
387 
388         for (final Option option : options)
389         {
390             if (opt.equals(option.getOpt()) || opt.equals(option.getLongOpt()))
391             {
392                 final List<String> values = option.getValuesList();
393                 if (values.size() >= 2)
394                 {
395                     // use the first 2 arguments as the key/value pair
396                     props.put(values.get(0), values.get(1));
397                 }
398                 else if (values.size() == 1)
399                 {
400                     // no explicit value, handle it as a boolean
401                     props.put(values.get(0), "true");
402                 }
403             }
404         }
405 
406         return props;
407     }
408 
409     /**
410      * Retrieve any left-over non-recognized options and arguments
411      *
412      * @return remaining items passed in but not parsed as an array.
413      */
414     public String[] getArgs()
415     {
416         final String[] answer = new String[args.size()];
417 
418         args.toArray(answer);
419 
420         return answer;
421     }
422 
423     /**
424      * Retrieve any left-over non-recognized options and arguments
425      *
426      * @return remaining items passed in but not parsed as a <code>List</code>.
427      */
428     public List<String> getArgList()
429     {
430         return args;
431     }
432 
433     /**
434      * jkeyes
435      * - commented out until it is implemented properly
436      * <p>Dump state, suitable for debugging.</p>
437      *
438      * @return Stringified form of this object.
439      */
440 
441     /*
442     public String toString() {
443         StringBuilder buf = new StringBuilder();
444 
445         buf.append("[ CommandLine: [ options: ");
446         buf.append(options.toString());
447         buf.append(" ] [ args: ");
448         buf.append(args.toString());
449         buf.append(" ] ]");
450 
451         return buf.toString();
452     }
453     */
454 
455     /**
456      * Add left-over unrecognized option/argument.
457      *
458      * @param arg the unrecognized option/argument.
459      */
460     protected void addArg(final String arg)
461     {
462         args.add(arg);
463     }
464 
465     /**
466      * Add an option to the command line.  The values of the option are stored.
467      *
468      * @param opt the processed option.
469      */
470     protected void addOption(final Option opt)
471     {
472         options.add(opt);
473     }
474 
475     /**
476      * Returns an iterator over the Option members of CommandLine.
477      *
478      * @return an <code>Iterator</code> over the processed {@link Option}
479      * members of this {@link CommandLine}.
480      */
481     public Iterator<Option> iterator()
482     {
483         return options.iterator();
484     }
485 
486     /**
487      * Returns an array of the processed {@link Option}s.
488      *
489      * @return an array of the processed {@link Option}s.
490      */
491     public Option[] getOptions()
492     {
493         final Collection<Option> processed = options;
494 
495         // reinitialise array
496         final Option[] optionsArray = new Option[processed.size()];
497 
498         // return the array
499         return processed.toArray(optionsArray);
500     }
501 
502     /**
503      * A nested builder class to create <code>CommandLine</code> instance
504      * using descriptive methods.
505      *
506      * @since 1.4
507      */
508     public static final class Builder
509     {
510         /**
511          * CommandLine that is being build by this Builder.
512          */
513         private final CommandLine commandLine = new CommandLine();
514 
515         /**
516          * Add an option to the command line. The values of the option are stored.
517          *
518          * @param opt the processed option.
519          *
520          * @return this Builder instance for method chaining.
521          */
522         public Builder addOption(final Option opt)
523         {
524             commandLine.addOption(opt);
525             return this;
526         }
527 
528         /**
529          * Add left-over unrecognized option/argument.
530          *
531          * @param arg the unrecognized option/argument.
532          *
533          * @return this Builder instance for method chaining.
534          */
535         public Builder addArg(final String arg)
536         {
537             commandLine.addArg(arg);
538             return this;
539         }
540 
541         public CommandLine build()
542         {
543             return commandLine;
544         }
545     }
546 }