Open perlun opened 5 years ago
You get use the System.console().readPassword()
API in your application.
With picocli this would look something like this (JCommander should be fairly similar):
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
@Command(name = "app", mixinStandardHelpOptions = true,
description = "Password example app", version = "1.0")
public class PasswordExample implements Runnable {
@Option(names = "--password", description = "Connection password", interactive = true)
protected String password = System.getenv("THE_PASSWORD");
public static void main(String[] args) {
CommandLine.run(new PasswordExample(), args);
}
public void run() {
if (password == null) {
password = new String(System.console().readPassword("Connection password: "));
}
System.out.printf("Your password is: %s", password);
}
}
If I start the app without arguments, it prompts me for the password. When the environment variable is defined, it uses that value as the password without prompting.
With --help
, it shows this:
Usage: app [-hV] [--password=<password>]
Password example app
--password=<password>
Connection password
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
@Parameter(names = { "-h", "--help" }, help = true)
protected boolean help;
@Parameter(names = "--password", description = "Connection password", password = true)
protected String password = System.getenv("THE_PASSWORD");
void someMethod(String[] args) {
List<String> argsList = Lists.newArrayList( args );
// check if it's a help request here itself, since password argument is not added it wont ask for password
if (help) {
jCommander.usage();
}
if ( password == null ) {
// Environment variable not set - add to list of arguments.
argsList.add( "--password" );
}
JCommander jCommander = JCommander.newBuilder()
.addObject( this )
.build();
jCommander.parse( modifiedArgs );
Thanks for a great library. My scenario: I am writing a command line tool that requires a password to be provided.
If I specify the
required = true
setting in the@Parameter
annotation for mypassword
field, the user will have to type--password
which isn't really what I want - I want them to always be asked for the password, unless the password is set using an environment variable.Because of this, I've come up with an approach that looks like below:
...i.e, add a "fake" argument
--password
to the list of argument being passed to JCommander.This works reasonably well for most scenarios, but I've seen at least one such where it does not:
--help
, they will be first prompted for the password where they can press Enter, and then they will get the command line usage.I believe this is flawed - the
help = true
argument should take precedence over allpassword = true
arguments. If the user asked for help, it does not make much sense to force them to provide all password-flagged arguments (even if they typed--password
on the command line, or as in my case, it was injected by the program) - since execution of the program will be aborted anyway.If you have some other suggestion(s), I'm open for it.