/*
* 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.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import io.airlift.airline.Cli;
import org.apache.activemq.artemis.cli.commands.Action;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.Create;
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.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.messages.Browse;
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.migration1x.Migrate1X;
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.UpdateQueue;
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.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.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;
/**
* Artemis is the main CLI entry point for managing/running a broker.
*
* Want to start or debug a broker from an IDE? This is probably the best class to
* run. Make sure set the -Dartemis.instance=path/to/instance system property.
* You should also use the 'apache-artemis' module for the class path since that
* includes all artemis modules.
*/
public class Artemis {
public static void main(String... args) throws Exception {
String home = System.getProperty("artemis.home");
File fileHome = home != null ? new File(home) : null;
String instance = System.getProperty("artemis.instance");
File fileInstance = instance != null ? new File(instance) : null;
execute(true, fileHome, fileInstance, args);
}
public static Object internalExecute(String... args) throws Exception {
return internalExecute(null, null, args);
}
public static Object execute(File artemisHome, File artemisInstance, List<String> args) throws Exception {
return execute(false, artemisHome, artemisInstance, args.toArray(new String[args.size()]));
}
public static Object execute(boolean inputEnabled, File artemisHome, File artemisInstance, ActionContext context, String... args) throws Exception {
if (inputEnabled) {
InputAbstract.enableInput();
}
try {
return internalExecute(artemisHome, artemisInstance, args, context);
} catch (ConfigurationException configException) {
System.err.println(configException.getMessage());
System.out.println();
System.out.println("Configuration should be specified as 'scheme:location'. Default configuration is 'xml:${ARTEMIS_INSTANCE}/etc/bootstrap.xml'");
return configException;
} catch (CLIException cliException) {
System.err.println(cliException.getMessage());
return cliException;
} catch (NullPointerException e) {
// Yeah.. I really meant System.err..
// this is the CLI and System.out and System.err are common places for interacting with the user
// this is a programming error that must be visualized and corrected
e.printStackTrace();
return e;
} catch (RuntimeException | InvalidOptionsError re) {
System.err.println(re.getMessage());
System.out.println();
Cli<Action> parser = builder(null).build();
parser.parse("help").execute(context);
return re;
}
}
public static Object execute(boolean inputEnabled, File artemisHome, File artemisInstance, String... args) throws Exception {
return execute(inputEnabled, artemisHome, artemisInstance, ActionContext.system(), args);
}
/**
* This method is used to validate exception returns.
* Useful on test cases
*/
private static Object internalExecute(File artemisHome, File artemisInstance, String[] args) throws Exception {
return internalExecute(artemisHome, artemisInstance, args, ActionContext.system());
}
public static Object internalExecute(File artemisHome, File artemisInstance, String[] args, ActionContext context) throws Exception {
Action action = builder(artemisInstance).build().parse(args);
action.setHomeValues(artemisHome, artemisInstance);
if (action.isVerbose()) {
System.out.print("Executing " + action.getClass().getName() + " ");
for (String arg : args) {
System.out.print(arg + " ");
}
System.out.println();
System.out.println("Home::" + action.getBrokerHome() + ", Instance::" + action.getBrokerInstance());
}
action.checkOptions(args);
return action.execute(context);
}
private static Cli.CliBuilder<Action> builder(File artemisInstance) {
String instance = artemisInstance != null ? artemisInstance.getAbsolutePath() : System.getProperty("artemis.instance");
Cli.CliBuilder<Action> builder = Cli.<Action>builder("artemis").withDescription("ActiveMQ Artemis Command Line").withCommand(HelpAction.class).withCommand(Producer.class).withCommand(Consumer.class).withCommand(Browse.class).withCommand(Mask.class).withDefaultCommand(HelpAction.class);
builder.withGroup("queue").withDescription("Queue tools group (create|delete|update) (example ./artemis queue create)").
withDefaultCommand(HelpQueue.class).withCommands(CreateQueue.class, DeleteQueue.class, UpdateQueue.class);
builder.withGroup("address").withDescription("Address tools group (create|delete|update|show) (example ./artemis address create)").
withDefaultCommand(HelpAddress.class).withCommands(CreateAddress.class, DeleteAddress.class, UpdateAddress.class, ShowAddress.class);
if (instance != null) {
builder.withGroup("data").withDescription("data tools group (print|imp|exp|encode|decode|compact) (example ./artemis data print)").
withDefaultCommand(HelpData.class).withCommands(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) (example ./artemis data print)").
withDefaultCommand(HelpData.class).withCommands(PrintData.class);
builder = builder.withCommand(Create.class);
builder = builder.withCommand(Migrate1X.class);
}
return builder;
}
public static void printBanner() throws Exception {
copy(Artemis.class.getResourceAsStream("banner.txt"), System.out);
}
private static long copy(InputStream in, OutputStream out) throws Exception {
try {
byte[] buffer = new byte[1024];
int len = in.read(buffer);
while (len != -1) {
out.write(buffer, 0, len);
len = in.read(buffer);
}
return len;
} finally {
in.close();
}
}
}