summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric Beust <cedric@beust.com>2014-10-06 08:59:54 -0700
committerCedric Beust <cedric@beust.com>2014-10-06 08:59:54 -0700
commitc5f63328c0668f074d96f76666e2ff84da853329 (patch)
treee61e35cabd73ba5da766200513c389a8c0b74c42
parent89820cc701ca41c85e3b000939f649df0636e35b (diff)
parent9d95b9d5cc6cf6eaa33b4170779e2191f2baefd9 (diff)
downloadjcommander-c5f63328c0668f074d96f76666e2ff84da853329.tar.gz
Merge branch 'master' of github.com:cbeust/jcommander
Conflicts: doc/index.html
-rwxr-xr-xbuild-with-maven7
-rw-r--r--doc/index.html18
-rw-r--r--pom.xml43
-rw-r--r--src/main/java/com/beust/jcommander/JCommander.java55
-rw-r--r--src/main/java/com/beust/jcommander/Parameter.java8
-rw-r--r--src/main/java/com/beust/jcommander/ParameterDescription.java6
-rw-r--r--src/main/java/com/beust/jcommander/Parameters.java5
-rw-r--r--src/main/java/com/beust/jcommander/WrappedParameter.java3
-rw-r--r--src/main/java/com/beust/jcommander/internal/DefaultConsole.java3
-rw-r--r--src/test/java/com/beust/jcommander/JCommanderTest.java91
-rw-r--r--src/test/java/com/beust/jcommander/args/AlternateNamesForListArgs.java32
-rw-r--r--src/test/java/com/beust/jcommander/command/CommandHidden.java17
-rw-r--r--src/test/java/com/beust/jcommander/command/CommandTest.java22
-rw-r--r--src/test/java/com/beust/jcommander/internal/DefaultConsoleTest.java64
14 files changed, 330 insertions, 44 deletions
diff --git a/build-with-maven b/build-with-maven
index 41aef5a..8323640 100755
--- a/build-with-maven
+++ b/build-with-maven
@@ -2,11 +2,12 @@ mvn -B clean source:jar javadoc:jar repository:bundle-create -P sign
#v=6.5.2beta
-export TESTNG=`echo ../testng/target/testng-6.8.7.jar`
+export TESTNG=`echo ../testng/target/testng-6.8.8.jar`
-run="java -classpath target/classes:target/test-classes:${TESTNG}:$CLASSPATH org.testng.TestNG src/test/resources/testng.xml"
+run="java -classpath \"target/classes;target/test-classes;${TESTNG};$CLASSPATH\" org.testng.TestNG src/test/resources/testng.xml"
echo "Launching tests: ${run}"
-java -classpath target/classes:target/test-classes:${TESTNG}:$CLASSPATH org.testng.TestNG src/test/resources/testng.xml
+$run
+#java -classpath target/classes:target/test-classes:${TESTNG}:$CLASSPATH org.testng.TestNG src/test/resources/testng.xml
echo "To deploy to the snapshot repository: mvn deploy"
echo "To deploy to the release directory: mvn -DskipTests=true release:clean release:prepare release:perform"
diff --git a/doc/index.html b/doc/index.html
index 6ed16c4..8ee8880 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -30,7 +30,19 @@
<td align="center">
<h1>JCommander</h1>
<h2>Because life is too short to parse command line parameters</h2>
-<h3>Donations welcome at <a href="bitcoin:1BhLmUZnDtjtqNetjqjHW1onqdykJW7Bd2">1BhLmUZnDtjtqNetjqjHW1onqdykJW7Bd2</a>
+<h3>
+ <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
+ <input type="hidden" name="cmd" value="_donations">
+ <input type="hidden" name="business" value="cedric@beust.com">
+ <input type="hidden" name="lc" value="US">
+ <input type="hidden" name="item_name" value="Cedric Beust">
+ <input type="hidden" name="no_note" value="0">
+ <input type="hidden" name="currency_code" value="USD">
+ <input type="hidden" name="bn" value="PP-DonationsBF:btn_donate_LG.gif:NonHostedGuest">
+ <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!">
+ <img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
+ </form>
+</h3>
</td>
</tr>
<tr>
@@ -40,7 +52,7 @@
</tr>
<tr>
<td align="right">
- Last updated: October 25th, 2012
+ Last updated: August 2nd, 2014
</td>
</tr>
<tr><td align="right"><a href="mailto:cedric@beust.com">C&eacute;dric Beust</a></td></tr>
@@ -201,7 +213,7 @@ For example, here is a converter that turns a string into a <tt>File</tt>:
<pre class="brush: java">
public class FileConverter implements IStringConverter&lt;File&gt; {
@Override
- private File convert(String value) {
+ public File convert(String value) {
return new File(value);
}
}
diff --git a/pom.xml b/pom.xml
index e5aff27..e7d15de 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
<artifactId>jcommander</artifactId>
<packaging>jar</packaging>
<name>JCommander</name>
- <version>1.33-SNAPSHOT</version>
+ <version>1.45-SNAPSHOT</version>
<description>A Java framework to parse command line options with annotations.</description>
<url>http://beust.com/jcommander</url>
<licenses>
@@ -40,6 +40,14 @@
<url>git@github.com:cbeust/jcommander.git</url>
</scm>
+ <distributionManagement>
+ <repository>
+ <id>nexus-site</id>
+ <name>Nexus Staging Repository</name>
+ <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+ </repository>
+ </distributionManagement>
+
<developers>
<developer>
<name>Cedric Beust</name>
@@ -155,6 +163,39 @@
</configuration>
</plugin>
</plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>
+ maven-bundle-plugin
+ </artifactId>
+ <versionRange>
+ [2.1.0,)
+ </versionRange>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
</build>
<dependencies>
diff --git a/src/main/java/com/beust/jcommander/JCommander.java b/src/main/java/com/beust/jcommander/JCommander.java
index b78d890..98f112e 100644
--- a/src/main/java/com/beust/jcommander/JCommander.java
+++ b/src/main/java/com/beust/jcommander/JCommander.java
@@ -154,6 +154,7 @@ public class JCommander {
private List<String> m_unknownArgs = Lists.newArrayList();
private boolean m_acceptUnknownOptions = false;
+ private boolean m_allowParameterOverwriting = false;
private static Console m_console;
@@ -485,8 +486,10 @@ public class JCommander {
// Read through file one line at time. Print line # and line
while ((line = bufRead.readLine()) != null) {
- // Allow empty lines in these at files
- if (line.length() > 0) result.add(line);
+ // Allow empty lines and # comments in these at files
+ if (line.length() > 0 && ! line.trim().startsWith("#")) {
+ result.add(line);
+ }
}
bufRead.close();
@@ -544,13 +547,13 @@ public class JCommander {
m_mainParameterDescription =
new ParameterDescription(object, p, parameterized, m_bundle, this);
} else {
+ ParameterDescription pd =
+ new ParameterDescription(object, p, parameterized, m_bundle, this);
for (String name : p.names()) {
if (m_descriptions.containsKey(new StringKey(name))) {
throw new ParameterException("Found the option " + name + " multiple times");
}
p("Adding description for " + name);
- ParameterDescription pd =
- new ParameterDescription(object, p, parameterized, m_bundle, this);
m_fields.put(parameterized, pd);
m_descriptions.put(new StringKey(name), pd);
@@ -677,6 +680,7 @@ public class JCommander {
// object)
boolean commandParsed = false;
int i = 0;
+ boolean isDashDash = false; // once we encounter --, everything goes into the main parameter
while (i < args.length && ! commandParsed) {
String arg = args[i];
String a = trim(arg);
@@ -685,7 +689,7 @@ public class JCommander {
JCommander jc = findCommandByAlias(arg);
int increment = 1;
- if (isOption(args, a) && jc == null) {
+ if (! isDashDash && ! "--".equals(a) && isOption(args, a) && jc == null) {
//
// Option
//
@@ -744,6 +748,10 @@ public class JCommander {
// Main parameter
//
if (! Strings.isStringEmpty(arg)) {
+ if ("--".equals(arg)) {
+ isDashDash = true;
+ a = trim(args[++i]);
+ }
if (m_commands.isEmpty()) {
//
// Regular (non-command) parsing
@@ -1116,13 +1124,17 @@ public class JCommander {
// The magic value 3 is the number of spaces between the name of the option
// and its description
for (Map.Entry<ProgramName, JCommander> commands : m_commands.entrySet()) {
- ProgramName progName = commands.getKey();
- String dispName = progName.getDisplayName();
- out.append(indent).append(" " + dispName); // + s(spaceCount) + getCommandDescription(progName.name) + "\n");
-
- // Options for this command
- usage(progName.getName(), out, " ");
- out.append("\n");
+ Object arg = commands.getValue().getObjects().get(0);
+ Parameters p = arg.getClass().getAnnotation(Parameters.class);
+ if (!p.hidden()) {
+ ProgramName progName = commands.getKey();
+ String dispName = progName.getDisplayName();
+ out.append(indent).append(" " + dispName); // + s(spaceCount) + getCommandDescription(progName.name) + "\n");
+
+ // Options for this command
+ usage(progName.getName(), out, " ");
+ out.append("\n");
+ }
}
}
}
@@ -1256,12 +1268,16 @@ public class JCommander {
if (converterClass != null && converterClass.isEnum()) {
try {
result = Enum.valueOf((Class<? extends Enum>) converterClass, value);
- if (result == null) {
- result = Enum.valueOf((Class<? extends Enum>) converterClass, value.toUpperCase());
- }
+ } catch (IllegalArgumentException e) {
+ try {
+ result = Enum.valueOf((Class<? extends Enum>) converterClass, value.toUpperCase());
+ } catch (IllegalArgumentException ex) {
+ throw new ParameterException("Invalid value for " + optionName + " parameter. Allowed values:" +
+ EnumSet.allOf((Class<? extends Enum>) converterClass));
+ }
} catch (Exception e) {
throw new ParameterException("Invalid value for " + optionName + " parameter. Allowed values:" +
- EnumSet.allOf((Class<? extends Enum>) converterClass));
+ EnumSet.allOf((Class<? extends Enum>) converterClass));
}
} else {
converter = instantiateConverter(optionName, converterClass);
@@ -1362,6 +1378,7 @@ public class JCommander {
JCommander jc = new JCommander(object);
jc.setProgramName(name, aliases);
jc.setDefaultProvider(m_defaultProvider);
+ jc.setAcceptUnknownOptions(m_acceptUnknownOptions);
ProgramName progName = jc.m_programName;
m_commands.put(progName, jc);
@@ -1563,7 +1580,13 @@ public class JCommander {
public List<String> getUnknownOptions() {
return m_unknownArgs;
}
+ public void setAllowParameterOverwriting(boolean b) {
+ m_allowParameterOverwriting = b;
+ }
+ public boolean isParameterOverwritingAllowed() {
+ return m_allowParameterOverwriting;
+ }
// public void setCaseSensitiveCommands(boolean b) {
// m_caseSensitiveCommands = b;
// }
diff --git a/src/main/java/com/beust/jcommander/Parameter.java b/src/main/java/com/beust/jcommander/Parameter.java
index 974eeaa..d8cf87d 100644
--- a/src/main/java/com/beust/jcommander/Parameter.java
+++ b/src/main/java/com/beust/jcommander/Parameter.java
@@ -119,4 +119,12 @@ public @interface Parameter {
* required parameters are no longer checked for their presence.
*/
boolean help() default false;
+
+ /**
+ * If true, this parameter can be overwritten through a file or another appearance of the parameter
+ * @return
+ */
+ boolean forceNonOverwritable() default false;
+
+
}
diff --git a/src/main/java/com/beust/jcommander/ParameterDescription.java b/src/main/java/com/beust/jcommander/ParameterDescription.java
index 33574a9..e41c782 100644
--- a/src/main/java/com/beust/jcommander/ParameterDescription.java
+++ b/src/main/java/com/beust/jcommander/ParameterDescription.java
@@ -231,7 +231,7 @@ public class ParameterDescription {
p("Adding " + (isDefault ? "default " : "") + "value:" + value
+ " to parameter:" + m_parameterized.getName());
String name = m_wrappedParameter.names()[0];
- if (m_assigned && ! isMultiOption()) {
+ if (m_assigned && ! isMultiOption() && !m_jCommander.isParameterOverwritingAllowed() || isNonOverwritableForced()) {
throw new ParameterException("Can only specify option " + name + " once.");
}
@@ -358,4 +358,8 @@ public class ParameterDescription {
public boolean isHelp() {
return m_wrappedParameter.isHelp();
}
+
+ public boolean isNonOverwritableForced() {
+ return m_wrappedParameter.isNonOverwritableForced();
+ }
}
diff --git a/src/main/java/com/beust/jcommander/Parameters.java b/src/main/java/com/beust/jcommander/Parameters.java
index 9834ea0..f2e8c76 100644
--- a/src/main/java/com/beust/jcommander/Parameters.java
+++ b/src/main/java/com/beust/jcommander/Parameters.java
@@ -67,4 +67,9 @@ public @interface Parameters {
* An array of allowed command names.
*/
String[] commandNames() default {};
+
+ /**
+ * If true, this command won't appear in the usage().
+ */
+ boolean hidden() default false;
}
diff --git a/src/main/java/com/beust/jcommander/WrappedParameter.java b/src/main/java/com/beust/jcommander/WrappedParameter.java
index 52cafc4..f4e7d56 100644
--- a/src/main/java/com/beust/jcommander/WrappedParameter.java
+++ b/src/main/java/com/beust/jcommander/WrappedParameter.java
@@ -109,4 +109,7 @@ public class WrappedParameter {
return m_parameter != null && m_parameter.help();
}
+ public boolean isNonOverwritableForced() {
+ return m_parameter != null && m_parameter.forceNonOverwritable();
+ }
}
diff --git a/src/main/java/com/beust/jcommander/internal/DefaultConsole.java b/src/main/java/com/beust/jcommander/internal/DefaultConsole.java
index 65e87ba..8fd7d6d 100644
--- a/src/main/java/com/beust/jcommander/internal/DefaultConsole.java
+++ b/src/main/java/com/beust/jcommander/internal/DefaultConsole.java
@@ -18,11 +18,10 @@ public class DefaultConsole implements Console {
public char[] readPassword(boolean echoInput) {
try {
+ // Do not close the readers since System.in should not be closed
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(isr);
String result = in.readLine();
- in.close();
- isr.close();
return result.toCharArray();
}
catch (IOException e) {
diff --git a/src/test/java/com/beust/jcommander/JCommanderTest.java b/src/test/java/com/beust/jcommander/JCommanderTest.java
index 356d442..ad2c5e8 100644
--- a/src/test/java/com/beust/jcommander/JCommanderTest.java
+++ b/src/test/java/com/beust/jcommander/JCommanderTest.java
@@ -40,6 +40,7 @@ import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
+import com.beust.jcommander.args.AlternateNamesForListArgs;
import com.beust.jcommander.args.Args1;
import com.beust.jcommander.args.Args1Setter;
import com.beust.jcommander.args.Args2;
@@ -96,6 +97,35 @@ public class JCommanderTest {
Assert.assertEquals(args.date, new SimpleDateFormat("yyyy-MM-dd").parse("2011-10-26"));
}
+ @DataProvider
+ public Object[][] alternateNamesListArgs() {
+ return new Object[][] {
+ new String[][] {new String[] {"--servers", "1", "-s", "2", "--servers", "3"}},
+ new String[][] {new String[] {"-s", "1", "-s", "2", "--servers", "3"}},
+ new String[][] {new String[] {"--servers", "1", "--servers", "2", "-s", "3"}},
+ new String[][] {new String[] {"-s", "1", "--servers", "2", "-s", "3"}},
+ new String[][] {new String[] {"-s", "1", "-s", "2", "--servers", "3"}},
+ };
+ }
+
+ /**
+ * Confirm that List<?> parameters with alternate names return the correct
+ * List regardless of how the arguments are specified
+ */
+
+ @Test(dataProvider = "alternateNamesListArgs")
+ public void testAlternateNamesForListArguments(String[] argv) {
+ AlternateNamesForListArgs args = new AlternateNamesForListArgs();
+
+ new JCommander(args, argv);
+
+ Assert.assertEquals(args.serverNames.size(), 3);
+ Assert.assertEquals(args.serverNames.get(0), argv[1]);
+ Assert.assertEquals(args.serverNames.get(1), argv[3]);
+ Assert.assertEquals(args.serverNames.get(2), argv[5]);
+ }
+
+
/**
* Make sure that if there are args with multiple names (e.g. "-log" and "-verbose"),
* the usage will only display it once.
@@ -566,12 +596,20 @@ public class JCommanderTest {
JCommander jc = new JCommander(args, argv);
Assert.assertEquals(args.choice, ArgsEnum.ChoiceType.ONE);
-
+
List<ChoiceType> expected = Arrays.asList(ChoiceType.ONE, ChoiceType.Two);
Assert.assertEquals(expected, args.choices);
Assert.assertEquals(jc.getParameters().get(0).getDescription(),
"Options: " + EnumSet.allOf((Class<? extends Enum>) ArgsEnum.ChoiceType.class));
-
+
+ }
+
+ public void enumArgsCaseInsensitive() {
+ ArgsEnum args = new ArgsEnum();
+ String[] argv = { "-choice", "one"};
+ JCommander jc = new JCommander(args, argv);
+
+ Assert.assertEquals(args.choice, ArgsEnum.ChoiceType.ONE);
}
@Test(expectedExceptions = ParameterException.class)
@@ -977,31 +1015,48 @@ public class JCommanderTest {
Assert.assertEquals(a.endpoint, Lists.newArrayList("dev"));
}
- public void a() {
+ public void dashDashParameter() {
class Arguments {
- @Parameter(names = { "-help", "-h" }, arity = 0, description = "Show this help message")
- public Boolean help = false;
-
- @Parameter(names = { "-verbose", "-v" }, arity = 0, description = "Verbose output mode")
- public Boolean verbose = false;
-
- @Parameter(names = { "-target" }, arity = 1, description = "Target directory", required = true)
- public File target;
-
- @Parameter(names = { "-input" }, variableArity = true, description = "Input paths", required = true)
- public List<String> paths;
+ @Parameter(names = { "-name" })
+ public String name;
+ @Parameter
+ public List<String> mainParameters;
}
+
+ Arguments a = new Arguments();
+ new JCommander(a, new String[] {
+ "-name", "theName", "--", "param1", "param2"}
+ );
+ Assert.assertEquals(a.name, "theName");
+ Assert.assertEquals(a.mainParameters.size(), 2);
+ Assert.assertEquals(a.mainParameters.get(0), "param1");
+ Assert.assertEquals(a.mainParameters.get(1), "param2");
+ }
+
+ public void dashDashParameter2() {
+ class Arguments {
+ @Parameter(names = { "-name" })
+ public String name;
+ @Parameter
+ public List<String> mainParameters;
+ }
+
Arguments a = new Arguments();
new JCommander(a, new String[] {
- "-input", "example_in1", "example_in2", "-target", "example_out" }
+ "param1", "param2", "--", "param3", "-name", "theName"}
);
- Assert.assertEquals(a.paths, Lists.newArrayList("example_in1", "example_in2"));
- Assert.assertEquals(a.target, new File("example_out"));
+ Assert.assertNull(a.name);
+ Assert.assertEquals(a.mainParameters.size(), 5);
+ Assert.assertEquals(a.mainParameters.get(0), "param1");
+ Assert.assertEquals(a.mainParameters.get(1), "param2");
+ Assert.assertEquals(a.mainParameters.get(2), "param3");
+ Assert.assertEquals(a.mainParameters.get(3), "-name");
+ Assert.assertEquals(a.mainParameters.get(4), "theName");
}
@Test(enabled = false)
public static void main(String[] args) throws Exception {
- new JCommanderTest().a();
+ new JCommanderTest().enumArgsFail();
// class A {
// @Parameter(names = "-short", required = true)
// List<String> parameters;
diff --git a/src/test/java/com/beust/jcommander/args/AlternateNamesForListArgs.java b/src/test/java/com/beust/jcommander/args/AlternateNamesForListArgs.java
new file mode 100644
index 0000000..18a1655
--- /dev/null
+++ b/src/test/java/com/beust/jcommander/args/AlternateNamesForListArgs.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 the original author or authors.
+ * See the notice.md file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.beust.jcommander.args;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.internal.Lists;
+import java.util.List;
+
+/**
+ *
+ * @author Andy Law <andy.law@roslin.ed.ac.uk>
+ */
+public class AlternateNamesForListArgs {
+
+ @Parameter(names = {"-s", "--servers"}, description = "blah")
+ public List<String> serverNames = Lists.newLinkedList();
+}
diff --git a/src/test/java/com/beust/jcommander/command/CommandHidden.java b/src/test/java/com/beust/jcommander/command/CommandHidden.java
new file mode 100644
index 0000000..a3fc4fa
--- /dev/null
+++ b/src/test/java/com/beust/jcommander/command/CommandHidden.java
@@ -0,0 +1,17 @@
+package com.beust.jcommander.command;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+
+import java.util.List;
+
+@Parameters(commandNames = "add", commandDescription = "Hidden command to add file contents to the index", hidden = true)
+public class CommandHidden {
+
+ @Parameter(description = "Patterns of files to be added")
+ public List<String> patterns;
+
+ @Parameter(names = "-i")
+ public Boolean interactive = false;
+
+}
diff --git a/src/test/java/com/beust/jcommander/command/CommandTest.java b/src/test/java/com/beust/jcommander/command/CommandTest.java
index 97e0007..cf921bd 100644
--- a/src/test/java/com/beust/jcommander/command/CommandTest.java
+++ b/src/test/java/com/beust/jcommander/command/CommandTest.java
@@ -87,6 +87,28 @@ public class CommandTest {
Assert.assertEquals(commit.files, Arrays.asList("A.java", "B.java"));
}
+ @Test
+ public void hiddenCommandTest() {
+ CommandMain cm = new CommandMain();
+ JCommander jc = new JCommander(cm);
+ CommandAdd add = new CommandAdd();
+ jc.addCommand("add", add);
+ CommandHidden hidden = new CommandHidden();
+ jc.addCommand("hidden", hidden);
+ jc.parse("hidden", "-i", "A.java");
+
+ Assert.assertEquals(jc.getParsedCommand(), "hidden");
+ Assert.assertEquals(hidden.interactive.booleanValue(), true);
+ Assert.assertEquals(hidden.patterns, Arrays.asList("A.java"));
+
+ jc.setProgramName("TestCommander");
+ StringBuilder out = new StringBuilder();
+ jc.usage(out);
+
+ Assert.assertTrue(out.toString().contains("add Add file contents to the index"));
+ Assert.assertFalse(out.toString().contains("hidden Hidden command to add file contents to the index"));
+ }
+
public static void main(String[] args) {
new CommandTest().shouldComplainIfNoAnnotations();
}
diff --git a/src/test/java/com/beust/jcommander/internal/DefaultConsoleTest.java b/src/test/java/com/beust/jcommander/internal/DefaultConsoleTest.java
new file mode 100644
index 0000000..e101439
--- /dev/null
+++ b/src/test/java/com/beust/jcommander/internal/DefaultConsoleTest.java
@@ -0,0 +1,64 @@
+package com.beust.jcommander.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@Test
+public class DefaultConsoleTest {
+ public void readPasswordCanBeCalledMultipleTimes() {
+ final InputStream inBackup = System.in;
+ try {
+ final StringInputStream in = new StringInputStream();
+ System.setIn(in);
+ final Console console = new DefaultConsole();
+
+ in.setData("password1\n");
+ char[] password = console.readPassword(false);
+ Assert.assertEquals(password, "password1".toCharArray());
+ Assert.assertFalse(in.isClosedCalled(), "System.in stream shouldn't be closed");
+
+ in.setData("password2\n");
+ password = console.readPassword(false);
+ Assert.assertEquals(password, "password2".toCharArray());
+ Assert.assertFalse(in.isClosedCalled(), "System.in stream shouldn't be closed");
+ } finally {
+ System.setIn(inBackup);
+ }
+ }
+
+ private static class StringInputStream extends InputStream {
+ private byte[] data = new byte[0];
+ private int offset = 0;
+ private boolean closedCalled;
+
+ StringInputStream() {
+ super();
+ }
+
+ void setData(final String strData) {
+ data = strData.getBytes();
+ offset = 0;
+ }
+
+ boolean isClosedCalled() {
+ return closedCalled;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (offset >= data.length) {
+ return -1;
+ }
+ return 0xFFFF & data[offset++];
+ }
+
+ @Override
+ public void close() throws IOException {
+ closedCalled = true;
+ super.close();
+ }
+ }
+}