You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2023/07/31 14:40:32 UTC
[activemq-artemis] branch main updated: ARTEMIS-4372 Implement Pico-cli and script auto-complete ARTEMIS-4375 Implement artemis shell using JLine3 integrated with auto-completion from picocli
This is an automated email from the ASF dual-hosted git repository.
clebertsuconic pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git
The following commit(s) were added to refs/heads/main by this push:
new 93ee61e35c ARTEMIS-4372 Implement Pico-cli and script auto-complete ARTEMIS-4375 Implement artemis shell using JLine3 integrated with auto-completion from picocli
93ee61e35c is described below
commit 93ee61e35c93564fb74b70f810a2a7a03dd0cb20
Author: Clebert Suconic <cl...@apache.org>
AuthorDate: Mon Jul 24 13:03:15 2023 -0400
ARTEMIS-4372 Implement Pico-cli and script auto-complete
ARTEMIS-4375 Implement artemis shell using JLine3 integrated with auto-completion from picocli
This commit involves two JIRAs. One is adding PicoCLI and the next is Using JLine3 and implement a shell.
I have tried to keep these commits separate but these changes became interdependent hence the two JIRAs are squashed in this commit.
---
artemis-cli/pom.xml | 18 +-
.../org/apache/activemq/artemis/cli/Artemis.java | 241 +++++++-----
.../org/apache/activemq/artemis/cli/Shell.java | 162 ++++++++
.../activemq/artemis/cli/commands/Action.java | 3 +-
.../artemis/cli/commands/ActionAbstract.java | 28 +-
.../artemis/cli/commands/AutoCompletion.java | 56 +++
.../artemis/cli/commands/Configurable.java | 40 +-
.../cli/commands/{Kill.java => Connect.java} | 28 +-
.../activemq/artemis/cli/commands/Create.java | 146 ++++----
.../cli/commands/{Kill.java => Disconnect.java} | 22 +-
.../activemq/artemis/cli/commands/HelpAction.java | 62 ++--
.../artemis/cli/commands/InputAbstract.java | 4 +-
.../artemis/cli/commands/InstallAbstract.java | 32 +-
.../apache/activemq/artemis/cli/commands/Kill.java | 2 +-
.../apache/activemq/artemis/cli/commands/Mask.java | 21 +-
.../activemq/artemis/cli/commands/OptionsUtil.java | 64 ----
.../artemis/cli/commands/PrintVersion.java | 2 +-
.../apache/activemq/artemis/cli/commands/Run.java | 8 +-
.../apache/activemq/artemis/cli/commands/Stop.java | 2 +-
.../activemq/artemis/cli/commands/Upgrade.java | 4 +-
.../{Kill.java => activation/ActivationGroup.java} | 31 +-
.../activation/ActivationSequenceList.java | 10 +-
.../commands/activation/ActivationSequenceSet.java | 14 +-
.../cli/commands/address/AddressAbstract.java | 12 +-
.../{Kill.java => address/AddressGroup.java} | 30 +-
.../cli/commands/address/CreateAddress.java | 2 +-
.../cli/commands/address/DeleteAddress.java | 6 +-
.../artemis/cli/commands/address/HelpAddress.java | 63 ----
.../artemis/cli/commands/address/ShowAddress.java | 6 +-
.../cli/commands/address/UpdateAddress.java | 2 +-
.../artemis/cli/commands/check/CheckAbstract.java | 8 +-
.../{Action.java => check/CheckGroup.java} | 23 +-
.../artemis/cli/commands/check/HelpCheck.java | 63 ----
.../artemis/cli/commands/check/NodeCheck.java | 16 +-
.../artemis/cli/commands/check/QueueCheck.java | 13 +-
.../artemis/cli/commands/messages/Browse.java | 8 +-
.../cli/commands/messages/ConnectionAbstract.java | 125 +++++--
.../ConnectionProtocol.java} | 35 +-
.../artemis/cli/commands/messages/Consumer.java | 16 +-
.../cli/commands/messages/ConsumerThread.java | 6 +-
.../cli/commands/messages/DestAbstract.java | 38 +-
.../artemis/cli/commands/messages/Producer.java | 22 +-
.../cli/commands/messages/ProducerThread.java | 20 +-
.../artemis/cli/commands/messages/Transfer.java | 50 +--
.../commands/messages/perf/PerfClientCommand.java | 63 ++--
.../cli/commands/messages/perf/PerfCommand.java | 32 +-
.../messages/perf/PerfConsumerCommand.java | 14 +-
.../{Kill.java => messages/perf/PerfGroup.java} | 31 +-
.../messages/perf/PerfProducerCommand.java | 31 +-
.../artemis/cli/commands/queue/CreateQueue.java | 2 +-
.../artemis/cli/commands/queue/DeleteQueue.java | 10 +-
.../artemis/cli/commands/queue/HelpQueue.java | 63 ----
.../artemis/cli/commands/queue/PurgeQueue.java | 6 +-
.../artemis/cli/commands/queue/QueueAbstract.java | 24 +-
.../commands/{Kill.java => queue/QueueGroup.java} | 31 +-
.../artemis/cli/commands/queue/StatQueue.java | 16 +-
.../artemis/cli/commands/queue/UpdateQueue.java | 2 +-
.../artemis/cli/commands/tools/DBOption.java | 47 ++-
.../artemis/cli/commands/tools/DataAbstract.java | 10 +-
.../artemis/cli/commands/tools/DataGroup.java | 43 +++
.../artemis/cli/commands/tools/HelpData.java | 66 ----
.../artemis/cli/commands/tools/LockAbstract.java | 6 +
.../cli/commands/tools/OptionalLocking.java | 4 +-
.../artemis/cli/commands/tools/PrintData.java | 16 +-
.../cli/commands/tools/RecoverMessages.java | 16 +-
.../cli/commands/tools/journal/CompactJournal.java | 2 +-
.../cli/commands/tools/journal/DecodeJournal.java | 16 +-
.../cli/commands/tools/journal/EncodeJournal.java | 12 +-
.../cli/commands/tools/journal/PerfJournal.java | 22 +-
.../cli/commands/tools/xml/XmlDataExporter.java | 6 +-
.../cli/commands/tools/xml/XmlDataImporter.java | 24 +-
.../artemis/cli/commands/user/AddUser.java | 6 +-
.../artemis/cli/commands/user/HelpUser.java | 62 ----
.../artemis/cli/commands/user/ListUser.java | 7 +-
.../artemis/cli/commands/user/PasswordAction.java | 4 +-
.../artemis/cli/commands/user/RemoveUser.java | 2 +-
.../artemis/cli/commands/user/ResetUser.java | 6 +-
.../artemis/cli/commands/user/UserAction.java | 6 +-
.../commands/{Kill.java => user/UserGroup.java} | 31 +-
.../commands/messages/ConnectionAbstractTest.java | 3 +-
.../org/apache/activemq/cli/test/ArtemisTest.java | 140 +++----
.../org/apache/activemq/cli/test/CheckTest.java | 11 +-
.../activemq/cli/test/OptionsValidationTest.java | 115 ------
.../src/main/resources/licenses/bin/LICENSE | 6 +
.../licenses/bin/licenses/LICENSE-jline.txt | 34 ++
docs/user-manual/en/SUMMARY.md | 1 +
docs/user-manual/en/architecture.md | 3 -
docs/user-manual/en/embedding-activemq.md | 5 +-
docs/user-manual/en/using-cli.md | 409 +++++++++++++++++++++
docs/user-manual/en/using-server.md | 5 +
pom.xml | 35 +-
.../artemis/tests/integration/cli/RecoverTest.java | 3 +-
tests/smoke-tests/pom.xml | 3 +-
tests/soak-tests/pom.xml | 4 -
94 files changed, 1734 insertions(+), 1346 deletions(-)
diff --git a/artemis-cli/pom.xml b/artemis-cli/pom.xml
index c4b32a9f90..a213bc36a0 100644
--- a/artemis-cli/pom.xml
+++ b/artemis-cli/pom.xml
@@ -124,10 +124,22 @@
<artifactId>jakarta.xml.bind-api</artifactId>
<version>${jakarta.xml.bind-api.version}</version>
</dependency>
-
<dependency>
- <groupId>com.github.rvesse</groupId>
- <artifactId>airline</artifactId>
+ <groupId>info.picocli</groupId>
+ <artifactId>picocli</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>info.picocli</groupId>
+ <artifactId>picocli-shell-jline3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jline</groupId>
+ <artifactId>jline</artifactId>
+ </dependency>
+ <!-- Jansi is an optional dependency for jline, to provide a proper ANSI Terminal -->
+ <dependency>
+ <groupId>org.fusesource.jansi</groupId>
+ <artifactId>jansi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
index f969bfd44b..9349fa83a6 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Artemis.java
@@ -16,65 +16,46 @@
*/
package org.apache.activemq.artemis.cli;
+import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
+import java.util.Arrays;
import java.util.List;
-import com.github.rvesse.airline.Cli;
-import com.github.rvesse.airline.builder.CliBuilder;
import org.apache.activemq.artemis.cli.commands.Action;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import org.apache.activemq.artemis.cli.commands.AutoCompletion;
import org.apache.activemq.artemis.cli.commands.Create;
+import org.apache.activemq.artemis.cli.commands.Disconnect;
import org.apache.activemq.artemis.cli.commands.HelpAction;
import org.apache.activemq.artemis.cli.commands.InputAbstract;
import org.apache.activemq.artemis.cli.commands.InvalidOptionsError;
import org.apache.activemq.artemis.cli.commands.Kill;
import org.apache.activemq.artemis.cli.commands.Mask;
import org.apache.activemq.artemis.cli.commands.PrintVersion;
-import org.apache.activemq.artemis.cli.commands.Upgrade;
-import org.apache.activemq.artemis.cli.commands.activation.ActivationSequenceSet;
-import org.apache.activemq.artemis.cli.commands.check.HelpCheck;
-import org.apache.activemq.artemis.cli.commands.check.NodeCheck;
-import org.apache.activemq.artemis.cli.commands.check.QueueCheck;
-import org.apache.activemq.artemis.cli.commands.messages.Transfer;
-import org.apache.activemq.artemis.cli.commands.messages.perf.PerfClientCommand;
-import org.apache.activemq.artemis.cli.commands.messages.perf.PerfConsumerCommand;
-import org.apache.activemq.artemis.cli.commands.messages.perf.PerfProducerCommand;
-import org.apache.activemq.artemis.cli.commands.queue.StatQueue;
import org.apache.activemq.artemis.cli.commands.Run;
import org.apache.activemq.artemis.cli.commands.Stop;
-import org.apache.activemq.artemis.cli.commands.address.CreateAddress;
-import org.apache.activemq.artemis.cli.commands.address.DeleteAddress;
-import org.apache.activemq.artemis.cli.commands.address.HelpAddress;
-import org.apache.activemq.artemis.cli.commands.address.ShowAddress;
-import org.apache.activemq.artemis.cli.commands.address.UpdateAddress;
+import org.apache.activemq.artemis.cli.commands.Upgrade;
+import org.apache.activemq.artemis.cli.commands.activation.ActivationGroup;
+import org.apache.activemq.artemis.cli.commands.address.AddressGroup;
+import org.apache.activemq.artemis.cli.commands.check.CheckGroup;
import org.apache.activemq.artemis.cli.commands.messages.Browse;
+import org.apache.activemq.artemis.cli.commands.Connect;
import org.apache.activemq.artemis.cli.commands.messages.Consumer;
import org.apache.activemq.artemis.cli.commands.messages.Producer;
-import org.apache.activemq.artemis.cli.commands.queue.CreateQueue;
-import org.apache.activemq.artemis.cli.commands.queue.DeleteQueue;
-import org.apache.activemq.artemis.cli.commands.queue.HelpQueue;
-import org.apache.activemq.artemis.cli.commands.queue.PurgeQueue;
-import org.apache.activemq.artemis.cli.commands.queue.UpdateQueue;
-import org.apache.activemq.artemis.cli.commands.activation.ActivationSequenceList;
-import org.apache.activemq.artemis.cli.commands.tools.HelpData;
-import org.apache.activemq.artemis.cli.commands.tools.PrintData;
-import org.apache.activemq.artemis.cli.commands.tools.RecoverMessages;
-import org.apache.activemq.artemis.cli.commands.tools.journal.CompactJournal;
-import org.apache.activemq.artemis.cli.commands.tools.journal.DecodeJournal;
-import org.apache.activemq.artemis.cli.commands.tools.journal.EncodeJournal;
+import org.apache.activemq.artemis.cli.commands.messages.Transfer;
+import org.apache.activemq.artemis.cli.commands.messages.perf.PerfGroup;
+import org.apache.activemq.artemis.cli.commands.queue.QueueGroup;
+import org.apache.activemq.artemis.cli.commands.tools.DataGroup;
import org.apache.activemq.artemis.cli.commands.tools.journal.PerfJournal;
-import org.apache.activemq.artemis.cli.commands.tools.xml.XmlDataExporter;
-import org.apache.activemq.artemis.cli.commands.tools.xml.XmlDataImporter;
-import org.apache.activemq.artemis.cli.commands.user.AddUser;
-import org.apache.activemq.artemis.cli.commands.user.HelpUser;
-import org.apache.activemq.artemis.cli.commands.user.ListUser;
-import org.apache.activemq.artemis.cli.commands.user.RemoveUser;
-import org.apache.activemq.artemis.cli.commands.user.ResetUser;
+import org.apache.activemq.artemis.cli.commands.user.UserGroup;
import org.apache.activemq.artemis.dto.ManagementContextDTO;
import org.apache.activemq.artemis.dto.XmlUtil;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
/**
* Artemis is the main CLI entry point for managing/running a broker.
@@ -87,7 +68,26 @@ import org.apache.activemq.artemis.dto.XmlUtil;
* Notice that this class should not use any logging as it's part of the bootstrap and using logging here could
* disrupt the order of bootstrapping on certain components (e.g. JMX being started from log4j)
*/
-public class Artemis {
+@Command(name = "artemis", description = "ActiveMQ Artemis Command Line")
+public class Artemis implements Runnable {
+
+ CommandLine commandLine;
+
+ public CommandLine getCommandLine() {
+ return commandLine;
+ }
+
+ public Artemis setCommandLine(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ return this;
+ }
+
+ @Override
+ public void run() {
+ // We are running the shell by default.
+ // if you type ./artemis we will go straight to the shell
+ Shell.runShell(true);
+ }
public static void main(String... args) throws Exception {
String home = System.getProperty("artemis.home");
@@ -179,10 +179,7 @@ public class Artemis {
} catch (RuntimeException | InvalidOptionsError re) {
context.err.println(re.getMessage());
context.out.println();
-
- Cli<Action> parser = builder(null).build();
-
- parser.parse("help").execute(context);
+ HelpAction.help(buildCommand(true, true), "help");
return re;
} finally {
ActionContext.setSystem(new ActionContext());
@@ -194,68 +191,140 @@ public class Artemis {
* Useful on test cases
*/
private static Object internalExecute(File artemisHome, File artemisInstance, File etcFolder, String[] args) throws Exception {
- return internalExecute(artemisHome, artemisInstance, etcFolder, args, ActionContext.system());
+ return internalExecute(artemisHome, artemisInstance, etcFolder, args, new ActionContext());
}
public static Object internalExecute(File artemisHome, File artemisInstance, File etcFolder, String[] args, ActionContext context) throws Exception {
- Action action = builder(artemisInstance).build().parse(args);
- action.setHomeValues(artemisHome, artemisInstance, etcFolder);
+ boolean isInstance = artemisInstance != null || System.getProperty("artemis.instance") != null;
+ CommandLine commandLine = buildCommand(isInstance, !isInstance);
+
+ Object userObject = parseAction(commandLine, args);
+
+ // Pico shouldn't allow generating a commandLine without an userObject.
+ // the following assert "should" never happen
+ assert userObject != null;
+
+ if (userObject instanceof Action) {
+ Action action = (Action) userObject;
+ action.setHomeValues(artemisHome, artemisInstance, etcFolder);
+ if (action.isVerbose()) {
+ context.out.print("Executing " + action.getClass().getName() + " ");
+ for (String arg : args) {
+ context.out.print(arg + " ");
+ }
+ context.out.println();
+ context.out.println("Home::" + action.getBrokerHome() + ", Instance::" + action.getBrokerInstance());
+ }
- if (action.isVerbose()) {
- context.out.print("Executing " + action.getClass().getName() + " ");
- for (String arg : args) {
- context.out.print(arg + " ");
+ try {
+ return action.execute(context);
+ } finally {
+ action.done();
+ }
+ } else {
+ if (userObject instanceof Runnable) {
+ ((Runnable) userObject).run();
+ } else {
+ throw new IllegalArgumentException(userObject.getClass() + " should implement either " + Action.class.getName() + " or " + Runnable.class.getName());
+ }
+ }
+ return null;
+ }
+
+ /*
+ Pico-cli traditionally would execute user objects that implement Runnable.
+ However as we used airline before, we needed parse for the proper action.
+ This method here is parsing the arg and find the proper user object in the hierarchy of sub-commands
+ and return it to the caller.
+ */
+ private static Object parseAction(CommandLine line, String[] args) {
+ CommandLine.ParseResult parseResult = line.parseArgs(args);
+ if (parseResult != null) {
+ while (parseResult.hasSubcommand()) {
+ parseResult = parseResult.subcommand();
}
- context.out.println();
- context.out.println("Home::" + action.getBrokerHome() + ", Instance::" + action.getBrokerInstance());
}
+ if (parseResult == null) {
+ throw new RuntimeException("Cannot match arg::" + Arrays.toString(args));
+ }
+ return parseResult.commandSpec().userObject();
+ }
+
+ public static CommandLine buildCommand(boolean includeInstanceCommands, boolean includeHomeCommands) {
+ return buildCommand(includeInstanceCommands, includeHomeCommands, false);
- action.checkOptions(args);
- return action.execute(context);
}
- private static CliBuilder<Action> builder(File artemisInstance) {
- String instance = artemisInstance != null ? artemisInstance.getAbsolutePath() : System.getProperty("artemis.instance");
- CliBuilder<Action> builder = Cli.<Action>builder("artemis").withDescription("ActiveMQ Artemis Command Line").
- withCommand(HelpAction.class).withCommand(Producer.class).withCommand(Transfer.class).withCommand(Consumer.class).
- withCommand(Browse.class).withCommand(Mask.class).withCommand(PrintVersion.class).withDefaultCommand(HelpAction.class);
-
- builder.withGroup("perf").withDescription("Perf tools group (example ./artemis perf client)")
- .withDefaultCommand(PerfClientCommand.class)
- .withCommands(PerfProducerCommand.class, PerfConsumerCommand.class, PerfClientCommand.class);
-
- builder.withGroup("check").withDescription("Check tools group (node|queue) (example ./artemis check node)").
- withDefaultCommand(HelpCheck.class).withCommands(NodeCheck.class, QueueCheck.class);
-
- builder.withGroup("queue").withDescription("Queue tools group (create|delete|update|stat|purge) (example ./artemis queue create)").
- withDefaultCommand(HelpQueue.class).withCommands(CreateQueue.class, DeleteQueue.class, UpdateQueue.class, StatQueue.class, PurgeQueue.class);
-
- builder.withGroup("address").withDescription("Address tools group (create|delete|update|show) (example ./artemis address create)").
- withDefaultCommand(HelpAddress.class).withCommands(CreateAddress.class, DeleteAddress.class, UpdateAddress.class, ShowAddress.class);
-
- if (instance != null) {
- builder.withGroup("activation")
- .withDescription("activation tools group (sync) (example ./artemis activation list)")
- .withDefaultCommand(ActivationSequenceList.class)
- .withCommands(ActivationSequenceList.class, ActivationSequenceSet.class);
- builder.withGroup("data").withDescription("data tools group (print|imp|exp|encode|decode|compact|recover) (example ./artemis data print)").
- withDefaultCommand(HelpData.class).withCommands(RecoverMessages.class, PrintData.class, XmlDataExporter.class, XmlDataImporter.class, DecodeJournal.class, EncodeJournal.class, CompactJournal.class);
- builder.withGroup("user").withDescription("default file-based user management (add|rm|list|reset) (example ./artemis user list)").
- withDefaultCommand(HelpUser.class).withCommands(ListUser.class, AddUser.class, RemoveUser.class, ResetUser.class);
- builder = builder.withCommands(Run.class, Stop.class, Kill.class, PerfJournal.class);
- } else {
- builder.withGroup("data").withDescription("data tools group (print|recover) (example ./artemis data print)").
- withDefaultCommand(HelpData.class).withCommands(RecoverMessages.class, PrintData.class);
- builder = builder.withCommands(Create.class, Upgrade.class);
+ public static CommandLine buildCommand(boolean includeInstanceCommands, boolean includeHomeCommands, boolean fromShell) {
+ Artemis artemis = new Artemis();
+
+ CommandLine commandLine = new CommandLine(artemis);
+ artemis.setCommandLine(commandLine);
+
+ HelpAction help = new HelpAction();
+ help.setCommandLine(commandLine);
+ commandLine.addSubcommand(help);
+
+ commandLine.addSubcommand(new AutoCompletion());
+
+ // we don't include the shell in the shell
+ if (!fromShell) {
+ commandLine.addSubcommand(new Shell(commandLine));
+ }
+
+ commandLine.addSubcommand(new Producer()).addSubcommand(new Transfer()).addSubcommand(new Consumer()).addSubcommand(new Browse()).addSubcommand(new Mask()).addSubcommand(new PrintVersion());
+
+ commandLine.addSubcommand(new PerfGroup(commandLine));
+ commandLine.addSubcommand(new CheckGroup(commandLine));
+ commandLine.addSubcommand(new QueueGroup(commandLine));
+ commandLine.addSubcommand(new AddressGroup(commandLine));
+
+ if (fromShell) {
+ commandLine.addSubcommand(new Connect());
+ commandLine.addSubcommand(new Disconnect());
}
- return builder;
+ if (includeInstanceCommands) {
+ commandLine.addSubcommand(new ActivationGroup(commandLine));
+ commandLine.addSubcommand(new DataGroup(commandLine));
+ commandLine.addSubcommand(new UserGroup(commandLine));
+
+ commandLine.addSubcommand(new Run());
+ commandLine.addSubcommand(new Stop());
+ commandLine.addSubcommand(new Kill());
+ commandLine.addSubcommand(new PerfJournal());
+ }
+
+ if (includeHomeCommands) {
+ if (!includeInstanceCommands) {
+ // Data is already present in InstanceCommands
+ commandLine.addSubcommand(new DataGroup(commandLine));
+ }
+ commandLine.addSubcommand(new Create());
+ commandLine.addSubcommand(new Upgrade());
+ }
+
+ return commandLine;
}
public static void printBanner(PrintStream out) throws Exception {
copy(Artemis.class.getResourceAsStream("banner.txt"), out);
}
+
+ public static String getNameFromBanner() throws Exception {
+ InputStream inputStream = Artemis.class.getResourceAsStream("banner.txt");
+ BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+ String lastLine = "";
+ while (reader.ready()) {
+ String line = reader.readLine();
+ if (!line.trim().isEmpty()) {
+ lastLine = line;
+ }
+ }
+ return lastLine.trim();
+ }
+
private static long copy(InputStream in, OutputStream out) throws Exception {
try {
byte[] buffer = new byte[1024];
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Shell.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Shell.java
new file mode 100644
index 0000000000..9cebfa67fa
--- /dev/null
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/Shell.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
+
+import org.apache.activemq.artemis.cli.commands.Connect;
+import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
+import org.jline.console.SystemRegistry;
+import org.jline.console.impl.SystemRegistryImpl;
+import org.jline.reader.EndOfFileException;
+import org.jline.reader.LineReader;
+import org.jline.reader.LineReaderBuilder;
+import org.jline.reader.MaskingCallback;
+import org.jline.reader.Parser;
+import org.jline.reader.UserInterruptException;
+import org.jline.reader.impl.DefaultParser;
+import org.jline.terminal.Terminal;
+import org.jline.terminal.TerminalBuilder;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+import picocli.shell.jline3.PicocliCommands;
+
+@Command(name = "shell", description = "JLine3 shell helping using the CLI")
+public class Shell implements Runnable {
+
+ @CommandLine.Option(names = "--url", description = "It will be used for an initial connection if set.")
+ protected String brokerURL = ConnectionAbstract.DEFAULT_BROKER_URL;
+
+ @CommandLine.Option(names = "--user", description = "It will be used for an initial connection if set.")
+ protected String user;
+
+ @CommandLine.Option(names = "--password", description = "It will be used for an initial connection if set.")
+ protected String password;
+
+
+ private static String RED_UNICODE = "\u001B[31m";
+ private static String YELLOW_UNICODE = "\u001B[33m";
+ private static String CLEAR_UNICODE = "\u001B[0m";
+
+ public Shell(CommandLine commandLine) {
+ }
+
+ @Override
+ public void run() {
+ setInShell();
+ printBanner();
+ if (brokerURL != ConnectionAbstract.DEFAULT_BROKER_URL || user != null || password != null) {
+ Connect connect = new Connect();
+ connect.setUser(user).setPassword(password).setBrokerURL(brokerURL);
+ connect.run();
+ }
+ runShell(false);
+ }
+
+ private static ThreadLocal<AtomicBoolean> IN_SHELL = ThreadLocal.withInitial(() -> new AtomicBoolean(false));
+
+ public static boolean inShell() {
+ return IN_SHELL.get().get();
+ }
+
+ public static void setInShell() {
+ IN_SHELL.get().set(true);
+ }
+
+ public static void runShell(boolean printBanner) {
+ try {
+ setInShell();
+
+ boolean isInstance = System.getProperty("artemis.instance") != null;
+
+ Supplier<Path> workDir = () -> Paths.get(System.getProperty("user.dir"));
+
+ PicocliCommands.PicocliCommandsFactory factory = new PicocliCommands.PicocliCommandsFactory();
+
+ CommandLine commandLine = Artemis.buildCommand(isInstance, !isInstance, true);
+
+ PicocliCommands picocliCommands = new PicocliCommands(commandLine);
+
+ Parser parser = new DefaultParser();
+ try (Terminal terminal = TerminalBuilder.terminal()) {
+ SystemRegistry systemRegistry = new SystemRegistryImpl(parser, terminal, workDir, null);
+ systemRegistry.setCommandRegistries(picocliCommands);
+ systemRegistry.register("help", picocliCommands);
+
+ LineReader reader = LineReaderBuilder.builder()
+ .terminal(terminal)
+ .completer(systemRegistry.completer())
+ .parser(parser)
+ .variable(LineReader.LIST_MAX, 50) // max tab completion candidates
+ .build();
+ factory.setTerminal(terminal);
+
+ String prompt = YELLOW_UNICODE + Artemis.getNameFromBanner() + " > " + CLEAR_UNICODE;
+ String rightPrompt = null;
+
+ if (printBanner) {
+ printBanner();
+ }
+
+ System.out.println("For a list of commands, type " + RED_UNICODE + "help" + CLEAR_UNICODE + " or press " + RED_UNICODE + "<TAB>" + CLEAR_UNICODE + ":");
+ System.out.println("Type " + RED_UNICODE + "exit" + CLEAR_UNICODE + " or press " + RED_UNICODE + "<CTRL-D>" + CLEAR_UNICODE + " to leave the session:");
+
+ // start the shell and process input until the user quits with Ctrl-D
+ String line;
+ while (true) {
+ try {
+ // We build a new command every time, as they could have state from previous executions
+ systemRegistry.setCommandRegistries(new PicocliCommands(Artemis.buildCommand(isInstance, !isInstance, true)));
+ systemRegistry.cleanUp();
+ line = reader.readLine(prompt, rightPrompt, (MaskingCallback) null, null);
+ systemRegistry.execute(line);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ // Ignore
+ } catch (UserInterruptException userInterruptException) {
+ // ignore
+ } catch (EndOfFileException e) {
+ return;
+ } catch (Exception e) {
+ systemRegistry.trace(e);
+ }
+ }
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ IN_SHELL.get().set(false);
+ }
+
+ }
+
+ private static void printBanner() {
+ System.out.print(YELLOW_UNICODE);
+ try {
+ Artemis.printBanner(System.out);
+ } catch (Exception e) {
+ System.out.println("Error recovering the banner:");
+ e.printStackTrace();
+ }
+ System.out.print(CLEAR_UNICODE);
+ }
+
+}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java
index 5ed583754d..80ca0a9a8c 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java
@@ -26,9 +26,10 @@ public interface Action {
Object execute(ActionContext context) throws Exception;
+ void done();
+
String getBrokerInstance();
String getBrokerHome();
- void checkOptions(String[] options) throws InvalidOptionsError;
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/ActionAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/ActionAbstract.java
index 6f038f4cc3..b20abe1fd5 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/ActionAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/ActionAbstract.java
@@ -22,7 +22,6 @@ import java.net.URI;
import java.util.Collection;
import java.util.Map;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.FileDeploymentManager;
@@ -30,14 +29,15 @@ import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.utils.ConfigurationHelper;
import org.apache.activemq.artemis.utils.uri.SchemaConstants;
+import picocli.CommandLine.Option;
-public abstract class ActionAbstract implements Action {
+public abstract class ActionAbstract implements Action, Runnable {
public static final String DEFAULT_BROKER_URL = "tcp://localhost:61616";
public static final String DEFAULT_BROKER_ACCEPTOR = "artemis";
- @Option(name = "--verbose", description = "Print additional information.")
+ @Option(names = "--verbose", description = "Print additional information.")
public boolean verbose;
// this could be changed by a test accessor for testing purposes.
@@ -205,6 +205,23 @@ public abstract class ActionAbstract implements Action {
return brokerHome;
}
+ @Override
+ public void run() {
+ try {
+ // this is used only by the Shell
+ // When using the CLI outside of the shell the execute(ActionContext) will be used instead.
+ execute(getActionContext());
+ } catch (Throwable e) {
+ e.printStackTrace();
+ } finally {
+ done();
+ }
+ }
+
+ @Override
+ public void done() {
+ }
+
@Override
public Object execute(ActionContext context) throws Exception {
this.actionContext = context;
@@ -213,9 +230,4 @@ public abstract class ActionAbstract implements Action {
return null;
}
- @Override
- public void checkOptions(String[] options) throws InvalidOptionsError {
- OptionsUtil.checkCommandOptions(this.getClass(), options);
- }
-
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/AutoCompletion.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/AutoCompletion.java
new file mode 100644
index 0000000000..d54f70033c
--- /dev/null
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/AutoCompletion.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli.commands;
+
+import java.io.File;
+
+import org.apache.activemq.artemis.cli.Artemis;
+import picocli.AutoComplete;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+
+@Command(name = "auto-complete", description = "Generates the auto complete script file to be used in bash or zsh.")
+public class AutoCompletion implements Runnable {
+
+ public AutoCompletion() {
+ }
+
+ @CommandLine.Parameters (description = "The generated auto-complete script", defaultValue = "auto-complete-artemis.sh")
+ File autoCompleteFile;
+
+ @Override
+ public void run() {
+ try {
+ CommandLine artemisCommand = Artemis.buildCommand(true, true);
+ AutoComplete.bash("artemis", autoCompleteFile, null, artemisCommand);
+ System.out.println("Type the following commands before you can use auto-complete:");
+ System.out.println("*******************************************************************************************************************************");
+ System.out.println("source " + autoCompleteFile.getAbsolutePath());
+ System.out.println("*******************************************************************************************************************************");
+
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ // I'm letting the possibility of calling AutoCompletion directly bypassing the artemis CLI.
+ public static void main(String[] args) {
+ CommandLine commandLine = new CommandLine(new AutoCompletion());
+ commandLine.execute(args);
+ }
+}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Configurable.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Configurable.java
index e676bda74b..d2aa15d30a 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Configurable.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Configurable.java
@@ -18,14 +18,8 @@
package org.apache.activemq.artemis.cli.commands;
import java.io.File;
+import java.lang.invoke.MethodHandles;
-import com.github.rvesse.airline.annotations.AirlineModule;
-import com.github.rvesse.airline.annotations.Arguments;
-import com.github.rvesse.airline.annotations.Option;
-import com.github.rvesse.airline.help.Help;
-import com.github.rvesse.airline.model.CommandGroupMetadata;
-import com.github.rvesse.airline.model.CommandMetadata;
-import com.github.rvesse.airline.model.GlobalMetadata;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.cli.factory.BrokerFactory;
import org.apache.activemq.artemis.cli.factory.jmx.ManagementFactory;
@@ -36,9 +30,8 @@ import org.apache.activemq.artemis.dto.ManagementContextDTO;
import org.apache.activemq.artemis.jms.server.config.impl.FileJMSConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.lang.invoke.MethodHandles;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.Parameters;
/**
* Abstract class where we can replace the configuration in various places *
@@ -47,15 +40,12 @@ public abstract class Configurable extends ActionAbstract {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- @Arguments(description = "Broker Configuration URI. Default: xml:${ARTEMIS_INSTANCE}/etc/bootstrap.xml.")
+ @Parameters(description = "Broker Configuration URI. Default: xml:${ARTEMIS_INSTANCE}/etc/bootstrap.xml.", defaultValue = "")
String configuration;
- @Option(name = "--broker", description = "Override the broker configuration from the bootstrap.xml.")
+ @Option(names = "--broker", description = "Override the broker configuration from the bootstrap.xml.")
String brokerConfig;
- @AirlineModule
- public GlobalMetadata<Object> global;
-
private BrokerDTO brokerDTO = null;
private FileConfiguration fileConfiguration;
@@ -69,24 +59,6 @@ public abstract class Configurable extends ActionAbstract {
if (!(e instanceof ActiveMQException)) {
e.printStackTrace();
}
- helpGroup(group, command);
- }
-
- protected void helpGroup(String groupName, String commandName) {
- for (CommandGroupMetadata group : global.getCommandGroups()) {
- if (group.getName().equals(groupName)) {
- for (CommandMetadata command : group.getCommands()) {
- if (command.getName().equals(commandName)) {
- try {
- Help.help(command);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
- break;
- }
- }
}
protected FileConfiguration getFileConfiguration() throws Exception {
@@ -145,7 +117,7 @@ public abstract class Configurable extends ActionAbstract {
}
protected String getConfiguration() {
- if (configuration == null) {
+ if (configuration == null || configuration.equals("")) {
File xmlFile = new File(new File(getBrokerEtc()), "bootstrap.xml");
configuration = "xml:" + xmlFile.toURI().toString().substring("file:".length());
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Connect.java
similarity index 64%
copy from artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
copy to artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Connect.java
index e34e376deb..5ff144f78a 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Connect.java
@@ -14,28 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
+package org.apache.activemq.artemis.cli.commands;
-import com.github.rvesse.airline.annotations.Command;
-import org.apache.activemq.artemis.dto.BrokerDTO;
+import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
+import picocli.CommandLine;
-@Command(name = "kill", description = "Kill a broker started with --allow-kill.")
-public class Kill extends Configurable {
+@CommandLine.Command(name = "connect", description = "Connect to the broker validating credentials for commands.")
+public class Connect extends ConnectionAbstract {
@Override
public Object execute(ActionContext context) throws Exception {
super.execute(context);
-
- BrokerDTO broker = getBrokerDTO();
-
- File file = broker.server.getConfigurationFile().getParentFile();
-
- File killFile = new File(file, "KILL_ME");
-
- killFile.createNewFile();
-
+ try {
+ CONNECTION_INFORMATION.remove();
+ createConnectionFactory();
+ System.out.println("Connection Successful!");
+ } catch (Exception e) {
+ System.out.println("Connection Failure!");
+ e.printStackTrace();
+ }
return null;
}
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
index f4e543a9a7..1717d042fb 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Create.java
@@ -25,8 +25,6 @@ import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.LinkedHashMap;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.cli.commands.util.HashUtil;
@@ -36,6 +34,8 @@ import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancing
import org.apache.activemq.artemis.nativo.jlibaio.LibaioContext;
import org.apache.activemq.artemis.nativo.jlibaio.LibaioFile;
import org.apache.activemq.artemis.utils.FileUtil;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
/**
* CLI action that creates a broker instance directory.
@@ -110,175 +110,175 @@ public class Create extends InstallAbstract {
public static final String ETC_PAGE_SYNC_SETTINGS = "etc/page-sync-settings.txt";
public static final String ETC_JOLOKIA_ACCESS_XML = "jolokia-access.xml";
- @Option(name = "--host", description = "Broker's host name. Default: 0.0.0.0 or input if clustered).")
+ @Option(names = "--host", description = "Broker's host name. Default: 0.0.0.0 or input if clustered).")
private String host;
- @Option(name = "--http-host", description = "Embedded web server's host name. Default: localhost.")
+ @Option(names = "--http-host", description = "Embedded web server's host name. Default: localhost.")
private String httpHost = HTTP_HOST;
- @Option(name = "--relax-jolokia", description = "Disable strict checking in jolokia-access.xml.")
+ @Option(names = "--relax-jolokia", description = "Disable strict checking in jolokia-access.xml.")
private boolean relaxJolokia;
- @Option(name = "--ping", description = "A comma separated string to be passed on to the broker config as network-check-list. The broker will shutdown when all these addresses are unreachable.")
+ @Option(names = "--ping", description = "A comma separated string to be passed on to the broker config as network-check-list. The broker will shutdown when all these addresses are unreachable.")
private String ping;
- @Option(name = "--default-port", description = "The port number to use for the main 'artemis' acceptor. Default: 61616.")
+ @Option(names = "--default-port", description = "The port number to use for the main 'artemis' acceptor. Default: 61616.")
private int defaultPort = DEFAULT_PORT;
- @Option(name = "--http-port", description = "Embedded web server's port. Default: 8161.")
+ @Option(names = "--http-port", description = "Embedded web server's port. Default: 8161.")
private int httpPort = HTTP_PORT;
- @Option(name = "--ssl-key", description = "Embedded web server's key store path.")
+ @Option(names = "--ssl-key", description = "Embedded web server's key store path.")
private String sslKey;
- @Option(name = "--ssl-key-password", description = "The key store's password.")
+ @Option(names = "--ssl-key-password", description = "The key store's password.")
private String sslKeyPassword;
- @Option(name = "--use-client-auth", description = "Require client certificate authentication when connecting to the embedded web server.")
+ @Option(names = "--use-client-auth", description = "Require client certificate authentication when connecting to the embedded web server.")
private boolean useClientAuth;
- @Option(name = "--ssl-trust", description = "The trust store path in case of client authentication.")
+ @Option(names = "--ssl-trust", description = "The trust store path in case of client authentication.")
private String sslTrust;
- @Option(name = "--ssl-trust-password", description = "The trust store's password.")
+ @Option(names = "--ssl-trust-password", description = "The trust store's password.")
private String sslTrustPassword;
- @Option(name = "--name", description = "The name of the broker. Default: same as host name.")
+ @Option(names = "--name", description = "The name of the broker. Default: same as host name.")
private String name;
- @Option(name = "--port-offset", description = "How much to off-set the ports of every acceptor.")
+ @Option(names = "--port-offset", description = "How much to off-set the ports of every acceptor.")
private int portOffset;
- @Option(name = "--force", description = "Overwrite configuration at destination directory.")
+ @Option(names = "--force", description = "Overwrite configuration at destination directory.")
private boolean force;
- @Option(name = "--data", description = "Directory where ActiveMQ data are stored. Paths can be absolute or relative to artemis.instance directory. Default: data.")
+ @Option(names = "--data", description = "Directory where ActiveMQ data are stored. Paths can be absolute or relative to artemis.instance directory. Default: data.")
private String data = "data";
- @Option(name = "--clustered", description = "Enable clustering.")
+ @Option(names = "--clustered", description = "Enable clustering.")
private boolean clustered = false;
- @Option(name = "--max-hops", description = "Number of hops on the cluster configuration.")
+ @Option(names = "--max-hops", description = "Number of hops on the cluster configuration.")
private int maxHops = 0;
- @Option(name = "--message-load-balancing", description = "Message load balancing policy for cluster. Default: ON_DEMAND. Valid values: ON_DEMAND, STRICT, OFF, OFF_WITH_REDISTRIBUTION.")
+ @Option(names = "--message-load-balancing", description = "Message load balancing policy for cluster. Default: ON_DEMAND. Valid values: ON_DEMAND, STRICT, OFF, OFF_WITH_REDISTRIBUTION.")
private MessageLoadBalancingType messageLoadBalancing = MessageLoadBalancingType.ON_DEMAND;
- @Option(name = "--replicated", description = "Enable broker replication.")
+ @Option(names = "--replicated", description = "Enable broker replication.")
private boolean replicated = false;
- @Option(name = "--shared-store", description = "Enable broker shared store.")
+ @Option(names = "--shared-store", description = "Enable broker shared store.")
private boolean sharedStore = false;
- @Option(name = "--slave", description = "Be a slave broker. Valid for shared store or replication.")
+ @Option(names = "--slave", description = "Be a slave broker. Valid for shared store or replication.")
private boolean slave;
- @Option(name = "--failover-on-shutdown", description = "Whether broker shutdown will trigger failover for clients using the core protocol. Valid only for shared store. Default: false.")
+ @Option(names = "--failover-on-shutdown", description = "Whether broker shutdown will trigger failover for clients using the core protocol. Valid only for shared store. Default: false.")
private boolean failoverOnShutodwn;
- @Option(name = "--cluster-user", description = "The user to use for clustering. Default: input.")
+ @Option(names = "--cluster-user", description = "The user to use for clustering. Default: input.")
private String clusterUser = null;
- @Option(name = "--cluster-password", description = "The password to use for clustering. Default: input.")
+ @Option(names = "--cluster-password", description = "The password to use for clustering. Default: input.")
private String clusterPassword = null;
- @Option(name = "--allow-anonymous", description = "Allow connections from users with no security credentials. Opposite of --require-login. Default: input.")
+ @Option(names = "--allow-anonymous", description = "Allow connections from users with no security credentials. Opposite of --require-login. Default: input.")
private Boolean allowAnonymous = null;
- @Option(name = "--require-login", description = "Require security credentials from users for connection. Opposite of --allow-anonymous.")
+ @Option(names = "--require-login", description = "Require security credentials from users for connection. Opposite of --allow-anonymous.")
private Boolean requireLogin = null;
- @Option(name = "--paging", description = "Page messages to disk when address becomes full. Opposite of --blocking. Default: true.")
+ @Option(names = "--paging", description = "Page messages to disk when address becomes full. Opposite of --blocking. Default: true.")
private Boolean paging;
- @Option(name = "--blocking", description = "Block producers when address becomes full. Opposite of --paging. Default: false.")
+ @Option(names = "--blocking", description = "Block producers when address becomes full. Opposite of --paging. Default: false.")
private Boolean blocking;
- @Option(name = "--no-autotune", description = "Disable auto tuning of the journal-buffer-timeout in broker.xml.")
+ @Option(names = "--no-autotune", description = "Disable auto tuning of the journal-buffer-timeout in broker.xml.")
private boolean noAutoTune;
- @Option(name = "--no-autocreate", description = "Disable auto creation for addresses & queues.")
+ @Option(names = "--no-autocreate", description = "Disable auto creation for addresses & queues.")
private Boolean noAutoCreate;
- @Option(name = "--autocreate", description = "Allow automatic creation of addresses & queues. Default: true.")
+ @Option(names = "--autocreate", description = "Allow automatic creation of addresses & queues. Default: true.")
private Boolean autoCreate;
- @Option(name = "--autodelete", description = "Allow automatic deletion of addresses & queues. Default: false.")
+ @Option(names = "--autodelete", description = "Allow automatic deletion of addresses & queues. Default: false.")
private boolean autoDelete;
- @Option(name = "--user", description = "The username. Default: input.")
+ @Option(names = "--user", description = "The username. Default: input.")
private String user;
- @Option(name = "--password", description = "The user's password. Default: input.")
+ @Option(names = "--password", description = "The user's password. Default: input.")
private String password;
- @Option(name = "--role", description = "The name for the role created. Default: amq.")
+ @Option(names = "--role", description = "The name for the role created. Default: amq.")
private String role = "amq";
- @Option(name = "--no-web", description = "Whether to omit the web-server definition from bootstrap.xml.")
+ @Option(names = "--no-web", description = "Whether to omit the web-server definition from bootstrap.xml.")
private boolean noWeb;
- @Option(name = "--queues", description = "A comma separated list of queues with the option to specify a routing type, e.g. --queues myQueue1,myQueue2:multicast. Routing-type default: anycast.")
+ @Option(names = "--queues", description = "A comma separated list of queues with the option to specify a routing type, e.g. --queues myQueue1,myQueue2:multicast. Routing-type default: anycast.")
private String queues;
- @Option(name = "--addresses", description = "A comma separated list of addresses with the option to specify a routing type, e.g. --addresses myAddress1,myAddress2:anycast. Routing-type default: multicast.")
+ @Option(names = "--addresses", description = "A comma separated list of addresses with the option to specify a routing type, e.g. --addresses myAddress1,myAddress2:anycast. Routing-type default: multicast.")
private String addresses;
- @Option(name = "--aio", description = "Set the journal as asyncio.")
+ @Option(names = "--aio", description = "Set the journal as asyncio.")
private boolean aio;
- @Option(name = "--nio", description = "Set the journal as nio.")
+ @Option(names = "--nio", description = "Set the journal as nio.")
private boolean nio;
- @Option(name = "--mapped", description = "Set the journal as mapped.")
+ @Option(names = "--mapped", description = "Set the journal as mapped.")
private boolean mapped;
// this is used by the setupJournalType method
private JournalType journalType;
- @Option(name = "--disable-persistence", description = "Disable message persistence to the journal")
+ @Option(names = "--disable-persistence", description = "Disable message persistence to the journal")
private boolean disablePersistence;
- @Option(name = "--no-amqp-acceptor", description = "Disable the AMQP specific acceptor.")
+ @Option(names = "--no-amqp-acceptor", description = "Disable the AMQP specific acceptor.")
private boolean noAmqpAcceptor;
- @Option(name = "--no-mqtt-acceptor", description = "Disable the MQTT specific acceptor.")
+ @Option(names = "--no-mqtt-acceptor", description = "Disable the MQTT specific acceptor.")
private boolean noMqttAcceptor;
- @Option(name = "--no-stomp-acceptor", description = "Disable the STOMP specific acceptor.")
+ @Option(names = "--no-stomp-acceptor", description = "Disable the STOMP specific acceptor.")
private boolean noStompAcceptor;
- @Option(name = "--no-hornetq-acceptor", description = "Disable the HornetQ specific acceptor.")
+ @Option(names = "--no-hornetq-acceptor", description = "Disable the HornetQ specific acceptor.")
private boolean noHornetQAcceptor;
- @Option(name = "--no-fsync", description = "Disable usage of fdatasync (channel.force(false) from Java NIO) on the journal.")
+ @Option(names = "--no-fsync", description = "Disable usage of fdatasync (channel.force(false) from Java NIO) on the journal.")
private boolean noJournalSync;
- @Option(name = "--journal-device-block-size", description = "The block size of the journal's storage device. Default: 4096.")
+ @Option(names = "--journal-device-block-size", description = "The block size of the journal's storage device. Default: 4096.")
private int journalDeviceBlockSize = 4096;
- @Option(name = "--journal-retention", description = "Configure journal retention in days. If > 0 then enable journal-retention-directory from broker.xml allowing replay options.")
+ @Option(names = "--journal-retention", description = "Configure journal retention in days. If > 0 then enable journal-retention-directory from broker.xml allowing replay options.")
private int retentionDays;
- @Option(name = "--journal-retention-max-bytes", description = "Maximum number of bytes to keep in the retention directory.")
+ @Option(names = "--journal-retention-max-bytes", description = "Maximum number of bytes to keep in the retention directory.")
private String retentionMaxBytes;
- @Option(name = "--global-max-size", description = "Maximum amount of memory which message data may consume. Default: half of the JVM's max memory.")
+ @Option(names = "--global-max-size", description = "Maximum amount of memory which message data may consume. Default: half of the JVM's max memory.")
private String globalMaxSize;
- @Option(name = "--global-max-messages", description = "Maximum number of messages that will be accepted in memory before using address full policy mode. Default: undefined.")
+ @Option(names = "--global-max-messages", description = "Maximum number of messages that will be accepted in memory before using address full policy mode. Default: undefined.")
private long globalMaxMessages = -1;
- @Option(name = "--jdbc", description = "Store message data in JDBC instead of local files.")
+ @Option(names = "--jdbc", description = "Store message data in JDBC instead of local files.")
boolean jdbc;
- @Option(name = "--staticCluster", description = "Cluster node connectors list separated by comma, e.g. \"tcp://server:61616,tcp://server2:61616,tcp://server3:61616\".")
+ @Option(names = "--staticCluster", description = "Cluster node connectors list separated by comma, e.g. \"tcp://server:61616,tcp://server2:61616,tcp://server3:61616\".")
String staticNode;
- @Option(name = "--support-advisory", description = "Support advisory messages for the OpenWire protocol.")
+ @Option(names = "--support-advisory", description = "Support advisory messages for the OpenWire protocol.")
boolean supportAdvisory = false;
- @Option(name = "--suppress-internal-management-objects", description = "Do not register any advisory addresses/queues for the OpenWire protocol with the broker's management service.")
+ @Option(names = "--suppress-internal-management-objects", description = "Do not register any advisory addresses/queues for the OpenWire protocol with the broker's management service.")
boolean suppressInternalManagementObjects = false;
public String[] getStaticNodes() {
@@ -289,37 +289,37 @@ public class Create extends InstallAbstract {
}
}
- @Option(name = "--security-manager", description = "Which security manager to use - jaas or basic. Default: jaas.")
+ @Option(names = "--security-manager", description = "Which security manager to use - jaas or basic. Default: jaas.")
private String securityManager = "jaas";
- @Option(name = "--jdbc-bindings-table-name", description = "Name of the jdbc bindings table.")
+ @Option(names = "--jdbc-bindings-table-name", description = "Name of the jdbc bindings table.")
private String jdbcBindings = ActiveMQDefaultConfiguration.getDefaultBindingsTableName();
- @Option(name = "--jdbc-message-table-name", description = "Name of the jdbc messages table.")
+ @Option(names = "--jdbc-message-table-name", description = "Name of the jdbc messages table.")
private String jdbcMessages = ActiveMQDefaultConfiguration.getDefaultMessageTableName();
- @Option(name = "--jdbc-large-message-table-name", description = "Name of the large messages table.")
+ @Option(names = "--jdbc-large-message-table-name", description = "Name of the large messages table.")
private String jdbcLargeMessages = ActiveMQDefaultConfiguration.getDefaultLargeMessagesTableName();
- @Option(name = "--jdbc-page-store-table-name", description = "Name of the page store messages table.")
+ @Option(names = "--jdbc-page-store-table-name", description = "Name of the page store messages table.")
private String jdbcPageStore = ActiveMQDefaultConfiguration.getDefaultPageStoreTableName();
- @Option(name = "--jdbc-node-manager-table-name", description = "Name of the jdbc node manager table.")
+ @Option(names = "--jdbc-node-manager-table-name", description = "Name of the jdbc node manager table.")
private String jdbcNodeManager = ActiveMQDefaultConfiguration.getDefaultNodeManagerStoreTableName();
- @Option(name = "--jdbc-connection-url", description = "The URL used for the database connection.")
+ @Option(names = "--jdbc-connection-url", description = "The URL used for the database connection.")
private String jdbcURL = null;
- @Option(name = "--jdbc-driver-class-name", description = "JDBC driver classname.")
+ @Option(names = "--jdbc-driver-class-name", description = "JDBC driver classname.")
private String jdbcClassName = ActiveMQDefaultConfiguration.getDefaultDriverClassName();
- @Option(name = "--jdbc-network-timeout", description = "Network timeout (in milliseconds).")
+ @Option(names = "--jdbc-network-timeout", description = "Network timeout (in milliseconds).")
long jdbcNetworkTimeout = ActiveMQDefaultConfiguration.getDefaultJdbcNetworkTimeout();
- @Option(name = "--jdbc-lock-renew-period", description = "Lock Renew Period (in milliseconds).")
+ @Option(names = "--jdbc-lock-renew-period", description = "Lock Renew Period (in milliseconds).")
long jdbcLockRenewPeriod = ActiveMQDefaultConfiguration.getDefaultJdbcLockRenewPeriodMillis();
- @Option(name = "--jdbc-lock-expiration", description = "Lock expiration (in milliseconds).")
+ @Option(names = "--jdbc-lock-expiration", description = "Lock expiration (in milliseconds).")
long jdbcLockExpiration = ActiveMQDefaultConfiguration.getDefaultJdbcLockExpirationMillis();
private boolean isAutoCreate() {
@@ -712,11 +712,9 @@ public class Create extends InstallAbstract {
File logFolder = createDirectory("log", directory);
File oomeDumpFile = new File(logFolder, "oom_dump.hprof");
- if (javaOptions == null || javaOptions.length() == 0) {
- javaOptions = "";
- }
+ String processedJavaOptions = getJavaOptions();
- addScriptFilters(filters, getHome(), getInstance(), etcFolder, dataFolder, oomeDumpFile, javaMemory, javaOptions, role);
+ addScriptFilters(filters, getHome(), getInstance(), etcFolder, dataFolder, oomeDumpFile, javaMemory, processedJavaOptions, role);
boolean allowAnonymous = isAllowAnonymous();
@@ -739,7 +737,7 @@ public class Create extends InstallAbstract {
filters.put("${journal-retention}", retentionTag);
- filters.put("${java-opts}", javaOptions);
+ filters.put("${java-opts}", processedJavaOptions);
filters.put("${java-memory}", javaMemory);
if (allowAnonymous) {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Disconnect.java
similarity index 68%
copy from artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
copy to artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Disconnect.java
index e34e376deb..4d05496b4c 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Disconnect.java
@@ -14,28 +14,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
+package org.apache.activemq.artemis.cli.commands;
-import com.github.rvesse.airline.annotations.Command;
-import org.apache.activemq.artemis.dto.BrokerDTO;
+import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
+import picocli.CommandLine;
-@Command(name = "kill", description = "Kill a broker started with --allow-kill.")
-public class Kill extends Configurable {
+@CommandLine.Command(name = "disconnect", description = "Clear previously typed user credentials.")
+public class Disconnect extends ConnectionAbstract {
@Override
public Object execute(ActionContext context) throws Exception {
super.execute(context);
-
- BrokerDTO broker = getBrokerDTO();
-
- File file = broker.server.getConfigurationFile().getParentFile();
-
- File killFile = new File(file, "KILL_ME");
-
- killFile.createNewFile();
-
+ CONNECTION_INFORMATION.remove();
+ System.out.println("Connection information cleared!");
return null;
}
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/HelpAction.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/HelpAction.java
index d11db8c06d..61309a820b 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/HelpAction.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/HelpAction.java
@@ -16,40 +16,48 @@
*/
package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
-
-import com.github.rvesse.airline.help.Help;
-
-public class HelpAction extends Help implements Action {
-
- @Override
- public boolean isVerbose() {
- return false;
- }
-
- @Override
- public void setHomeValues(File brokerHome, File brokerInstance, File etcFolder) {
-
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+
+@Command(name = "help", description = "use 'help <command>' for more information")
+public class HelpAction implements Runnable {
+
+ CommandLine commandLine;
+
+ @CommandLine.Parameters
+ String[] args;
+
+ public static void help(CommandLine commandLine, String... args) {
+ if (args != null) {
+ CommandLine theLIn = commandLine;
+ for (String i : args) {
+ Object subCommand = theLIn.getSubcommands().get(i);
+ if (subCommand == null) {
+ commandLine.usage(System.out);
+ } else if (subCommand instanceof CommandLine) {
+ theLIn = (CommandLine) subCommand;
+ } else {
+ commandLine.usage(System.out);
+ }
+ }
+ theLIn.usage(System.out);
+ } else {
+ commandLine.usage(System.out);
+ }
}
- @Override
- public String getBrokerInstance() {
- return null;
+ public CommandLine getCommandLine() {
+ return commandLine;
}
- @Override
- public String getBrokerHome() {
- return null;
+ public HelpAction setCommandLine(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ return this;
}
@Override
- public void checkOptions(String[] options) throws InvalidOptionsError {
- OptionsUtil.checkCommandOptions(this.getClass(), options);
+ public void run() {
+ help(commandLine, args);
}
- @Override
- public Object execute(ActionContext context) throws Exception {
- super.run();
- return null;
- }
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InputAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InputAbstract.java
index 3915816f7e..9720c1d632 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InputAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InputAbstract.java
@@ -19,7 +19,7 @@ package org.apache.activemq.artemis.cli.commands;
import java.util.Scanner;
-import com.github.rvesse.airline.annotations.Option;
+import picocli.CommandLine.Option;
public class InputAbstract extends ActionAbstract {
@@ -34,7 +34,7 @@ public class InputAbstract extends ActionAbstract {
inputEnabled = true;
}
- @Option(name = "--silent", description = "Disable all the inputs, and make a best guess for any required input.")
+ @Option(names = "--silent", description = "Disable all the inputs, and make a best guess for any required input.")
private boolean silentInput = false;
public boolean isSilentInput() {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InstallAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InstallAbstract.java
index dc28622d26..e13f1c8b93 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InstallAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/InstallAbstract.java
@@ -26,42 +26,48 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import com.github.rvesse.airline.annotations.Arguments;
-import com.github.rvesse.airline.annotations.Option;
-import com.github.rvesse.airline.annotations.restrictions.Required;
import org.apache.activemq.artemis.cli.CLIException;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.Parameters;
public class InstallAbstract extends InputAbstract {
- @Arguments(description = "The instance directory to hold the broker's configuration and data. Path must be writable.")
- @Required
+ @Parameters(description = "The instance directory to hold the broker's configuration and data. Path must be writable.")
protected File directory;
- @Option(name = "--etc", description = "Directory where ActiveMQ configuration is located. Paths can be absolute or relative to artemis.instance directory. Default: etc.")
+ @Option(names = "--etc", description = "Directory where ActiveMQ configuration is located. Paths can be absolute or relative to artemis.instance directory. Default: etc.")
protected String etc = "etc";
- @Option(name = "--home", description = "Directory where ActiveMQ Artemis is installed.")
+ @Option(names = "--home", description = "Directory where ActiveMQ Artemis is installed.")
protected File home;
- @Option(name = "--encoding", description = "The encoding that text files should use. Default: UTF-8.")
+ @Option(names = "--encoding", description = "The encoding that text files should use. Default: UTF-8.")
protected String encoding = "UTF-8";
- @Option(name = "--windows", description = "Force Windows script creation. Default: based on your actual system.")
+ @Option(names = "--windows", description = "Force Windows script creation. Default: based on your actual system.")
protected boolean windows = false;
- @Option(name = "--cygwin", description = "Force Cygwin script creation. Default: based on your actual system.")
+ @Option(names = "--cygwin", description = "Force Cygwin script creation. Default: based on your actual system.")
protected boolean cygwin = false;
- @Option(name = "--java-options", description = "Extra Java options to be passed to the profile.")
- protected String javaOptions = "";
+ @Option(names = "--java-options", description = "Extra Java options to be passed to the profile.")
+ protected List<String> javaOptions;
- @Option(name = "--java-memory", description = "Define the -Xmx memory parameter for the broker. Default: 2G.")
+ @Option(names = "--java-memory", description = "Define the -Xmx memory parameter for the broker. Default: 2G.")
protected String javaMemory = "2G";
+ protected String getJavaOptions() {
+ StringBuilder builder = new StringBuilder();
+ if (javaOptions != null) {
+ javaOptions.forEach(s -> builder.append(s).append(" "));
+ }
+ return builder.toString();
+ }
public String getEncoding() {
return encoding;
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
index e34e376deb..cfe9613436 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
@@ -18,8 +18,8 @@ package org.apache.activemq.artemis.cli.commands;
import java.io.File;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.dto.BrokerDTO;
+import picocli.CommandLine.Command;
@Command(name = "kill", description = "Kill a broker started with --allow-kill.")
public class Kill extends Configurable {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Mask.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Mask.java
index 40ef0ae856..aefb5c0b3f 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Mask.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Mask.java
@@ -19,29 +19,27 @@ package org.apache.activemq.artemis.cli.commands;
import java.util.HashMap;
import java.util.Map;
-import com.github.rvesse.airline.annotations.Arguments;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
-import com.github.rvesse.airline.annotations.restrictions.Required;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;
import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
import org.apache.activemq.artemis.utils.SensitiveDataCodec;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.Parameters;
@Command(name = "mask", description = "Mask a password and print it out.")
public class Mask extends ActionAbstract {
- @Arguments(description = "The password to be masked.")
- @Required
+ @Parameters(description = "The password to be masked.")
String password;
- @Option(name = "--hash", description = "Whether to use a hash (one-way). Default: false.")
+ @Option(names = "--hash", description = "Whether to use a hash (one-way). Default: false.")
boolean hash = false;
- @Option(name = "--key", description = "The key (Blowfish) to mask a password.")
+ @Option(names = "--key", description = "The key (Blowfish) to mask a password.")
String key;
- @Option(name = "--password-codec", description = "Whether to use the password codec defined in the configuration. Default: false")
+ @Option(names = "--password-codec", description = "Whether to use the password codec defined in the configuration. Default: false")
boolean passwordCodec = false;
private SensitiveDataCodec<String> codec;
@@ -100,9 +98,4 @@ public class Mask extends ActionAbstract {
return codec;
}
- @Override
- public void checkOptions(String[] options) throws InvalidOptionsError {
- OptionsUtil.checkCommandOptions(this.getClass(), options);
- }
-
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/OptionsUtil.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/OptionsUtil.java
deleted file mode 100644
index 9c12b83dfd..0000000000
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/OptionsUtil.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli.commands;
-
-import java.lang.reflect.Field;
-import java.util.HashSet;
-import java.util.Set;
-
-import com.github.rvesse.airline.annotations.Option;
-
-public class OptionsUtil {
-
- private static void findAllOptions(Set<String> options, Class<? extends Action> command) {
- for (Field field : command.getDeclaredFields()) {
- if (field.isAnnotationPresent(Option.class)) {
- Option annotation = field.getAnnotation(Option.class);
- String[] names = annotation.name();
- for (String n : names) {
- options.add(n);
- }
- }
- }
- Class parent = command.getSuperclass();
- if (Action.class.isAssignableFrom(parent)) {
- findAllOptions(options, parent);
- }
- }
-
- private static Set<String> findCommandOptions(Class<? extends Action> command) {
- Set<String> options = new HashSet<>();
- findAllOptions(options, command);
-
- return options;
- }
-
- public static void checkCommandOptions(Class<? extends Action> cmdClass, String[] options) throws InvalidOptionsError {
- Set<String> definedOptions = OptionsUtil.findCommandOptions(cmdClass);
- for (String opt : options) {
- if (opt.startsWith("--") && !"--".equals(opt.trim())) {
- int index = opt.indexOf("=");
- if (index > 0) {
- opt = opt.substring(0, index);
- }
- if (!definedOptions.contains(opt)) {
- throw new InvalidOptionsError("Found unexpected parameters: [" + opt + "]");
- }
- }
- }
- }
-}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/PrintVersion.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/PrintVersion.java
index 4bb2217e8f..fc0fb48f6c 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/PrintVersion.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/PrintVersion.java
@@ -16,9 +16,9 @@
*/
package org.apache.activemq.artemis.cli.commands;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.core.version.Version;
import org.apache.activemq.artemis.utils.VersionLoader;
+import picocli.CommandLine.Command;
@Command(name = "version", description = "Print version information.")
public class PrintVersion extends ActionAbstract {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
index 96b3e00761..bb3d926570 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
@@ -21,8 +21,6 @@ import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicReference;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.cli.Artemis;
@@ -41,14 +39,16 @@ import org.apache.activemq.artemis.integration.Broker;
import org.apache.activemq.artemis.integration.bootstrap.ActiveMQBootstrapLogger;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
import org.apache.activemq.artemis.utils.ReusableLatch;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "run", description = "Run the broker.")
public class Run extends LockAbstract {
- @Option(name = "--allow-kill", description = "This will allow the server to kill itself. Useful for tests (e.g. failover tests).")
+ @Option(names = "--allow-kill", description = "This will allow the server to kill itself. Useful for tests (e.g. failover tests).")
boolean allowKill;
- @Option(name = "--properties", description = "URL to a properties file that is applied to the server's configuration.")
+ @Option(names = "--properties", description = "URL to a properties file that is applied to the server's configuration.")
String properties;
private static boolean embedded = false;
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Stop.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Stop.java
index 1232a9fb16..2ef2e8abcb 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Stop.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Stop.java
@@ -18,8 +18,8 @@ package org.apache.activemq.artemis.cli.commands;
import java.io.File;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.dto.BrokerDTO;
+import picocli.CommandLine.Command;
@Command(name = "stop", description = "Stop the broker.")
public class Stop extends Configurable {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Upgrade.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Upgrade.java
index 2d7001821b..9185ef4dd4 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Upgrade.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Upgrade.java
@@ -30,8 +30,8 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.util.JVMArgumentParser;
+import picocli.CommandLine.Command;
@Command(name = "upgrade", description = "Update a broker instance to the current artemis.home, keeping all the data and broker.xml. Warning: backup your instance before using this command and compare the files.")
public class Upgrade extends InstallAbstract {
@@ -107,7 +107,7 @@ public class Upgrade extends InstallAbstract {
}
HashMap<String, String> filters = new HashMap<>();
- Create.addScriptFilters(filters, getHome(), getInstance(), etcFolder, new File(getInstance(), "notUsed"), new File(getInstance(), "om-not-used.dmp"), javaMemory, javaOptions, "NA");
+ Create.addScriptFilters(filters, getHome(), getInstance(), etcFolder, new File(getInstance(), "notUsed"), new File(getInstance(), "om-not-used.dmp"), javaMemory, getJavaOptions(), "NA");
if (IS_WINDOWS) {
// recreating the service.exe and config in case we ever upgrade it
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationGroup.java
similarity index 57%
copy from artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
copy to artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationGroup.java
index e34e376deb..6112ba0039 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationGroup.java
@@ -14,28 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
+package org.apache.activemq.artemis.cli.commands.activation;
-import com.github.rvesse.airline.annotations.Command;
-import org.apache.activemq.artemis.dto.BrokerDTO;
+import org.apache.activemq.artemis.cli.commands.HelpAction;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
-@Command(name = "kill", description = "Kill a broker started with --allow-kill.")
-public class Kill extends Configurable {
+@Command(name = "activation", description = "use 'help activation' for sub commands list", subcommands = {ActivationSequenceList.class, ActivationSequenceSet.class})
+public class ActivationGroup implements Runnable {
- @Override
- public Object execute(ActionContext context) throws Exception {
- super.execute(context);
-
- BrokerDTO broker = getBrokerDTO();
-
- File file = broker.server.getConfigurationFile().getParentFile();
-
- File killFile = new File(file, "KILL_ME");
+ CommandLine commandLine;
- killFile.createNewFile();
+ public ActivationGroup(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ }
- return null;
+ @Override
+ public void run() {
+ HelpAction.help(commandLine, "activation");
}
+
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationSequenceList.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationSequenceList.java
index cd3c47dd08..39066beb9d 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationSequenceList.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationSequenceList.java
@@ -20,8 +20,6 @@ import java.io.PrintStream;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.tools.LockAbstract;
import org.apache.activemq.artemis.core.config.Configuration;
@@ -34,6 +32,8 @@ import org.apache.activemq.artemis.core.server.impl.FileLockNodeManager;
import org.apache.activemq.artemis.quorum.DistributedLock;
import org.apache.activemq.artemis.quorum.DistributedPrimitiveManager;
import org.apache.activemq.artemis.quorum.MutableLong;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
import static org.apache.activemq.artemis.cli.commands.activation.ActivationSequenceUtils.applyCoordinationId;
@@ -41,11 +41,11 @@ import static org.apache.activemq.artemis.cli.commands.activation.ActivationSequ
public class ActivationSequenceList extends LockAbstract {
private static final int MANAGER_START_TIMEOUT_SECONDS = 60;
- @Option(name = "--node-id", description = "This can be used just with --remote option. If not set, broker NodeID is used instead.")
+ @Option(names = "--node-id", description = "This can be used just with --remote option. If not set, broker NodeID is used instead.")
public String nodeId = null;
- @Option(name = "--remote", description = "List just remote (i.e. coordinated) activation sequence.")
+ @Option(names = "--remote", description = "List just remote (i.e. coordinated) activation sequence.")
public boolean remote = false;
- @Option(name = "--local", description = "List just local activation sequence.")
+ @Option(names = "--local", description = "List just local activation sequence.")
public boolean local = false;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationSequenceSet.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationSequenceSet.java
index 4551a626fa..71b7fa35ac 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationSequenceSet.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/activation/ActivationSequenceSet.java
@@ -20,9 +20,6 @@ import java.io.PrintStream;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
-import com.github.rvesse.airline.annotations.restrictions.Required;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.tools.LockAbstract;
import org.apache.activemq.artemis.core.config.Configuration;
@@ -35,6 +32,8 @@ import org.apache.activemq.artemis.core.server.impl.FileLockNodeManager;
import org.apache.activemq.artemis.quorum.DistributedLock;
import org.apache.activemq.artemis.quorum.DistributedPrimitiveManager;
import org.apache.activemq.artemis.quorum.MutableLong;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
import static org.apache.activemq.artemis.cli.commands.activation.ActivationSequenceUtils.applyCoordinationId;
@@ -43,17 +42,16 @@ public class ActivationSequenceSet extends LockAbstract {
private static final int MANAGER_START_TIMEOUT_SECONDS = 60;
- @Option(name = "--node-id", description = "Target sequence for this UUID overwriting the NodeID of this broker too. If not set, broker NodeID is used instead.")
+ @Option(names = "--node-id", description = "Target sequence for this UUID overwriting the NodeID of this broker too. If not set, broker NodeID is used instead.")
public String nodeId = null;
- @Option(name = "--remote", description = "Set just remote (i.e. coordinated) activation sequence.")
+ @Option(names = "--remote", description = "Set just remote (i.e. coordinated) activation sequence.")
public boolean remote = false;
- @Option(name = "--local", description = "Set just local activation sequence.")
+ @Option(names = "--local", description = "Set just local activation sequence.")
public boolean local = false;
- @Option(name = "--to", description = "The new activation sequence.")
- @Required
+ @Option(names = "--to", description = "The new activation sequence.", required = true)
public long value;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressAbstract.java
index 337b8c4b48..9398763e85 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressAbstract.java
@@ -16,24 +16,24 @@
*/
package org.apache.activemq.artemis.cli.commands.address;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
+import picocli.CommandLine.Option;
public abstract class AddressAbstract extends ConnectionAbstract {
- @Option(name = "--name", description = "The address's name.")
+ @Option(names = "--name", description = "The address's name.")
private String name;
- @Option(name = "--anycast", description = "Whether the address supports anycast queues.")
+ @Option(names = "--anycast", description = "Whether the address supports anycast queues.")
private Boolean anycast;
- @Option(name = "--no-anycast", description = "Whether the address won't support anycast queues.")
+ @Option(names = "--no-anycast", description = "Whether the address won't support anycast queues.")
private Boolean noAnycast;
- @Option(name = "--multicast", description = "Whether the address supports multicast queues.")
+ @Option(names = "--multicast", description = "Whether the address supports multicast queues.")
private Boolean multicast;
- @Option(name = "--no-multicast", description = "Whether the address won't support multicast queues.")
+ @Option(names = "--no-multicast", description = "Whether the address won't support multicast queues.")
private Boolean noMulticast;
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressGroup.java
similarity index 57%
copy from artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
copy to artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressGroup.java
index e34e376deb..118698e953 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/AddressGroup.java
@@ -14,28 +14,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
+package org.apache.activemq.artemis.cli.commands.address;
-import com.github.rvesse.airline.annotations.Command;
-import org.apache.activemq.artemis.dto.BrokerDTO;
+import org.apache.activemq.artemis.cli.commands.HelpAction;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
-@Command(name = "kill", description = "Kill a broker started with --allow-kill.")
-public class Kill extends Configurable {
+@Command(name = "address", description = "use 'help address' for sub commands list", subcommands = {CreateAddress.class, DeleteAddress.class, UpdateAddress.class, ShowAddress.class})
+public class AddressGroup implements Runnable {
- @Override
- public Object execute(ActionContext context) throws Exception {
- super.execute(context);
-
- BrokerDTO broker = getBrokerDTO();
-
- File file = broker.server.getConfigurationFile().getParentFile();
+ CommandLine commandLine;
- File killFile = new File(file, "KILL_ME");
-
- killFile.createNewFile();
+ public AddressGroup(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ }
- return null;
+ @Override
+ public void run() {
+ HelpAction.help(commandLine, "address");
}
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/CreateAddress.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/CreateAddress.java
index 6d5a004d46..354e983cc5 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/CreateAddress.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/CreateAddress.java
@@ -17,9 +17,9 @@
package org.apache.activemq.artemis.cli.commands.address;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
@Command(name = "create", description = "Create an address.")
public class CreateAddress extends AddressAbstract {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/DeleteAddress.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/DeleteAddress.java
index 6f18b442f6..2822d4ce18 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/DeleteAddress.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/DeleteAddress.java
@@ -17,15 +17,15 @@
package org.apache.activemq.artemis.cli.commands.address;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "delete", description = "Delete an address.")
public class DeleteAddress extends AddressAbstract {
- @Option(name = "--force", description = "Delete the address even if it has queues. All messages in those queues will be deleted! Default: false.")
+ @Option(names = "--force", description = "Delete the address even if it has queues. All messages in those queues will be deleted! Default: false.")
private Boolean force = false;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/HelpAddress.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/HelpAddress.java
deleted file mode 100644
index cf28abb3dd..0000000000
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/HelpAddress.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli.commands.address;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.github.rvesse.airline.help.Help;
-import org.apache.activemq.artemis.cli.commands.Action;
-import org.apache.activemq.artemis.cli.commands.ActionContext;
-import org.apache.activemq.artemis.cli.commands.InvalidOptionsError;
-import org.apache.activemq.artemis.cli.commands.OptionsUtil;
-
-public class HelpAddress extends Help implements Action {
-
- @Override
- public boolean isVerbose() {
- return false;
- }
-
- @Override
- public void setHomeValues(File brokerHome, File brokerInstance, File etc) {
- }
-
- @Override
- public String getBrokerInstance() {
- return null;
- }
-
- @Override
- public String getBrokerHome() {
- return null;
- }
-
- @Override
- public void checkOptions(String[] options) throws InvalidOptionsError {
- OptionsUtil.checkCommandOptions(this.getClass(), options);
- }
-
- @Override
- public Object execute(ActionContext context) throws Exception {
- List<String> commands = new ArrayList<>(1);
- commands.add("address");
- help(global, commands);
- return null;
- }
-}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/ShowAddress.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/ShowAddress.java
index f2b7b42c3a..c6fd475949 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/ShowAddress.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/ShowAddress.java
@@ -17,15 +17,15 @@
package org.apache.activemq.artemis.cli.commands.address;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "show", description = "Show the selected address.")
public class ShowAddress extends AddressAbstract {
- @Option(name = "--bindings", description = "Show the bindings for this address.")
+ @Option(names = "--bindings", description = "Show the bindings for this address.")
boolean bindings;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/UpdateAddress.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/UpdateAddress.java
index 614e7b61c2..2b9cfca6c2 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/UpdateAddress.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/address/UpdateAddress.java
@@ -16,9 +16,9 @@
*/
package org.apache.activemq.artemis.cli.commands.address;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
@Command(name = "update", description = "Update an address.")
public class UpdateAddress extends AddressAbstract {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/CheckAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/CheckAbstract.java
index dff6238f7e..e2a066f6c8 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/CheckAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/CheckAbstract.java
@@ -23,23 +23,23 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.ActiveMQManagementProxy;
import org.apache.activemq.artemis.cli.CLIException;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.commons.lang3.time.StopWatch;
+import picocli.CommandLine.Option;
public abstract class CheckAbstract extends ConnectionAbstract {
- @Option(name = "--name", description = "Name of the target to check.")
+ @Option(names = "--name", description = "Name of the target to check.")
protected String name;
- @Option(name = "--timeout", description = "Time to wait for the check to complete (in milliseconds).")
+ @Option(names = "--timeout", description = "Time to wait for the check to complete (in milliseconds).")
private int timeout = 30000;
- @Option(name = "--fail-at-end", description = "Continue with the rest of the checks even if a particular module check fails.")
+ @Option(names = "--fail-at-end", description = "Continue with the rest of the checks even if a particular module check fails.")
private boolean failAtEnd = false;
public String getName() {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/CheckGroup.java
similarity index 58%
copy from artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java
copy to artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/CheckGroup.java
index 5ed583754d..c5d1dddadf 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Action.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/CheckGroup.java
@@ -14,21 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
+package org.apache.activemq.artemis.cli.commands.check;
-public interface Action {
+import org.apache.activemq.artemis.cli.commands.HelpAction;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
- boolean isVerbose();
+@Command(name = "check", description = "use 'help check' for sub commands list", subcommands = {NodeCheck.class, QueueCheck.class})
+public class CheckGroup implements Runnable {
- void setHomeValues(File brokerHome, File brokerInstance, File etcFolder);
+ CommandLine commandLine;
- Object execute(ActionContext context) throws Exception;
+ public CheckGroup(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ }
- String getBrokerInstance();
+ @Override
+ public void run() {
+ HelpAction.help(commandLine, "check");
- String getBrokerHome();
+ }
- void checkOptions(String[] options) throws InvalidOptionsError;
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/HelpCheck.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/HelpCheck.java
deleted file mode 100644
index 30a25b88fc..0000000000
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/HelpCheck.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli.commands.check;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.github.rvesse.airline.help.Help;
-import org.apache.activemq.artemis.cli.commands.Action;
-import org.apache.activemq.artemis.cli.commands.ActionContext;
-import org.apache.activemq.artemis.cli.commands.InvalidOptionsError;
-import org.apache.activemq.artemis.cli.commands.OptionsUtil;
-
-public class HelpCheck extends Help implements Action {
-
- @Override
- public boolean isVerbose() {
- return false;
- }
-
- @Override
- public void setHomeValues(File brokerHome, File brokerInstance, File etc) {
- }
-
- @Override
- public String getBrokerInstance() {
- return null;
- }
-
- @Override
- public String getBrokerHome() {
- return null;
- }
-
- @Override
- public void checkOptions(String[] options) throws InvalidOptionsError {
- OptionsUtil.checkCommandOptions(this.getClass(), options);
- }
-
- @Override
- public Object execute(ActionContext context) throws Exception {
- List<String> commands = new ArrayList<>(1);
- commands.add("check");
- help(global, commands);
- return null;
- }
-}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/NodeCheck.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/NodeCheck.java
index 71b7354a94..71a50a8e9f 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/NodeCheck.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/NodeCheck.java
@@ -19,29 +19,29 @@ package org.apache.activemq.artemis.cli.commands.check;
import java.util.ArrayList;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.NodeInfo;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "node", description = "Check a node.")
public class NodeCheck extends CheckAbstract {
- @Option(name = "--up", description = "Check that the node is started. This check is executed by default if there are no other checks.")
+ @Option(names = "--up", description = "Check that the node is started. This check is executed by default if there are no other checks.")
private boolean up;
- @Option(name = "--diskUsage", description = "Disk usage percentage to check or -1 to use the max-disk-usage.")
+ @Option(names = "--diskUsage", description = "Disk usage percentage to check or -1 to use the max-disk-usage.")
private Integer diskUsage;
- @Option(name = "--memoryUsage", description = "Memory usage percentage to check.")
+ @Option(names = "--memoryUsage", description = "Memory usage percentage to check.")
private Integer memoryUsage;
- @Option(name = "--live", description = "Check that the node has a connected live.")
+ @Option(names = "--live", description = "Check that the node has a connected live.")
private boolean live;
- @Option(name = "--backup", description = "Check that the node has a connected backup.")
+ @Option(names = "--backup", description = "Check that the node has a connected backup.")
private boolean backup;
- @Option(name = "--peers", description = "Number of peers to check.")
+ @Option(names = "--peers", description = "Number of peers to check.")
private Integer peers;
public boolean isUp() {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/QueueCheck.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/QueueCheck.java
index 9cee8a072e..db3592e712 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/QueueCheck.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/QueueCheck.java
@@ -23,27 +23,26 @@ import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.QueueBrowser;
import javax.jms.Session;
-
import java.util.ArrayList;
import java.util.Enumeration;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.ResourceNames;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "queue", description = "Check a queue.")
public class QueueCheck extends CheckAbstract {
- @Option(name = "--up", description = "Check that the queue exists and is not paused. This check is executed by default if there are no other checks.")
+ @Option(names = "--up", description = "Check that the queue exists and is not paused. This check is executed by default if there are no other checks.")
private boolean up;
- @Option(name = "--browse", description = "Number of the messages to browse or -1 to check that the queue is browsable.")
+ @Option(names = "--browse", description = "Number of the messages to browse or -1 to check that the queue is browsable.")
private Integer browse;
- @Option(name = "--consume", description = "Number of the messages to consume or -1 to check that the queue is consumable.")
+ @Option(names = "--consume", description = "Number of the messages to consume or -1 to check that the queue is consumable.")
private Integer consume;
- @Option(name = "--produce", description = "Number of the messages to produce.")
+ @Option(names = "--produce", description = "Number of the messages to produce.")
private Integer produce;
public boolean isUp() {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Browse.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Browse.java
index 4e4a7b7301..c133ed7d89 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Browse.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Browse.java
@@ -22,14 +22,14 @@ import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Session;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "browser", description = "Browse messages on a queue.")
public class Browse extends DestAbstract {
- @Option(name = "--filter", description = "The message filter.")
+ @Option(names = "--filter", description = "The message filter.")
String filter;
@Override
@@ -66,7 +66,7 @@ public class Browse extends DestAbstract {
connection.start();
- int received = 0;
+ long received = 0;
for (ConsumerThread thread : threadsArray) {
thread.join();
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionAbstract.java
index c9ee1a4fb8..ba8a2fd3f9 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionAbstract.java
@@ -21,32 +21,44 @@ import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.JMSSecurityException;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
+import org.apache.activemq.artemis.cli.Shell;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.InputAbstract;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.qpid.jms.JmsConnectionFactory;
+import picocli.CommandLine.Option;
public class ConnectionAbstract extends InputAbstract {
-
- @Option(name = "--url", description = "Connection URL. Default: build URL from the 'artemis' acceptor defined in the broker.xml or tcp://localhost:61616 if the acceptor cannot be parsed.")
+ @Option(names = "--url", description = "Connection URL. Default: build URL from the 'artemis' acceptor defined in the broker.xml or tcp://localhost:61616 if the acceptor cannot be parsed.")
protected String brokerURL = DEFAULT_BROKER_URL;
- @Option(name = "--acceptor", description = "Name used to find the default connection URL on the acceptor list. If an acceptor with that name cannot be found the CLI will look for a connector with the same name.")
+ @Option(names = "--acceptor", description = "Name used to find the default connection URL on the acceptor list. If an acceptor with that name cannot be found the CLI will look for a connector with the same name.")
protected String acceptor;
- @Option(name = "--user", description = "User used to connect.")
+ @Option(names = "--user", description = "User used to connect.")
protected String user;
- @Option(name = "--password", description = "Password used to connect.")
+ @Option(names = "--password", description = "Password used to connect.")
protected String password;
- @Option(name = "--clientID", description = "ClientID set on the connection.")
+ @Option(names = "--clientID", description = "ClientID set on the connection.")
protected String clientID;
- @Option(name = "--protocol", description = "Protocol used. Valid values are amqp or core. Default: core.")
- protected String protocol = "core";
+ @Option(names = "--protocol", description = "Protocol used. Valid values are ${COMPLETION-CANDIDATES}", converter = ConnectionProtocol.ProtocolConverter.class)
+ protected ConnectionProtocol protocol = ConnectionProtocol.CORE;
+
+ protected static ThreadLocal<ConnectionInformation> CONNECTION_INFORMATION = new ThreadLocal<>();
+
+ static class ConnectionInformation {
+ String uri, user, password;
+
+ private ConnectionInformation(String uri, String user, String password) {
+ this.uri = uri;
+ this.user = user;
+ this.password = password;
+ }
+ }
public String getBrokerURL() {
return brokerURL;
@@ -92,14 +104,18 @@ public class ConnectionAbstract extends InputAbstract {
return this;
}
- public String getProtocol() {
+ public ConnectionProtocol getProtocol() {
return protocol;
}
- public void setProtocol(String protocol) {
+ public void setProtocol(ConnectionProtocol protocol) {
this.protocol = protocol;
}
+ public void setProtocol(String protocol) {
+ this.protocol = ConnectionProtocol.fromString(protocol);
+ }
+
@SuppressWarnings("StringEquality")
@Override
public Object execute(ActionContext context) throws Exception {
@@ -126,6 +142,7 @@ public class ConnectionAbstract extends InputAbstract {
}
protected ConnectionFactory createConnectionFactory() throws Exception {
+ recoverConnectionInformation();
return createConnectionFactory(brokerURL, user, password, clientID, protocol);
}
@@ -133,10 +150,10 @@ public class ConnectionAbstract extends InputAbstract {
String user,
String password,
String clientID,
- String protocol) throws Exception {
- if (protocol.equals("core")) {
+ ConnectionProtocol protocol) throws Exception {
+ if (protocol == ConnectionProtocol.CORE) {
return createCoreConnectionFactory(brokerURL, user, password, clientID);
- } else if (protocol.equals("amqp")) {
+ } else if (protocol == ConnectionProtocol.AMQP) {
return createAMQPConnectionFactory(brokerURL, user, password, clientID);
} else {
throw new IllegalStateException("protocol " + protocol + " not supported");
@@ -157,68 +174,132 @@ public class ConnectionAbstract extends InputAbstract {
}
try {
- Connection connection = cf.createConnection();
- connection.close();
+ tryConnect(brokerURL, user, password, cf);
return cf;
} catch (JMSSecurityException e) {
// if a security exception will get the user and password through an input
getActionContext().err.println("Connection failed::" + e.getMessage());
- cf = new JmsConnectionFactory(inputUser(user), inputPassword(password), brokerURL);
+ user = inputUser(user);
+ password = inputPassword(password);
+ cf = new JmsConnectionFactory(user, password, brokerURL);
if (clientID != null) {
cf.setClientID(clientID);
}
+ try {
+ tryConnect(brokerURL, user, password, cf);
+ } catch (Exception e2) {
+ e.printStackTrace();
+ }
return cf;
} catch (JMSException e) {
// if a connection exception will ask for the URL, user and password
getActionContext().err.println("Connection failed::" + e.getMessage());
- cf = new JmsConnectionFactory(inputUser(user), inputPassword(password), inputBrokerURL(brokerURL));
+ brokerURL = inputBrokerURL(brokerURL);
+ user = inputUser(user);
+ password = inputPassword(password);
+ cf = new JmsConnectionFactory(user, password, brokerURL);
if (clientID != null) {
cf.setClientID(clientID);
}
+ try {
+ tryConnect(brokerURL, user, password, cf);
+ } catch (Exception e2) {
+ e2.printStackTrace();
+ }
return cf;
}
}
protected ActiveMQConnectionFactory createCoreConnectionFactory() {
+ recoverConnectionInformation();
return createCoreConnectionFactory(brokerURL, user, password, clientID);
}
+ private void recoverConnectionInformation() {
+ if (CONNECTION_INFORMATION.get() != null) {
+ ConnectionInformation connectionInfo = CONNECTION_INFORMATION.get();
+ if (this.user == null) {
+ this.user = connectionInfo.user;
+ }
+ if (this.password == null) {
+ this.password = connectionInfo.password;
+ }
+ if (this.brokerURL == null) {
+ this.brokerURL = connectionInfo.uri;
+ }
+
+ }
+ }
+
+ void saveConnectionInfo(String brokerURL, String user, String password) {
+ if (Shell.inShell() && CONNECTION_INFORMATION.get() == null) {
+ CONNECTION_INFORMATION.set(new ConnectionInformation(brokerURL, user, password));
+ System.out.println("CLI connected to broker " + brokerURL + ", user:" + user);
+ }
+ }
+
protected ActiveMQConnectionFactory createCoreConnectionFactory(String brokerURL,
String user,
String password,
String clientID) {
+ if (brokerURL.startsWith("amqp://")) {
+ // replacing amqp:// by tcp://
+ brokerURL = "tcp" + brokerURL.substring(4);
+ }
+
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(brokerURL, user, password);
if (clientID != null) {
getActionContext().out.println("Consumer:: clientID = " + clientID);
cf.setClientID(clientID);
}
try {
- Connection connection = cf.createConnection();
- connection.close();
+ tryConnect(brokerURL, user, password, cf);
return cf;
} catch (JMSSecurityException e) {
// if a security exception will get the user and password through an input
if (getActionContext() != null) {
getActionContext().err.println("Connection failed::" + e.getMessage());
}
- cf = new ActiveMQConnectionFactory(brokerURL, inputUser(user), inputPassword(password));
+ user = inputUser(user);
+ password = inputPassword(password);
+ cf = new ActiveMQConnectionFactory(brokerURL, user, password);
if (clientID != null) {
cf.setClientID(clientID);
}
+ try {
+ tryConnect(brokerURL, user, password, cf);
+ } catch (Exception e2) {
+ }
return cf;
} catch (JMSException e) {
// if a connection exception will ask for the URL, user and password
if (getActionContext() != null) {
getActionContext().err.println("Connection failed::" + e.getMessage());
}
- cf = new ActiveMQConnectionFactory(inputBrokerURL(brokerURL), inputUser(user), inputPassword(password));
+ brokerURL = inputBrokerURL(brokerURL);
+ user = inputUser(user);
+ password = inputPassword(password);
+ cf = new ActiveMQConnectionFactory(brokerURL, user, password);
if (clientID != null) {
cf.setClientID(clientID);
}
+ try {
+ tryConnect(brokerURL, user, password, cf);
+ } catch (Exception e2) {
+ }
return cf;
}
}
+ private void tryConnect(String brokerURL,
+ String user,
+ String password,
+ ConnectionFactory cf) throws JMSException {
+ Connection connection = cf.createConnection();
+ connection.close();
+ saveConnectionInfo(brokerURL, user, password);
+ }
+
private String inputBrokerURL(String defaultValue) {
return input("--url", "Type in the connection URL for a retry (e.g. tcp://localhost:61616)", defaultValue);
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionProtocol.java
similarity index 54%
copy from artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
copy to artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionProtocol.java
index e34e376deb..3fb9c14bdd 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionProtocol.java
@@ -14,28 +14,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
+package org.apache.activemq.artemis.cli.commands.messages;
-import com.github.rvesse.airline.annotations.Command;
-import org.apache.activemq.artemis.dto.BrokerDTO;
+import picocli.CommandLine;
-@Command(name = "kill", description = "Kill a broker started with --allow-kill.")
-public class Kill extends Configurable {
+public enum ConnectionProtocol {
+ AMQP("AMQP"), CORE("CORE");
- @Override
- public Object execute(ActionContext context) throws Exception {
- super.execute(context);
- BrokerDTO broker = getBrokerDTO();
+ private final String name;
- File file = broker.server.getConfigurationFile().getParentFile();
+ ConnectionProtocol(String name) {
+ this.name = name;
+ }
- File killFile = new File(file, "KILL_ME");
+ @Override
+ public String toString() {
+ return name;
+ }
- killFile.createNewFile();
+ public static ConnectionProtocol fromString(String value) {
+ return ConnectionProtocol.valueOf(value.toUpperCase());
+ }
- return null;
+ public static class ProtocolConverter implements CommandLine.ITypeConverter<ConnectionProtocol> {
+ @Override
+ public ConnectionProtocol convert(String value) throws Exception {
+ return ConnectionProtocol.fromString(value);
+ }
}
}
+
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Consumer.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Consumer.java
index fa7dd1854b..e137d04165 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Consumer.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Consumer.java
@@ -26,27 +26,27 @@ import javax.jms.Session;
import java.io.FileOutputStream;
import java.io.OutputStream;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.factory.serialize.MessageSerializer;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "consumer", description = "Consume messages from a queue.")
public class Consumer extends DestAbstract {
- @Option(name = "--durable", description = "Whether the consumer's subscription will be durable.")
+ @Option(names = "--durable", description = "Whether the consumer's subscription will be durable.")
boolean durable = false;
- @Option(name = "--break-on-null", description = "Stop consuming when a null message is received.")
+ @Option(names = "--break-on-null", description = "Stop consuming when a null message is received.")
boolean breakOnNull = false;
- @Option(name = "--receive-timeout", description = "Timeout for receiving messages (in milliseconds).")
+ @Option(names = "--receive-timeout", description = "Timeout for receiving messages (in milliseconds).")
int receiveTimeout = 3000;
- @Option(name = "--filter", description = "The message filter.")
+ @Option(names = "--filter", description = "The message filter.")
String filter;
- @Option(name = "--data", description = "Serialize the messages to the specified file as they are consumed.")
+ @Option(names = "--data", description = "Serialize the messages to the specified file as they are consumed.")
String file;
@Override
@@ -111,7 +111,7 @@ public class Consumer extends DestAbstract {
connection.start();
- int received = 0;
+ long received = 0;
for (ConsumerThread thread : threadsArray) {
thread.join();
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConsumerThread.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConsumerThread.java
index f80a628bdd..f2bee77ba4 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConsumerThread.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ConsumerThread.java
@@ -33,7 +33,7 @@ import java.util.concurrent.CountDownLatch;
public class ConsumerThread extends Thread {
- int messageCount = 1000;
+ long messageCount = 1000;
int receiveTimeOut = 3000;
Destination destination;
Session session;
@@ -259,7 +259,7 @@ public class ConsumerThread extends Thread {
return this;
}
- public ConsumerThread setMessageCount(int messageCount) {
+ public ConsumerThread setMessageCount(long messageCount) {
this.messageCount = messageCount;
return this;
}
@@ -278,7 +278,7 @@ public class ConsumerThread extends Thread {
return this;
}
- public int getMessageCount() {
+ public long getMessageCount() {
return messageCount;
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/DestAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/DestAbstract.java
index e50cef6834..7ded6ecb77 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/DestAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/DestAbstract.java
@@ -21,29 +21,33 @@ import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Session;
-import com.github.rvesse.airline.annotations.Option;
+import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.factory.serialize.MessageSerializer;
import org.apache.activemq.artemis.cli.factory.serialize.XMLMessageSerializer;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
+import picocli.CommandLine.Option;
public class DestAbstract extends ConnectionAbstract {
- @Option(name = "--destination", description = "Destination to be used. It can be prefixed with queue:// or topic:// and can be an FQQN in the form of <address>::<queue>. Default: queue://TEST.")
+ @Option(names = "--destination", description = "Destination to be used. It can be prefixed with queue:// or topic:// and can be an FQQN in the form of <address>::<queue>. Default: queue://TEST.")
String destination = "queue://TEST";
- @Option(name = "--message-count", description = "Number of messages to act on. Default: 1000.")
- int messageCount = 1000;
+ @Option(names = "--message-count", description = "Number of messages to act on. Default: 1000.")
+ long messageCount = 1000;
- @Option(name = "--sleep", description = "Time wait between each message.")
+ @Option(names = "--sleep", description = "Time wait between each message.")
int sleep = 0;
- @Option(name = "--txt-size", description = "Transaction batch size.")
- int txBatchSize;
+ @Option(names = {"--txt-size"}, description = "Transaction batch size. (deprecated)", hidden = true)
+ int oldBatchSize;
- @Option(name = "--threads", description = "Number of threads to use. Default: 1.")
+ @Option(names = {"--commit-interval"}, description = "Transaction batch size.")
+ protected int txBatchSize;
+
+ @Option(names = "--threads", description = "Number of threads to use. Default: 1.")
int threads = 1;
- @Option(name = "--serializer", description = "The class name of the custom serializer implementation to use intead of the default.")
+ @Option(names = "--serializer", description = "The class name of the custom serializer implementation to use intead of the default.")
String serializer;
protected MessageSerializer getMessageSerializer() {
@@ -56,7 +60,7 @@ public class DestAbstract extends ConnectionAbstract {
}
}
- if (!protocol.equalsIgnoreCase("CORE")) {
+ if (protocol != ConnectionProtocol.CORE) {
System.err.println("Default Serializer does not support: " + protocol + " protocol");
return null;
}
@@ -93,7 +97,7 @@ public class DestAbstract extends ConnectionAbstract {
return this;
}
- public int getMessageCount() {
+ public long getMessageCount() {
return messageCount;
}
@@ -137,4 +141,16 @@ public class DestAbstract extends ConnectionAbstract {
this.serializer = serializer;
return this;
}
+
+ @Override
+ public Object execute(ActionContext context) throws Exception {
+ super.execute(context);
+
+ if (oldBatchSize > 0) {
+ context.out.println("--txt-size is deprecated, please use --commit-interval");
+ txBatchSize = oldBatchSize;
+ }
+
+ return null;
+ }
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Producer.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Producer.java
index eed6f5ef24..20235f7e0c 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Producer.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Producer.java
@@ -27,38 +27,38 @@ import javax.jms.Session;
import java.io.FileInputStream;
import java.io.InputStream;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.factory.serialize.MessageSerializer;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "producer", description = "Send message(s) to a broker.")
public class Producer extends DestAbstract {
public static final String DEMO_TEXT = "demo.txt";
- @Option(name = "--non-persistent", description = "Send messages non persistently.")
+ @Option(names = "--non-persistent", description = "Send messages non persistently.")
boolean nonpersistent = false;
- @Option(name = "--message-size", description = "Size of each bytesMessage. The producer will use JMS BytesMessage.")
+ @Option(names = "--message-size", description = "Size of each bytesMessage. The producer will use JMS BytesMessage.")
int messageSize = 0;
- @Option(name = "--message", description = "Content of each textMessage. The producer will use JMS TextMessage.")
+ @Option(names = "--message", description = "Content of each textMessage. The producer will use JMS TextMessage.")
String message = null;
- @Option(name = "--text-size", description = "Size of each textMessage. The producer will use JMS TextMessage.")
+ @Option(names = "--text-size", description = "Size of each textMessage. The producer will use JMS TextMessage.")
int textMessageSize;
- @Option(name = "--object-size", description = "Size of each ObjectMessage. The producer will use JMS ObjectMessage.")
+ @Option(names = "--object-size", description = "Size of each ObjectMessage. The producer will use JMS ObjectMessage.")
int objectSize;
- @Option(name = "--msgttl", description = "TTL for each message.")
+ @Option(names = "--msgttl", description = "TTL for each message.")
long msgTTL = 0L;
- @Option(name = "--group", description = "Message Group to be used.")
+ @Option(names = "--group", description = "Message Group to be used.")
String msgGroupID = null;
- @Option(name = "--data", description = "Messages will be read from the specified file. Other message options will be ignored.")
+ @Option(names = "--data", description = "Messages will be read from the specified file. Other message options will be ignored.")
String file = null;
public boolean isNonpersistent() {
@@ -216,7 +216,7 @@ public class Producer extends DestAbstract {
thread.start();
}
- int messagesProduced = 0;
+ long messagesProduced = 0;
for (ProducerThread thread : threadsArray) {
thread.join();
messagesProduced += thread.getSentCount();
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ProducerThread.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ProducerThread.java
index 19fbba9a09..efff71af67 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ProducerThread.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/ProducerThread.java
@@ -28,7 +28,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.activemq.artemis.utils.ReusableLatch;
@@ -37,7 +37,7 @@ public class ProducerThread extends Thread {
protected final Session session;
boolean verbose;
- int messageCount = 1000;
+ long messageCount = 1000;
boolean runIndefinitely = false;
Destination destination;
int sleep = 0;
@@ -50,7 +50,7 @@ public class ProducerThread extends Thread {
int transactionBatchSize;
int transactions = 0;
- final AtomicInteger sentCount = new AtomicInteger(0);
+ final AtomicLong sentCount = new AtomicLong(0);
String message = null;
String messageText = null;
String payloadUrl = null;
@@ -146,7 +146,7 @@ public class ProducerThread extends Thread {
}
}
- protected Message createMessage(int i, String threadName) throws Exception {
+ protected Message createMessage(long i, String threadName) throws Exception {
Message answer;
if (payload != null) {
answer = session.createBytesMessage();
@@ -188,12 +188,12 @@ public class ProducerThread extends Thread {
answer.setStringProperty("JMSXGroupID", msgGroupID);
}
- answer.setIntProperty("count", i);
+ answer.setLongProperty("count", i);
answer.setStringProperty("ThreadSent", threadName);
return answer;
}
- private String readInputStream(InputStream is, int size, int messageNumber) throws IOException {
+ private String readInputStream(InputStream is, int size, long messageNumber) throws IOException {
try (InputStreamReader reader = new InputStreamReader(is)) {
char[] buffer;
if (size > 0) {
@@ -214,11 +214,11 @@ public class ProducerThread extends Thread {
}
}
- private String createDefaultMessage(int messageNumber) {
+ private String createDefaultMessage(long messageNumber) {
return "test message: " + messageNumber;
}
- public ProducerThread setMessageCount(int messageCount) {
+ public ProducerThread setMessageCount(long messageCount) {
this.messageCount = messageCount;
return this;
}
@@ -232,11 +232,11 @@ public class ProducerThread extends Thread {
return this;
}
- public int getMessageCount() {
+ public long getMessageCount() {
return messageCount;
}
- public int getSentCount() {
+ public long getSentCount() {
return sentCount.get();
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Transfer.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Transfer.java
index 8674b3e9ba..abb1bf6e2a 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Transfer.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Transfer.java
@@ -28,84 +28,84 @@ import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.Topic;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.InputAbstract;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.qpid.jms.JmsConnectionFactory;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "transfer", description = "Move messages from one destination towards another destination.")
public class Transfer extends InputAbstract {
- @Option(name = "--source-url", description = "URL for the source broker. Default: build URL from 'artemis' acceptor defined in the broker.xml or tcp://localhost:61616 if the default cannot be parsed.")
+ @Option(names = "--source-url", description = "URL for the source broker. Default: build URL from 'artemis' acceptor defined in the broker.xml or tcp://localhost:61616 if the default cannot be parsed.")
protected String sourceURL = DEFAULT_BROKER_URL;
- @Option(name = "--source-acceptor", description = "Acceptor used to build URL towards the broker. Default: 'artemis'.")
+ @Option(names = "--source-acceptor", description = "Acceptor used to build URL towards the broker. Default: 'artemis'.")
protected String sourceAcceptor = DEFAULT_BROKER_ACCEPTOR;
- @Option(name = "--source-user", description = "User used to connect to source broker.")
+ @Option(names = "--source-user", description = "User used to connect to source broker.")
protected String sourceUser;
- @Option(name = "--source-password", description = "Password used to connect to source broker.")
+ @Option(names = "--source-password", description = "Password used to connect to source broker.")
protected String sourcePassword;
- @Option(name = "--target-url", description = "URL for the target broker. Default: build URL from 'artemis' acceptor defined in the broker.xml or tcp://localhost:61616 if the default cannot be parsed.")
+ @Option(names = "--target-url", description = "URL for the target broker. Default: build URL from 'artemis' acceptor defined in the broker.xml or tcp://localhost:61616 if the default cannot be parsed.")
protected String targetURL = DEFAULT_BROKER_URL;
- @Option(name = "--target-user", description = "User used to connect to target broker.")
+ @Option(names = "--target-user", description = "User used to connect to target broker.")
protected String targetUser;
- @Option(name = "--target-password", description = "Password used to connect to target broker.")
+ @Option(names = "--target-password", description = "Password used to connect to target broker.")
protected String targetPassword;
- @Option(name = "--receive-timeout", description = "Amount of time (in milliseconds) to wait before giving up the receiving loop; 0 means no wait, -1 means wait forever. Default: 5000.")
+ @Option(names = "--receive-timeout", description = "Amount of time (in milliseconds) to wait before giving up the receiving loop; 0 means no wait, -1 means wait forever. Default: 5000.")
int receiveTimeout = 5000;
- @Option(name = "--source-client-id", description = "ClientID to be associated with source connection.")
+ @Option(names = "--source-client-id", description = "ClientID to be associated with source connection.")
String sourceClientID;
- @Option(name = "--source-protocol", description = "Protocol used. Valid values are amqp or core. Default: core.")
+ @Option(names = "--source-protocol", description = "Protocol used. Valid values are amqp or core. Default: core.")
String sourceProtocol = "core";
- @Option(name = "--source-queue", description = "Source JMS queue to be used. Cannot be set with --source-topic.")
+ @Option(names = "--source-queue", description = "Source JMS queue to be used. Cannot be set with --source-topic.")
String sourceQueue;
- @Option(name = "--shared-durable-subscription", description = "Name of a shared subscription name to be used on the source topic.")
+ @Option(names = "--shared-durable-subscription", description = "Name of a shared subscription name to be used on the source topic.")
String sharedDurableSubscription;
- @Option(name = "--shared-subscription", description = "Name of a shared subscription name to be used on the source topic.")
+ @Option(names = "--shared-subscription", description = "Name of a shared subscription name to be used on the source topic.")
String sharedSubscription;
- @Option(name = "--durable-consumer", description = "Name of a durable consumer to be used on the source topic.")
+ @Option(names = "--durable-consumer", description = "Name of a durable consumer to be used on the source topic.")
String durableConsumer;
- @Option(name = "--no-Local", description = "Use noLocal when applicable on topic operation")
+ @Option(names = "--no-Local", description = "Use noLocal when applicable on topic operation")
boolean noLocal;
- @Option(name = "--source-topic", description = "Source JMS topic to be used. Cannot bet set with --source-queue.")
+ @Option(names = "--source-topic", description = "Source JMS topic to be used. Cannot bet set with --source-queue.")
String sourceTopic;
- @Option(name = "--source-filter", description = "Filter to be used with the source consumer.")
+ @Option(names = "--source-filter", description = "Filter to be used with the source consumer.")
String filter;
- @Option(name = "--target-protocol", description = "Protocol used. Valid values are amqp or core. Default: core.")
+ @Option(names = "--target-protocol", description = "Protocol used. Valid values are amqp or core. Default: core.")
String targetProtocol = "core";
- @Option(name = "--commit-interval", description = "Transaction batch interval.")
+ @Option(names = {"--commit-interval"}, description = "Transaction batch size.")
int commitInterval = 1000;
- @Option(name = "--copy", description = "If this option is chosen we will perform a copy by rolling back the original transaction on the source.")
+ @Option(names = "--copy", description = "If this option is chosen we will perform a copy by rolling back the original transaction on the source.")
boolean copy;
- @Option(name = "--target-queue", description = "Target JMS queue to be used. Cannot be set with --target-topic.")
+ @Option(names = "--target-queue", description = "Target JMS queue to be used. Cannot be set with --target-topic.")
String targetQueue;
- @Option(name = "--target-topic", description = "Target JMS topic to be used. Cannot bet set with --target-queue.")
+ @Option(names = "--target-topic", description = "Target JMS topic to be used. Cannot bet set with --target-queue.")
String targetTopic;
- @Option(name = "--message-count", description = "Number of messages to transfer.")
+ @Option(names = "--message-count", description = "Number of messages to transfer.")
int messageCount = Integer.MAX_VALUE;
public String getSourceURL() {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfClientCommand.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfClientCommand.java
index e258f52be8..ca98a63dc7 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfClientCommand.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfClientCommand.java
@@ -25,79 +25,77 @@ import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import io.netty.channel.DefaultEventLoop;
import io.netty.channel.DefaultEventLoopGroup;
import io.netty.channel.EventLoop;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import org.apache.activemq.artemis.cli.commands.messages.ConnectionProtocol;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "client", description = "Produce messages to and consume messages from a broker instance.")
public class PerfClientCommand extends PerfCommand {
- @Option(name = "--tx", description = "Perform Message::acknowledge per each message received. Default: disabled.")
+ @Option(names = "--tx", description = "Perform Message::acknowledge per each message received. Default: disabled.")
protected boolean transaction;
- @Option(name = "--shared", description = "Create a shared subscription. Default: 0.")
+ @Option(names = "--shared", description = "Create a shared subscription. Default: 0.")
protected int sharedSubscription = 0;
- @Option(name = "--durable", description = "Enabled durable subscription. Default: disabled.")
+ @Option(names = "--durable", description = "Enabled durable subscription. Default: disabled.")
protected boolean durableSubscription = false;
- @Option(name = "--consumer-connections", description = "Number of consumer connections to be used. Default: same as the total number of consumers")
+ @Option(names = "--consumer-connections", description = "Number of consumer connections to be used. Default: same as the total number of consumers")
protected int consumerConnections = 0;
- @Option(name = "--consumers", description = "Number of consumer to use for each generated destination. Default: 1.")
+ @Option(names = "--consumers", description = "Number of consumer to use for each generated destination. Default: 1.")
protected int consumersPerDestination = 1;
- @Option(name = "--persistent", description = "Send messages persistently. Default: non persistent")
+ @Option(names = "--persistent", description = "Send messages persistently. Default: non persistent")
protected boolean persistent = false;
- @Option(name = "--message-size", description = "Size of each bytesMessage. Default: is 1024.")
+ @Option(names = "--message-size", description = "Size of each bytesMessage. Default: is 1024.")
protected int messageSize = 1024;
- @Option(name = "--rate", description = "Expected total message rate. Default: unbounded.")
+ @Option(names = "--rate", description = "Expected total message rate. Default: unbounded.")
protected Long rate = null;
- @Option(name = "--ttl", description = "TTL for each message.")
+ @Option(names = "--ttl", description = "TTL for each message.")
protected long ttl = 0L;
- @Option(name = "--group", description = "Message Group to be used.")
+ @Option(names = "--group", description = "Message Group to be used.")
protected String msgGroupID = null;
- @Option(name = "--shared-connections", description = "Create --threads shared connections among producers. Default: not shared.")
+ @Option(names = "--shared-connections", description = "Create --threads shared connections among producers. Default: not shared.")
protected boolean sharedConnections = false;
- @Option(name = "--tx-size", description = "Transaction size.")
- protected long txSize;
-
- @Option(name = "--producers", description = "Number of producers to use for each generated destination. Default: 1")
+ @Option(names = "--producers", description = "Number of producers to use for each generated destination. Default: 1")
protected int producersPerDestination = 1;
- @Option(name = "--threads", description = "Number of worker threads to schedule producer load tasks. Default: 1.")
+ @Option(names = "--threads", description = "Number of worker threads to schedule producer load tasks. Default: 1.")
protected int threads = 1;
- @Option(name = "--max-pending", description = "How many not yet completed messages can exists. Default: 1.")
+ @Option(names = "--max-pending", description = "How many not yet completed messages can exists. Default: 1.")
protected long maxPending = 1;
- @Option(name = "--consumer-url", description = "The url used for MessageListener(s) connections. Default: same as --url.")
+ @Option(names = "--consumer-url", description = "The url used for MessageListener(s) connections. Default: same as --url.")
protected String consumerUrl = null;
- @Option(name = "--consumer-protocol", description = "The protocol used for MessageListener(s) connections. Default: same as --protocol.")
- protected String consumerProtocol = null;
+ @Option(names = "--consumer-protocol", description = "The protocol used for MessageListener(s) connections. Default: same as --protocol. Valid values are ${COMPLETION-CANDIDATES}", converter = ConnectionProtocol.ProtocolConverter.class)
+ protected ConnectionProtocol consumerProtocol = null;
- @Option(name = "--enable-msg-id", description = "Set JMS messageID per-message. Default: disabled.")
+ @Option(names = "--enable-msg-id", description = "Set JMS messageID per-message. Default: disabled.")
protected boolean enableMessageID;
- @Option(name = "--enable-timestamp", description = "Set JMS timestamp per-message. Default: disabled.")
+ @Option(names = "--enable-timestamp", description = "Set JMS timestamp per-message. Default: disabled.")
protected boolean enableTimestamp;
private volatile BenchmarkService producerBenchmark;
@Override
protected void onExecuteBenchmark(final ConnectionFactory producerConnectionFactory, final Destination[] jmsDestinations, final ActionContext context) throws Exception {
- final String listenerProtocol = this.consumerProtocol != null ? this.consumerProtocol : getProtocol();
+ final ConnectionProtocol listenerProtocol = this.consumerProtocol != null ? this.consumerProtocol : protocol;
final String listenerUrl = this.consumerUrl != null ? this.consumerUrl : brokerURL;
final ConnectionFactory consumerConnectionFactory = createConnectionFactory(listenerUrl, user, password, null, listenerProtocol);
if (consumerConnections == 0) {
@@ -152,7 +150,7 @@ public class PerfClientCommand extends PerfCommand {
.setDestinations(jmsDestinations)
.setFactory(producerConnectionFactory)
.setTtl(ttl)
- .setTransactionCapacity(txSize)
+ .setTransactionCapacity(commitInterval)
.setGroup(msgGroupID)
.setProducers(producersPerDestination)
.setMessageRate(rate)
@@ -316,15 +314,6 @@ public class PerfClientCommand extends PerfCommand {
return this;
}
- public long getTxSize() {
- return txSize;
- }
-
- public PerfClientCommand setTxSize(long txSize) {
- this.txSize = txSize;
- return this;
- }
-
public int getProducersPerDestination() {
return producersPerDestination;
}
@@ -362,11 +351,11 @@ public class PerfClientCommand extends PerfCommand {
}
public String getConsumerProtocol() {
- return consumerProtocol;
+ return consumerProtocol.toString();
}
public PerfClientCommand setConsumerProtocol(String consumerProtocol) {
- this.consumerProtocol = consumerProtocol;
+ this.consumerProtocol = ConnectionProtocol.fromString(consumerProtocol);
return this;
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfCommand.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfCommand.java
index 2aa4f84fa1..a8f3011dd1 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfCommand.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfCommand.java
@@ -26,38 +26,44 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
-import com.github.rvesse.airline.annotations.Arguments;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
import org.apache.activemq.artemis.cli.commands.messages.DestAbstract;
+import picocli.CommandLine.Option;
+import picocli.CommandLine.Parameters;
import static java.util.Collections.singletonList;
public abstract class PerfCommand extends ConnectionAbstract {
- @Option(name = "--show-latency", description = "Show latencies at interval on output. Default: disabled.")
+ @Option(names = "--show-latency", description = "Show latencies at interval on output. Default: disabled.")
protected boolean showLatency = false;
- @Option(name = "--json", description = "Report file name. Default: none.")
+ @Option(names = "--json", description = "Report file name. Default: none.")
protected String reportFileName = null;
- @Option(name = "--hdr", description = "HDR Histogram Report file name. Default: none.")
+ @Option(names = "--hdr", description = "HDR Histogram Report file name. Default: none.")
protected String hdrFileName = null;
- @Option(name = "--duration", description = "Test duration (in seconds). Default: 0.")
+ @Option(names = "--duration", description = "Test duration (in seconds). Default: 0.")
protected int duration = 0;
- @Option(name = "--warmup", description = "Warmup time (in seconds). Default: 0.")
+ @Option(names = "--warmup", description = "Warmup time (in seconds). Default: 0.")
protected int warmup = 0;
- @Option(name = "--message-count", description = "Total number of messages. Default: 0.")
+ @Option(names = "--message-count", description = "Total number of messages. Default: 0.")
protected long messageCount = 0;
- @Option(name = "--num-destinations", description = "If present, generate --num-destinations for each destination name, using it as a prefix and adding a number [0,--num-destinations) as suffix. Default: none.")
+ @Option(names = "--num-destinations", description = "If present, generate --num-destinations for each destination name, using it as a prefix and adding a number [0,--num-destinations) as suffix. Default: none.")
protected int numDestinations = 1;
- @Arguments(description = "List of destination names. Each name can be prefixed with queue:// or topic:// and can be an FQQN in the form of <address>::<queue>. Default: queue://TEST.")
+ @Option(names = "--tx-size", description = "Transaction size.", hidden = true)
+ protected long txSize;
+
+ @Option(names = "--commit-interval", description = "Transaction size.")
+ protected long commitInterval;
+
+ @Parameters(description = "List of destination names. Each name can be prefixed with queue:// or topic:// and can be an FQQN in the form of <address>::<queue>. Default: queue://TEST.")
protected List<String> destinations;
private final CountDownLatch completed = new CountDownLatch(1);
@@ -65,7 +71,11 @@ public abstract class PerfCommand extends ConnectionAbstract {
@Override
public Object execute(ActionContext context) throws Exception {
super.execute(context);
- final ConnectionFactory factory = createConnectionFactory(brokerURL, user, password, null, getProtocol());
+ if (txSize > 0) {
+ System.out.println("--tx-size is deprecated, please use --commit-interval");
+ commitInterval = txSize;
+ }
+ final ConnectionFactory factory = createConnectionFactory(brokerURL, user, password, null, protocol);
final Destination[] jmsDestinations = lookupDestinations(factory, destinations, numDestinations);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
onInterruptBenchmark();
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfConsumerCommand.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfConsumerCommand.java
index 5b307b738a..1465306105 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfConsumerCommand.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfConsumerCommand.java
@@ -21,26 +21,26 @@ import javax.jms.Destination;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "consumer", description = "Consume messages from a queue.")
public class PerfConsumerCommand extends PerfCommand {
- @Option(name = "--tx", description = "Individually acknowledge each message received. Default: disabled.")
+ @Option(names = "--tx", description = "Individually acknowledge each message received. Default: disabled.")
protected boolean transaction;
- @Option(name = "--shared", description = "Create shared subscription. Default: 0.")
+ @Option(names = "--shared", description = "Create shared subscription. Default: 0.")
protected int sharedSubscription = 0;
- @Option(name = "--durable", description = "Enabled durable subscription. Default: disabled.")
+ @Option(names = "--durable", description = "Enabled durable subscription. Default: disabled.")
protected boolean durableSubscription = false;
- @Option(name = "--num-connections", description = "Number of connections to be used. Default: same as the total number of consumers.")
+ @Option(names = "--num-connections", description = "Number of connections to be used. Default: same as the total number of consumers.")
protected int connections = 0;
- @Option(name = "--consumers", description = "Number of consumer to use for each generated destination. Default: 1.")
+ @Option(names = "--consumers", description = "Number of consumer to use for each generated destination. Default: 1.")
protected int consumersPerDestination = 1;
private BenchmarkService benchmark;
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfGroup.java
similarity index 57%
copy from artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
copy to artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfGroup.java
index e34e376deb..31326a8740 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfGroup.java
@@ -14,28 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
+package org.apache.activemq.artemis.cli.commands.messages.perf;
-import com.github.rvesse.airline.annotations.Command;
-import org.apache.activemq.artemis.dto.BrokerDTO;
+import org.apache.activemq.artemis.cli.commands.HelpAction;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
-@Command(name = "kill", description = "Kill a broker started with --allow-kill.")
-public class Kill extends Configurable {
+@Command(name = "perf", description = "use 'help perf' for sub commands list", subcommands = {PerfClientCommand.class, PerfProducerCommand.class, PerfConsumerCommand.class})
+public class PerfGroup implements Runnable {
- @Override
- public Object execute(ActionContext context) throws Exception {
- super.execute(context);
-
- BrokerDTO broker = getBrokerDTO();
-
- File file = broker.server.getConfigurationFile().getParentFile();
-
- File killFile = new File(file, "KILL_ME");
+ CommandLine commandLine;
- killFile.createNewFile();
+ public PerfGroup(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ }
- return null;
+ @Override
+ public void run() {
+ HelpAction.help(commandLine, "perf");
}
+
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfProducerCommand.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfProducerCommand.java
index 4440ef5f8f..0e8d58464f 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfProducerCommand.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/perf/PerfProducerCommand.java
@@ -25,49 +25,46 @@ import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import io.netty.channel.DefaultEventLoop;
import io.netty.channel.DefaultEventLoopGroup;
import io.netty.channel.EventLoop;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "producer", description = "Send messages to a broker.")
public class PerfProducerCommand extends PerfCommand {
- @Option(name = "--persistent", description = "Send messages persistently. Default: non persistent.")
+ @Option(names = "--persistent", description = "Send messages persistently. Default: non persistent.")
protected boolean persistent = false;
- @Option(name = "--message-size", description = "Size of each bytesMessage. Default: 1024.")
+ @Option(names = "--message-size", description = "Size of each bytesMessage. Default: 1024.")
protected int messageSize = 1024;
- @Option(name = "--rate", description = "Expected total message rate. Default: unbounded.")
+ @Option(names = "--rate", description = "Expected total message rate. Default: unbounded.")
protected Long rate = null;
- @Option(name = "--ttl", description = "TTL for each message.")
+ @Option(names = "--ttl", description = "TTL for each message.")
protected long ttl = 0L;
- @Option(name = "--group", description = "Message Group to be used.")
+ @Option(names = "--group", description = "Message Group to be used.")
protected String msgGroupID = null;
- @Option(name = "--shared-connections", description = "Create --threads shared connections among producers. Default: not shared.")
+ @Option(names = "--shared-connections", description = "Create --threads shared connections among producers. Default: not shared.")
protected boolean sharedConnections = false;
- @Option(name = "--tx-size", description = "Transaction size.")
- protected long txSize;
-
- @Option(name = "--producers", description = "Number of producers to use for each generated destination. Default: 1.")
+ @Option(names = "--producers", description = "Number of producers to use for each generated destination. Default: 1.")
protected int producersPerDestination = 1;
- @Option(name = "--threads", description = "Number of worker threads to schedule producer load tasks. Default: 1.")
+ @Option(names = "--threads", description = "Number of worker threads to schedule producer load tasks. Default: 1.")
protected int threads = 1;
- @Option(name = "--max-pending", description = "How many not yet completed messages can exists. Default is 1.")
+ @Option(names = "--max-pending", description = "How many not yet completed messages can exists. Default is 1.")
protected long maxPending = 1;
- @Option(name = "--enable-msg-id", description = "Enable setting JMS messageID per-message. Default: disabled.")
+ @Option(names = "--enable-msg-id", description = "Enable setting JMS messageID per-message. Default: disabled.")
protected boolean enableMessageID;
- @Option(name = "--enable-timestamp", description = "Enable setting JMS timestamp per-message. Default: disabled.")
+ @Option(names = "--enable-timestamp", description = "Enable setting JMS timestamp per-message. Default: disabled.")
protected boolean enableTimestamp;
protected volatile BenchmarkService benchmark;
@@ -114,7 +111,7 @@ public class PerfProducerCommand extends PerfCommand {
.setDestinations(jmsDestinations)
.setFactory(factory)
.setTtl(ttl)
- .setTransactionCapacity(txSize)
+ .setTransactionCapacity(commitInterval)
.setGroup(msgGroupID)
.setProducers(producersPerDestination)
.setMessageRate(rate)
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/CreateQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/CreateQueue.java
index a015b1f317..29e4a86dfd 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/CreateQueue.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/CreateQueue.java
@@ -17,9 +17,9 @@
package org.apache.activemq.artemis.cli.commands.queue;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
@Command(name = "create", description = "Create a queue.")
public class CreateQueue extends QueueAbstract {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/DeleteQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/DeleteQueue.java
index 38e994d7d1..3e90f2592a 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/DeleteQueue.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/DeleteQueue.java
@@ -17,22 +17,22 @@
package org.apache.activemq.artemis.cli.commands.queue;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "delete", description = "Delete a queue.")
public class DeleteQueue extends ConnectionAbstract {
- @Option(name = "--name", description = "The queue's name")
+ @Option(names = "--name", description = "The queue's name")
String name;
- @Option(name = "--removeConsumers", description = "Whether to delete the queue even if it has active consumers. Default: false.")
+ @Option(names = "--removeConsumers", description = "Whether to delete the queue even if it has active consumers. Default: false.")
boolean removeConsumers = false;
- @Option(name = "--autoDeleteAddress", description = "Whether to delete the address if this is its only queue.")
+ @Option(names = "--autoDeleteAddress", description = "Whether to delete the address if this is its only queue.")
boolean autoDeleteAddress = false;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/HelpQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/HelpQueue.java
deleted file mode 100644
index f353bc7f88..0000000000
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/HelpQueue.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli.commands.queue;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.github.rvesse.airline.help.Help;
-import org.apache.activemq.artemis.cli.commands.Action;
-import org.apache.activemq.artemis.cli.commands.ActionContext;
-import org.apache.activemq.artemis.cli.commands.InvalidOptionsError;
-import org.apache.activemq.artemis.cli.commands.OptionsUtil;
-
-public class HelpQueue extends Help implements Action {
-
- @Override
- public boolean isVerbose() {
- return false;
- }
-
- @Override
- public void setHomeValues(File brokerHome, File brokerInstance, File etc) {
- }
-
- @Override
- public String getBrokerInstance() {
- return null;
- }
-
- @Override
- public String getBrokerHome() {
- return null;
- }
-
- @Override
- public void checkOptions(String[] options) throws InvalidOptionsError {
- OptionsUtil.checkCommandOptions(this.getClass(), options);
- }
-
- @Override
- public Object execute(ActionContext context) throws Exception {
- List<String> commands = new ArrayList<>(1);
- commands.add("queue");
- help(global, commands);
- return null;
- }
-}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/PurgeQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/PurgeQueue.java
index 09d217da3d..31e6fb9920 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/PurgeQueue.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/PurgeQueue.java
@@ -17,17 +17,17 @@
package org.apache.activemq.artemis.cli.commands.queue;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.api.core.management.ResourceNames;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "purge", description = "Delete all messages in a queue.")
public class PurgeQueue extends ConnectionAbstract {
- @Option(name = "--name", description = "The queue's name.")
+ @Option(names = "--name", description = "The queue's name.")
String name;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueAbstract.java
index 69bb869b4a..5fb757d90b 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueAbstract.java
@@ -16,42 +16,42 @@
*/
package org.apache.activemq.artemis.cli.commands.queue;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
+import picocli.CommandLine.Option;
public class QueueAbstract extends ConnectionAbstract {
- @Option(name = "--name", description = "The queue's name.")
+ @Option(names = "--name", description = "The queue's name.")
private String name;
- @Option(name = "--filter", description = "The queue's filter string. Default: null.")
+ @Option(names = "--filter", description = "The queue's filter string. Default: null.")
private String filter = null;
- @Option(name = "--address", description = "The queue's address. Default: queue's name.")
+ @Option(names = "--address", description = "The queue's address. Default: queue's name.")
private String address;
- @Option(name = "--durable", description = "The queue is durable. Default: input.")
+ @Option(names = "--durable", description = "The queue is durable. Default: input.")
private Boolean durable;
- @Option(name = "--no-durable", description = "The queue is not durable. Default: input.")
+ @Option(names = "--no-durable", description = "The queue is not durable. Default: input.")
private Boolean noDurable;
- @Option(name = "--purge-on-no-consumers", description = "Delete the contents of this queue when its last consumer disconnects. Default: input.")
+ @Option(names = "--purge-on-no-consumers", description = "Delete the contents of this queue when its last consumer disconnects. Default: input.")
private Boolean purgeOnNoConsumers;
- @Option(name = "--preserve-on-no-consumers", description = "Preserve the contents of this queue when its last consumer disconnects. Default: input.")
+ @Option(names = "--preserve-on-no-consumers", description = "Preserve the contents of this queue when its last consumer disconnects. Default: input.")
private Boolean preserveOnNoConsumers;
- @Option(name = "--max-consumers", description = "The maximum number of concurrent consumers allowed on this queue. Default: no limit.")
+ @Option(names = "--max-consumers", description = "The maximum number of concurrent consumers allowed on this queue. Default: no limit.")
private Integer maxConsumers;
- @Option(name = "--auto-create-address", description = "Automatically create the address (if it doesn't exist) with default values. Default: input.")
+ @Option(names = "--auto-create-address", description = "Automatically create the address (if it doesn't exist) with default values. Default: input.")
private Boolean autoCreateAddress;
- @Option(name = "--anycast", description = "Create an anycast queue. Default: input.")
+ @Option(names = "--anycast", description = "Create an anycast queue. Default: input.")
private Boolean anycast;
- @Option(name = "--multicast", description = "Create a multicast queue. Default: input.")
+ @Option(names = "--multicast", description = "Create a multicast queue. Default: input.")
private Boolean multicast;
public void setFilter(String filter) {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueGroup.java
similarity index 57%
copy from artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
copy to artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueGroup.java
index e34e376deb..92a55e0f49 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/QueueGroup.java
@@ -14,28 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
+package org.apache.activemq.artemis.cli.commands.queue;
-import com.github.rvesse.airline.annotations.Command;
-import org.apache.activemq.artemis.dto.BrokerDTO;
+import org.apache.activemq.artemis.cli.commands.HelpAction;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
-@Command(name = "kill", description = "Kill a broker started with --allow-kill.")
-public class Kill extends Configurable {
+@Command(name = "queue", description = "use 'help check' for sub commands list", subcommands = {CreateQueue.class, DeleteQueue.class, UpdateQueue.class, StatQueue.class, PurgeQueue.class})
+public class QueueGroup implements Runnable {
- @Override
- public Object execute(ActionContext context) throws Exception {
- super.execute(context);
-
- BrokerDTO broker = getBrokerDTO();
-
- File file = broker.server.getConfigurationFile().getParentFile();
-
- File killFile = new File(file, "KILL_ME");
+ CommandLine commandLine;
- killFile.createNewFile();
+ public QueueGroup(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ }
- return null;
+ @Override
+ public void run() {
+ HelpAction.help(commandLine, "queue");
}
+
}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java
index 17b2ed70ec..9a22631aa1 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/StatQueue.java
@@ -21,14 +21,14 @@ import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.JsonUtil;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
import org.apache.activemq.artemis.json.JsonArray;
import org.apache.activemq.artemis.json.JsonObject;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "stat", description = "Print basic stats of a queue. Output includes CONSUMER_COUNT (number of consumers), MESSAGE_COUNT (current message count on the queue, including scheduled, paged and in-delivery messages), MESSAGES_ADDED (messages added to the queue), DELIVERING_COUNT (messages broker is currently delivering to consumer(s)), MESSAGES_ACKED (messages acknowledged from the consumer(s))." + " Queues can be filtered using EITHER '--queueName X' where X is contained in t [...]
public class StatQueue extends ConnectionAbstract {
@@ -67,22 +67,22 @@ public class StatQueue extends ConnectionAbstract {
public static final int DEFAULT_MAX_COLUMN_SIZE = 25;
- @Option(name = "--queueName", description = "Display queue stats for queue(s) with names containing this string.")
+ @Option(names = "--queueName", description = "Display queue stats for queue(s) with names containing this string.")
private String queueName;
- @Option(name = "--field", description = "The field to filter. Possible values: NAME, ADDRESS, MESSAGE_COUNT, MESSAGES_ADDED, DELIVERING_COUNT, MESSAGES_ACKED, SCHEDULED_COUNT, ROUTING_TYPE.")
+ @Option(names = "--field", description = "The field to filter. Possible values: NAME, ADDRESS, MESSAGE_COUNT, MESSAGES_ADDED, DELIVERING_COUNT, MESSAGES_ACKED, SCHEDULED_COUNT, ROUTING_TYPE.")
private String fieldName;
- @Option(name = "--operation", description = "The operation to filter. Possible values: CONTAINS, NOT_CONTAINS, EQUALS, GREATER_THAN, LESS_THAN.")
+ @Option(names = "--operation", description = "The operation to filter. Possible values: CONTAINS, NOT_CONTAINS, EQUALS, GREATER_THAN, LESS_THAN.")
private String operationName;
- @Option(name = "--value", description = "The value to filter.")
+ @Option(names = "--value", description = "The value to filter.")
private String value;
- @Option(name = "--maxRows", description = "The max number of queues displayed. Default is 50.")
+ @Option(names = "--maxRows", description = "The max number of queues displayed. Default is 50.")
private int maxRows = DEFAULT_MAX_ROWS;
- @Option(name = "--maxColumnSize", description = "The max width of data column. Set to -1 for no limit. Default is 25.")
+ @Option(names = "--maxColumnSize", description = "The max width of data column. Set to -1 for no limit. Default is 25.")
private int maxColumnSize = DEFAULT_MAX_COLUMN_SIZE;
private int statCount = 0;
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/UpdateQueue.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/UpdateQueue.java
index 416fbc61cc..7adaa783c4 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/UpdateQueue.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/queue/UpdateQueue.java
@@ -16,9 +16,9 @@
*/
package org.apache.activemq.artemis.cli.commands.queue;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
@Command(name = "update", description = "Update a queue.")
public class UpdateQueue extends QueueAbstract {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DBOption.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DBOption.java
index e757a9592e..9cdea178c1 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DBOption.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DBOption.java
@@ -17,6 +17,7 @@
package org.apache.activemq.artemis.cli.commands.tools;
+import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.concurrent.ExecutorService;
@@ -25,7 +26,6 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.core.config.Configuration;
@@ -46,6 +46,7 @@ import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.actors.OrderedExecutorFactory;
import org.apache.activemq.artemis.utils.critical.EmptyCriticalAnalyzer;
+import picocli.CommandLine.Option;
public class DBOption extends OptionalLocking {
@@ -59,31 +60,35 @@ public class DBOption extends OptionalLocking {
protected ScheduledExecutorService scheduledExecutorService;
- @Option(name = "--output", description = "Output name for the file.")
- private String output;
+ @Option(names = "--output", description = "Output name for the file.")
+ private File output;
- @Option(name = "--jdbc", description = "Whether to store message data in JDBC instead of local files.")
+ private FileOutputStream fileOutputStream;
+
+ private PrintStream originalOut;
+
+ @Option(names = "--jdbc", description = "Whether to store message data in JDBC instead of local files.")
Boolean jdbc;
- @Option(name = "--jdbc-bindings-table-name", description = "Name of the jdbc bindings table.")
+ @Option(names = "--jdbc-bindings-table-name", description = "Name of the jdbc bindings table.")
private String jdbcBindings = ActiveMQDefaultConfiguration.getDefaultBindingsTableName();
- @Option(name = "--jdbc-message-table-name", description = "Name of the jdbc messages table.")
+ @Option(names = "--jdbc-message-table-name", description = "Name of the jdbc messages table.")
private String jdbcMessages = ActiveMQDefaultConfiguration.getDefaultMessageTableName();
- @Option(name = "--jdbc-large-message-table-name", description = "Name of the large messages table.")
+ @Option(names = "--jdbc-large-message-table-name", description = "Name of the large messages table.")
private String jdbcLargeMessages = ActiveMQDefaultConfiguration.getDefaultLargeMessagesTableName();
- @Option(name = "--jdbc-page-store-table-name", description = "Name of the page store messages table.")
+ @Option(names = "--jdbc-page-store-table-name", description = "Name of the page store messages table.")
private String jdbcPageStore = ActiveMQDefaultConfiguration.getDefaultPageStoreTableName();
- @Option(name = "--jdbc-node-manager-table-name", description = "Name of the jdbc node manager table.")
+ @Option(names = "--jdbc-node-manager-table-name", description = "Name of the jdbc node manager table.")
private String jdbcNodeManager = ActiveMQDefaultConfiguration.getDefaultNodeManagerStoreTableName();
- @Option(name = "--jdbc-connection-url", description = "The URL used for the database connection.")
+ @Option(names = "--jdbc-connection-url", description = "The URL used for the database connection.")
private String jdbcURL = null;
- @Option(name = "--jdbc-driver-class-name", description = "JDBC driver classname.")
+ @Option(names = "--jdbc-driver-class-name", description = "JDBC driver classname.")
private String jdbcClassName = ActiveMQDefaultConfiguration.getDefaultDriverClassName();
public boolean isJDBC() throws Exception {
@@ -167,15 +172,29 @@ public class DBOption extends OptionalLocking {
super.execute(context);
if (output != null) {
- FileOutputStream fileOutputStream = new FileOutputStream(output);
+ fileOutputStream = new FileOutputStream(output);
+ originalOut = context.out;
PrintStream printStream = new PrintStream(fileOutputStream);
context.out = printStream;
-
- Runtime.getRuntime().addShutdownHook(new Thread(printStream::close));
}
return null;
}
+ @Override
+ public void done() {
+ super.done();
+ if (fileOutputStream != null) {
+ try {
+ fileOutputStream.close();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ getActionContext().out = originalOut;
+ fileOutputStream = null;
+ originalOut = null;
+ }
+ }
+
private void parseDBConfig() throws Exception {
if (jdbc == null) {
FileConfiguration fileConfiguration = getFileConfiguration();
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataAbstract.java
index d3b2cb8a91..98c251c491 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataAbstract.java
@@ -19,24 +19,24 @@ package org.apache.activemq.artemis.cli.commands.tools;
import java.io.File;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.Configurable;
+import picocli.CommandLine.Option;
/**
* Abstract class for places where you need bindings, journal paging and large messages configuration
*/
public abstract class DataAbstract extends Configurable {
- @Option(name = "--bindings", description = "The folder used for bindings. Default: read from broker.xml.")
+ @Option(names = "--bindings", description = "The folder used for bindings. Default: read from broker.xml.")
public String binding;
- @Option(name = "--journal", description = "The folder used for normal messages. Default: read from broker.xml.")
+ @Option(names = "--journal", description = "The folder used for normal messages. Default: read from broker.xml.")
public String journal;
- @Option(name = "--paging", description = "The folder used for paged messages. Default: read from broker.xml.")
+ @Option(names = "--paging", description = "The folder used for paged messages. Default: read from broker.xml.")
public String paging;
- @Option(name = "--large-messages", description = "The folder used for large-messages. Default: read from broker.xml.")
+ @Option(names = "--large-messages", description = "The folder used for large-messages. Default: read from broker.xml.")
public String largeMessges;
public String getLargeMessages() throws Exception {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataGroup.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataGroup.java
new file mode 100644
index 0000000000..f1f077c5a8
--- /dev/null
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/DataGroup.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli.commands.tools;
+
+import org.apache.activemq.artemis.cli.commands.HelpAction;
+import org.apache.activemq.artemis.cli.commands.tools.journal.CompactJournal;
+import org.apache.activemq.artemis.cli.commands.tools.journal.DecodeJournal;
+import org.apache.activemq.artemis.cli.commands.tools.journal.EncodeJournal;
+import org.apache.activemq.artemis.cli.commands.tools.xml.XmlDataExporter;
+import org.apache.activemq.artemis.cli.commands.tools.xml.XmlDataImporter;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+
+@Command(name = "data", description = "use 'help data' for sub commands list", subcommands = {RecoverMessages.class, PrintData.class, XmlDataExporter.class, XmlDataImporter.class, DecodeJournal.class, EncodeJournal.class, CompactJournal.class})
+public class DataGroup implements Runnable {
+
+ CommandLine commandLine;
+
+ public DataGroup(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ }
+
+ @Override
+ public void run() {
+ HelpAction.help(commandLine, "data");
+ }
+
+}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/HelpData.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/HelpData.java
deleted file mode 100644
index 0598737b2f..0000000000
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/HelpData.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli.commands.tools;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.github.rvesse.airline.help.Help;
-import org.apache.activemq.artemis.cli.commands.Action;
-import org.apache.activemq.artemis.cli.commands.ActionContext;
-import org.apache.activemq.artemis.cli.commands.InvalidOptionsError;
-import org.apache.activemq.artemis.cli.commands.OptionsUtil;
-
-public class HelpData extends Help implements Action {
-
- @Override
- public boolean isVerbose() {
- return false;
- }
-
- @Override
- public void setHomeValues(File brokerHome, File brokerInstance, File etc) {
-
- }
-
- @Override
- public String getBrokerInstance() {
- return null;
- }
-
- @Override
- public String getBrokerHome() {
- return null;
- }
-
- @Override
- public Object execute(ActionContext context) throws Exception {
-
- List<String> commands = new ArrayList<>(1);
- commands.add("data");
- help(global, commands);
- return null;
- }
-
- @Override
- public void checkOptions(String[] options) throws InvalidOptionsError {
- OptionsUtil.checkCommandOptions(this.getClass(), options);
- }
-
-}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/LockAbstract.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/LockAbstract.java
index bef4e90fb4..88e9e8375b 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/LockAbstract.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/LockAbstract.java
@@ -60,6 +60,12 @@ public abstract class LockAbstract extends DataAbstract {
return null;
}
+ @Override
+ public void done() {
+ super.done();
+ unlock();
+ }
+
void lockCLI(File lockPlace) throws Exception {
if (lockPlace != null) {
lockPlace.mkdirs();
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/OptionalLocking.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/OptionalLocking.java
index 9285ea6386..afa3cb1671 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/OptionalLocking.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/OptionalLocking.java
@@ -18,14 +18,14 @@ package org.apache.activemq.artemis.cli.commands.tools;
import java.io.File;
-import com.github.rvesse.airline.annotations.Option;
+import picocli.CommandLine.Option;
/**
* This is for commands where --f on ignoring lock could be valid.
*/
public class OptionalLocking extends LockAbstract {
- @Option(name = "--f", description = "This will allow certain tools like print-data to be performed ignoring any running servers. WARNING: Changing data concurrently with a running broker may damage your data. Be careful with this option.")
+ @Option(names = "--f", description = "This will allow certain tools like print-data to be performed ignoring any running servers. WARNING: Changing data concurrently with a running broker may damage your data. Be careful with this option.")
boolean ignoreLock;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java
index 7e09b01296..93361abcde 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/PrintData.java
@@ -27,8 +27,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.SimpleString;
@@ -63,25 +61,25 @@ import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.actors.ArtemisExecutor;
import org.apache.activemq.artemis.utils.collections.LinkedList;
import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "print", description = "Print data records information. WARNING: don't use while a production server is running.")
public class PrintData extends DBOption {
-
- @Option(name = "--safe", description = "Print your data structure without showing your data.")
+ @Option(names = "--safe", description = "Print your data structure without showing your data.")
private boolean safe = false;
-
- @Option(name = "--reclaimed", description = "Try to print as many records as possible from reclaimed files.")
+ @Option(names = "--reclaimed", description = "Try to print as many records as possible from reclaimed files.")
private boolean reclaimed = false;
- @Option(name = "--max-pages", description = "Maximum number of pages to read. Default: unlimited (-1).")
+ @Option(names = "--max-pages", description = "Maximum number of pages to read. Default: unlimited (-1).")
private int maxPages = -1;
- @Option(name = "--skip-bindings", description = "Do not print data from the bindings journal.")
+ @Option(names = "--skip-bindings", description = "Do not print data from the bindings journal.")
private boolean skipBindings = false;
- @Option(name = "--skip-journal", description = "Do not print data from the messages journal.")
+ @Option(names = "--skip-journal", description = "Do not print data from the messages journal.")
private boolean skipJournal = false;
private static final String BINDINGS_BANNER = "B I N D I N G S J O U R N A L";
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/RecoverMessages.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/RecoverMessages.java
index 085c892e94..8431e681af 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/RecoverMessages.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/RecoverMessages.java
@@ -20,9 +20,6 @@ import java.io.File;
import java.util.HashSet;
import java.util.List;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
-import com.github.rvesse.airline.annotations.restrictions.Required;
import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.core.config.Configuration;
@@ -38,6 +35,8 @@ import org.apache.activemq.artemis.core.message.impl.CoreMessagePersister;
import org.apache.activemq.artemis.core.persistence.impl.journal.JournalRecordIds;
import org.apache.activemq.artemis.spi.core.protocol.MessagePersister;
import org.apache.activemq.artemis.utils.ByteUtil;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "recover", description = "Recover (undelete) every message on the journal by creating a new output journal. Rolled back and acked messages will be sent out to the output as much as possible.")
public class RecoverMessages extends DBOption {
@@ -46,11 +45,10 @@ public class RecoverMessages extends DBOption {
MessagePersister.registerPersister(CoreMessagePersister.getInstance());
}
- @Option(name = "--reclaimed", description = "Try to recover as many records as possible from reclaimed files.")
+ @Option(names = "--reclaimed", description = "Try to recover as many records as possible from reclaimed files.")
private boolean reclaimed = false;
- @Option(name = "--target", description = "Output folder container the new journal with all the generated messages.")
- @Required
+ @Option(names = "--target", description = "Output folder container the new journal with all the generated messages.", required = true)
private String outputJournal;
@@ -67,7 +65,7 @@ public class RecoverMessages extends DBOption {
if (configuration.isJDBC()) {
throw new IllegalAccessException("JDBC Not supported on recover");
} else {
- recover(configuration, getJournal(), journalOutput, new File(getLargeMessages()), reclaimed);
+ recover(context, configuration, getJournal(), journalOutput, new File(getLargeMessages()), reclaimed);
}
} catch (Exception e) {
treatError(e, "data", "recover");
@@ -75,9 +73,7 @@ public class RecoverMessages extends DBOption {
return null;
}
- public static void recover(Configuration configuration, String journallocation, File journalOutput, File largeMessage, boolean reclaimed) throws Exception {
-
- final ActionContext context = ActionContext.system();
+ public static void recover(ActionContext context, Configuration configuration, String journallocation, File journalOutput, File largeMessage, boolean reclaimed) throws Exception {
File journal = new File(journallocation);
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/CompactJournal.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/CompactJournal.java
index 41e5cd59c8..198c94d494 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/CompactJournal.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/CompactJournal.java
@@ -18,7 +18,6 @@ package org.apache.activemq.artemis.cli.commands.tools.journal;
import java.io.File;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.tools.LockAbstract;
import org.apache.activemq.artemis.core.config.Configuration;
@@ -26,6 +25,7 @@ import org.apache.activemq.artemis.core.io.IOCriticalErrorListener;
import org.apache.activemq.artemis.core.io.nio.NIOSequentialFileFactory;
import org.apache.activemq.artemis.core.journal.impl.JournalImpl;
import org.apache.activemq.artemis.core.persistence.impl.journal.JournalRecordIds;
+import picocli.CommandLine.Command;
@Command(name = "compact", description = "Compact the journal of a non running server.")
public final class CompactJournal extends LockAbstract {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/DecodeJournal.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/DecodeJournal.java
index f0cb73b64e..ffc7496e34 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/DecodeJournal.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/DecodeJournal.java
@@ -27,33 +27,31 @@ import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
-import com.github.rvesse.airline.annotations.restrictions.Required;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.tools.LockAbstract;
import org.apache.activemq.artemis.core.io.nio.NIOSequentialFileFactory;
import org.apache.activemq.artemis.core.journal.RecordInfo;
import org.apache.activemq.artemis.core.journal.impl.JournalImpl;
import org.apache.activemq.artemis.utils.Base64;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "decode", description = "Decode a journal's internal format into a new set of journal files.")
public class DecodeJournal extends LockAbstract {
- @Option(name = "--directory", description = "The journal folder. Default: read 'journal-directory' from broker.xml.")
+ @Option(names = "--directory", description = "The journal folder. Default: read 'journal-directory' from broker.xml.")
public String directory;
- @Option(name = "--prefix", description = "The journal prefix. Default: activemq-data.")
+ @Option(names = "--prefix", description = "The journal prefix. Default: activemq-data.")
public String prefix = "activemq-data";
- @Option(name = "--suffix", description = "The journal suffix. Default: amq.")
+ @Option(names = "--suffix", description = "The journal suffix. Default: amq.")
public String suffix = "amq";
- @Option(name = "--file-size", description = "The journal size. Default: 10485760.")
+ @Option(names = "--file-size", description = "The journal size. Default: 10485760.")
public int size = 10485760;
- @Option(name = "--input", description = "The input file name. Default: exp.dmp.")
- @Required
+ @Option(names = "--input", description = "The input file name. Default: exp.dmp.", required = true)
public String input = "exp.dmp";
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/EncodeJournal.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/EncodeJournal.java
index 1a3db097bc..81c0ee6b44 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/EncodeJournal.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/EncodeJournal.java
@@ -22,8 +22,6 @@ import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.List;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.tools.LockAbstract;
import org.apache.activemq.artemis.core.io.SequentialFileFactory;
@@ -33,20 +31,22 @@ import org.apache.activemq.artemis.core.journal.impl.JournalFile;
import org.apache.activemq.artemis.core.journal.impl.JournalImpl;
import org.apache.activemq.artemis.core.journal.impl.JournalReaderCallback;
import org.apache.activemq.artemis.utils.Base64;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "encode", description = "Encode a set of journal files into an internal encoded data format.")
public class EncodeJournal extends LockAbstract {
- @Option(name = "--directory", description = "The journal folder. Default: read 'journal-directory' from broker.xml.")
+ @Option(names = "--directory", description = "The journal folder. Default: read 'journal-directory' from broker.xml.")
public String directory;
- @Option(name = "--prefix", description = "The journal prefix. Default: activemq-data.")
+ @Option(names = "--prefix", description = "The journal prefix. Default: activemq-data.")
public String prefix = "activemq-data";
- @Option(name = "--suffix", description = "The journal suffix. Default: amq.")
+ @Option(names = "--suffix", description = "The journal suffix. Default: amq.")
public String suffix = "amq";
- @Option(name = "--file-size", description = "The journal size. Default: 10485760.")
+ @Option(names = "--file-size", description = "The journal size. Default: 10485760.")
public int size = 10485760;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/PerfJournal.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/PerfJournal.java
index 471af9f0f7..ba7b9b46d6 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/PerfJournal.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/journal/PerfJournal.java
@@ -18,43 +18,43 @@ package org.apache.activemq.artemis.cli.commands.tools.journal;
import java.text.DecimalFormat;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.tools.OptionalLocking;
import org.apache.activemq.artemis.cli.commands.util.SyncCalculation;
import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
import org.apache.activemq.artemis.core.server.JournalType;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
@Command(name = "perf-journal", description = "Calculate the journal-buffer-timeout to use with the current data folder.")
public class PerfJournal extends OptionalLocking {
- @Option(name = "--block-size", description = "The block size for each write. Default 4096.")
+ @Option(names = "--block-size", description = "The block size for each write. Default 4096.")
public int size = 4 * 1024;
- @Option(name = "--writes", description = "The number of writes to be performed. Default: 250.")
+ @Option(names = "--writes", description = "The number of writes to be performed. Default: 250.")
public int writes = 250;
- @Option(name = "--tries", description = "The number of tries for the test. Default: 5.")
+ @Option(names = "--tries", description = "The number of tries for the test. Default: 5.")
public int tries = 5;
- @Option(name = "--no-sync", description = "Disable syncs.")
+ @Option(names = "--no-sync", description = "Disable syncs.")
public boolean nosyncs = false;
- @Option(name = "--sync", description = "Enable syncs.")
+ @Option(names = "--sync", description = "Enable syncs.")
public boolean syncs = false;
- @Option(name = "--journal-type", description = "Journal type to be used: Default: read from broker.xml.")
+ @Option(names = "--journal-type", description = "Journal type to be used: Default: read from broker.xml.")
public String journalType = null;
- @Option(name = "--sync-writes", description = "Perform each write synchronously, e.g. if there was a single producer.")
+ @Option(names = "--sync-writes", description = "Perform each write synchronously, e.g. if there was a single producer.")
public boolean syncWrites = false;
- @Option(name = "--file", description = "The file name to be used. Default: test.tmp.")
+ @Option(names = "--file", description = "The file name to be used. Default: test.tmp.")
public String fileName = "test.tmp";
- @Option(name = "--max-aio", description = "libaio.maxAIO to be used. Default: read from broker.xml.")
+ @Option(names = "--max-aio", description = "libaio.maxAIO to be used. Default: read from broker.xml.")
public int maxAIO = 0;
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporter.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporter.java
index 23e6d6c7d0..f230fdfed8 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporter.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporter.java
@@ -21,6 +21,7 @@ import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.io.File;
import java.io.OutputStream;
+import java.lang.invoke.MethodHandles;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@@ -32,8 +33,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import java.util.stream.Collectors;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.ICoreMessage;
@@ -66,8 +67,7 @@ import org.apache.activemq.artemis.core.server.JournalType;
import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.lang.invoke.MethodHandles;
-import java.util.stream.Collectors;
+import picocli.CommandLine.Command;
@Command(name = "exp", description = "Export all message-data using an XML that could be interpreted by any system.")
public final class XmlDataExporter extends DBOption {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataImporter.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataImporter.java
index 6f515a3cfe..7922a36a89 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataImporter.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataImporter.java
@@ -23,6 +23,7 @@ import javax.xml.validation.Validator;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
+import java.lang.invoke.MethodHandles;
import java.net.URL;
import java.nio.ByteBuffer;
import java.security.AccessController;
@@ -34,9 +35,6 @@ import java.util.List;
import java.util.Map;
import java.util.TreeSet;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
-import com.github.rvesse.airline.annotations.restrictions.Required;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
@@ -63,7 +61,8 @@ import org.apache.activemq.artemis.utils.ListUtil;
import org.apache.activemq.artemis.utils.XmlProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.lang.invoke.MethodHandles;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
/**
* Read XML output from <code>org.apache.activemq.artemis.core.persistence.impl.journal.XmlDataExporter</code>, create a core session, and
@@ -92,29 +91,28 @@ public final class XmlDataImporter extends ActionAbstract {
private ClientSession session;
- @Option(name = "--host", description = "The host used to import the data. Default: localhost.")
+ @Option(names = "--host", description = "The host used to import the data. Default: localhost.")
public String host = "localhost";
- @Option(name = "--port", description = "The port used to import the data. Default: 61616.")
+ @Option(names = "--port", description = "The port used to import the data. Default: 61616.")
public int port = 61616;
- @Option(name = "--transaction", description = "Import every message using a single transction. If anything goes wrong during the process the entire import will be aborted. Default: false.")
+ @Option(names = "--transaction", description = "Import every message using a single transction. If anything goes wrong during the process the entire import will be aborted. Default: false.")
public boolean transactional;
- @Option(name = "--user", description = "User name used to import the data. Default: null.")
+ @Option(names = "--user", description = "User name used to import the data. Default: null.")
public String user = null;
- @Option(name = "--password", description = "User name used to import the data. Default: null.")
+ @Option(names = "--password", description = "User name used to import the data. Default: null.")
public String password = null;
- @Option(name = "--input", description = "The input file name. Default: exp.dmp.")
- @Required
+ @Option(names = "--input", description = "The input file name. Default: exp.dmp.", required = true)
public String input = "exp.dmp";
- @Option(name = "--sort", description = "Sort the messages from the input (used for older versions that won't sort messages).")
+ @Option(names = "--sort", description = "Sort the messages from the input (used for older versions that won't sort messages).")
public boolean sort = false;
- @Option(name = "--legacy-prefixes", description = "Do not remove prefixes from legacy imports.")
+ @Option(names = "--legacy-prefixes", description = "Do not remove prefixes from legacy imports.")
public boolean legacyPrefixes = false;
TreeSet<XMLMessageImporter.MessageInfo> messages;
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/AddUser.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/AddUser.java
index 73f7cf6340..3f91ef7de8 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/AddUser.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/AddUser.java
@@ -16,10 +16,10 @@
*/
package org.apache.activemq.artemis.cli.commands.user;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
/**
* Adding a new user, example:
@@ -28,7 +28,7 @@ import org.apache.activemq.artemis.cli.commands.ActionContext;
@Command(name = "add", description = "Add a user.")
public class AddUser extends PasswordAction {
- @Option(name = "--plaintext", description = "Store the password in plaintext. Default: false.")
+ @Option(names = "--plaintext", description = "Store the password in plaintext. Default: false.")
boolean plaintext = false;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/HelpUser.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/HelpUser.java
deleted file mode 100644
index 925c645412..0000000000
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/HelpUser.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.activemq.artemis.cli.commands.user;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.github.rvesse.airline.help.Help;
-import org.apache.activemq.artemis.cli.commands.Action;
-import org.apache.activemq.artemis.cli.commands.ActionContext;
-import org.apache.activemq.artemis.cli.commands.InvalidOptionsError;
-import org.apache.activemq.artemis.cli.commands.OptionsUtil;
-
-public class HelpUser extends Help implements Action {
-
- @Override
- public boolean isVerbose() {
- return false;
- }
-
- @Override
- public void setHomeValues(File brokerHome, File brokerInstance, File etcFolder) {
- }
-
- @Override
- public String getBrokerInstance() {
- return null;
- }
-
- @Override
- public String getBrokerHome() {
- return null;
- }
-
- @Override
- public void checkOptions(String[] options) throws InvalidOptionsError {
- OptionsUtil.checkCommandOptions(this.getClass(), options);
- }
-
- @Override
- public Object execute(ActionContext context) throws Exception {
- List<String> commands = new ArrayList<>(1);
- commands.add("user");
- help(global, commands);
- return null;
- }
-}
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ListUser.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ListUser.java
index a01cbf00a0..ad7455627d 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ListUser.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ListUser.java
@@ -16,13 +16,12 @@
*/
package org.apache.activemq.artemis.cli.commands.user;
-import org.apache.activemq.artemis.json.JsonArray;
-import org.apache.activemq.artemis.json.JsonObject;
-
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.api.core.JsonUtil;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import org.apache.activemq.artemis.json.JsonArray;
+import org.apache.activemq.artemis.json.JsonObject;
+import picocli.CommandLine.Command;
/**
* list existing users, example:
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/PasswordAction.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/PasswordAction.java
index f49caf8fe9..7e0a74448f 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/PasswordAction.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/PasswordAction.java
@@ -16,11 +16,11 @@
*/
package org.apache.activemq.artemis.cli.commands.user;
-import com.github.rvesse.airline.annotations.Option;
+import picocli.CommandLine.Option;
public class PasswordAction extends UserAction {
- @Option(name = "--user-command-password", description = "The password to use for the chosen user command. Default: input.")
+ @Option(names = "--user-command-password", description = "The password to use for the chosen user command. Default: input.")
String userCommandPassword;
void checkInputPassword() {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/RemoveUser.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/RemoveUser.java
index 9073dab1f8..de17056cbc 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/RemoveUser.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/RemoveUser.java
@@ -16,9 +16,9 @@
*/
package org.apache.activemq.artemis.cli.commands.user;
-import com.github.rvesse.airline.annotations.Command;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
/**
* Remove a user, example:
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ResetUser.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ResetUser.java
index e221b8ea03..795d1b739e 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ResetUser.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ResetUser.java
@@ -16,10 +16,10 @@
*/
package org.apache.activemq.artemis.cli.commands.user;
-import com.github.rvesse.airline.annotations.Command;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.ActionContext;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
/**
* Reset a user's password or roles, example:
@@ -28,7 +28,7 @@ import org.apache.activemq.artemis.cli.commands.ActionContext;
@Command(name = "reset", description = "Reset user's password or roles.")
public class ResetUser extends PasswordAction {
- @Option(name = "--plaintext", description = "Store the password in plaintext. Default: false.")
+ @Option(names = "--plaintext", description = "Store the password in plaintext. Default: false.")
boolean plaintext = false;
@Override
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/UserAction.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/UserAction.java
index 50fcecd5e4..3f0cd0efa3 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/UserAction.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/UserAction.java
@@ -16,15 +16,15 @@
*/
package org.apache.activemq.artemis.cli.commands.user;
-import com.github.rvesse.airline.annotations.Option;
import org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
+import picocli.CommandLine.Option;
public abstract class UserAction extends ConnectionAbstract {
- @Option(name = "--role", description = "The user's role(s). Separate multiple roles with comma.")
+ @Option(names = "--role", description = "The user's role(s). Separate multiple roles with comma.")
String role;
- @Option(name = "--user-command-user", description = "The username to use for the chosen user command. Default: input.")
+ @Option(names = "--user-command-user", description = "The username to use for the chosen user command. Default: input.")
String userCommandUser = null;
void checkInputUser() {
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/UserGroup.java
similarity index 57%
copy from artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
copy to artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/UserGroup.java
index e34e376deb..ef4aecdc28 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Kill.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/UserGroup.java
@@ -14,28 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.activemq.artemis.cli.commands;
-import java.io.File;
+package org.apache.activemq.artemis.cli.commands.user;
-import com.github.rvesse.airline.annotations.Command;
-import org.apache.activemq.artemis.dto.BrokerDTO;
+import org.apache.activemq.artemis.cli.commands.HelpAction;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
-@Command(name = "kill", description = "Kill a broker started with --allow-kill.")
-public class Kill extends Configurable {
+@Command(name = "user", description = "file-based user management. Use 'help user' for sub commands list.", subcommands = {ListUser.class, AddUser.class, RemoveUser.class, ResetUser.class})
+public class UserGroup implements Runnable {
- @Override
- public Object execute(ActionContext context) throws Exception {
- super.execute(context);
-
- BrokerDTO broker = getBrokerDTO();
-
- File file = broker.server.getConfigurationFile().getParentFile();
-
- File killFile = new File(file, "KILL_ME");
+ CommandLine commandLine;
- killFile.createNewFile();
+ public UserGroup(CommandLine commandLine) {
+ this.commandLine = commandLine;
+ }
- return null;
+ @Override
+ public void run() {
+ HelpAction.help(commandLine, "user");
}
+
}
diff --git a/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionAbstractTest.java b/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionAbstractTest.java
index 331afbce9f..fbe060ad12 100644
--- a/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionAbstractTest.java
+++ b/artemis-cli/src/test/java/org/apache/activemq/artemis/cli/commands/messages/ConnectionAbstractTest.java
@@ -48,11 +48,12 @@ public class ConnectionAbstractTest {
@Test
public void testDefaultSourceAcceptorNoArtemis() {
- ConnectionAbstract connectionAbstract = new ConnectionAbstract();
File brokerInstanceEtc = new File(this.getClass().getClassLoader().getResource("broker.xml").getFile()).getParentFile();
System.setProperty("artemis.instance.etc", brokerInstanceEtc.getAbsolutePath());
+
+ ConnectionAbstract connectionAbstract = new ConnectionAbstract();
try {
connectionAbstract.setHomeValues(null, brokerInstanceEtc.getParentFile(), null);
ActionAbstractAccessor.setBrokerConfig(connectionAbstract, "broker-with-connector.xml");
diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
index 6d1f994b12..e06e0a68b5 100644
--- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
+++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
@@ -144,12 +144,12 @@ public class ArtemisTest extends CliTestBase {
org.apache.activemq.artemis.api.config.ActiveMQDefaultConfigurationTestAccessor.setDefaultAddressQueueScanPeriod(timeBefore);
}
- @Test
+ @Test(timeout = 60_000)
public void invalidCliDoesntThrowException() {
testCli("--silent", "create");
}
- @Test
+ @Test(timeout = 60_000)
public void invalidPathDoesntThrowException() {
if (isWindows()) {
testCli("create", "zzzzz:/rawr", "--silent");
@@ -158,14 +158,14 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testSupportsLibaio() throws Exception {
Create x = new Create();
x.setInstance(new File("/tmp/foo"));
x.supportsLibaio();
}
- @Test
+ @Test(timeout = 60_000)
public void testSync() throws Exception {
int writes = 2;
int tries = 5;
@@ -177,7 +177,7 @@ public class ArtemisTest extends CliTestBase {
}
- @Test
+ @Test(timeout = 60_000)
public void testSimpleCreate() throws Exception {
//instance1: default using http
File instance1 = new File(temporaryFolder.getRoot(), "instance1");
@@ -185,14 +185,14 @@ public class ArtemisTest extends CliTestBase {
}
- @Test
+ @Test(timeout = 60_000)
public void testCreateDB() throws Exception {
File instance1 = new File(temporaryFolder.getRoot(), "instance1");
Artemis.internalExecute("create", instance1.getAbsolutePath(), "--silent", "--jdbc");
}
- @Test
+ @Test(timeout = 60_000)
public void testSimpleCreateMapped() throws Throwable {
try {
//instance1: default using http
@@ -204,7 +204,7 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testOpenwireSupportAdvisoryDisabledByDefault() throws Exception {
FileConfiguration configuration = createFileConfiguration("supportAdvisory",
"--force", "--silent", "--no-web", "--no-autotune");
@@ -214,7 +214,7 @@ public class ArtemisTest extends CliTestBase {
Assert.assertFalse(Boolean.parseBoolean(params.get("suppressInternalManagementObjects").toString()));
}
- @Test
+ @Test(timeout = 60_000)
public void testOpenwireEnabledSupportAdvisory() throws Exception {
FileConfiguration configuration = createFileConfiguration("supportAdvisory",
"--force", "--silent", "--no-web", "--no-autotune",
@@ -249,7 +249,7 @@ public class ArtemisTest extends CliTestBase {
return fc;
}
- @Test
+ @Test(timeout = 60_000)
public void testWebConfig() throws Exception {
setupAuth();
Run.setEmbedded(true);
@@ -326,7 +326,7 @@ public class ArtemisTest extends CliTestBase {
assertEquals("password2", trustPass);
}
- @Test
+ @Test(timeout = 60_000)
public void testSecurityManagerConfiguration() throws Exception {
setupAuth();
Run.setEmbedded(true);
@@ -403,7 +403,7 @@ public class ArtemisTest extends CliTestBase {
stopServer();
}
- @Test
+ @Test(timeout = 60_000)
public void testStopManagementContext() throws Exception {
Run.setEmbedded(true);
File instance1 = new File(temporaryFolder.getRoot(), "instance_user");
@@ -418,12 +418,12 @@ public class ArtemisTest extends CliTestBase {
stopServer();
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandJAAS() throws Exception {
testUserCommand(false);
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandBasic() throws Exception {
testUserCommand(true);
}
@@ -482,7 +482,7 @@ public class ArtemisTest extends CliTestBase {
addCmd.setRole("admin,operator");
addCmd.setUser("admin");
addCmd.setPassword("admin");
- addCmd.execute(ActionContext.system());
+ addCmd.execute(new ActionContext());
//verify
context = new TestActionContext();
@@ -592,22 +592,22 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandViaManagementPlaintextJAAS() throws Exception {
internalTestUserCommandViaManagement(true, false);
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandViaManagementHashedJAAS() throws Exception {
internalTestUserCommandViaManagement(false, false);
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandViaManagementPlaintextBasic() throws Exception {
internalTestUserCommandViaManagement(true, true);
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandViaManagementHashedBasic() throws Exception {
internalTestUserCommandViaManagement(false, true);
}
@@ -713,7 +713,7 @@ public class ArtemisTest extends CliTestBase {
stopServer();
}
- @Test
+ @Test(timeout = 60_000)
public void testListUserWithMultipleRolesWithSpaces() throws Exception {
try {
Run.setEmbedded(true);
@@ -753,12 +753,12 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testProperReloadWhenAddingUserViaManagementJAAS() throws Exception {
testProperReloadWhenAddingUserViaManagement(false);
}
- @Test
+ @Test(timeout = 60_000)
public void testProperReloadWhenAddingUserViaManagementBasic() throws Exception {
testProperReloadWhenAddingUserViaManagement(true);
}
@@ -802,7 +802,7 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testMissingUserFileViaManagement() throws Exception {
Run.setEmbedded(true);
File instance1 = new File(temporaryFolder.getRoot(), "instance_user");
@@ -825,7 +825,7 @@ public class ArtemisTest extends CliTestBase {
stopServer();
}
- @Test
+ @Test(timeout = 60_000)
public void testMissingRoleFileViaManagement() throws Exception {
Run.setEmbedded(true);
File instance1 = new File(temporaryFolder.getRoot(), "instance_user");
@@ -848,12 +848,12 @@ public class ArtemisTest extends CliTestBase {
stopServer();
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandResetJAAS() throws Exception {
testUserCommandReset(false);
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandResetBasic() throws Exception {
testUserCommandReset(true);
}
@@ -979,12 +979,12 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testConcurrentUserAdministrationJAAS() throws Exception {
testConcurrentUserAdministration(false);
}
- @Test
+ @Test(timeout = 60_000)
public void testConcurrentUserAdministrationBasic() throws Exception {
testConcurrentUserAdministration(true);
}
@@ -1091,7 +1091,7 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testRoleWithSpaces() throws Exception {
String roleWithSpaces = "amq with spaces";
Run.setEmbedded(true);
@@ -1121,12 +1121,12 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandResetViaManagementPlaintext() throws Exception {
internalTestUserCommandResetViaManagement(true);
}
- @Test
+ @Test(timeout = 60_000)
public void testUserCommandResetViaManagementHashed() throws Exception {
internalTestUserCommandResetViaManagement(false);
}
@@ -1200,7 +1200,7 @@ public class ArtemisTest extends CliTestBase {
stopServer();
}
- @Test
+ @Test(timeout = 60_000)
public void testMaskCommand() throws Exception {
String password1 = "password";
@@ -1236,7 +1236,7 @@ public class ArtemisTest extends CliTestBase {
assertEquals(encrypt2, result);
}
- @Test
+ @Test(timeout = 60_000)
public void testMaskCommandWithPasswordCodec() throws Exception {
File instanceWithPasswordCodec = new File(temporaryFolder.getRoot(), "instance_with_password_codec");
Files.createDirectories(Paths.get(instanceWithPasswordCodec.getAbsolutePath(), "etc"));
@@ -1265,17 +1265,17 @@ public class ArtemisTest extends CliTestBase {
assertEquals(password, result);
}
- @Test
+ @Test(timeout = 60_000)
public void testSimpleRun() throws Exception {
testSimpleRun("server");
}
- @Test
+ @Test(timeout = 60_000)
public void testProducerRetry() throws Exception {
File instanceFolder = temporaryFolder.newFolder("server");
setupAuth(instanceFolder);
Run.setEmbedded(true);
- Artemis.main("create", instanceFolder.getAbsolutePath(), "--verbose", "--force", "--silent", "--no-web", "--queues", "q1", "--no-autotune", "--require-login", "--default-port", "61616");
+ Artemis.main("create", instanceFolder.getAbsolutePath(), "--verbose", "--force", "--disable-persistence", "--silent", "--no-web", "--queues", "q1", "--no-autotune", "--require-login", "--default-port", "61616");
System.setProperty("artemis.instance", instanceFolder.getAbsolutePath());
try {
@@ -1288,20 +1288,20 @@ public class ArtemisTest extends CliTestBase {
* it will read from the InputStream in the ActionContext. It can't read the password since it's using
* System.console.readPassword() for that.
*/
- assertEquals(Integer.valueOf(100), Artemis.internalExecute(null, null, null, new String[] {"producer", "--destination", "queue://q1", "--message-count", "100", "--password", "admin"}, context));
+ assertEquals(Long.valueOf(100), Artemis.internalExecute(null, null, null, new String[] {"producer", "--destination", "queue://q1", "--message-count", "100", "--password", "admin"}, context));
/*
* This is the same as above except it will prompt the user to re-enter both the URL and the username.
*/
in = new ByteArrayInputStream("tcp://localhost:61616\nadmin\n".getBytes());
context = new ActionContext(in, System.out, System.err);
- assertEquals(Integer.valueOf(100), Artemis.internalExecute(null, null, null, new String[] {"producer", "--destination", "queue://q1", "--message-count", "100", "--password", "admin", "--url", "tcp://badhost:11111"}, context));
+ assertEquals(Long.valueOf(100), Artemis.internalExecute(null, null, null, new String[] {"producer", "--destination", "queue://q1", "--message-count", "100", "--password", "admin", "--url", "tcp://badhost:11111"}, context));
} finally {
stopServer();
}
}
- @Test
+ @Test(timeout = 60_000)
public void testQueueStatRetry() throws Exception {
File instanceFolder = temporaryFolder.newFolder("server");
setupAuth(instanceFolder);
@@ -1332,24 +1332,24 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testWeirdCharacter() throws Exception {
testSimpleRun("test%26%26x86_6");
}
- @Test
+ @Test(timeout = 60_000)
public void testSpaces() throws Exception {
testSimpleRun("with space");
}
- @Test
+ @Test(timeout = 60_000)
public void testCustomPort() throws Exception {
testSimpleRun("server", 61696);
}
- @Test
+ @Test(timeout = 60_000)
public void testPerfJournal() throws Exception {
File instanceFolder = temporaryFolder.newFolder("server1");
setupAuth(instanceFolder);
@@ -1411,14 +1411,14 @@ public class ArtemisTest extends CliTestBase {
}
Artemis.internalExecute("data", "print", "--f");
- assertEquals(Integer.valueOf(100), Artemis.internalExecute("producer", "--destination", "queue://q1", "--message-count", "100", "--user", "admin", "--password", "admin"));
- assertEquals(Integer.valueOf(100), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
- assertEquals(Integer.valueOf(10), Artemis.internalExecute("producer", "--destination", "queue://q1", "--text-size", "500", "--message-count", "10", "--user", "admin", "--password", "admin"));
- assertEquals(Integer.valueOf(10), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
- assertEquals(Integer.valueOf(10), Artemis.internalExecute("producer", "--destination", "queue://q1", "--message-size", "500", "--message-count", "10", "--user", "admin", "--password", "admin"));
- assertEquals(Integer.valueOf(10), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
- assertEquals(Integer.valueOf(10), Artemis.internalExecute("producer", "--destination", "queue://q1", "--message", "message", "--message-count", "10", "--user", "admin", "--password", "admin"));
- assertEquals(Integer.valueOf(10), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(100), Artemis.internalExecute("producer", "--destination", "queue://q1", "--message-count", "100", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(100), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(10), Artemis.internalExecute("producer", "--destination", "queue://q1", "--text-size", "500", "--message-count", "10", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(10), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(10), Artemis.internalExecute("producer", "--destination", "queue://q1", "--message-size", "500", "--message-count", "10", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(10), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(10), Artemis.internalExecute("producer", "--destination", "queue://q1", "--message", "message", "--message-count", "10", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(10), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:" + acceptorPort);
Connection connection = cf.createConnection("admin", "admin");
@@ -1439,20 +1439,20 @@ public class ArtemisTest extends CliTestBase {
connection.close();
cf.close();
- assertEquals(Integer.valueOf(1), Artemis.internalExecute("browser", "--destination", "queue://q1", "--txt-size", "50", "--filter", "fruit='banana'", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(1), Artemis.internalExecute("browser", "--destination", "queue://q1", "--txt-size", "50", "--filter", "fruit='banana'", "--user", "admin", "--password", "admin"));
- assertEquals(Integer.valueOf(100), Artemis.internalExecute("browser", "--destination", "queue://q1", "--txt-size", "50", "--filter", "fruit='orange'", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(100), Artemis.internalExecute("browser", "--destination", "queue://q1", "--txt-size", "50", "--filter", "fruit='orange'", "--user", "admin", "--password", "admin"));
- assertEquals(Integer.valueOf(101), Artemis.internalExecute("browser", "--destination", "queue://q1", "--txt-size", "50", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(101), Artemis.internalExecute("browser", "--destination", "queue://q1", "--txt-size", "50", "--user", "admin", "--password", "admin"));
// should only receive 10 messages on browse as I'm setting messageCount=10
- assertEquals(Integer.valueOf(10), Artemis.internalExecute("browser", "--destination", "queue://q1", "--txt-size", "50", "--message-count", "10", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(10), Artemis.internalExecute("browser", "--destination", "queue://q1", "--txt-size", "50", "--message-count", "10", "--user", "admin", "--password", "admin"));
// Nothing was consumed until here as it was only browsing, check it's receiving again
- assertEquals(Integer.valueOf(1), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--txt-size", "50", "--break-on-null", "--receive-timeout", "100", "--filter", "fruit='banana'", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(1), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--txt-size", "50", "--break-on-null", "--receive-timeout", "100", "--filter", "fruit='banana'", "--user", "admin", "--password", "admin"));
// Checking it was acked before
- assertEquals(Integer.valueOf(100), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--txt-size", "50", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
+ assertEquals(Long.valueOf(100), Artemis.internalExecute("consumer", "--destination", "queue://q1", "--txt-size", "50", "--break-on-null", "--receive-timeout", "100", "--user", "admin", "--password", "admin"));
//add a simple user
AddUser addCmd = new AddUser();
@@ -1477,12 +1477,12 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testAutoDeleteTrue() throws Exception {
testAutoDelete(true);
}
- @Test
+ @Test(timeout = 60_000)
public void testAutoDeleteFalse() throws Exception {
testAutoDelete(false);
}
@@ -1535,7 +1535,7 @@ public class ArtemisTest extends CliTestBase {
- @Test
+ @Test(timeout = 60_000)
public void testPing() throws Exception {
File instanceFolder = temporaryFolder.newFolder("pingTest");
@@ -1545,7 +1545,7 @@ public class ArtemisTest extends CliTestBase {
// This is usually set when run from the command line via artemis.profile
Run.setEmbedded(true);
- Artemis.main("create", instanceFolder.getAbsolutePath(), "--force", "--silent", "--no-web", "--queues", queues, "--addresses", topics, "--no-autotune", "--require-login", "--ping", "127.0.0.1", "--no-autotune");
+ Artemis.main("create", instanceFolder.getAbsolutePath(), "--force", "--silent", "--no-web", "--queues", queues, "--addresses", topics, "--require-login", "--ping", "127.0.0.1", "--no-autotune");
System.setProperty("artemis.instance", instanceFolder.getAbsolutePath());
FileConfiguration fc = new FileConfiguration();
@@ -1557,7 +1557,7 @@ public class ArtemisTest extends CliTestBase {
}
- @Test
+ @Test(timeout = 60_000)
public void testAutoTune() throws Exception {
File instanceFolder = temporaryFolder.newFolder("autoTuneTest");
@@ -1578,7 +1578,7 @@ public class ArtemisTest extends CliTestBase {
Assert.assertNotEquals(-1, fc.getPageSyncTimeout());
}
- @Test
+ @Test(timeout = 60_000)
public void testQstat() throws Exception {
File instanceQstat = new File(temporaryFolder.getRoot(), "instanceQStat");
@@ -1828,7 +1828,7 @@ public class ArtemisTest extends CliTestBase {
}
- @Test
+ @Test(timeout = 60_000)
public void testHugeQstat() throws Exception {
File instanceQstat = new File(temporaryFolder.getRoot(), "instanceQStat");
@@ -1855,7 +1855,7 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testQstatColumnWidth() throws Exception {
File instanceQstat = new File(temporaryFolder.getRoot(), "instanceQStat");
@@ -1930,7 +1930,7 @@ public class ArtemisTest extends CliTestBase {
}
- @Test
+ @Test(timeout = 60_000)
public void testQstatErrors() throws Exception {
File instanceQstat = new File(temporaryFolder.getRoot(), "instanceQStatErrors");
@@ -2033,7 +2033,7 @@ public class ArtemisTest extends CliTestBase {
}
- @Test
+ @Test(timeout = 60_000)
public void testQstatWarnings() throws Exception {
File instanceQstat = new File(temporaryFolder.getRoot(), "instanceQStat");
@@ -2115,7 +2115,7 @@ public class ArtemisTest extends CliTestBase {
}
- @Test
+ @Test(timeout = 60_000)
public void testRunPropertiesArgumentSetsAcceptorPort() throws Exception {
File instanceFile = new File(temporaryFolder.getRoot(), "testRunPropertiesArgumentSetsAcceptorPort");
setupAuth(instanceFile);
@@ -2136,7 +2136,7 @@ public class ArtemisTest extends CliTestBase {
}
}
- @Test
+ @Test(timeout = 60_000)
public void testRunPropertiesDudArgument() throws Exception {
File instanceFile = new File(temporaryFolder.getRoot(), "testRunPropertiesDudArgument");
setupAuth(instanceFile);
@@ -2149,7 +2149,7 @@ public class ArtemisTest extends CliTestBase {
assertTrue(ret instanceof FileNotFoundException);
}
- @Test
+ @Test(timeout = 60_000)
public void testVersionCommand() throws Exception {
TestActionContext context = new TestActionContext();
PrintVersion printVersion = new PrintVersion();
diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/CheckTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/CheckTest.java
index e7ba8e0023..7545d23f0a 100644
--- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/CheckTest.java
+++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/CheckTest.java
@@ -26,7 +26,6 @@ import org.apache.activemq.artemis.api.core.management.QueueControl;
import org.apache.activemq.artemis.api.core.management.ResourceNames;
import org.apache.activemq.artemis.cli.Artemis;
import org.apache.activemq.artemis.cli.CLIException;
-import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.Run;
import org.apache.activemq.artemis.cli.commands.check.NodeCheck;
import org.apache.activemq.artemis.cli.commands.check.QueueCheck;
@@ -148,9 +147,9 @@ public class CheckTest extends CliTestBase {
setupAuth(masterInstance);
Artemis.main("create", masterInstance.getAbsolutePath(), "--cluster-password", "artemis", "--cluster-user", "artemis", "--clustered",
- "--replicated", "--host", "127.0.0.1", "--default-port", "61616", "--silent", "--no-autotune", "--no-web", "--require-login");
+ "--replicated", "--host", "127.0.0.1", "--default-port", "61616", "--silent", "--no-autotune", "--no-web", "--require-login", "--name=live");
Artemis.main("create", slaveInstance.getAbsolutePath(), "--cluster-password", "artemis", "--cluster-user", "artemis", "--clustered",
- "--replicated", "--host", "127.0.0.1", "--default-port", "61626", "--silent", "--no-autotune", "--no-web", "--require-login", "--slave");
+ "--replicated", "--host", "127.0.0.1", "--default-port", "61626", "--silent", "--no-autotune", "--no-web", "--require-login", "--slave", "--name=backup");
System.setProperty("artemis.instance", masterInstance.getAbsolutePath());
Object master = Artemis.execute(false, false, null, masterInstance, null, "run");
@@ -196,10 +195,12 @@ public class CheckTest extends CliTestBase {
nodeCheck.setPeers(2);
Assert.assertEquals(3, nodeCheck.execute(context));
} finally {
- Artemis.internalExecute(null, slaveInstance, null, new String[] {"stop"}, ActionContext.system());
+ Artemis.execute(false, false, null, slaveInstance, null, "stop");
+ Wait.assertFalse(slaveServer::isStarted);
}
} finally {
- stopServer();
+ Artemis.execute(false, false, null, masterInstance, null, "stop");
+ Wait.assertFalse(masterServer::isStarted);
}
}
diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/OptionsValidationTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/OptionsValidationTest.java
deleted file mode 100644
index 3d2f03611c..0000000000
--- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/OptionsValidationTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.activemq.cli.test;
-
-import com.github.rvesse.airline.parser.errors.ParseArgumentsUnexpectedException;
-import org.apache.activemq.artemis.cli.Artemis;
-import org.apache.activemq.artemis.cli.commands.ActionContext;
-import org.apache.activemq.artemis.cli.commands.InvalidOptionsError;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collection;
-
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-@RunWith(value = Parameterized.class)
-public class OptionsValidationTest extends CliTestBase {
-
- private File artemisInstance;
-
- private String group;
- private String command;
- private boolean needInstance;
-
- @Parameterized.Parameters(name = "group={0}, command={1}, need-instance={2}")
- public static Collection getParameters() {
- return Arrays.asList(new Object[][]{{null, "create", false},
- {null, "run", true},
- {null, "kill", true},
- {null, "stop", true},
- {"address", "create", false},
- {"address", "delete", false},
- {"address", "update", false},
- {"address", "show", false},
- {null, "browser", false},
- {null, "consumer", false},
- {null, "mask", false},
- {null, "help", false},
- {null, "migrate1x", false},
- {null, "producer", false},
- {"queue", "create", false},
- {"queue", "delete", false},
- {"queue", "update", false},
- {"data", "print", false},
- {"data", "print", true},
- {"data", "exp", true},
- {"data", "imp", true},
- {"data", "encode", true},
- {"data", "decode", true},
- {"data", "compact", true},
- {"user", "add", true},
- {"user", "rm", true},
- {"user", "list", true},
- {"user", "reset", true}
- });
- }
-
- public OptionsValidationTest(String group, String command, boolean needInstance) {
- this.group = group;
- this.command = command;
- this.needInstance = needInstance;
- }
-
- @Before
- public void setUp() throws Exception {
- super.setup();
- this.artemisInstance = new File(temporaryFolder.getRoot() + "instance1");
- }
-
- @After
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- }
-
- @Test
- public void testCommand() throws Exception {
- ActionContext context = new TestActionContext();
- String[] invalidArgs = null;
- if (group == null) {
- invalidArgs = new String[] {command, "--blahblah-" + command, "--rubbish-" + command + "=" + "more-rubbish", "--input=blahblah"};
- } else {
- invalidArgs = new String[] {group, command, "--blahblah-" + command, "--rubbish-" + command + "=" + "more-rubbish", "--input=blahblah"};
- }
- try {
- Artemis.internalExecute(null, needInstance ? this.artemisInstance : null, null, invalidArgs, context);
- fail("cannot detect invalid options");
- } catch (InvalidOptionsError e) {
- assertTrue(e.getMessage().contains("Found unexpected parameters"));
- } catch (ParseArgumentsUnexpectedException e) {
- //airline can detect some invalid args during parsing
- //which is fine.
- }
- }
-}
diff --git a/artemis-distribution/src/main/resources/licenses/bin/LICENSE b/artemis-distribution/src/main/resources/licenses/bin/LICENSE
index 2c4e096055..f40c8ec910 100644
--- a/artemis-distribution/src/main/resources/licenses/bin/LICENSE
+++ b/artemis-distribution/src/main/resources/licenses/bin/LICENSE
@@ -286,6 +286,12 @@ For HdrHistogram:
This product bundles HdrHistogram, which is available under the
"2-clause BSD" license. For details, see licences/LICENSE-hdrhistogram.txt.
+==============================================================================
+For JLine:
+==============================================================================
+This product bundles JLine, which is available under the
+"3-clause BSD" license. For details, see licences/LICENSE-jline.txt.
+
==============================================================================
Apache ActiveMQ Artemis Subcomponents:
diff --git a/artemis-distribution/src/main/resources/licenses/bin/licenses/LICENSE-jline.txt b/artemis-distribution/src/main/resources/licenses/bin/licenses/LICENSE-jline.txt
new file mode 100644
index 0000000000..d159219c31
--- /dev/null
+++ b/artemis-distribution/src/main/resources/licenses/bin/licenses/LICENSE-jline.txt
@@ -0,0 +1,34 @@
+Copyright (c) 2002-2018, the original author or authors.
+All rights reserved.
+
+https://opensource.org/licenses/BSD-3-Clause
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following
+conditions are met:
+
+Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with
+the distribution.
+
+Neither the name of JLine nor the names of its contributors
+may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/docs/user-manual/en/SUMMARY.md b/docs/user-manual/en/SUMMARY.md
index 7fadf46a19..0ece7a6a66 100644
--- a/docs/user-manual/en/SUMMARY.md
+++ b/docs/user-manual/en/SUMMARY.md
@@ -8,6 +8,7 @@
* [Messaging Concepts](messaging-concepts.md)
* [Architecture](architecture.md)
* [Using the Server](using-server.md)
+* [Command Line Interface](using-cli.md)
* [Upgrading](upgrading.md)
* Address
* [Model](address-model.md)
diff --git a/docs/user-manual/en/architecture.md b/docs/user-manual/en/architecture.md
index 5dd62db87e..572ff60207 100644
--- a/docs/user-manual/en/architecture.md
+++ b/docs/user-manual/en/architecture.md
@@ -66,9 +66,6 @@ The normal stand-alone messaging broker configuration comprises a core
messaging broker and a number of protocol managers that provide support for the
various protocol mentioned earlier.
-The standalone broker configuration uses
-[Airline](http://rvesse.github.io/airline/) for bootstrapping the Broker.
-
The stand-alone broker architecture is shown in figure 3.3 below:
![ActiveMQ Artemis architecture3](images/architecture3.jpg)
diff --git a/docs/user-manual/en/embedding-activemq.md b/docs/user-manual/en/embedding-activemq.md
index be4b15b380..7b00c45089 100644
--- a/docs/user-manual/en/embedding-activemq.md
+++ b/docs/user-manual/en/embedding-activemq.md
@@ -122,7 +122,4 @@ server.start();
You may also choose to use a dependency injection framework such as The Spring
Framework. See [Spring Integration](spring-integration.md) for more details on
-Spring and Apache ActiveMQ Artemis.
-
-Apache ActiveMQ Artemis standalone uses
-[Airline](http://rvesse.github.io/airline/) to bootstrap.
+Spring and Apache ActiveMQ Artemis.
\ No newline at end of file
diff --git a/docs/user-manual/en/using-cli.md b/docs/user-manual/en/using-cli.md
new file mode 100644
index 0000000000..059ea334f1
--- /dev/null
+++ b/docs/user-manual/en/using-cli.md
@@ -0,0 +1,409 @@
+## Command Line Interface
+
+ActiveMQ Artemis has a Command Line Interface (CLI) that can used to manage a few aspects of the broker like instance creation, basic user management, queues, etc.
+
+There are two ways the CLI can be used:
+
+- Bash Shell
+ - A traditional CLI that can be accessed by './artemis <COMMAND> ARGUMENTS...'
+- Artemis Shell
+ - A shell emulation that is accesssed by './artemis' or './artemis shell".
+
+
+All commands available through the traditional Command Line Interface (CLI) are also available through the Shell interface.
+
+The Shell interface will reuse some information as you repeat commands, such as the user, password, and target broker URI making the repetitive use a bit simpler.
+
+The CLI interface however could be used in your bash scripts for your own automation while the Shell session being a user interface in a terminal session.
+
+### Getting Help
+
+All of these commands can be accessed in the form of calling "artemis [COMMAND] [PARAMETERS]". You can get a complete list of available commands by typing:
+
+./artemis help
+
+```shell
+Usage: artemis [COMMAND]
+ActiveMQ Artemis Command Line
+Commands:
+ help use 'help <command>' for more information
+ auto-complete Generates the auto complete script file to be used in bash or
+ zsh.
+ shell JLine3 shell helping using the CLI
+ producer Send message(s) to a broker.
+ transfer Move messages from one destination towards another destination.
+ consumer Consume messages from a queue.
+ browser Browse messages on a queue.
+ mask Mask a password and print it out.
+ version Print version information.
+ perf use 'help perf' for sub commands list
+ check use 'help check' for sub commands list
+ queue use 'help check' for sub commands list
+ address use 'help address' for sub commands list
+ data use 'help data' for sub commands list
+ create Create a new broker instance.
+ upgrade Update a broker instance to the current artemis.home, keeping
+ all the data and broker.xml. Warning: backup your instance
+ before using this command and compare the files.
+```
+
+It is also possible to use help at a specific command or sub-command for more information.
+Examples:
+
+To get a list of sub commands for data, you type './artemis help data':
+
+```shell
+Commands:
+ recover Recover (undelete) every message on the journal by creating a new
+ output journal. Rolled back and acked messages will be sent out to
+ the output as much as possible.
+ print Print data records information. WARNING: don't use while a
+ production server is running.
+ exp Export all message-data using an XML that could be interpreted by
+ any system.
+ imp Import all message-data using an XML that could be interpreted by
+ any system.
+ decode Decode a journal's internal format into a new set of journal files.
+ encode Encode a set of journal files into an internal encoded data format.
+ compact Compact the journal of a non running server.
+```
+
+Or getting information about a particular command.
+
+For example './artemis help create'
+
+```shell
+Usage: artemis create [--aio] [--allow-anonymous] [--autocreate] [--autodelete]
+ [--blocking] [--clustered] [--cygwin]
+ [--disable-persistence] [--failover-on-shutdown]
+ [--force] [--jdbc] [--mapped] [--nio]
+ [--no-amqp-acceptor] [--no-autocreate] [--no-autotune]
+ [--no-fsync] [--no-hornetq-acceptor] [--no-mqtt-acceptor]
+ [--no-stomp-acceptor] [--no-web] [--paging]
+ [--relax-jolokia] [--replicated] [--require-login]
+ [--shared-store] [--silent] [--slave]
+ [--support-advisory]
+ [--suppress-internal-management-objects]
+ [--use-client-auth] [--verbose] [--windows]
+ [--addresses=<addresses>]
+ [--cluster-password=<clusterPassword>]
+ [--cluster-user=<clusterUser>] [--data=<data>]
+ [--default-port=<defaultPort>] [--encoding=<encoding>]
+ [--etc=<etc>] [--global-max-messages=<globalMaxMessages>]
+ [--global-max-size=<globalMaxSize>] [--home=<home>]
+ [--host=<host>] [--http-host=<httpHost>]
+ [--http-port=<httpPort>] [--java-memory=<javaMemory>]
+ [--jdbc-bindings-table-name=<jdbcBindings>]
+ [--jdbc-connection-url=<jdbcURL>]
+ [--jdbc-driver-class-name=<jdbcClassName>]
+ [--jdbc-large-message-table-name=<jdbcLargeMessages>]
+ [--jdbc-lock-expiration=<jdbcLockExpiration>]
+ [--jdbc-lock-renew-period=<jdbcLockRenewPeriod>]
+ [--jdbc-message-table-name=<jdbcMessages>]
+ [--jdbc-network-timeout=<jdbcNetworkTimeout>]
+ [--jdbc-node-manager-table-name=<jdbcNodeManager>]
+ [--jdbc-page-store-table-name=<jdbcPageStore>]
+ [--journal-device-block-size=<journalDeviceBlockSize>]
+ [--journal-retention=<retentionDays>]
+ [--journal-retention-max-bytes=<retentionMaxBytes>]
+ [--max-hops=<maxHops>]
+ [--message-load-balancing=<messageLoadBalancing>]
+ [--name=<name>] [--password=<password>] [--ping=<ping>]
+ [--port-offset=<portOffset>] [--queues=<queues>]
+ [--role=<role>] [--security-manager=<securityManager>]
+ [--ssl-key=<sslKey>]
+ [--ssl-key-password=<sslKeyPassword>]
+ [--ssl-trust=<sslTrust>]
+ [--ssl-trust-password=<sslTrustPassword>]
+ [--staticCluster=<staticNode>] [--user=<user>]
+ [--java-options=<javaOptions>]... <directory>
+Create a new broker instance.
+ <directory> The instance directory to hold the broker's
+ configuration and data. Path must be writable.
+ --addresses=<addresses>
+ A comma separated list of addresses with the
+ option to specify a routing type, e.g.
+ --addresses myAddress1,myAddress2:anycast.
+ Routing-type default: multicast.
+ --aio Set the journal as asyncio.
+ --allow-anonymous Allow connections from users with no security
+ credentials. Opposite of --require-login.
+ Default: input.
+ --autocreate Allow automatic creation of addresses & queues.
+ Default: true.
+ --autodelete Allow automatic deletion of addresses & queues.
+ Default: false.
+ --blocking Block producers when address becomes full.
+ Opposite of --paging. Default: false.
+ --cluster-password=<clusterPassword>
+ The password to use for clustering. Default: input.
+ --cluster-user=<clusterUser>
+ The user to use for clustering. Default: input.
+ --clustered Enable clustering.
+ --cygwin Force Cygwin script creation. Default: based on
+ your actual system.
+ --data=<data> Directory where ActiveMQ data are stored. Paths
+ can be absolute or relative to artemis.instance
+ directory. Default: data.
+ --default-port=<defaultPort>
+ The port number to use for the main 'artemis'
+ acceptor. Default: 61616.
+ --disable-persistence Disable message persistence to the journal
+ --encoding=<encoding> The encoding that text files should use. Default:
+ UTF-8.
+ --etc=<etc> Directory where ActiveMQ configuration is located.
+ Paths can be absolute or relative to artemis.
+ instance directory. Default: etc.
+ --failover-on-shutdown Whether broker shutdown will trigger failover for
+ clients using the core protocol. Valid only for
+ shared store. Default: false.
+ --force Overwrite configuration at destination directory.
+ --global-max-messages=<globalMaxMessages>
+ Maximum number of messages that will be accepted
+ in memory before using address full policy mode.
+ Default: undefined.
+ --global-max-size=<globalMaxSize>
+ Maximum amount of memory which message data may
+ consume. Default: half of the JVM's max memory.
+ --home=<home> Directory where ActiveMQ Artemis is installed.
+ --host=<host> Broker's host name. Default: 0.0.0.0 or input if
+ clustered).
+ --http-host=<httpHost> Embedded web server's host name. Default:
+ localhost.
+ --http-port=<httpPort> Embedded web server's port. Default: 8161.
+ --java-memory=<javaMemory>
+ Define the -Xmx memory parameter for the broker.
+ Default: 2G.
+ --java-options=<javaOptions>
+ Extra Java options to be passed to the profile.
+ --jdbc Store message data in JDBC instead of local files.
+ --jdbc-bindings-table-name=<jdbcBindings>
+ Name of the jdbc bindings table.
+ --jdbc-connection-url=<jdbcURL>
+ The URL used for the database connection.
+ --jdbc-driver-class-name=<jdbcClassName>
+ JDBC driver classname.
+ --jdbc-large-message-table-name=<jdbcLargeMessages>
+ Name of the large messages table.
+ --jdbc-lock-expiration=<jdbcLockExpiration>
+ Lock expiration (in milliseconds).
+ --jdbc-lock-renew-period=<jdbcLockRenewPeriod>
+ Lock Renew Period (in milliseconds).
+ --jdbc-message-table-name=<jdbcMessages>
+ Name of the jdbc messages table.
+ --jdbc-network-timeout=<jdbcNetworkTimeout>
+ Network timeout (in milliseconds).
+ --jdbc-node-manager-table-name=<jdbcNodeManager>
+ Name of the jdbc node manager table.
+ --jdbc-page-store-table-name=<jdbcPageStore>
+ Name of the page store messages table.
+ --journal-device-block-size=<journalDeviceBlockSize>
+ The block size of the journal's storage device.
+ Default: 4096.
+ --journal-retention=<retentionDays>
+ Configure journal retention in days. If > 0 then
+ enable journal-retention-directory from broker.
+ xml allowing replay options.
+ --journal-retention-max-bytes=<retentionMaxBytes>
+ Maximum number of bytes to keep in the retention
+ directory.
+ --mapped Set the journal as mapped.
+ --max-hops=<maxHops> Number of hops on the cluster configuration.
+ --message-load-balancing=<messageLoadBalancing>
+ Message load balancing policy for cluster.
+ Default: ON_DEMAND. Valid values: ON_DEMAND,
+ STRICT, OFF, OFF_WITH_REDISTRIBUTION.
+ --name=<name> The name of the broker. Default: same as host name.
+ --nio Set the journal as nio.
+ --no-amqp-acceptor Disable the AMQP specific acceptor.
+ --no-autocreate Disable auto creation for addresses & queues.
+ --no-autotune Disable auto tuning of the journal-buffer-timeout
+ in broker.xml.
+ --no-fsync Disable usage of fdatasync (channel.force(false)
+ from Java NIO) on the journal.
+ --no-hornetq-acceptor Disable the HornetQ specific acceptor.
+ --no-mqtt-acceptor Disable the MQTT specific acceptor.
+ --no-stomp-acceptor Disable the STOMP specific acceptor.
+ --no-web Whether to omit the web-server definition from
+ bootstrap.xml.
+ --paging Page messages to disk when address becomes full.
+ Opposite of --blocking. Default: true.
+ --password=<password> The user's password. Default: input.
+ --ping=<ping> A comma separated string to be passed on to the
+ broker config as network-check-list. The broker
+ will shutdown when all these addresses are
+ unreachable.
+ --port-offset=<portOffset>
+ How much to off-set the ports of every acceptor.
+ --queues=<queues> A comma separated list of queues with the option
+ to specify a routing type, e.g. --queues
+ myQueue1,myQueue2:multicast. Routing-type
+ default: anycast.
+ --relax-jolokia Disable strict checking in jolokia-access.xml.
+ --replicated Enable broker replication.
+ --require-login Require security credentials from users for
+ connection. Opposite of --allow-anonymous.
+ --role=<role> The name for the role created. Default: amq.
+ --security-manager=<securityManager>
+ Which security manager to use - jaas or basic.
+ Default: jaas.
+ --shared-store Enable broker shared store.
+ --silent Disable all the inputs, and make a best guess for
+ any required input.
+ --slave Be a slave broker. Valid for shared store or
+ replication.
+ --ssl-key=<sslKey> Embedded web server's key store path.
+ --ssl-key-password=<sslKeyPassword>
+ The key store's password.
+ --ssl-trust=<sslTrust> The trust store path in case of client
+ authentication.
+ --ssl-trust-password=<sslTrustPassword>
+ The trust store's password.
+ --staticCluster=<staticNode>
+ Cluster node connectors list separated by comma, e.
+ g. "tcp://server:61616,tcp://server2:61616,tcp:
+ //server3:61616".
+ --support-advisory Support advisory messages for the OpenWire
+ protocol.
+ --suppress-internal-management-objects
+ Do not register any advisory addresses/queues for
+ the OpenWire protocol with the broker's
+ management service.
+ --use-client-auth Require client certificate authentication when
+ connecting to the embedded web server.
+ --user=<user> The username. Default: input.
+ --verbose Print additional information.
+ --windows Force Windows script creation. Default: based on
+ your actual system.
+```
+
+#### Bash and ZSH auto complete
+
+Bash and ZSH provide ways to auto-complete command line interfaces. To integrate with that functionality you have the option to generate the 'auto-complete' script:
+
+```shell
+./artemis auto-complete
+```
+
+This will generate a file named auto-complete-artemis.sh that should be used with:
+
+```shell
+source ./auto-complete-artemis.sh
+```
+
+After the auto completion installed in the bash session, bash would start to show auto-completion information upon the pressure of the key [TAB]:
+
+```shell
+ bin % ./artemis
+activation browser create kill perf-journal run transfer version
+address check data mask producer shell upgrade
+auto-complete consumer help perf queue stop user
+```
+
+Same showing options:
+
+```
+ bin % ./artemis create --
+--addresses --jdbc-bindings-table-name --paging
+--aio --jdbc-connection-url --password
+--allow-anonymous --jdbc-driver-class-name --ping
+--autocreate --jdbc-large-message-table-name --port-offset
+--autodelete --jdbc-lock-expiration --queues
+--blocking --jdbc-lock-renew-period --relax-jolokia
+--cluster-password --jdbc-message-table-name --replicated
+--cluster-user --jdbc-network-timeout --require-login
+--clustered --jdbc-node-manager-table-name --role
+
+```
+
+## Input required
+
+Some functionality on the CLI may require user input if not provided through a parameter in cases like connecting to a broker or creating the broker instance.
+
+For example:
+
+```shell
+bin % ./artemis queue stat
+Connection brokerURL = tcp://localhost:61616
+Connection failed::AMQ229031: Unable to validate user from /127.0.0.1:56320. Username: null; SSL certificate subject DN: unavailable
+
+--user:
+Type the username for a retry
+a
+
+--password: is mandatory with this configuration:
+Type the password for a retry
+```
+
+## Artemis Shell
+
+To initialize the shell session, type './artemis shell' (or just ./artemis if you prefer):
+
+```shell
+./artemis
+```
+
+The ActiveMQ Artemis Shell provides an interface that can be used to call the CLI commands directly without leaving the Java Virtual Machine.
+
+```shell
+ _ _ _
+ / \ ____| |_ ___ __ __(_) _____
+ / _ \| _ \ __|/ _ \ \/ | |/ __/
+ / ___ \ | \/ |_/ __/ |\/| | |\___ \
+ /_/ \_\| \__\____|_| |_|_|/___ /
+ Apache ActiveMQ Artemis
+
+
+For a list of commands, type help or press <TAB>:
+Type exit or press <CTRL-D> to leave the session:
+Apache ActiveMQ Artemis >
+```
+
+### Connecting
+
+It is possible to authenticate your CLI client once to the server, and reuse the connection information for future commands being performed:
+
+```shell
+Apache ActiveMQ Artemis > connect --user=a --password=b --url tcp://localhost:61616
+Connection brokerURL = tcp://localhost:61616
+Connection Successful!
+```
+Now any command requiring authentication will reuse these parameters.
+
+For example the sub-command 'queue stat' will reuse previous information to perform its connection to the broker.
+
+````shell
+Apache ActiveMQ Artemis > queue stat
+Connection brokerURL = tcp://localhost:61616
+|NAME |ADDRESS |CONSUMER_COUNT|MESSAGE_COUNT|MESSAGES_ADDED|DELIVERING_COUNT|MESSAGES_ACKED|SCHEDULED_COUNT|ROUTING_TYPE|
+|DLQ |DLQ |0 |0 |0 |0 |0 |0 |ANYCAST |
+|ExpiryQueue |ExpiryQueue |0 |0 |0 |0 |0 |0 |ANYCAST |
+|Order |Order |0 |4347 |4347 |0 |0 |0 |ANYCAST |
+|activemq.management.0b...|activemq.management.0b...|1 |0 |0 |0 |0 |0 |MULTICAST |
+````
+
+#### Connecting from Command Line
+
+To make the initial connection simpler, it is possible to start the shell with an initial connection from the startup:
+
+```shell
+./artemis shell --user <username> --password <password> --url <tcp://myserver:myport>
+```
+
+The CLI should not ask for an user/password for any further commands with this option being used:
+
+Example:
+
+```shell
+bin % ./artemis shell --user a --password b
+...
+
+
+Apache ActiveMQ Artemis > queue stat
+Connection brokerURL = tcp://localhost:61616
+|NAME |ADDRESS |CONSUMER_COUNT|MESSAGE_COUNT|MESSAGES_ADDED|DELIVERING_COUNT|MESSAGES_ACKED|SCHEDULED_COUNT|ROUTING_TYPE|
+|DLQ |DLQ |0 |0 |0 |0 |0 |0 |ANYCAST |
+|ExpiryQueue |ExpiryQueue |0 |0 |0 |0 |0 |0 |ANYCAST |
+|TEST |TEST |0 |8743 |8743 |0 |0 |0 |ANYCAST |
+|activemq.management.2a...|activemq.management.2a...|1 |0 |0 |0 |0 |0 |MULTICAST |
+```
\ No newline at end of file
diff --git a/docs/user-manual/en/using-server.md b/docs/user-manual/en/using-server.md
index 1c6b087c39..59681e2a0f 100644
--- a/docs/user-manual/en/using-server.md
+++ b/docs/user-manual/en/using-server.md
@@ -63,6 +63,11 @@ On Unix systems, it is a common convention to store this kind of runtime data
under the `/var/lib` directory. For example, to create an instance at
`/var/lib/mybroker`, run the following commands in your command line shell:
+Before the broker is used, a broker *instance* must be created.
+This process requires the use of the [Command Line Interface](using-cli.md) which is better explained in its own chapter.
+
+In the following example a broker instance named mybroker will be created.
+
```sh
cd /var/lib
${ARTEMIS_HOME}/bin/artemis create mybroker
diff --git a/pom.xml b/pom.xml
index 806c4611b8..347ac8226b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -130,7 +130,9 @@
<johnzon.version>1.2.21</johnzon.version>
<hawtbuff.version>1.11</hawtbuff.version>
<hawtdispatch.version>1.22</hawtdispatch.version>
- <airline.version>2.9.0</airline.version>
+ <picocli.version>4.7.4</picocli.version>
+ <jline.version>3.23.0</jline.version>
+ <jansi.version>2.4.0</jansi.version>
<jakarta.activation-api.version>1.2.2</jakarta.activation-api.version>
<jakarta.annotation-api.version>1.3.5</jakarta.annotation-api.version>
<jakarta.ejb-api.version>3.2.6</jakarta.ejb-api.version>
@@ -586,15 +588,28 @@
<!-- License: Apache 2.0 -->
</dependency>
<dependency>
- <groupId>com.github.rvesse</groupId>
- <artifactId>airline</artifactId>
- <version>${airline.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.github.rvesse</groupId>
- <artifactId>airline-backcompat-javaxinject</artifactId>
- </exclusion>
- </exclusions>
+ <groupId>info.picocli</groupId>
+ <artifactId>picocli</artifactId>
+ <version>${picocli.version}</version>
+ <!-- License: Apache 2.0 -->
+ </dependency>
+ <dependency>
+ <groupId>info.picocli</groupId>
+ <artifactId>picocli-shell-jline3</artifactId>
+ <version>${picocli.version}</version>
+ <!-- License: Apache 2.0 -->
+ </dependency>
+ <dependency>
+ <groupId>org.jline</groupId>
+ <artifactId>jline</artifactId>
+ <version>${jline.version}</version>
+ <!-- License: BSD 3-Clause -->
+ </dependency>
+ <dependency>
+ <!-- used by jline to provide an ansi terminal -->
+ <groupId>org.fusesource.jansi</groupId>
+ <artifactId>jansi</artifactId>
+ <version>${jansi.version}</version>
<!-- License: Apache 2.0 -->
</dependency>
<!--needed to compile transport jar-->
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/RecoverTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/RecoverTest.java
index 299e7e71c6..e6374f93a6 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/RecoverTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/RecoverTest.java
@@ -28,6 +28,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
+import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.tools.RecoverMessages;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.JournalType;
@@ -173,7 +174,7 @@ public class RecoverTest extends JMSTestBase {
File newJournalLocation = new File(server.getConfiguration().getJournalLocation().getParentFile(), "recovered");
- RecoverMessages.recover(server.getConfiguration(), server.getConfiguration().getJournalRetentionDirectory(), newJournalLocation, server.getConfiguration().getLargeMessagesLocation(), false);
+ RecoverMessages.recover(new ActionContext(), server.getConfiguration(), server.getConfiguration().getJournalRetentionDirectory(), newJournalLocation, server.getConfiguration().getLargeMessagesLocation(), false);
if (large) {
File[] largeMessageFiles = server.getConfiguration().getLargeMessagesLocation().listFiles();
diff --git a/tests/smoke-tests/pom.xml b/tests/smoke-tests/pom.xml
index f790821530..8200629364 100644
--- a/tests/smoke-tests/pom.xml
+++ b/tests/smoke-tests/pom.xml
@@ -1220,6 +1220,7 @@
<password>artemis</password>
<allowAnonymous>true</allowAnonymous>
<noWeb>true</noWeb>
+ <portOffset>100</portOffset>
<instance>${basedir}/target/clusteredLargeMessage/cluster2</instance>
<configuration>${basedir}/target/classes/servers/clusteredLargeMessage/cluster2</configuration>
<args>
@@ -1230,8 +1231,6 @@
<arg>tcp://localhost:61616</arg>
<arg>--max-hops</arg>
<arg>1</arg>
- <arg>--port-offset</arg>
- <arg>100</arg>
<arg>--queues</arg>
<arg>testQueue</arg>
</args>
diff --git a/tests/soak-tests/pom.xml b/tests/soak-tests/pom.xml
index 1cb11fcb0b..9559ad2491 100644
--- a/tests/soak-tests/pom.xml
+++ b/tests/soak-tests/pom.xml
@@ -387,8 +387,6 @@
<arg>--clustered</arg>
<arg>--staticCluster</arg>
<arg>tcp://localhost:61716</arg>
- <arg>--java-options</arg>
- <arg>-Djava.rmi.server.hostname=localhost</arg>
<arg>--queues</arg>
<arg>ClusteredLargeMessageInterruptTest</arg>
<arg>--name</arg>
@@ -417,8 +415,6 @@
<arg>--clustered</arg>
<arg>--staticCluster</arg>
<arg>tcp://localhost:61616</arg>
- <arg>--java-options</arg>
- <arg>-Djava.rmi.server.hostname=localhost</arg>
<arg>--queues</arg>
<arg>ClusteredLargeMessageInterruptTest</arg>
<arg>--name</arg>