For every command I have a concrete class which implement certain interface.
For example:
public class FooCommand implements Command{
#Parameter(names = {"-?","--help"}, description = "display this help",help = true)
private boolean helpRequested = false;
...
}
And this is the usage message I get:
Usage: foo-command [options]
Options:
-?, --help
display this help
How can I add description to command (but not to option). For example I want to get such usage message:
Usage: foo-command [options] - This command is used as base foo
Options:
-?, --help
display this help
EDIT I have foo-command, boo-command, lala-command. However, all these commands are separate and are not within one main command (by other words this is not like git clone ...).
This is the way I get usage
JCommander jCommander=new JCommander(command, args);
jCommander.setProgramName(commandName);//for example foo-command
StringBuilder builder=new StringBuilder();
jCommander.usage(builder);
Following snippet might be a starting point for what you are looking for.
#Parameters(commandDescription = "foo-command short description")
public class FooCommand implements Command {
#Parameter(names = {"-?", "--help"}, description = "display this help",
help = true)
private boolean helpRequested = false;
#Parameter(description = "This command is used as base foo")
public List<String> commandOptions;
// your command code goes below
}
public class CommandMain {
public static void main(String[] args) {
JCommander jc = new JCommander();
jc.setProgramName(CommandMain.class.getSimpleName());
FooCommand foo = new FooCommand();
jc.addCommand("foo-command", foo);
// display the help
jc.usage();
}
}
output
Usage: CommandMain [options] [command] [command options]
Commands:
foo-command foo-command short description
Usage: foo-command [options] This command is used as base foo
Options:
-?, --help
display this help
Default: false
Also have a look at: JCommander command syntax
edit Show the description for a command itself. The annotation #Parameters(commandDescription = "foo-command short description") on the class FooCommand can be omitted in that case.
Command command = new FooCommand();
JCommander jc = new JCommander(command, args);
jc.setProgramName("foo-command");
StringBuilder builder = new StringBuilder();
jc.usage(builder);
System.out.println(builder);
output
Usage: foo-command [options] This command is used as base foo
Options:
-?, --help
display this help
Default: false
Related
So it might seem like a trivial question, but I cannot find any information out there that answers my question. Nonetheless, it is a very general coding question.
Suppose you have a java program that reads a file and creates a data structure based on the information provided by the file. So you do:
javac javaprogram.java
java javaprogram
Easy enough, but what I want to do here is to provide the program with a file specified in the command line, like this:
javac javaprogram.java
java javaprogram -file
What code do I have to write to conclude this very concern?
Thanks.
One of the best command-line utility libraries for Java out there is JCommander.
A trivial implementation based on your thread description would be:
public class javaprogram {
#Parameter(names={"-file"})
String filePath;
public static void main(String[] args) {
// instantiate your main class
javaprogram program = new javaprogram();
// intialize JCommander and parse input arguments
JCommander.newBuilder().addObject(program).build().parse(args);
// use your file path which is now accessible through the 'filePath' field
}
}
You should make sure that the library jar is available under your classpath when compiling the javaprogram.java class file.
Otherwise, in case you don't need an utility around you program argument, you may keep the program entry simple enough reading the file path as a raw program argument:
public class javaprogram {
private static final String FILE_SWITCH = "-file";
public static void main(String[] args) {
if ((args.length == 2) && (FILE_SWITCH.equals(args[0]))) {
final String filePath = args[1];
// use your file path which is now accessible through the 'filePath' local variable
}
}
}
The easiest way to do it is using -D, so if you have some file, you could call
java -Dmy.file=file.txt javaprogram
And inside you program you could read it with System.getProperty("my.file").
public class Main {
public static void main(String[] args) {
String filename = System.getProperty("my.file");
if (filename == null) {
System.exit(-1); // Or wharever you want
}
// Read and process your file
}
}
Or you could use third a party tool like picocli
import java.io.File;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
#Command(name = "Sample", header = "%n#|green Sample demo|#")
public class Sample implements Runnable {
#Option(names = {"-f", "--file"}, required = true, description = "Filename")
private File file;
#Override
public void run() {
System.out.printf("Loading %s%n", file.getAbsolutePath());
}
public static void main(String[] args) {
CommandLine.run(new Sample(), System.err, args);
}
}
You can pass file path as argument in two ways:
1)
public class Main {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("File path plz");
return;
}
System.out.println("File path: " + args[0]);
}
}
2) Use JCommander
Let's go step by step. First you need to pass the file path to your program.
Lets say you execute your program like this:
java javaprogram /foo/bar/file.txt
Strings that come after "javaprogram" will be passed as arguments to your program. This is the reason behind the syntax of the main method:
public static void main(String[] args) {
//args is the array that would store all the values passed when executing your program
String filePath = args[0]; //filePath will contain /foo/bar/file.txt
}
Now that you were able to get a the file path and name from the command-line, you need to open and read your file.
Take a look at File class and FileInputStream class.
https://www.mkyong.com/java/how-to-read-file-in-java-fileinputstream/
That should get you started.
Good luck!
I have a self-contained Java application packaged with the javapackager tool (version 8.0, Windows). How do I pass it system property values at application runtime (not at package time) on the command line?
The doc does not seem to address this.
I tried the standard Java way as in:
mypackagedapp.exe -Dmyprop=myvalue
but that does not appear to have an effect.
Here is a code that validates if an argument exists in the command line.
See if the next code can help you.
public static void main(final String[] args) throws Exception {
CommandLine line = validateArgs(args);
if (null == line) {
return;
}
}
private static CommandLine validateArgs(String[] args) {
Options flags = getArgs();
CommandLineParser parser = new BasicParser();
CommandLine line = null;
try {
// parse the command line arguments
line = parser.parse(flags, args);
if (line == null) {
return null;
}
} catch (ParseException exp) {
System.out.println(exp.getMessage());
}
return line;
}
static Options getArgs() {
Options flags = new Options();
Option dmyprop = OptionBuilder.withArgName("dmyprop")
.hasArg()
.withDescription("add description")
.create("Dmyprop");
flags.addOption(dmyprop);
return flags;
}
In order to get environment variable you need to use:
String env = System.getenv(option);
where option is your desired environment variable.
Hope it helped.
I'm trying to run a groovy(2.4.3) script on windows that calls a goovy class xxxxx.groovy. I've tried a number of variations using classpath and various scripts, some examples below, always getting MultipleCompliationErrorsException.... unable to resolve class
classfile is firstclass.groovy
import org.apache.commons.io.FilenameUtils
class firstclassstart {
def wluid, wlpwd, wlserver, port
private wlconnection, connectString, jmxConnector, Filpath, Filpass, Filname, OSRPDpath, Passphrase
// object constructor
firstclassstart(wluid, wlpwd, wlserver, port) {
this.wluid = wluid
this.wlpwd = wlpwd
this.wlserver = wlserver
this.port = port
}
def isFile(Filpath) {
// Create a File object representing the folder 'A/B'
def folder = new File(Filpath)
if (!org.apache.commons.io.FilenameUtils.isExtension(Filpath, "txt")) {
println "bad extension"
return false
} else if (!folder.exists()) {
// Create all folders up-to and including B
println " path is wrong"
return false
} else
println "file found"
return true
}
}
cmd line script test.groovy
import firstclass
def sample = new firstclass.firstclassstart("weblogic", "Admin123", "x.com", "7002")
//def sample = new firstclassstart("weblogic", "Admin123", "x.com", "7002")
sample.isFile("./firstclass.groovy")
..\groovy -cp "firstclass.groovy;commons-io-1.3.2.jar" testfc.groovy
script test.groovy
GroovyShell shell = new GroovyShell()
def script = shell.parse(new File('mylib/firstclass.groovy'))
firstclass sample = new script.firstclass("uid", "pwd", "url", "port")
sample.getstatus()
c:>groovy test.groovy
script test.groovy v2 put firstclass.groovy in directory test below script
import test.firstclass
firstclass sample = new script.firstclass("uid", "pwd", "url", "port")
sample.getstatus()
c:>groovy test.groovy
just looking for a bullet proof, portable way to oranize my java classes, .groovy classess, etc. and scripts.
Thanks
I think that you can do using for example your first approach:
groovy -cp mylib/firstclass.groovy mylib/test.groovy
However I see some problems in your code which are probably causing MultipleCompliationErrorsException.
Since you're including firstclass.groovy in your classpath, you've to add the import firstclass in the test.groovy.
Why are you using script.firstclass in test.groovy? you're class is called simply firstclass.
In your firstclass.groovy you're using import org.apache.commons.io.FilenameUtils and probably other, however you're not including it in the classpath.
So finally I think that, you've to change your test.groovy for something like:
import firstclass
firstclass sample = new firstclass("uid", "pwd", "url", "port")
sample.getstatus()
And in your command add the remaining includes for apache Commons IO to the classpath.
groovy -cp "mylib/firstclass.groovy;commons-io-2.4.jar;" mylib/testexe.groovy
Hope this helps,
UPDATE BASED ON OP CHANGES:
After the changes you've some things wrong, I try to enumerate it:
If your file is called firstclass.groovy your class must be class firstclass not class firstclassstart.
In your test.groovy use new firstclass not new firstclass.firstclassstart.
So the thing is, your code must be:
class file firstclass.groovy:
import org.apache.commons.io.FilenameUtils
class firstclass {
def wluid, wlpwd, wlserver, port
private wlconnection, connectString, jmxConnector, Filpath, Filpass, Filname, OSRPDpath, Passphrase
// object constructor
firstclass(wluid, wlpwd, wlserver, port) {
this.wluid = wluid
this.wlpwd = wlpwd
this.wlserver = wlserver
this.port = port
}
def isFile(Filpath) {
// Create a File object representing the folder 'A/B'
def folder = new File(Filpath)
if (!org.apache.commons.io.FilenameUtils.isExtension(Filpath, "txt")) {
println "bad extension"
return false
} else if (!folder.exists()) {
// Create all folders up-to and including B
println " path is wrong"
return false
} else
println "file found"
return true
}
}
script test.groovy:
import firstclass
def sample = new firstclass("weblogic", "Admin123", "x.com", "7002")
sample.isFile("./firstclass.groovy")
Finally the command to execute it:
groovy -cp "firstclass.groovy;commons-io-1.3.2.jar" test.groovy
With this changes your code must works, I try it and works as expected.
I know that I can run non GUI jar files from the command line. Is there any way that can do so by clicking or something and not writing the commands again and again.? Is there any software to do so. ( I am talking about a compiled jar and don't want to run from any ide)
public static final String TITLE = "CONSOLE title";
public static final String FILENAME = "myjar.jar";
public static void main(String[] args) throws InterruptedException, IOException {
if(args.length==0 || !args[args.length-1].equals("terminal")) {
String[] command;
if(System.getProperty("os.name").toLowerCase().contains("win")) {
command = new String[]{"cmd", "/c", "start \"title \\\""+TITLE+"\\\" & java -jar \\\""+new File(FILENAME).getAbsolutePath()+"\\\" terminal\""};
} else {
command =new String[]{"sh", "-c", "gnome-terminal -t \""+TITLE+"\" -x sh -c \"java -jar \\\""+new File(FILENAME).getAbsolutePath()+"\\\" terminal\""};
}
try {
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
} catch(Throwable t){
t.printStackTrace();
}
} else {
//THERE IS YOUR CONSOLE PROGRAM:
System.out.println("Hey! What's your name?");
String read = new BufferedReader(new InputStreamReader(System.in)).readLine();
System.out.println("Hey, "+read+"!");
Thread.sleep(10000);
}
}
You can run it with double clicking on .jar file. Don't forget about MANIFEST.MF! :) (working on linux, also!)
Example (I only double clicked on jar file):
The way intended by Java is that you call java -jar XXXX.jar on the jars you need. Drawback is that you can't specify a classpath so all classes should be there.
A cooler way to package an application is by using Java WebStart. With that the user installs the application jut by clicking on a web browser. Check here http://docs.oracle.com/javase/8/docs/technotes/guides/javaws/developersguide/contents.html
I want something like:
java programName -jobs1 -C 10 -W 20
java programName -job2
java programName -job3
With contents:
Option o1 = new Option("job2", "some desc");
Option o2 = new Option("job3" , "(some desc")
Option o3 = OptionBuilder.hasArgs(2).withArgName( "W" ).withArgName("C").withDescription( "Some desc" ).create("job1")
Option o4 = new Option("help");
Options os = new Options().addOption(o1).addOption(o2).addOption(o3).addOption(o4).
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp( "ProgramName", options );
...where the output is:
Usage ProgramName
-job1 <c> Some Desc
-job2 Some desc
-job3 Some desc
-help Print this message
I expect for -job1 it should print -job1 -C <> -W <>
Am I missing something? It doesn't work with more than one argument. By the way, I used commons-cli 1.2.
You cannot have context-sensitive arguments. You can have the arguments: job1, job2, job3, C & W, but you cannot say (through the library) that C & W are only valid for job1.
If job1/2/3 are mutually exclusive, create an OptionGroup. Then in code, make sure C & W are only given for job1.
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.HelpFormatter;
public class StackOverflowExample
{
public static final String JOB1 = "job1";
public static final Option job1 =
OptionBuilder.hasArg(false)
.isRequired(false)
.withDescription("description of job1")
.create(JOB1);
public static final String JOB2 = "job2";
public static final Option job2 =
OptionBuilder.hasArg(false)
.isRequired(false)
.withDescription("description of job2")
.create(JOB2);
public static final String JOB3 = "job3";
public static final Option job3 =
OptionBuilder.hasArg(false)
.isRequired(false)
.withDescription("description of job3")
.create(JOB3);
public static final String MY_C = "C";
public static final Option my_c =
OptionBuilder.hasArg(true)
.withArgName("count")
.isRequired(false)
.withDescription("description of C")
.create(MY_C);
public static final String MY_W = "W";
public static final Option my_w =
OptionBuilder.hasArg(true)
.withArgName("width")
.isRequired(false)
.withDescription("description of W")
.create(MY_W);
public static void main(String[] args)
{
Options options = new Options();
OptionGroup optgrp = new OptionGroup();
optgrp.addOption(job1);
optgrp.addOption(job2);
optgrp.addOption(job3);
options.addOptionGroup(optgrp);
options.addOption(my_c);
options.addOption(my_w);
try {
CommandLineParser parser = new GnuParser();
CommandLine cmdline = parser.parse(options, args);
if (((cmdline.hasOption(MY_C)) || (cmdline.hasOption(MY_W))) &&
(! cmdline.hasOption(JOB1))) {
HelpFormatter help = new HelpFormatter();
help.printHelp("cmdname", options);
System.exit(-1);
}
System.out.println("OK");
}
catch (Exception ex) {
ex.printStackTrace();
System.exit(-1);
}
}
}
Which produces the following output:
<~/sandbox/CoreUtils/scratch> $ javac -d . -cp ~/sandbox/CoreUtils/lib/commons-cli-1.2.jar:. StackOverflowExample.java
<~/sandbox/CoreUtils/scratch> $ java -cp ~/sandbox/CoreUtils/lib/commons-cli-1.2.jar:. StackOverflowExample -C foo -job1
OK
<~/sandbox/CoreUtils/scratch> $ java -cp ~/sandbox/CoreUtils/lib/commons-cli-1.2.jar:. StackOverflowExample -C foo -job2
usage: cmdname
-C <count> description of C
-job1 description of job1
-job2 description of job2
-job3 description of job3
-W <width> description of W