| <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> |
| <html> <head> |
| <title>JCommander</title> |
| |
| <link rel="stylesheet" href="testng.css" type="text/css" /> |
| <link type="text/css" rel="stylesheet" href="http://beust.com/beust.css" /> |
| <script type="text/javascript" src="http://beust.com/prettify.js"></script> |
| <script type="text/javascript" src="http://testng.org/doc/banner.js"></script> |
| |
| <script type="text/javascript" src="http://beust.com/scripts/shCore.js"></script> |
| <script type="text/javascript" src="http://beust.com/scripts/shBrushJava.js"></script> |
| <script type="text/javascript" src="http://beust.com/scripts/shBrushXml.js"></script> |
| <script type="text/javascript" src="http://beust.com/scripts/shBrushBash.js"></script> |
| <script type="text/javascript" src="http://beust.com/scripts/shBrushPlain.js"></script> |
| <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shCore.css"/> |
| <link type="text/css" rel="stylesheet" href="http://beust.com/styles/shThemeCedric.css"/> |
| <script type="text/javascript"> |
| SyntaxHighlighter.config.clipboardSwf = 'scripts/clipboard.swf'; |
| SyntaxHighlighter.defaults['gutter'] = false; |
| SyntaxHighlighter.all(); |
| </script> |
| |
| </head> |
| |
| <body> |
| <table width="100%"> |
| <tr> |
| <td align="center"> |
| <h1>JCommander</h1> |
| <h2>Because life is too short to parse command line parameters</h2> |
| </td> |
| </tr> |
| <tr> |
| <td align="right"> |
| Created: July 13th, 2010 |
| </td> |
| </tr> |
| <tr><td align="right"><a href="mailto:cedric@beust.com">Cédric Beust</a></td></tr> |
| </table> |
| |
| <h2> |
| Overview |
| </h2> |
| |
| JCommander is a very small Java framework that makes it trivial to parse command line parameters. |
| <p> |
| You annotate fields with descriptions of your options: |
| |
| <pre class="brush: java"> |
| import com.beust.jcommander.Parameter; |
| |
| public class JCommanderTest { |
| @Parameter |
| public List<String> parameters = Lists.newArrayList(); |
| |
| @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity") |
| public Integer verbose = 1; |
| |
| @Parameter(names = "-groups", description = "Comma-separated list of group names to be run") |
| public String groups; |
| |
| @Parameter(names = "-debug", description = "Debug mode") |
| public boolean debug = false; |
| } |
| </pre> |
| |
| and then you simply ask JCommander to parse: |
| |
| <pre class="brush: java"> |
| JCommanderTest jct = new JCommanderTest(); |
| String[] argv = { "-log", "2", "-groups", "unit", "a", "b", "c" }; |
| new JCommander(jct, argv); |
| |
| Assert.assertEquals(jct.verbose.intValue(), 2); |
| </pre> |
| |
| <h2> |
| Types of options |
| </h2> |
| |
| JCommander supports many types of options. |
| |
| <h4>Boolean</h4> |
| |
| When 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: |
| |
| <pre class="brush: java"> |
| @Parameter(names = "-debug", description = "Debug mode") |
| public boolean debug = false; |
| </pre> |
| |
| Such 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>. |
| |
| <h4>String, Integer, Long</h4> |
| |
| When 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: |
| |
| |
| <pre class="brush: java"> |
| @Parameter(names = "-log", description = "Level of verbosity") |
| public Integer verbose = 1; |
| </pre> |
| |
| <pre class="brush: bash"> |
| java Main -log 3 |
| </pre> |
| |
| will cause the field <tt>verbose</tt> to receive the value 3, however: |
| |
| <pre class="brush: bash"> |
| java Main -log test |
| </pre> |
| |
| will cause an exception to be thrown. |
| |
| <h4>Lists</h4> |
| |
| When 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: |
| |
| <pre class="brush: java"> |
| @Parameter(names = "-hosts", description = "Level of verbosity") |
| public List<String> hosts = new ArrayList<String>(); |
| </pre> |
| |
| will allow you to parse the following command line: |
| |
| <pre class="brush: bash"> |
| java Main -host host1 -verbose -host host2 |
| </pre> |
| |
| When JCommander is done parsing the line above, the field <tt>hosts</tt> will contain the strings "host1" and "host2". |
| |
| <h4>Main parameter</h4> |
| So 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: |
| |
| <pre class="brush: java"> |
| @Parameter(description = "Files") |
| public List<String> files = new ArrayList<String>(); |
| |
| @Parameter(names = "-debug", description = "Debugging level") |
| public Integer verbose = 1; |
| </pre> |
| |
| will allow you to parse: |
| |
| <pre class="brush: bash"> |
| java Main -debug file1 file2 |
| </pre> |
| |
| and the field <tt>files</tt> will receive the strings "file1" and |
| "file2". |
| |
| <h2>Multiple descriptions</h2> |
| |
| You can spread the description of your parameters on more than one |
| class. For example, you can define the following two classes: |
| |
| <p> |
| |
| <h3 class="sourcetitle">ArgsMaster.java</h3> |
| <pre class="brush: java"> |
| public class ArgsMaster { |
| @Parameter(names = "-master") |
| public String master; |
| } |
| </pre> |
| |
| <h3 class="sourcetitle">ArgsSlave.java</h3> |
| <pre class="brush: java"> |
| public class ArgsSlave { |
| @Parameter(names = "-slave") |
| public String slave; |
| } |
| </pre> |
| |
| and pass these two objects to JCommander: |
| |
| <pre class="brush: java"> |
| ArgsMaster m = new ArgsMaster(); |
| ArgsSlave s = new ArgsSlave(); |
| String[] argv = { "-master", "master", "-slave", "slave" }; |
| new JCommander(new Object[] { m , s }, argv); |
| |
| Assert.assertEquals(m.master, "master"); |
| Assert.assertEquals(s.slave, "slave"); |
| </pre> |
| |
| |
| <h2>@ syntax</h2> |
| |
| JCommander supports the @ syntax, which allows you to put all your options into a file and pass this file as parameter: |
| |
| <p> |
| |
| <h3 class="sourcetitle">/tmp/parameters</h3> |
| <pre class="brush: bash"> |
| -verbose |
| file1 |
| file2 |
| file3 |
| </pre> |
| <pre class="brush: bash"> |
| java Main @/tmp/parameters |
| </pre> |
| |
| <h2>Arities (multiple values for parameters)</h2> |
| |
| If some of your parameters require more than one value, such as the |
| following example where two values are expected after <tt>-pairs</tt>: |
| |
| <pre class="brush: bash"> |
| java Main -pairs slave master foo.xml |
| </pre> |
| |
| then you need to define your parameter with the <tt>arity</tt> |
| attribute and make that parameter a <tt>List<String></tt>: |
| |
| <pre class="brush: java"> |
| @Parameter(names = "-pairs", arity = 2, description = "Pairs") |
| public List<String> pairs; |
| </pre> |
| |
| You don't need to specify an arity for parameters of type |
| <tt>boolean</tt> or <tt>Boolean</tt> (which have a default arity of 0) |
| and of types <tt>String</tt>, <tt>Integer</tt>, <tt>int</tt>, |
| <tt>Long</tt> and <tt>long</tt> (which have a default arity of 1). |
| |
| <p> |
| Also, note that only <tt>List<String></tt> is allowed for |
| parameters that define an arity. You will have to convert these values |
| yourself if the parameters you need are of type <tt>Integer</tt> or |
| other (this limitation is due to Java's erasure). |
| |
| <h2>Multiple option names</h2> |
| |
| You can specify more than one option name: |
| |
| <pre class="brush: java"> |
| |
| @Parameter(names = { "-d", "--outputDirectory" }, description = "Directory") |
| public String outputDirectory; |
| |
| </pre> |
| |
| will allow both following syntaxes: |
| |
| <pre class="brush: bash"> |
| java Main -d /tmp |
| java Main --outputDirectory /tmp |
| </pre> |
| |
| <h2>Required and optional parameters</h2> |
| |
| If some of your parameters are mandatory, you can use the |
| <tt>required</tt> attribute (which default to <tt>false</tt>): |
| |
| <pre class="brush: java"> |
| |
| @Parameter(names = "-host", required = true) |
| public String host; |
| |
| </pre> |
| |
| If this parameter is not specified, JCommander will throw an exception |
| telling you which options are missing. |
| |
| <h2>Exception</h2> |
| |
| Whenever JCommander detects an error, it will throw a |
| <tt>ParameterException</tt>. Note that this is a Runtime Exception, |
| since your application is probably not initialized correctly at this |
| point. |
| |
| |
| <h2>Usage</h2> |
| |
| You 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: |
| |
| <pre class="brush: bash"> |
| Usage: |
| -port The port number |
| -debug Debug mode |
| -src, --sources The source directory |
| -testclass List of classes |
| </pre> |
| |
| <h2>Internationalization</h2> |
| |
| You can internationalize the descriptions of your parameters. First, |
| you use the <tt>descriptionKey</tt> attribute instead of |
| <tt>description</tt>. This <tt>descriptionKey</tt> is the key to the |
| string into your message bundle: |
| |
| <h3 class="sourcetitle">I18N.java</h3> |
| <pre class="brush:java"> |
| @Parameter(names = "-host", descriptionKey = "host") |
| String hostName; |
| </pre> |
| |
| Your bundle needs to define this key: |
| |
| <br> |
| |
| <h3 class="sourcetitle">MessageBundle_fr_FR.properties</h3> |
| <pre class="brush: bash"> |
| host: Hôte |
| </pre> |
| |
| Then you pass the <tt>Locale</tt> when you initialize the JCommander |
| object: |
| |
| <pre class="brush: java"> |
| Locale locale = new Locale("fr", "FR"); |
| ResourceBundle bundle = ResourceBundle.getBundle("MessageBundle", locale); |
| I18N i18n = new I18N(); |
| String[] argv = { "-host", "localhost" }; |
| JCommander jc = new JCommander(i18n, bundle, argv); |
| jc.usage(); |
| </pre> |
| will display: |
| |
| <pre class="brush: bash"> |
| Usage: |
| -host Hôte |
| </pre> |
| |
| <h2>More examples</h2> |
| |
| TestNG uses JCommander to parse its command line, here is <a href="http://github.com/cbeust/testng/blob/master/src/main/java/org/testng/CommandLineArgs.java">its definition file</a>. |
| |
| <h2>Download</h2> |
| |
| You can download JCommander from the following locations: |
| |
| <ul> |
| <li><a href="http://beust.com/jcommander/jcommander-1.0-SNAPSHOT.jar">Binary</a></li> |
| <li><a href="http://github.com/cbeust/jcommander">Source on github</a></li> |
| </ul> |
| |
| </body> |
| |
| </html> |