1<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> 2<html> <head> 3<title>JCommander</title> 4 5<!-- 6<link rel="stylesheet" href="testng.css" type="text/css" /> 7--> 8 9 <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css" /> 10 <link type="text/css" rel="stylesheet" href="http://jcommander.org/jcommander.css" /> 11 <script type="text/javascript" src="http://beust.com/prettify.js"></script> 12 13 <script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script> 14 <script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script> 15 <script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script> 16 <script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script> 17 <script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script> 18 <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/> 19 <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/> 20 <script type="text/javascript" src="http://beust.com/toc.js"></script> 21 <script type="text/javascript"> 22 SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf'; 23 SyntaxHighlighter.defaults['gutter'] = false; 24 SyntaxHighlighter.all(); 25 </script> 26</head> 27 28<table width="100%"> 29 <tr> 30 <td align="center"> 31<h1>JCommander</h1> 32<h2>Because life is too short to parse command line parameters</h2> 33<h3> 34 <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top"> 35 <input type="hidden" name="cmd" value="_donations"> 36 <input type="hidden" name="business" value="cedric@beust.com"> 37 <input type="hidden" name="lc" value="US"> 38 <input type="hidden" name="item_name" value="Cedric Beust"> 39 <input type="hidden" name="no_note" value="0"> 40 <input type="hidden" name="currency_code" value="USD"> 41 <input type="hidden" name="bn" value="PP-DonationsBF:btn_donate_LG.gif:NonHostedGuest"> 42 <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!"> 43 <img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1"> 44 </form> 45</h3> 46 </td> 47 </tr> 48 <tr> 49 <td align="right"> 50 Created: July 13th, 2010 51 </td> 52 </tr> 53 <tr> 54 <td align="right"> 55 Last updated: January 14th, 2015 56 </td> 57 </tr> 58 <tr><td align="right"><a href="mailto:cedric@beust.com">Cédric Beust</a></td></tr> 59</table> 60 61<h2>Table of contents</h2> 62<div id="table-of-contents"> 63</div> 64 65 66 67<h2><a class="section" name="Overview">Overview</a></h2> 68 69JCommander is a very small Java framework that makes it trivial to parse command line parameters. 70<p> 71You annotate fields with descriptions of your options: 72 73<pre class="brush: java"> 74import com.beust.jcommander.Parameter; 75 76public class JCommanderExample { 77 @Parameter 78 private List<String> parameters = new ArrayList<String>(); 79 80 @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity") 81 private Integer verbose = 1; 82 83 @Parameter(names = "-groups", description = "Comma-separated list of group names to be run") 84 private String groups; 85 86 @Parameter(names = "-debug", description = "Debug mode") 87 private boolean debug = false; 88} 89</pre> 90 91and then you simply ask JCommander to parse: 92 93<pre class="brush: java"> 94JCommanderExample jct = new JCommanderExample(); 95String[] argv = { "-log", "2", "-groups", "unit" }; 96new JCommander(jct, argv); 97 98Assert.assertEquals(jct.verbose.intValue(), 2); 99</pre> 100 101<h2><a class="section" name="Types_of_options">Types of options</a></h2> 102 103The fields representing your parameters can be of any type. Basic types (<tt>Integer</tt>, <tt>Boolean</tt/>., etc...) are supported by default and you can write type converters to support any other type (<tt>File</tt>, etc...). 104 105<h4>Boolean</h4> 106 107When a <tt>Parameter</tt> annotation is found on a field of type <tt>boolean</tt> or <tt>Boolean</tt>, JCommander interprets it as an option with an <em>arity</em> of 0: 108 109<pre class="brush: java"> 110@Parameter(names = "-debug", description = "Debug mode") 111private boolean debug = false; 112</pre> 113 114Such a parameter does not require any additional parameter on the command line and if it's detected during parsing, the corresponding field will be set to <tt>true</tt>. 115 116<p> 117 118 If you want to define a boolean parameter that's <tt>true</tt> by default, you can declare it as having an arity of 1. Users will then have to specify the value they want explicitly: 119 120 <pre class="brush: java"> 121 @Parameter(names = "-debug", description = "Debug mode", arity = 1) 122 private boolean debug = true; 123 </pre> 124 125 Invoke with either of: 126 127 <pre class="brush: plain"> 128 program -debug true 129 program -debug false 130 </pre> 131 132<h4>String, Integer, Long</h4> 133 134When a <tt>Parameter</tt> annotation is found on a field of type <tt>String</tt>, <tt>Integer</tt>, <tt>int</tt>, <tt>Long</tt> or <tt>long</tt>, JCommander will parse the following parameter and it will attempt to cast it to the right type: 135 136<pre class="brush: java"> 137@Parameter(names = "-log", description = "Level of verbosity") 138private Integer verbose = 1; 139</pre> 140 141<pre class="brush: plain"> 142java Main -log 3 143</pre> 144 145will cause the field <tt>verbose</tt> to receive the value 3, however: 146 147<pre class="brush: plain"> 148java Main -log test 149</pre> 150 151will cause an exception to be thrown. 152 153<h4>Lists</h4> 154 155When a <tt>Parameter</tt> annotation is found on a field of type <tt>List</tt>, JCommander will interpret it as an option that can occur multiple times: 156 157<pre class="brush: java"> 158@Parameter(names = "-host", description = "The host") 159private List<String> hosts = new ArrayList<String>(); 160</pre> 161 162will allow you to parse the following command line: 163 164<pre class="brush: plain"> 165java Main -host host1 -verbose -host host2 166</pre> 167 168When JCommander is done parsing the line above, the field <tt>hosts</tt> will contain the strings "host1" and "host2". 169 170<h4>Password</h4> 171 172If one of your parameters is a password or some other value that you do not wish to appear in your history or in clear, you can declare it of type <tt>password</tt> and JCommander will then ask you to enter it in the console: 173 174<pre class="brush: java"> 175public class ArgsPassword { 176 @Parameter(names = "-password", description = "Connection password", password = true) 177 private String password; 178} 179</pre> 180 181When you run your program, you will get the following prompt: 182 183<pre class="brush: plain"> 184Value for -password (Connection password): 185</pre> 186 187You will need to type the value at this point before JCommander resumes. 188 189<h4>Echo Input</h4> 190 191In Java 6, by default, you will not be able to see what you type for passwords entered at the prompt (Java 5 and lower will always show the password). However, you can override this by setting <tt>echoInput</tt> to "true" (default is "false" and this setting only has an effect when <tt>password</tt> is "true"): 192<pre class="brush: java"> 193public class ArgsPassword { 194 @Parameter(names = "-password", description = "Connection password", password = true, echoInput = true) 195 private String password; 196} 197</pre> 198 199<h2><a class="section" name="Custom_types">Custom types</a></h2> 200 201<h3>By annotation</h3> 202 203By default, JCommander parses the command line into basic types only (strings, booleans, integers and longs). Very often, your application actually needs more complex types, such as files, host names, lists, etc... To achieve this, you can write a type converter by implementing the following interface: 204 205<pre class="brush: java"> 206public interface IStringConverter<T> { 207 T convert(String value); 208} 209</pre> 210 211For example, here is a converter that turns a string into a <tt>File</tt>: 212 213<pre class="brush: java"> 214public class FileConverter implements IStringConverter<File> { 215 @Override 216 public File convert(String value) { 217 return new File(value); 218 } 219} 220</pre> 221 222Then, all you need to do is declare your field with the correct type and specify the converter as an attribute: 223 224<pre class="brush: java"> 225@Parameter(names = "-file", converter = FileConverter.class) 226File file; 227</pre> 228 229JCommander ships with a few common converters (e.g. one that turns a comma separated list into a <tt>List<String>)</tt>. 230 231<h3>By factory</h3> 232 233If the custom types you use appear multiple times in your application, having to specify the converter in each annotation can become tedious. To address this, you can use an <tt>IStringConverterFactory</tt>: 234 235<pre class="brush: java"> 236public interface IStringConverterFactory { 237 <T> Class<? extends IStringConverter<T>> getConverter(Class<T> forType); 238} 239</pre> 240 241For example, suppose you need to parse a string representing a host and a port: 242 243<pre class="brush: plain"> 244java App -target example.com:8080 245</pre> 246 247You define the holder class : 248 249<pre class="brush: java"> 250public class HostPort { 251 private String host; 252 private Integer port; 253} 254</pre> 255 256and the string converter to create instances of this class: 257 258<pre class="brush: java"> 259class HostPortConverter implements IStringConverter<HostPort> { 260 @Override 261 public HostPort convert(String value) { 262 HostPort result = new HostPort(); 263 String[] s = value.split(":"); 264 result.host = s[0]; 265 result.port = Integer.parseInt(s[1]); 266 267 return result; 268 } 269} 270</pre> 271 272The factory is straightforward: 273 274<pre class="brush: java"> 275public class Factory implements IStringConverterFactory { 276 public Class<? extends IStringConverter<?>> getConverter(Class forType) { 277 if (forType.equals(HostPort.class)) return HostPortConverter.class; 278 else return null; 279 } 280</pre> 281 282You can now use the type <tt>HostPort</tt> as a parameter without any <tt>converterClass</tt> attribute: 283 284<pre class="brush: java"> 285public class ArgsConverterFactory { 286 @Parameter(names = "-hostport") 287 private HostPort hostPort; 288} 289</pre> 290 291 292All you need to do is add the factory to your JCommander object: 293 294<pre class="brush: java"> 295 ArgsConverterFactory a = new ArgsConverterFactory(); 296 JCommander jc = new JCommander(a); 297 jc.addConverterFactory(new Factory()); 298 jc.parse("-hostport", "example.com:8080"); 299 300 Assert.assertEquals(a.hostPort.host, "example.com"); 301 Assert.assertEquals(a.hostPort.port.intValue(), 8080); 302</pre> 303 304 305Another advantage of using string converter factories is that your factories can come from a dependency injection framework. 306 307<h2><a class="section" name="Parameter_validation">Parameter validation</a></h2> 308 309You can ask JCommander to perform early validation on your parameters by providing a class that implements the following interface: 310 311<pre class="brush:java"> 312public interface IParameterValidator { 313 /** 314 * Validate the parameter. 315 * 316 * @param name The name of the parameter (e.g. "-host"). 317 * @param value The value of the parameter that we need to validate 318 * 319 * @throws ParameterException Thrown if the value of the parameter is invalid. 320 */ 321 void validate(String name, String value) throws ParameterException; 322} 323 324</pre> 325 326Here is an example implementation that will make sure that the parameter is a positive integer: 327 328<pre class="brush:java"> 329public class PositiveInteger implements IParameterValidator { 330 public void validate(String name, String value) 331 throws ParameterException { 332 int n = Integer.parseInt(value); 333 if (n < 0) { 334 throw new ParameterException("Parameter " + name + " should be positive (found " + value +")"); 335 } 336 } 337} 338</pre> 339 340Specify the name of a class implementing this interface in the <tt>validateWith</tt> attribute of your <tt>@Parameter</tt> annotations: 341 342<pre class="brush:java"> 343@Parameter(names = "-age", validateWith = PositiveInteger.class) 344private Integer age; 345</pre> 346 347Attempting to pass a negative integer to this option will cause a <tt>ParameterException</tt> to be thrown. 348 349 350<h2><a class="section" name="Main_parameter">Main parameter</a></h2> 351So far, all the <tt>@Parameter</tt> annotations we have seen had defined an attribute called <tt>names</tt>. You can define one (and at most one) parameter without any such attribute. This parameter needs to be a <tt>List<String></tt> and it will contain all the parameters that are not options: 352 353<pre class="brush: java"> 354@Parameter(description = "Files") 355private List<String> files = new ArrayList<String>(); 356 357@Parameter(names = "-debug", description = "Debugging level") 358private Integer debug = 1; 359</pre> 360 361will allow you to parse: 362 363<pre class="brush: plain"> 364java Main -debug file1 file2 365</pre> 366 367and the field <tt>files</tt> will receive the strings "file1" and "file2". 368 369<h2><a class="section" name="Private_parameters">Private parameters</a></h2> 370 371Parameters can be private: 372 373<pre class="brush: java"> 374public class ArgsPrivate { 375 @Parameter(names = "-verbose") 376 private Integer verbose = 1; 377 378 public Integer getVerbose() { 379 return verbose; 380 } 381} 382</pre> 383 384<pre class="brush: java"> 385ArgsPrivate args = new ArgsPrivate(); 386new JCommander(args, "-verbose", "3"); 387Assert.assertEquals(args.getVerbose().intValue(), 3); 388</pre> 389 390<h2><a class="section" name="Separators">Parameter separators</a></h2> 391 392By default, parameters are separated by spaces, but you can change this setting to allow different separators: 393 394<pre class="brush: plain"> 395java Main -log:3 396</pre> 397 398or 399 400<pre class="brush: plain"> 401java Main -level=42 402</pre> 403 404You define the separator with the <tt>@Parameters</tt> annotation: 405 406<pre class="brush: java"> 407@Parameters(separators = "=") 408public class SeparatorEqual { 409 @Parameter(names = "-level") 410 private Integer level = 2; 411} 412</pre> 413 414 415 416 417 418<h2><a class="section" name="Multiple_descriptions">Multiple descriptions</a></h2> 419 420You can spread the description of your parameters on more than one 421class. For example, you can define the following two classes: 422 423<p> 424 425<h3 class="sourcetitle">ArgsMaster.java</h3> 426<pre class="brush: java"> 427public class ArgsMaster { 428 @Parameter(names = "-master") 429 private String master; 430} 431</pre> 432 433<h3 class="sourcetitle">ArgsSlave.java</h3> 434<pre class="brush: java"> 435public class ArgsSlave { 436 @Parameter(names = "-slave") 437 private String slave; 438} 439</pre> 440 441and pass these two objects to JCommander: 442 443<pre class="brush: java"> 444ArgsMaster m = new ArgsMaster(); 445ArgsSlave s = new ArgsSlave(); 446String[] argv = { "-master", "master", "-slave", "slave" }; 447new JCommander(new Object[] { m , s }, argv); 448 449Assert.assertEquals(m.master, "master"); 450Assert.assertEquals(s.slave, "slave"); 451</pre> 452 453 454<h2><a class="section" name="Syntax">@ syntax</a></h2> 455 456JCommander supports the @ syntax, which allows you to put all your options into a file and pass this file as parameter: 457 458<p> 459 460<div class="sourcetitle">/tmp/parameters</div> 461<pre class="brush: plain"> 462-verbose 463file1 464file2 465file3 466</pre> 467<pre class="brush: plain"> 468java Main @/tmp/parameters 469</pre> 470 471<h2><a class="section" name="Arities">Arities (multiple values for parameters)</a></h2> 472 473<h3><a class="section" name="fixed-arities" indent="..">Fixed arities</a></h3> 474 475If some of your parameters require more than one value, such as the 476following example where two values are expected after <tt>-pairs</tt>: 477 478<pre class="brush: plain"> 479java Main -pairs slave master foo.xml 480</pre> 481 482then you need to define your parameter with the <tt>arity</tt> 483attribute and make that parameter a <tt>List<String></tt>: 484 485<pre class="brush: java"> 486@Parameter(names = "-pairs", arity = 2, description = "Pairs") 487private List<String> pairs; 488</pre> 489 490You don't need to specify an arity for parameters of type 491<tt>boolean</tt> or <tt>Boolean</tt> (which have a default arity of 0) 492and of types <tt>String</tt>, <tt>Integer</tt>, <tt>int</tt>, 493<tt>Long</tt> and <tt>long</tt> (which have a default arity of 1). 494 495<p> 496Also, note that only <tt>List<String></tt> is allowed for 497parameters that define an arity. You will have to convert these values 498yourself if the parameters you need are of type <tt>Integer</tt> or 499other (this limitation is due to Java's erasure). 500 501<h3><a class="section" name="variable-arities" indent="..">Variable arities</a></h3> 502 503You can specify that a parameter can receive an indefinite number of parameters, up to the next option. For example: 504 505<pre class="brush: java"> 506program -foo a1 a2 a3 -bar 507program -foo a1 -bar 508</pre> 509 510Such a parameter must be of type <tt>List<String></tt> and have the boolean <tt>variableArity</tt> set to <tt>true</tt> 511 512<pre class="brush: java"> 513@Parameter(names = "-foo", variableArity = true) 514public List<String> foo = new ArrayList<String>(); 515</pre> 516 517<h2><a class="section" name="Multiple_option_names">Multiple option names</a></h2> 518 519You can specify more than one option name: 520 521<pre class="brush: java"> 522 523 @Parameter(names = { "-d", "--outputDirectory" }, description = "Directory") 524 private String outputDirectory; 525 526</pre> 527 528will allow both following syntaxes: 529 530<pre class="brush: plain"> 531java Main -d /tmp 532java Main --outputDirectory /tmp 533</pre> 534 535<h2><a class="section" name="Other option configurations">Other option configurations</a></h2> 536 537You can configure how options are looked up in a few different ways: 538 539<ul> 540 <li><tt>JCommander#setCaseSensitiveOptions(boolean)</tt>: specify whether options are case sensitive. If you call this method with <tt>false</tt>, then <tt>"-param"</tt> and 541 <tt>"-PARAM"</tt> are considered equal. 542 </li> 543 <li><tt>JCommander#setAllowAbbreviatedOptions(boolean)</tt>: specify whether users can 544 pass abbreviated options. If you call this method with <tt>true</tt> then users 545 can pass <tt>"-par"</tt> to specify an option called <tt>-param</tt>. JCommander will 546 throw a <tt>ParameterException</tt> if the abbreviated name is ambiguous. 547 </li> 548</ul> 549 550<h2><a class="section" name="Required_and_optional">Required and optional parameters</a></h2> 551 552If some of your parameters are mandatory, you can use the 553<tt>required</tt> attribute (which default to <tt>false</tt>): 554 555<pre class="brush: java"> 556 557 @Parameter(names = "-host", required = true) 558 private String host; 559 560</pre> 561 562If this parameter is not specified, JCommander will throw an exception 563telling you which options are missing. 564 565<h2><a class="section" name="Default_values">Default values</a></h2> 566 567The most common way to specify a default value for your parameters is to initialize the field at declaration time: 568 569<pre class="brush: java"> 570private Integer logLevel = 3; 571</pre> 572 573For more complicated cases, you might want to be able to reuse identical default values across several main classes or be able to specify these default values in a centralized location such as a .properties or an XML fie. In this case, you can use an <tt>IDefaultProvider</tt> 574 575<pre class="brush: java"> 576public interface IDefaultProvider { 577 /** 578 * @param optionName The name of the option as specified in the names() attribute 579 * of the @Parameter option (e.g. "-file"). 580 * 581 * @return the default value for this option. 582 */ 583 String getDefaultValueFor(String optionName); 584} 585</pre> 586 587By passing an implementation of this interface to your <tt>JCommander</tt> object, you can now control which default value will be used for your options. Note that the value returned by this method will then be passed to a string converter, if any is applicable, thereby allowing you to specify default values for any types you need. 588 589<p> 590 591For example, here is a default provider that will assign a default value of 42 for all your parameters except "-debug": 592 593<pre class="brush: java"> 594private static final IDefaultProvider DEFAULT_PROVIDER = new IDefaultProvider() { 595 @Override 596 public String getDefaultValueFor(String optionName) { 597 return "-debug".equals(optionName) ? "false" : "42"; 598 } 599}; 600 601// ... 602 603JCommander jc = new JCommander(new Args()); 604jc.setDefaultProvider(DEFAULT_PROVIDER); 605</pre> 606 607<h2><a class="section" name="Help_parameter">Help parameter</a></h2> 608 609If one of your parameters is used to display some help or usage, you need use the <tt>help</tt> attribute: 610 611<pre class="brush: java"> 612 @Parameter(names = "--help", help = true) 613 private boolean help; 614</pre> 615 616If you omit this boolean, JCommander will instead issue an error message when it tries to validate your command and it finds that you didn't specify some of the required parameters. 617 618<h2><a class="section" name="Complex">More complex syntaxes (commands)</a></h2> 619 620Complex tools such as <tt>git</tt> or <tt>svn</tt> understand a whole set of commands, each of which with their own specific syntax: 621 622<pre class="brush: plain"> 623 git commit --amend -m "Bug fix" 624</pre> 625 626Words such as "commit" above are called "commands" in JCommander, and you can specify them by creating one arg object per command: 627 628<pre class="brush: java"> 629@Parameters(separators = "=", commandDescription = "Record changes to the repository") 630private class CommandCommit { 631 632 @Parameter(description = "The list of files to commit") 633 private List<String> files; 634 635 @Parameter(names = "--amend", description = "Amend") 636 private Boolean amend = false; 637 638 @Parameter(names = "--author") 639 private String author; 640} 641</pre> 642 643<pre class="brush: java"> 644@Parameters(commandDescription = "Add file contents to the index") 645public class CommandAdd { 646 647 @Parameter(description = "File patterns to add to the index") 648 private List<String> patterns; 649 650 @Parameter(names = "-i") 651 private Boolean interactive = false; 652} 653</pre> 654 655Then you register these commands with your JCommander object. After the parsing phase, you call <tt>getParsedCommand()</tt> on your JCommander object, and based on the command that is returned, you know which arg object to inspect (you can still use a main arg object if you want to support options before the first command appears on the command line): 656 657<pre class="brush: java"> 658CommandMain cm = new CommandMain(); 659JCommander jc = new JCommander(cm); 660 661CommandAdd add = new CommandAdd(); 662jc.addCommand("add", add); 663CommandCommit commit = new CommandCommit(); 664jc.addCommand("commit", commit); 665 666jc.parse("-v", "commit", "--amend", "--author=cbeust", "A.java", "B.java"); 667 668Assert.assertTrue(cm.verbose); 669Assert.assertEquals(jc.getParsedCommand(), "commit"); 670Assert.assertTrue(commit.amend); 671Assert.assertEquals(commit.author, "cbeust"); 672Assert.assertEquals(commit.files, Arrays.asList("A.java", "B.java")); 673</pre> 674 675<h2><a class="section" name="Exceptions">Exception</a></h2> 676 677Whenever JCommander detects an error, it will throw a 678<tt>ParameterException</tt>. Note that this is a Runtime Exception, 679since your application is probably not initialized correctly at this 680point. 681 682 683<h2><a class="section" name="Usage">Usage</a></h2> 684 685You can invoke <tt>usage()</tt> on the <tt>JCommander</tt> instance that you used to parse your command line in order to generate a summary of all the options that your program understands: 686 687<pre class="brush: plain"> 688Usage: <main class> [options] 689 Options: 690 -debug Debug mode (default: false) 691 -groups Comma-separated list of group names to be run 692 * -log, -verbose Level of verbosity (default: 1) 693 -long A long number (default: 0) 694</pre> 695 696You can customize the name of your program by calling <tt>setProgramName()</tt> on your <tt>JCommander</tt> object. 697 698Options preceded by an asterisk are required. 699 700<h2><a class="section" name="Hiding">Hiding parameters</a></h2> 701 702If you don't want certain parameters to appear in the usage, you can mark them as "hidden": 703 704<pre class="brush: java"> 705@Parameter(names = "-debug", description = "Debug mode", hidden = true) 706private boolean debug = false; 707</pre> 708 709<h2><a class="section" name="Internationalization">Internationalization</a></h2> 710 711You can internationalize the descriptions of your parameters. 712 713<p> 714 715First you use the <tt>@Parameters</tt> annotation at the top of your class to define the name of your message bundle, and then you use the <tt>descriptionKey</tt> attribute instead of <tt>description</tt> on all the <tt>@Parameters</tt> that require translations. This <tt>descriptionKey</tt> is the key to the string into your message bundle: 716 717<h3 class="sourcetitle">I18N.java</h3> 718<pre class="brush:java"> 719@Parameters(resourceBundle = "MessageBundle") 720private class ArgsI18N2 { 721 @Parameter(names = "-host", description = "Host", descriptionKey = "host") 722 String hostName; 723} 724</pre> 725 726Your bundle needs to define this key: 727 728<br> 729 730<h3 class="sourcetitle">MessageBundle_fr_FR.properties</h3> 731<pre class="brush: plain"> 732host: Hôte 733</pre> 734 735JCommander will then use the default locale to resolve your descriptions. 736 737<h2><a class="section" name="Parameter_delegates">Parameter delegates</a></h2> 738 739If you are writing many different tools in the same project, you will probably find that most of these tools can share configurations. While you can use inheritance with your objects to avoid repeating this code, the restriction to single inheritance of implementation might limit your flexibility. To address this problem, JCommander supports parameter delegates. 740 741<p> 742 743When JCommander encounters an object annotated with <tt>@ParameterDelegate</tt> in one of your objects, it acts as if this object had been added as a description object itself: 744 745<pre class="brush: java"> 746class Delegate { 747 @Parameter(names = "-port") 748 private int port; 749} 750 751class MainParams { 752 @Parameter(names = "-v") 753 private boolean verbose; 754 755 @ParametersDelegate 756 private Delegate delegate = new Delegate(); 757} 758</pre> 759 760The example above specifies a delegate parameter <tt>Delegate</tt> which is then referenced in <tt>MainParams</tt>. You only need to add a <tt>MainParams</tt> object to your JCommander configuration in order to use the delegate: 761 762<pre class="brush: java"> 763MainParams p = new MainParams(); 764new JCommander(p).parse("-v", "-port", "1234"); 765Assert.assertTrue(p.isVerbose); 766Assert.assertEquals(p.delegate.port, 1234); 767</pre> 768 769<h2><a class="section" name="DynamicParameters">Dynamic parameters</a></h2> 770 771JCommander allows you to specify parameters that are not known at compile time, such as <tt>"-Da=b -Dc=d"</tt>. Such parameters are specified with the <tt><a href="apidocs/com/beust/jcommander/DynamicParameter.html">@DynamicParameter</a></tt> annotation and must be of type <tt>Map<String, String></tt>. Dynamic parameters are allowed to appear multiple times on the command line: 772 773<pre class="brush: java"> 774@DynamicParameter(names = "-D", description = "Dynamic parameters go here") 775private Map<String, String> params = new HashMap<String, String>(); 776</pre> 777 778You can specify a different assignment string than <tt>=</tt> by using the attribute <tt>assignment</tt>. 779 780<h2><a class="section" name="Scala">JCommander in Scala</a></h2> 781 782Here is a quick example of how to use JCommander in Scala (courtesy of Patrick Linskey): 783 784<pre class="brush: java"> 785import java.io.File 786import com.beust.jcommander.{JCommander, Parameter} 787import collection.JavaConversions._ 788 789object Main { 790 object Args { 791 // Declared as var because JCommander assigns a new collection declared 792 // as java.util.List because that's what JCommander will replace it with. 793 // It'd be nice if JCommander would just use the provided List so this 794 // could be a val and a Scala LinkedList. 795 @Parameter( 796 names = Array("-f", "--file"), 797 description = "File to load. Can be specified multiple times.") 798 var file: java.util.List[String] = null 799 } 800 801 def main(args: Array[String]): Unit = { 802 new JCommander(Args, args.toArray: _*) 803 for (filename <- Args.file) { 804 val f = new File(filename) 805 printf("file: %s\n", f.getName) 806 } 807 } 808} 809</pre> 810 811<h2><a class="section" name="Groovy">JCommander in Groovy</a></h2> 812 813Here is a quick example of how to use JCommander in Groovy (courtesy of Paul King): 814 815 816<pre class="brush: java"> 817import com.beust.jcommander.* 818 819class Args { 820 @Parameter(names = ["-f", "--file"], description = "File to load. Can be specified multiple times.") 821 List<String> file 822} 823 824new Args().with { 825 new JCommander(it, args) 826 file.each { println "file: ${new File(it).name}" } 827} 828</pre> 829 830<h2><a class="section" name="More_examples">More examples</a></h2> 831 832TestNG uses JCommander to parse its own command line, here is <a href="http://github.com/cbeust/testng/blob/master/src/main/java/org/testng/CommandLineArgs.java">its definition file</a>. 833 834<h2><a class="section" name="Mailing_list">Mailing list</a></h2> 835 836Join the <a href="http://groups.google.com/group/jcommander">JCommander Google group</a> if you are interested in discussions about JCommander. 837 838<h2><a class="section" name="Javadocs">Javadocs</a></h2> 839 840The Javadocs for JCommander can be found <a href="apidocs/">here</a>. 841 842<h2><a class="section" name="License">License</a></h2> 843 844JCommander is released under the <a 845href="https://github.com/cbeust/jcommander/blob/master/license.txt">Apache 2.0</a> license. 846 847<h2><a class="section" name="Download">Download</a></h2> 848 849You can download JCommander from the following locations: 850 851<ul> 852 <li><a href="http://github.com/cbeust/jcommander">Source on github</a></li> 853 <li>If you are using Maven, add the following dependency to your <tt>pom.xml</tt>: 854 855 <pre class="brush: xml"> 856 857<dependency> 858 <groupId>com.beust</groupId> 859 <artifactId>jcommander</artifactId> 860 <version>1.30</version> 861</dependency> 862 </pre> 863 864</ul> 865 866</body> 867 868<script type="text/javascript" src="http://beust.com/toc.js"></script> 869<script type="text/javascript"> generateToc(); </script> 870 871</html> 872