
com.swiftmq.admin.cli.CLI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swiftmq-client Show documentation
Show all versions of swiftmq-client Show documentation
Client for SwiftMQ Messaging System with JMS, AMQP 1.0 and file transfer over JMS.
The newest version!
/*
* Copyright 2019 IIT Software GmbH
*
* IIT Software GmbH 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 com.swiftmq.admin.cli;
import com.swiftmq.admin.cli.event.RouterListener;
import com.swiftmq.admin.mgmt.*;
import com.swiftmq.jms.ReconnectListener;
import com.swiftmq.mgmt.Command;
import com.swiftmq.mgmt.CommandExecutor;
import com.swiftmq.mgmt.CommandRegistry;
import com.swiftmq.mgmt.TreeCommands;
import com.swiftmq.tools.collection.ConcurrentList;
import com.swiftmq.tools.concurrent.Semaphore;
import com.swiftmq.tools.requestreply.RequestService;
import com.swiftmq.util.SwiftUtilities;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.terminal.TerminalBuilder;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.io.*;
import java.net.InetAddress;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
/**
* CLI is SwiftMQ's command line interface.
*
* It can be invoked from command line and can also be used for programmatic
* administration. For latter usage, CLI is to be constructed with a valid and stopped QueueConnection.
* The user of this QueueConnection must have full administrator rights which takes
* place if he has full right for the queue swiftmqmgmt of the respective routers or
* if the authentication is disabled.
*
* Programmatic administration with CLI is the same as invoking it from command line. All
* CLI commands can be invoked by the executeCommand method. There is only
* an exception regarding commands that return a result as 'ar', 'lc', 'show template'. These
* commands are not available for programmatic administration. Invoking such a command
* results in a CLIException.
*
* Please refer to the CLI documentation to get involved with the available CLI commands.
*
* Note (1):
* To detect a connection lost, for example, as a result of a 'reboot' command for the
* router the QueueConnection is connected to, you have to register your own ExceptionListener
* on the QueueConnection.
* Note (2):
* CLI can be used only from a single thread of execution. Executing methods from different
* threads concurrently can result in an unexpected behavior.
* Note (3):
* If the connection factory from which the CLI JMS connection is created is configured for
* transparent reconnect (default in SwiftMQ HA Router), CLI reconnects as well. However, it does
* not restore the last router in use ('sr' command) nor does it restore the last CLI context
* ('cc' command). This is the responsibility of the application that uses CLI. In order to
* restore the router and context, an application must catch CLIReconnectedException and
* issue the last 'sr' and 'cc' commands before retrying the command that leads to the
* CLIReconnectedException.
*
* @author IIT GmbH, Bremen/Germany
* @since 1.2
*/
public class CLI implements ReconnectListener {
private static String INIT_FILE_PROP = "swiftmq.cli.init";
private static final String DEFAULT_INIT_FILE = System.getProperty("user.home") + File.separatorChar + ".init.cli";
ConnectionHolder connectionHolder = null;
LineReader inReader = null;
// BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in));
BufferedReader scriptReader = null;
boolean programmatic = false;
Semaphore waitSem = new Semaphore();
volatile String waitFor = null;
List listeners = new ConcurrentList<>(new ArrayList<>());
Set availableRouters = ConcurrentHashMap.newKeySet();
CommandRegistry commandRegistry = new CommandRegistry("CLI shell", null);
Endpoint actRouter = null;
EndpointRegistry endpointRegistry = new EndpointRegistry();
Map aliases = new ConcurrentSkipListMap<>();
;
PrintWriter outWriter = null;
boolean reconnected = false;
boolean substitute = false;
boolean verbose = false;
Map vars = new ConcurrentHashMap<>();
Semaphore waitForRouters = new Semaphore();
private CLI() {
CommandExecutor exitExecutor = (context, entity, cmd) -> {
if (cmd.length != 1)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'exit'"};
close();
System.exit(-1);
return null;
};
Command exitCommand = new Command("exit", "exit", "Exit CLI", true, exitExecutor);
commandRegistry.addCommand(exitCommand);
CommandExecutor switchExecutor = (context, entity, cmd) -> {
if (cmd.length != 2)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'sr '"};
if (availableRouters.contains(cmd[1])) {
try {
Endpoint routerContext = endpointRegistry.get(cmd[1]);
if (routerContext == null)
routerContext = createEndpoint(cmd[1], false);
actRouter = routerContext;
commandRegistry.setDefaultCommand(actRouter);
vars.put("routername", cmd[1]);
} catch (Exception e) {
return new String[]{TreeCommands.ERROR, e.toString()};
}
return null;
}
return new String[]{TreeCommands.ERROR, "Router '" + cmd[1] + "' is unknown."};
};
Command switchCommand = new Command("sr", "sr ", "Switch to Router ", true, switchExecutor);
commandRegistry.addCommand(switchCommand);
CommandExecutor availExecutor = (context, entity, cmd) -> {
if (cmd.length != 1)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'ar'"};
ArrayList al = new ArrayList();
al.add(TreeCommands.RESULT);
al.add("Available Routers:");
al.add("");
String[] s = (String[]) availableRouters.toArray(new String[availableRouters.size()]);
for (int i = 0; i < s.length; i++)
al.add(s[i]);
al.add("");
return (String[]) al.toArray(new String[al.size()]);
};
Command availCommand = new Command("ar", "ar", "Show all available Routers", true, availExecutor);
commandRegistry.addCommand(availCommand);
CommandExecutor wrExecutor = (context, entity, cmd) -> {
if (cmd.length < 2 || cmd.length > 3)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'wr []'"};
if (cmd.length == 2)
waitForRouter(cmd[1]);
else
waitForRouter(cmd[1], Long.valueOf(cmd[2]));
return null;
};
Command wrCommand = new Command("wr", "wr []", "Wait for availability of router ", true, wrExecutor);
commandRegistry.addCommand(wrCommand);
CommandExecutor substituteExecutor = (context, entity, cmd) -> {
if (cmd.length != 2)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'substitute on | off'"};
if (cmd[1].equals("on"))
substitute = true;
else if (cmd[1].equals("off"))
substitute = false;
else
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'substitute on | off'"};
return null;
};
Command substituteCommand = new Command("substitute", "substitute on | off", "Substitutes variables in a command", true, substituteExecutor);
commandRegistry.addCommand(substituteCommand);
CommandExecutor verboseExecutor = (context, entity, cmd) -> {
if (cmd.length != 2)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'verbose on | off'"};
if (cmd[1].equals("on"))
verbose = true;
else if (cmd[1].equals("off"))
verbose = false;
else
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'verbose on | off'"};
return null;
};
Command verboseCommand = new Command("verbose", "verbose on | off", "Displays each CLI script command before execution", true, verboseExecutor);
commandRegistry.addCommand(verboseCommand);
CommandExecutor outputExecutor = (context, entity, cmd) -> {
if (cmd.length != 2)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'output | console'"};
try {
if (cmd[1].equals("console"))
outWriter = null;
else {
File f = new File(cmd[1]);
if (f.exists())
f.delete();
outWriter = new PrintWriter(new FileWriter(f), true);
}
} catch (IOException e) {
return new String[]{TreeCommands.ERROR, e.getMessage()};
}
return null;
};
Command outputCommand = new Command("output", "output | console", "Redirect result output", true, outputExecutor);
commandRegistry.addCommand(outputCommand);
CommandExecutor echoExecutor = (context, entity, cmd) -> {
StringBuffer b = new StringBuffer("");
if (cmd.length > 1) {
for (int i = 1; i < cmd.length; i++) {
if (i != 1)
b.append(' ');
b.append(cmd[i]);
}
}
return new String[]{TreeCommands.RESULT, b.toString()};
};
Command echoCommand = new Command("echo", "echo []", "Echos a message", true, echoExecutor);
commandRegistry.addCommand(echoCommand);
CommandExecutor varExecutor = (context, entity, cmd) -> {
if (cmd.length > 3)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'var [ []]'"};
if (cmd.length == 3)
vars.put(cmd[1], cmd[2]);
else if (cmd.length == 2)
vars.remove(cmd[1]);
else {
for (Iterator iter = vars.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry) iter.next();
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
return null;
};
Command varCommand = new Command("var", "var [ []]", "Lists, sets or deletes variables", true, varExecutor);
commandRegistry.addCommand(varCommand);
CommandExecutor asetExecutor = (context, entity, cmd) -> {
if (cmd.length < 3)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'aset '"};
String alias = cmd[1];
StringBuffer b = new StringBuffer();
for (int i = 2; i < cmd.length; i++) {
if (i != 2)
b.append(' ');
b.append(cmd[i]);
}
aliases.put(alias, b.toString());
return null;
};
Command asetCommand = new Command("aset", "aset ", "Set a command alias", true, asetExecutor);
commandRegistry.addCommand(asetCommand);
CommandExecutor adelExecutor = (context, entity, cmd) -> {
if (cmd.length != 2)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'adel '"};
aliases.remove(cmd[1]);
return null;
};
Command adelCommand = new Command("adel", "adel ", "Remove a command alias", true, adelExecutor);
commandRegistry.addCommand(adelCommand);
CommandExecutor alistExecutor = (context, entity, cmd) -> {
if (cmd.length > 2)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'alist []'"};
System.out.println();
StringBuffer b = new StringBuffer();
b.append(SwiftUtilities.fillToLength("Alias", 33));
b.append("Command");
System.out.println(b.toString());
System.out.println(SwiftUtilities.fillLeft("", 72, '-'));
if (cmd.length == 2) {
String value = (String) aliases.get(cmd[1]);
if (value == null)
System.out.println("Alias not defined.");
else {
StringBuffer s = new StringBuffer();
s.append(SwiftUtilities.fillToLength(cmd[1], 33));
s.append(value);
System.out.println(s.toString());
}
} else {
if (aliases.size() == 0)
System.out.println("No aliases defined.");
else {
for (Iterator iter = aliases.keySet().iterator(); iter.hasNext(); ) {
String key = (String) iter.next();
String value = (String) aliases.get(key);
StringBuffer s = new StringBuffer();
s.append(SwiftUtilities.fillToLength(key, 33));
s.append(value);
System.out.println(s.toString());
}
}
}
System.out.println();
return null;
};
Command alistCommand = new Command("alist", "alist []", "List one or all alias(es)", true, alistExecutor);
commandRegistry.addCommand(alistCommand);
CommandExecutor asaveExecutor = (context, entity, cmd) -> {
if (cmd.length > 2)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'execute []'"};
String filename = null;
if (cmd.length == 2)
filename = cmd[1];
else
filename = System.getProperty("user.home") + File.separatorChar + ".init.cli";
System.out.println("Saving aliases to file: " + filename);
try {
PrintWriter pw = new PrintWriter(new FileWriter(filename));
pw.println("# CLI aliases, saved: " + new Date());
for (Iterator iter = aliases.keySet().iterator(); iter.hasNext(); ) {
String key = (String) iter.next();
String value = (String) aliases.get(key);
pw.println("aset " + key + " " + value);
}
pw.flush();
pw.close();
} catch (IOException e) {
return new String[]{TreeCommands.ERROR, "Unable to saves aliases, exception = " + e};
}
return null;
};
Command asaveCommand = new Command("asave", "asave []", "Saves all aliases into a file", true, asaveExecutor);
commandRegistry.addCommand(asaveCommand);
CommandExecutor executeExecutor = (context, entity, cmd) -> {
if (cmd.length != 2)
return new String[]{TreeCommands.ERROR, "Invalid command, please try 'execute '"};
String filename = cmd[1];
try {
executeScript(filename);
} catch (Exception e) {
return new String[]{TreeCommands.ERROR, "Unable to execute " + filename + ", exception = " + e};
}
return null;
};
Command executeCommand = new Command("execute", "execute ", "Executes a CLI script", true, executeExecutor);
commandRegistry.addCommand(executeCommand);
}
CLI(String smqpURL, String qcfName, String scriptFile) throws Exception {
this();
inReader = LineReaderBuilder.builder()
.terminal(TerminalBuilder.terminal())
.build();
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.swiftmq.jndi.InitialContextFactoryImpl");
env.put(Context.PROVIDER_URL, smqpURL);
InitialContext ctx = new InitialContext(env);
connectionHolder = new JMSConnectionHolder((QueueConnectionFactory) ctx.lookup(qcfName));
ctx.close();
String filename = System.getProperty(INIT_FILE_PROP, DEFAULT_INIT_FILE);
if (new File(filename).exists())
executeScript(filename);
if (scriptFile != null) {
try {
scriptReader = new BufferedReader(new InputStreamReader(new FileInputStream(scriptFile)));
} catch (Exception e) {
throw new Exception("Exception opening Script File: " + e.getMessage());
}
}
}
public CLI(ConnectionHolder connectionHolder, String scriptFile) throws Exception {
this();
inReader = LineReaderBuilder.builder()
.terminal(TerminalBuilder.terminal())
.build();
this.connectionHolder = connectionHolder;
String filename = System.getProperty(INIT_FILE_PROP, DEFAULT_INIT_FILE);
if (new File(filename).exists())
executeScript(filename);
if (scriptFile != null) {
try {
scriptReader = new BufferedReader(new InputStreamReader(new FileInputStream(scriptFile)));
} catch (Exception e) {
throw new Exception("Exception opening Script File: " + e.getMessage());
}
}
}
/**
* Creates a new CLI object and does the necessary setup
* (creating some sessions, senders and receivers). After the initial
* setup, CLI will start the connection.
*
* @param queueConnection queue connection, should be in stopped mode
* @throws Exception if anything goes wrong during setup
*/
public CLI(QueueConnection queueConnection) throws Exception {
this();
programmatic = true;
connectionHolder = new JMSConnectionHolder(queueConnection);
connectionHolder.start();
init();
connectionHolder.addReconnectListener(this);
String filename = System.getProperty(INIT_FILE_PROP, DEFAULT_INIT_FILE);
if (new File(filename).exists())
executeScript(filename);
}
public static void main(String[] args) {
if (args.length < 2) {
System.out.println();
System.out.println("usage: java com.swiftmq.admin.cli.CLI []");
System.out.println();
System.out.println(" is the JNDI-Provider-URL like 'smqp://localhost:4001/timeout=10000'");
System.out.println(" is the name of the queue connection factory");
System.out.println(" like 'QueueConnectionFactory'");
System.out.println(" name of an optional file with CLI commands");
System.out.println();
System.out.println("See SwiftMQ's documentation for details");
System.out.println();
System.exit(-1);
}
try {
CLI cli = new CLI(args[0], args[1], args.length == 3 ? args[2] : null);
cli.run();
} catch (Exception e) {
System.out.println(e);
System.exit(-1);
}
}
public void reconnected(String host, int port) {
reconnected = true;
EndpointRegistry old = endpointRegistry;
endpointRegistry = new EndpointRegistry();
actRouter = null;
commandRegistry.setDefaultCommand(null);
try {
init();
} catch (Exception e) {
e.printStackTrace();
}
old.close();
}
/**
* Returns the actual router name, resulting from the last 'sr' command.
* If no actual router is set, null is returned.
*
* @return actual router name or null
*/
public String getActRouter() {
return actRouter != null ? actRouter.getRouterName() : null;
}
/**
* Returns the actual context, resulting from the last 'cc' command. If
* no actual context is set, null is returned.
* Example:
* Say, the last 'cc' command was cc sys$queuemanager/queues, then
* the actual context returned is /sys$queuemanager/queues.
*
* @return actual context or null
*/
public String getActContext() {
String[] context = actRouter != null ? actRouter.getActContext() : null;
return context != null ? "/" + SwiftUtilities.concat(context, "/") : null;
}
/**
* Returns a property value from the actual context. If the property name is
* not defined in the actual context or no actual context is set, a CLIException
* is thrown. The value of the property is always casted to String, regardless
* of the property type. If the property value is null, null is returned.
*
* Example:
* Say, you like to determine the value of the cache.size property of
* the queue testqueue. First, you have to set your actual context:
* cli.executeCommand("cc /sys$queuemanager/queues/testqueue");
* Next, you can get the property value:
* int cacheSize = Integer.parseInt(cli.getProperty("cache.size"));
*
* @param name name of the property
* @return value of the property
* @throws CLIException if no actual context set or property is unknown in the actual context
*/
public String getContextProperty(String name) throws CLIException {
String[] context = actRouter != null ? actRouter.getActContext() : null;
if (context == null)
throw new CLIException("No actual context set!");
String[] result = commandRegistry.executeCommand(context, new String[]{TreeCommands.GET_CONTEXT_PROP, name});
if (result == null)
throw new CLIException("Property '" + name + "' is unknown in this context!");
if (result[0].equals(TreeCommands.ERROR)) {
if (reconnected) {
reconnected = false;
throw new CLIReconnectedException(result[1]);
} else
throw new CLIException(result[1]);
}
return result.length == 2 ? result[1] : null;
}
/**
* Returns an array with names of all entities of the actual context.
*
* Example:
* Say, you like to determine all defined queues. First, you have to set your actual context:
* cli.executeCommand("cc /sys$queuemanager/queues");
* Next, you can get the context entities which are the queue names:
* String[] currentQueueNames = cli.getContextEntities();
*
* @return array of entity names
* @throws CLIException if no actual context set
*/
public String[] getContextEntities() throws CLIException {
String[] context = actRouter != null ? actRouter.getActContext() : null;
if (context == null)
throw new CLIException("No actual context set!");
return commandRegistry.executeCommand(context, new String[]{TreeCommands.GET_CONTEXT_ENTITIES});
}
/**
* Returns all currently available router names.
*
* @return array of router names
*/
public String[] getAvailableRouters() {
return (String[]) availableRouters.toArray(new String[availableRouters.size()]);
}
/**
* Wait for availability of a specific router. If the router is already available, the method
* returns immediatly. Otherwise it will wait until the router becomes available.
*
* @param routerName router name
*/
public void waitForRouter(String routerName) {
waitFor = routerName;
if (!availableRouters.contains(routerName)) {
try {
if (!programmatic)
System.out.println("Waiting for router '" + routerName + "'");
waitSem.waitHere();
} catch (Exception ignored) {
}
}
waitFor = null;
}
/**
* Wait for availability of a specific router with timeout. If the router is already available, the method
* returns immediatly. Otherwise it will wait until the router becomes available or the timeout
* is reached.
*
* @param routerName router name
* @param timeout timeout value in milliseconds
*/
public void waitForRouter(String routerName, long timeout) {
waitFor = routerName;
if (!availableRouters.contains(routerName)) {
try {
if (!programmatic)
System.out.println("Waiting for router '" + routerName + "' with timeout " + timeout + " ms");
waitSem.waitHere(timeout);
} catch (Exception ignored) {
}
}
waitFor = null;
}
/**
* Executes a CLI command. Refer to the CLI documentation for an overview
* and description of all CLI commands. The method throw a CLIException if
* the command returns a result. Therefore, commads such as 'ar', 'sr', 'lc'
* cannot be invoked via this method. Note also that the command 'exit' will terminate
* the whole JVM!
*
* @param cmd CLI command to be executed
* @throws CLIException if something goes wrong such as invalid command or command returns a result
*/
public void executeCommand(String cmd) throws CLIException {
try {
List cmdList = SwiftUtilities.parseCLICommandList(cmd);
for (Iterator iter = cmdList.iterator(); iter.hasNext(); ) {
String[] parsedCmd = (String[]) iter.next();
String aliasValue = (String) aliases.get(parsedCmd[0]);
if (aliasValue != null) {
_processAlias(aliasValue, parsedCmd);
continue;
}
String[] result = commandRegistry.executeCommand(actRouter == null ? null : actRouter.getActContext(), substitute(parsedCmd));
if (result != null) {
if (result[0].equals(TreeCommands.ERROR)) {
String s = SwiftUtilities.concat(SwiftUtilities.cutFirst(result), " ");
if (reconnected) {
reconnected = false;
throw new CLIReconnectedException(s);
} else
throw new CLIException(s);
} else if (result[0].equals(TreeCommands.RESULT))
throw new CLIException("Invalid method; command returns a result!");
}
}
} catch (CLIException e) {
throw e;
} catch (Exception e1) {
throw new CLIException(e1.getMessage());
}
}
private String[] substitute(String[] cmd) {
String[] result = cmd;
if (substitute) {
for (int i = 0; i < result.length; i++) {
for (Map.Entry stringStringEntry : vars.entrySet()) {
Entry entry = (Map.Entry) stringStringEntry;
String name = (String) entry.getKey();
String value = (String) entry.getValue();
result[i] = SwiftUtilities.substitute(result[i], name, value);
}
}
}
try {
if (verbose)
out(SwiftUtilities.concat(result, " "));
} catch (Exception e) {
}
return result;
}
private void _processAlias(String aliasValue, String[] aliasCmd)
throws Exception {
String s = aliasValue;
String[] t = SwiftUtilities.parseCLICommand(s);
if (t.length == 1) {
if (aliasCmd.length > 1) {
StringBuffer b = new StringBuffer(t[0]);
for (int i = 1; i < aliasCmd.length; i++) {
b.append(" ");
b.append(aliasCmd[i]);
}
s = b.toString();
} else
s = aliasValue;
} else {
if (aliasCmd.length > 1 && t.length > 1) {
s = SwiftUtilities.substitute(s, SwiftUtilities.cutFirst(aliasCmd));
for (int i = 1; i < aliasCmd.length; i++) {
s = SwiftUtilities.substitute(s, String.valueOf(i), aliasCmd[i]);
}
}
}
executeCommand(s);
}
/**
* Add a router listener
*
* @param l router listener
*/
public void addRouterListener(RouterListener l) {
listeners.add(l);
}
/**
* Remove a router listener.
*
* @param l router listener
*/
public void removeRouterListener(RouterListener l) {
listeners.remove(l);
}
private void fireRouterEvent(String routerName, boolean available) {
for (int i = 0; i < listeners.size(); i++) {
(listeners.get(i)).onRouterEvent(routerName, available);
}
}
public boolean isProgrammatic() {
return programmatic;
}
public void markRouter(String routerName, boolean available) {
if (available) {
availableRouters.add(routerName);
if (waitFor != null && waitFor.equals(routerName))
waitSem.notifySingleWaiter();
if (programmatic) {
fireRouterEvent(routerName, true);
} else {
System.out.println("Router '" + routerName + "' is available for administration.");
waitForRouters.notifySingleWaiter();
}
} else {
availableRouters.remove(routerName);
removeEndpoint(routerName);
if (programmatic)
fireRouterEvent(routerName, false);
else
System.out.println("Router '" + routerName + "' is unavailable for administration.");
}
}
public Endpoint createEndpoint(String routerName, boolean routeInfos) throws Exception {
Endpoint endpoint = connectionHolder.createEndpoint(routerName, new RequestServiceFactory() {
public RequestService createRequestService(int protocolVersion) {
if (protocolVersion == 750)
return new com.swiftmq.admin.cli.v750.RequestProcessor(CLI.this);
throw new RuntimeException("Invalid protocol version: " + protocolVersion);
}
}, programmatic);
endpoint.setRouteInfos(routeInfos);
String name = null;
endpoint.connect(0, InetAddress.getLocalHost().getHostName(), "CLI" + (programmatic ? " Admin API" : ""), routeInfos, false, false);
endpoint.setStarted(true);
name = endpoint.getRouterName();
try {
endpointRegistry.put(endpoint.getRouterName(), endpoint);
} catch (EndpointRegistryClosedException e) {
endpoint.close();
endpoint = null;
}
return endpoint;
}
public void removeEndpoint(String routerName) {
Endpoint routerContext = endpointRegistry.remove(routerName);
if (routerContext != null) {
if (routerContext == actRouter) {
actRouter = null;
commandRegistry.setDefaultCommand(null);
}
routerContext.close();
}
}
private void init() throws Exception {
Endpoint endpoint = createEndpoint(null, true);
markRouter(endpoint.getRouterName(), true);
}
private String readLine(boolean nullOnEmpty, boolean isPassword) {
String line = null;
boolean ok = false;
try {
while (!ok) {
if (scriptReader != null) {
line = scriptReader.readLine();
if (line == null) {
scriptReader.close();
scriptReader = null;
}
}
if (line == null)
line = isPassword ? inReader.readLine(new Character('*')) : inReader.readLine();
ok = line != null && !line.trim().startsWith("#") || line == null;
}
if (nullOnEmpty && line != null && line.equals(""))
line = null;
} catch (Exception e) {
}
return line;
}
private void out(String line) throws Exception {
if (outWriter == null)
System.out.println(line);
else
outWriter.println(line);
}
private void executeScript(String filename)
throws Exception {
vars.put("scriptpath", new File(filename).getParent());
try {
BufferedReader reader = new BufferedReader(new FileReader(filename));
String line = null;
while ((line = reader.readLine()) != null) {
if (!line.startsWith("#") && line.trim().length() > 0)
processCommand(line);
}
} finally {
vars.remove("scriptpath");
}
}
private void processAlias(String aliasValue, String[] aliasCmd)
throws Exception {
String s = aliasValue;
String[] t = SwiftUtilities.parseCLICommand(s);
if (t.length == 1) {
if (aliasCmd.length > 1) {
StringBuffer b = new StringBuffer(t[0]);
for (int i = 1; i < aliasCmd.length; i++) {
b.append(" ");
b.append(aliasCmd[i]);
}
s = b.toString();
} else
s = aliasValue;
} else {
if (aliasCmd.length > 1 && t.length > 1) {
s = SwiftUtilities.substitute(s, SwiftUtilities.cutFirst(aliasCmd));
for (int i = 1; i < aliasCmd.length; i++) {
s = SwiftUtilities.substitute(s, String.valueOf(i), aliasCmd[i]);
}
}
}
processCommand(s.trim());
}
private void processCommand(String command)
throws Exception {
List cmdList = SwiftUtilities.parseCLICommandList(command);
for (Iterator iter = cmdList.iterator(); iter.hasNext(); ) {
String[] parsedCmd = (String[]) iter.next();
parsedCmd[0] = parsedCmd[0].trim();
String aliasValue = (String) aliases.get(parsedCmd[0]);
if (aliasValue != null) {
processAlias(aliasValue, parsedCmd);
continue;
}
String[] result = commandRegistry.executeCommand(actRouter == null ? null : actRouter.getActContext(), substitute(parsedCmd));
if (result != null) {
if (result[0].equals(TreeCommands.ERROR) && result.length > 1) {
System.out.println(result[1]);
} else {
for (int i = 0; i < result.length; i++) {
if (!(result[i].equals(TreeCommands.RESULT) ||
result[i].equals(TreeCommands.INFO)))
out(result[i]);
}
}
}
}
}
private void mainLoop() {
String prompt = null;
String[] context = null;
boolean shouldExit = false;
while (!shouldExit) {
if (actRouter != null) {
prompt = actRouter.getRouterName();
if (actRouter.getActContext() != null)
prompt += '/' + SwiftUtilities.concat(actRouter.getActContext(), "/");
context = actRouter.getActContext();
} else
prompt = "";
prompt += "> ";
if (scriptReader == null)
System.out.print(prompt);
String command = readLine(false, false);
if (command == null) {
System.out.println("Bye.");
return;
}
command = command.trim();
if (command.length() > 0) {
try {
processCommand(command);
} catch (Exception e) {
System.out.println();
System.out.println(e.getMessage());
System.out.println();
}
}
}
}
public void run() {
String userName = null;
String password = null;
if (scriptReader == null) {
System.out.println();
System.out.println("Welcome to SwiftMQ!");
System.out.println();
System.out.print("Username: ");
userName = readLine(true, false);
System.out.print("Password: ");
password = readLine(true, true);
} else {
userName = System.getProperty("cli.username");
password = System.getProperty("cli.password");
}
if (scriptReader == null)
System.out.print("Trying to connect ... ");
try {
connectionHolder.connect(userName, password);
if (scriptReader == null)
System.out.println("connected");
} catch (Exception e) {
System.out.println("failed, exception: " + e.getMessage());
close();
return;
}
try {
connectionHolder.setExceptionListener(new ExceptionListener() {
public void onException(Exception e) {
if (e.getMessage() == null)
System.out.println("Connection lost.");
else
System.out.println("Exception occurred: " + e.getMessage());
System.exit(-1);
}
});
connectionHolder.start();
init();
connectionHolder.addReconnectListener(this);
} catch (Exception e) {
System.out.println("failed to establish route listener, exception: " + e.getMessage());
close();
return;
}
if (scriptReader == null)
System.out.println("Type 'help' to get a list of available commands.");
else {
// Wait for Router announcement
waitForRouters.waitHere();
}
mainLoop();
close();
}
/**
* Closed all resources created by CLI. This method will not close the QueueConnection!
*/
public void close() {
if (connectionHolder == null)
return;
connectionHolder.removeReconnectListener(this);
endpointRegistry.close();
if (!programmatic) {
try {
connectionHolder.close();
} catch (Exception ignored) {
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy