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.
This commit is contained in:
parent
1efb7e87d8
commit
93ee61e35c
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
||||
if (action.isVerbose()) {
|
||||
context.out.print("Executing " + action.getClass().getName() + " ");
|
||||
for (String arg : args) {
|
||||
context.out.print(arg + " ");
|
||||
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());
|
||||
}
|
||||
context.out.println();
|
||||
context.out.println("Home::" + action.getBrokerHome() + ", Instance::" + action.getBrokerInstance());
|
||||
}
|
||||
|
||||
action.checkOptions(args);
|
||||
return action.execute(context);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
/*
|
||||
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();
|
||||
}
|
||||
}
|
||||
if (parseResult == null) {
|
||||
throw new RuntimeException("Cannot match arg::" + Arrays.toString(args));
|
||||
}
|
||||
return parseResult.commandSpec().userObject();
|
||||
}
|
||||
|
||||
builder.withGroup("perf").withDescription("Perf tools group (example ./artemis perf client)")
|
||||
.withDefaultCommand(PerfClientCommand.class)
|
||||
.withCommands(PerfProducerCommand.class, PerfConsumerCommand.class, PerfClientCommand.class);
|
||||
public static CommandLine buildCommand(boolean includeInstanceCommands, boolean includeHomeCommands) {
|
||||
return buildCommand(includeInstanceCommands, includeHomeCommands, false);
|
||||
|
||||
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);
|
||||
public static CommandLine buildCommand(boolean includeInstanceCommands, boolean includeHomeCommands, boolean fromShell) {
|
||||
Artemis artemis = new Artemis();
|
||||
|
||||
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);
|
||||
CommandLine commandLine = new CommandLine(artemis);
|
||||
artemis.setCommandLine(commandLine);
|
||||
|
||||
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);
|
||||
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));
|
||||
}
|
||||
|
||||
return builder;
|
||||
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());
|
||||
}
|
||||
|
||||
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];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@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);
|
||||
try {
|
||||
CONNECTION_INFORMATION.remove();
|
||||
createConnectionFactory();
|
||||
System.out.println("Connection Successful!");
|
||||
} catch (Exception e) {
|
||||
System.out.println("Connection Failure!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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 org.apache.activemq.artemis.cli.commands.messages.ConnectionAbstract;
|
||||
import picocli.CommandLine;
|
||||
|
||||
@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);
|
||||
CONNECTION_INFORMATION.remove();
|
||||
System.out.println("Connection information cleared!");
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -16,40 +16,48 @@
|
|||
*/
|
||||
package org.apache.activemq.artemis.cli.commands;
|
||||
|
||||
import java.io.File;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
import com.github.rvesse.airline.help.Help;
|
||||
@Command(name = "help", description = "use 'help <command>' for more information")
|
||||
public class HelpAction implements Runnable {
|
||||
|
||||
public class HelpAction extends Help implements Action {
|
||||
CommandLine commandLine;
|
||||
|
||||
@Override
|
||||
public boolean isVerbose() {
|
||||
return false;
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
public CommandLine getCommandLine() {
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
public HelpAction setCommandLine(CommandLine commandLine) {
|
||||
this.commandLine = commandLine;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHomeValues(File brokerHome, File brokerInstance, File etcFolder) {
|
||||
|
||||
public void run() {
|
||||
help(commandLine, args);
|
||||
}
|
||||
|
||||
@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 {
|
||||
super.run();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.activation;
|
||||
|
||||
import org.apache.activemq.artemis.cli.commands.HelpAction;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
@Command(name = "activation", description = "use 'help activation' for sub commands list", subcommands = {ActivationSequenceList.class, ActivationSequenceSet.class})
|
||||
public class ActivationGroup implements Runnable {
|
||||
|
||||
CommandLine commandLine;
|
||||
|
||||
public ActivationGroup(CommandLine commandLine) {
|
||||
this.commandLine = commandLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HelpAction.help(commandLine, "activation");
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 org.apache.activemq.artemis.cli.commands.HelpAction;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
@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 {
|
||||
|
||||
CommandLine commandLine;
|
||||
|
||||
public AddressGroup(CommandLine commandLine) {
|
||||
this.commandLine = commandLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HelpAction.help(commandLine, "address");
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 org.apache.activemq.artemis.cli.commands.HelpAction;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
@Command(name = "check", description = "use 'help check' for sub commands list", subcommands = {NodeCheck.class, QueueCheck.class})
|
||||
public class CheckGroup implements Runnable {
|
||||
|
||||
CommandLine commandLine;
|
||||
|
||||
public CheckGroup(CommandLine commandLine) {
|
||||
this.commandLine = commandLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HelpAction.help(commandLine, "check");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.messages;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
public enum ConnectionProtocol {
|
||||
AMQP("AMQP"), CORE("CORE");
|
||||
|
||||
|
||||
private final String name;
|
||||
|
||||
ConnectionProtocol(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static ConnectionProtocol fromString(String value) {
|
||||
return ConnectionProtocol.valueOf(value.toUpperCase());
|
||||
}
|
||||
|
||||
public static class ProtocolConverter implements CommandLine.ITypeConverter<ConnectionProtocol> {
|
||||
@Override
|
||||
public ConnectionProtocol convert(String value) throws Exception {
|
||||
return ConnectionProtocol.fromString(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.messages.perf;
|
||||
|
||||
import org.apache.activemq.artemis.cli.commands.HelpAction;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
@Command(name = "perf", description = "use 'help perf' for sub commands list", subcommands = {PerfClientCommand.class, PerfProducerCommand.class, PerfConsumerCommand.class})
|
||||
public class PerfGroup implements Runnable {
|
||||
|
||||
CommandLine commandLine;
|
||||
|
||||
public PerfGroup(CommandLine commandLine) {
|
||||
this.commandLine = commandLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HelpAction.help(commandLine, "perf");
|
||||
}
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 org.apache.activemq.artemis.cli.commands.HelpAction;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
@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 {
|
||||
|
||||
CommandLine commandLine;
|
||||
|
||||
public QueueGroup(CommandLine commandLine) {
|
||||
this.commandLine = commandLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HelpAction.help(commandLine, "queue");
|
||||
}
|
||||
|
||||
}
|
|
@ -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 the queue name OR using a full filter '--field NAME --operation EQUALS --value X'.")
|
||||
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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 org.apache.activemq.artemis.cli.commands.HelpAction;
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
@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 {
|
||||
|
||||
CommandLine commandLine;
|
||||
|
||||
public UserGroup(CommandLine commandLine) {
|
||||
this.commandLine = commandLine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HelpAction.help(commandLine, "user");
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
|
@ -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 |
|
||||
```
|
|
@ -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
|
||||
|
|
35
pom.xml
35
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-->
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue