From: Mathieu Baudier Date: Fri, 28 Oct 2022 06:48:47 +0000 (+0200) Subject: Improve command line X-Git-Tag: v2.3.11~68 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=38918c51589fe96cefab71f01721254f624769e5 Improve command line --- diff --git a/org.argeo.api.cli/src/org/argeo/api/cli/CommandArgsException.java b/org.argeo.api.cli/src/org/argeo/api/cli/CommandArgsException.java index b2a12a603..935247fee 100644 --- a/org.argeo.api.cli/src/org/argeo/api/cli/CommandArgsException.java +++ b/org.argeo.api.cli/src/org/argeo/api/cli/CommandArgsException.java @@ -1,5 +1,6 @@ package org.argeo.api.cli; +/** Exception thrown when the provided arguments are not correct. */ public class CommandArgsException extends IllegalArgumentException { private static final long serialVersionUID = -7271050747105253935L; private String commandName; diff --git a/org.argeo.api.cli/src/org/argeo/api/cli/CommandRuntimeException.java b/org.argeo.api.cli/src/org/argeo/api/cli/CommandRuntimeException.java index 52c033433..b3f0517b4 100644 --- a/org.argeo.api.cli/src/org/argeo/api/cli/CommandRuntimeException.java +++ b/org.argeo.api.cli/src/org/argeo/api/cli/CommandRuntimeException.java @@ -3,7 +3,7 @@ package org.argeo.api.cli; import java.util.List; /** {@link RuntimeException} referring during a command run. */ -public class CommandRuntimeException extends RuntimeException { +class CommandRuntimeException extends RuntimeException { private static final long serialVersionUID = 5595999301269377128L; private final DescribedCommand command; diff --git a/org.argeo.api.cli/src/org/argeo/api/cli/CommandsCli.java b/org.argeo.api.cli/src/org/argeo/api/cli/CommandsCli.java index b82308a2b..5bbfcfa07 100644 --- a/org.argeo.api.cli/src/org/argeo/api/cli/CommandsCli.java +++ b/org.argeo.api.cli/src/org/argeo/api/cli/CommandsCli.java @@ -18,8 +18,6 @@ import org.apache.commons.cli.ParseException; /** Base class for a CLI managing sub commands. */ public abstract class CommandsCli implements DescribedCommand { - public final static String HELP = "help"; - private final String commandName; private Map, ?>> commands = new TreeMap<>(); @@ -33,11 +31,17 @@ public abstract class CommandsCli implements DescribedCommand { public Object apply(List args) { String cmd = null; List newArgs = new ArrayList<>(); + boolean isHelpOption = false; try { CommandLineParser clParser = new DefaultParser(); CommandLine commonCl = clParser.parse(getOptions(), args.toArray(new String[args.size()]), true); List leftOvers = commonCl.getArgList(); for (String arg : leftOvers) { + if (arg.equals("--" + HelpCommand.HELP_OPTION.getLongOpt())) { + isHelpOption = true; + // TODO break? + } + if (!arg.startsWith("-") && cmd == null) { cmd = arg; } else { @@ -50,6 +54,18 @@ public abstract class CommandsCli implements DescribedCommand { } Function, ?> function = cmd != null ? getCommand(cmd) : getDefaultCommand(); + + // --help option + if (!(function instanceof CommandsCli)) + if (function instanceof DescribedCommand command) + if (isHelpOption) { + throw new PrintHelpRequestException(cmd, this); +// StringWriter out = new StringWriter(); +// HelpCommand.printHelp(command, out); +// System.out.println(out.toString()); +// return null; + } + if (function == null) throw new IllegalArgumentException("Uknown command " + cmd); try { @@ -85,7 +101,7 @@ public abstract class CommandsCli implements DescribedCommand { protected void addCommandsCli(CommandsCli commandsCli) { addCommand(commandsCli.getCommandName(), commandsCli); - commandsCli.addCommand(HELP, new HelpCommand(this, commandsCli)); + commandsCli.addCommand(HelpCommand.HELP, new HelpCommand(this, commandsCli)); } public String getCommandName() { @@ -101,7 +117,7 @@ public abstract class CommandsCli implements DescribedCommand { } public HelpCommand getHelpCommand() { - return (HelpCommand) getCommand(HELP); + return (HelpCommand) getCommand(HelpCommand.HELP); } public Function, String> getDefaultCommand() { @@ -111,10 +127,15 @@ public abstract class CommandsCli implements DescribedCommand { /** In order to implement quickly a main method. */ public static void mainImpl(CommandsCli cli, String[] args) { try { - cli.addCommand(CommandsCli.HELP, new HelpCommand(null, cli)); + cli.addCommand(HelpCommand.HELP, new HelpCommand(null, cli)); Object output = cli.apply(Arrays.asList(args)); - System.out.println(output); + if (output != null) + System.out.println(output); System.exit(0); + } catch (PrintHelpRequestException e) { + StringWriter out = new StringWriter(); + HelpCommand.printHelp(e.getCommandsCli(), e.getCommandName(), out); + System.out.println(out.toString()); } catch (CommandArgsException e) { System.err.println("Wrong arguments " + Arrays.toString(args) + ": " + e.getMessage()); Throwable cause = e.getCause(); diff --git a/org.argeo.api.cli/src/org/argeo/api/cli/DescribedCommand.java b/org.argeo.api.cli/src/org/argeo/api/cli/DescribedCommand.java index 7a9d5d901..51cb2ceca 100644 --- a/org.argeo.api.cli/src/org/argeo/api/cli/DescribedCommand.java +++ b/org.argeo.api.cli/src/org/argeo/api/cli/DescribedCommand.java @@ -41,6 +41,11 @@ public interface DescribedCommand extends Function, T> { Object output = command.apply(Arrays.asList(args)); System.out.println(output); System.exit(0); + } catch (PrintHelpRequestException e) { + StringWriter out = new StringWriter(); + HelpCommand.printHelp(command, out); + System.out.println(out.toString()); + System.exit(1); } catch (IllegalArgumentException e) { StringWriter out = new StringWriter(); HelpCommand.printHelp(command, out); diff --git a/org.argeo.api.cli/src/org/argeo/api/cli/HelpCommand.java b/org.argeo.api.cli/src/org/argeo/api/cli/HelpCommand.java index d5285a60c..fdcaf0224 100644 --- a/org.argeo.api.cli/src/org/argeo/api/cli/HelpCommand.java +++ b/org.argeo.api.cli/src/org/argeo/api/cli/HelpCommand.java @@ -6,10 +6,20 @@ import java.util.List; import java.util.function.Function; import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; /** A special command that can describe {@link DescribedCommand}. */ public class HelpCommand implements DescribedCommand { + /** + * System property forcing the root command to this value (typically the name of + * a script). + */ + public final static String ROOT_COMMAND_PROPERTY = "org.argeo.api.cli.rootCommand"; + + final static String HELP = "help"; + final static Option HELP_OPTION = Option.builder().longOpt(HELP).desc("print this help").build(); + private CommandsCli commandsCli; private CommandsCli parentCommandsCli; @@ -91,6 +101,9 @@ public class HelpCommand implements DescribedCommand { if (hc.getParentCommandsCli() != null) { return getCommandCall(hc.getParentCommandsCli()) + " " + commandsCli.getCommandName(); } else { + String rootCommand = System.getProperty(ROOT_COMMAND_PROPERTY); + if (rootCommand != null) + return rootCommand; return commandsCli.getCommandName(); } } @@ -99,8 +112,10 @@ public class HelpCommand implements DescribedCommand { String usage = "java " + command.getClass().getName() + (command.getUsage() != null ? " " + command.getUsage() : ""); HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(new PrintWriter(out), helpWidth, usage, command.getDescription(), command.getOptions(), - helpLeftPad, helpDescPad, command.getExamples(), false); + Options options = command.getOptions(); + options.addOption(HelpCommand.HELP_OPTION); + formatter.printHelp(new PrintWriter(out), helpWidth, usage, command.getDescription(), options, helpLeftPad, + helpDescPad, command.getExamples(), false); } @@ -108,8 +123,10 @@ public class HelpCommand implements DescribedCommand { DescribedCommand command = (DescribedCommand) commandsCli.getCommand(commandName); String usage = commandsCli.getHelpCommand().getCommandUsage(commandName, command); HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(new PrintWriter(out), helpWidth, usage, command.getDescription(), command.getOptions(), - helpLeftPad, helpDescPad, command.getExamples(), false); + Options options = command.getOptions(); + options.addOption(HelpCommand.HELP_OPTION); + formatter.printHelp(new PrintWriter(out), helpWidth, usage, command.getDescription(), options, helpLeftPad, + helpDescPad, command.getExamples(), false); } diff --git a/org.argeo.api.cli/src/org/argeo/api/cli/PrintHelpRequestException.java b/org.argeo.api.cli/src/org/argeo/api/cli/PrintHelpRequestException.java new file mode 100644 index 000000000..017386b83 --- /dev/null +++ b/org.argeo.api.cli/src/org/argeo/api/cli/PrintHelpRequestException.java @@ -0,0 +1,29 @@ +package org.argeo.api.cli; + +/** An exception indicating that help should be printed. */ +class PrintHelpRequestException extends RuntimeException { + + private static final long serialVersionUID = -9029122270660656639L; + + private String commandName; + private volatile CommandsCli commandsCli; + + public PrintHelpRequestException(String commandName, CommandsCli commandsCli) { + super(); + this.commandName = commandName; + this.commandsCli = commandsCli; + } + + public static long getSerialversionuid() { + return serialVersionUID; + } + + public String getCommandName() { + return commandName; + } + + public CommandsCli getCommandsCli() { + return commandsCli; + } + +} diff --git a/org.argeo.cms.cli/bnd.bnd b/org.argeo.cms.cli/bnd.bnd index e69de29bb..3b7027710 100644 --- a/org.argeo.cms.cli/bnd.bnd +++ b/org.argeo.cms.cli/bnd.bnd @@ -0,0 +1,71 @@ +Main-Class: org.argeo.cms.cli.ArgeoCli + +Class-Path: \ +org.argeo.api.acr.2.3.jar \ +org.argeo.api.cli.2.3.jar \ +org.argeo.api.cms.2.3.jar \ +org.argeo.api.uuid.2.3.jar \ +org.argeo.cms.2.3.jar \ +org.argeo.cms.ee.2.3.jar \ +org.argeo.cms.lib.equinox.2.3.jar \ +org.argeo.cms.lib.jetty.2.3.jar \ +org.argeo.cms.lib.pgsql.2.3.jar \ +org.argeo.cms.lib.sshd.2.3.jar \ +org.argeo.cms.ux.2.3.jar \ +org.argeo.init.2.3.jar \ +org.argeo.util.2.3.jar \ +../org.argeo.tp/bcmail.1.71.jar \ +../org.argeo.tp/bcpg.1.71.jar \ +../org.argeo.tp/bcpkix.1.71.jar \ +../org.argeo.tp/bcprov.1.71.jar \ +../org.argeo.tp/bcutil.1.71.jar \ +../org.argeo.tp/com.fasterxml.jackson.core.jackson-annotations.2.13.jar \ +../org.argeo.tp/com.fasterxml.jackson.core.jackson-core.2.13.jar \ +../org.argeo.tp/com.fasterxml.jackson.core.jackson-databind.2.13.jar \ +../org.argeo.tp/com.googlecode.javaewah.JavaEWAH.1.1.jar \ +../org.argeo.tp/com.sun.mail.mbox.1.6.jar \ +../org.argeo.tp/com.zaxxer.sparsebits.1.2.jar \ +../org.argeo.tp/jakarta.mail.1.6.jar \ +../org.argeo.tp/jakarta.servlet.api.4.0.jar \ +../org.argeo.tp/javax.activation.1.2.jar \ +../org.argeo.tp/javax.websocket.1.1.jar \ +../org.argeo.tp/net.i2p.crypto.eddsa.0.3.jar \ +../org.argeo.tp/org.argeo.ext.slf4j.2.3.jar \ +../org.argeo.tp/org.h2.1.4.jar \ +../org.argeo.tp/org.postgresql.jdbc42.42.3.jar \ +../org.argeo.tp/org.slf4j.api.1.7.jar \ +../org.argeo.tp/org.slf4j.commons.logging.1.7.jar \ +../org.argeo.tp/org.tukaani.xz.1.9.jar \ +../org.argeo.tp/org.w3c.css.sac.1.3.jar \ +../org.argeo.tp/org.w3c.dom.smil.1.0.jar \ +../org.argeo.tp/org.w3c.dom.svg.1.1.jar \ +../org.argeo.tp.apache/org.apache.batik.1.14.jar \ +../org.argeo.tp.apache/org.apache.batik.constants.1.14.jar \ +../org.argeo.tp.apache/org.apache.batik.css.1.14.jar \ +../org.argeo.tp.apache/org.apache.batik.i18n.1.14.jar \ +../org.argeo.tp.apache/org.apache.batik.util.1.14.jar \ +../org.argeo.tp.apache/org.apache.commons.cli.1.5.jar \ +../org.argeo.tp.apache/org.apache.commons.codec.1.15.jar \ +../org.argeo.tp.apache/org.apache.commons.compress.1.21.jar \ +../org.argeo.tp.apache/org.apache.commons.exec.1.3.jar \ +../org.argeo.tp.apache/org.apache.commons.fileupload.1.4.jar \ +../org.argeo.tp.apache/org.apache.commons.httpclient.3.1.jar \ +../org.argeo.tp.apache/org.apache.commons.io.2.11.jar \ +../org.argeo.tp.apache/org.apache.commons.vfs.2.9.jar \ +../org.argeo.tp.apache/org.apache.httpcomponents.httpclient.4.5.jar \ +../org.argeo.tp.apache/org.apache.httpcomponents.httpcore.4.4.jar \ +../org.argeo.tp.apache/org.apache.httpcomponents.httpmime.4.5.jar \ +../org.argeo.tp.apache/org.apache.sshd.2.8.jar \ +../org.argeo.tp.apache/org.apache.sshd.cli.2.8.jar \ +../org.argeo.tp.apache/org.apache.sshd.git.2.8.jar \ +../org.argeo.tp.apache/org.apache.sshd.putty.2.8.jar \ +../org.argeo.tp.apache/org.apache.sshd.scp.2.8.jar \ +../org.argeo.tp.apache/org.apache.sshd.sftp.2.8.jar \ +../org.argeo.tp.apache/org.apache.tika.core.1.28.jar \ +../org.argeo.tp.apache/org.apache.tika.parsers.1.28.jar \ +../org.argeo.tp.apache/org.apache.tomcat.jni.9.0.jar \ +../org.argeo.tp.apache/org.apache.xalan.2.7.jar \ +../org.argeo.tp.apache/org.apache.xerces.2.12.jar \ +../org.argeo.tp.apache/org.apache.xmlgraphics.2.7.jar \ +../org.argeo.tp.apache/org.apache.xml.resolver.1.2.jar \ + diff --git a/org.argeo.cms.cli/src/org/argeo/cms/cli/ArgeoCli.java b/org.argeo.cms.cli/src/org/argeo/cms/cli/ArgeoCli.java index 1dd57f3df..346cb3c3a 100644 --- a/org.argeo.cms.cli/src/org/argeo/cms/cli/ArgeoCli.java +++ b/org.argeo.cms.cli/src/org/argeo/cms/cli/ArgeoCli.java @@ -22,7 +22,11 @@ public class ArgeoCli extends CommandsCli { @Override public String getDescription() { - return "Argeo utilities"; + return "Argeo CMS utilities"; + } + + public static void main(String[] args) { + mainImpl(new ArgeoCli("argeo"), args); } } diff --git a/org.argeo.cms.lib.sshd/src/org/argeo/cms/ssh/cli/SshCli.java b/org.argeo.cms.lib.sshd/src/org/argeo/cms/ssh/cli/SshCli.java index 4ec456b34..287727544 100644 --- a/org.argeo.cms.lib.sshd/src/org/argeo/cms/ssh/cli/SshCli.java +++ b/org.argeo.cms.lib.sshd/src/org/argeo/cms/ssh/cli/SshCli.java @@ -2,6 +2,7 @@ package org.argeo.cms.ssh.cli; import org.argeo.api.cli.CommandsCli; +/** SSH command line interface. */ public class SshCli extends CommandsCli { public SshCli(String commandName) { super(commandName); diff --git a/sdk/deploy/argeo-cms/usr/.gitignore b/sdk/deploy/argeo-cms/usr/.gitignore new file mode 100644 index 000000000..08eb0a07a --- /dev/null +++ b/sdk/deploy/argeo-cms/usr/.gitignore @@ -0,0 +1 @@ +!bin/ \ No newline at end of file diff --git a/sdk/deploy/argeo-cms/usr/bin/argeo b/sdk/deploy/argeo-cms/usr/bin/argeo new file mode 100755 index 000000000..636fd4769 --- /dev/null +++ b/sdk/deploy/argeo-cms/usr/bin/argeo @@ -0,0 +1,2 @@ +#!/bin/sh +java -Dorg.argeo.api.cli.rootCommand=$0 -jar /usr/share/a2/org.argeo.cms/org.argeo.cms.cli.2.3.jar "$@" \ No newline at end of file