
oracle.kv.util.shell.CommonShell Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oracle-nosql-server Show documentation
Show all versions of oracle-nosql-server Show documentation
NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.
The newest version!
/*-
* Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle NoSQL
* Database made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle NoSQL Database for a copy of the license and
* additional information.
*/
package oracle.kv.util.shell;
import static oracle.kv.impl.api.table.TableImpl.validateNamespace;
import static oracle.kv.impl.util.CommandParser.CONSISTENCY_FLAG;
import static oracle.kv.impl.util.CommandParser.DURABILITY_FLAG;
import static oracle.kv.impl.util.CommandParser.FROM_FLAG;
import static oracle.kv.impl.util.CommandParser.HOST_FLAG;
import static oracle.kv.impl.util.CommandParser.LAST_FLAG;
import static oracle.kv.impl.util.CommandParser.NAME_FLAG;
import static oracle.kv.impl.util.CommandParser.OFF_FLAG;
import static oracle.kv.impl.util.CommandParser.ON_FLAG;
import static oracle.kv.impl.util.CommandParser.PORT_FLAG;
import static oracle.kv.impl.util.CommandParser.SECURITY_FLAG;
import static oracle.kv.impl.util.CommandParser.TIMEOUT_FLAG;
import static oracle.kv.impl.util.CommandParser.TO_FLAG;
import static oracle.kv.impl.util.CommandParser.USER_FLAG;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import oracle.kv.AuthenticationFailureException;
import oracle.kv.Consistency;
import oracle.kv.Durability;
import oracle.kv.KVStore;
import oracle.kv.KVStoreConfig;
import oracle.kv.KVStoreFactory;
import oracle.kv.LoginCredentials;
import oracle.kv.StatementResult;
import oracle.kv.impl.admin.CommandResult;
import oracle.kv.impl.api.table.NameUtils;
import oracle.kv.impl.client.DdlJsonFormat;
import oracle.kv.impl.query.shell.output.ResultOutputFactory;
import oracle.kv.impl.query.shell.output.ResultOutputFactory.OutputMode;
import oracle.kv.impl.query.shell.output.ResultOutputFactory.ResultOutput;
import oracle.kv.impl.security.PasswordExpiredException;
import oracle.kv.impl.security.util.KVStoreLogin;
import oracle.kv.impl.security.util.KVStoreLogin.CredentialsProvider;
import oracle.kv.impl.util.CommandParser;
import oracle.kv.impl.util.HostPort;
import oracle.kv.query.ExecuteOptions;
import oracle.kv.util.ErrorMessage;
/*
* This class encapsulates some sharable utility commands:
* history, timer, page, connect store.
*/
public abstract class CommonShell extends Shell {
private String kvstoreName = null;
private String storeHostname = null;
private int storePort = 0;
private String storeUser = null;
private String storeSecurityFile = null;
private List helperHosts = null;
protected String[] commandToRun;
private int nextCommandIdx = 0;
private boolean noprompt = false;
private boolean noconnect = false;
/*
* This is an internal flag used by tests to allow them to
* call CommandShell.main without exiting.
*/
private boolean dontExit = false;
private Integer storeTimeout = null;
private Consistency storeConsistency = null;
private Durability storeDurability = null;
private LoginHelper loginHelper = null;
private KVStore store = null;
private KVStoreConfig kvstoreConfig = null;
private int pageHeight = 0;
private String namespace = null;
/* Default consistency policy used for this connection. */
final static Consistency CONSISTENCY_DEF = Consistency.NONE_REQUIRED;
/*
* By default, use a more aggressive default Durability to make
* sure that records get into a database.
*/
final static Durability DURABILITY_DEF = Durability.COMMIT_SYNC;
/* Default request timeout used for this connection. */
final static int REQUEST_TIMEOUT_DEF = 5000;
private static Map consistencyMap;
private static Map durabilityMap;
static {
Map consMap = new HashMap<>();
consMap.put("NONE_REQUIRED", Consistency.NONE_REQUIRED);
@SuppressWarnings("deprecation")
final Consistency NONE_REQUIRED_NO_MASTER =
Consistency.NONE_REQUIRED_NO_MASTER;
consMap.put("NONE_REQUIRED_NO_MASTER", NONE_REQUIRED_NO_MASTER);
consMap.put("ABSOLUTE", Consistency.ABSOLUTE);
consistencyMap = Collections.unmodifiableMap(consMap);
Map durMap = new HashMap<>();
durMap.put("COMMIT_SYNC", Durability.COMMIT_SYNC);
durMap.put("COMMIT_NO_SYNC", Durability.COMMIT_NO_SYNC);
durMap.put("COMMIT_WRITE_NO_SYNC", Durability.COMMIT_WRITE_NO_SYNC);
durabilityMap = Collections.unmodifiableMap(durMap);
}
public CommonShell(InputStream input,
PrintStream output) {
this(input, output, null);
}
public CommonShell(InputStream input,
PrintStream output,
String[] maskFlags) {
super(input, output, true, maskFlags);
}
public KVStore getStore() throws ShellException {
if (store == null) {
throw new ShellException("Not Connected.");
}
return store;
}
public KVStoreConfig getKVStoreConfig() {
return kvstoreConfig;
}
public void setStoreConsistency(Consistency consistency) {
storeConsistency = consistency;
}
public Consistency getStoreConsistency() {
return (storeConsistency != null) ?
storeConsistency : CONSISTENCY_DEF;
}
public static String getConsistencyName(Consistency consistency) {
if (consistency instanceof Consistency.Time) {
final Consistency.Time tcons = (Consistency.Time) consistency;
return tcons.getName() + "[permissibleLag_ms=" +
tcons.getPermissibleLag(TimeUnit.MILLISECONDS) +
", timeout_ms=" + tcons.getTimeout(TimeUnit.MILLISECONDS) +
"]";
}
for (Entry entry : consistencyMap.entrySet()) {
if (consistency.equals(entry.getValue())) {
return entry.getKey();
}
}
return null;
}
public void setStoreDurability(Durability durability) {
storeDurability = durability;
}
public Durability getStoreDurability() {
return (storeDurability != null) ?
storeDurability : DURABILITY_DEF;
}
public static String getDurabilityName(Durability durability) {
for (Entry entry : durabilityMap.entrySet()) {
if (durability.equals(entry.getValue())) {
return entry.getKey();
}
}
return "Durability[MasterSync=" + durability.getMasterSync() +
", ReplicaSync=" + durability.getReplicaSync() +
", ReplicaAck= " + durability.getReplicaAck() + "]";
}
public void setRequestTimeout(int timeout) {
storeTimeout = timeout;
}
public int getRequestTimeout() {
return (storeTimeout != null) ?
storeTimeout.intValue() : REQUEST_TIMEOUT_DEF;
}
public void connectStore() throws ShellException {
connectStore(null);
}
public void connectStore(List extraHostPorts)
throws ShellException {
if (kvstoreName != null) {
getLoginHelper().updateStoreLogin(storeUser, storeSecurityFile);
openStore(extraHostPorts);
}
}
void setPageHeight(int height) {
pageHeight = height;
}
public int getPageHeight() {
if (pageHeight == 0) {
final ShellInputReader inputReader = getInput();
return (inputReader == null) ? -1 : inputReader.getTerminalHeight();
}
return pageHeight;
}
public boolean isPagingEnabled() {
return (getPageHeight() >= 0);
}
public boolean isNoPrompt() {
return noprompt;
}
public boolean isNoConnect() {
return noconnect;
}
public boolean dontExit() {
return dontExit;
}
public static Consistency getConsistency(String name) {
return consistencyMap.get(name.toUpperCase());
}
public static Set getConsistencyNames() {
return consistencyMap.keySet();
}
public static Durability getDurability(String name) {
return durabilityMap.get(name.toUpperCase());
}
public static Set getDurabilityNames() {
return durabilityMap.keySet();
}
public void setNamespace(final String namespace) {
if (namespace != null) {
validateNamespace(namespace);
}
this.namespace = namespace;
}
public String getNamespace() {
return namespace;
}
public ExecuteOptions getExecuteOptions() {
return new ExecuteOptions()
.setConsistency(getStoreConsistency())
.setTimeout(getRequestTimeout(), TimeUnit.MILLISECONDS)
.setNamespace(getNamespace());
}
public void setLoginHelper(LoginHelper loginHelper) {
this.loginHelper = loginHelper;
}
public LoginHelper getLoginHelper() {
if (loginHelper == null) {
loginHelper = new LoginHelper();
}
return loginHelper;
}
public void openStore(String host,
int port,
String storeName,
String user,
String securityFile)
throws ShellException {
openStore(host, port, storeName, user, securityFile,
null /* timeout */, null /* consistency */,
null /* durability */);
}
public void openStore(String host,
int port,
String storeName,
String user,
String securityFile,
Integer timeout,
Consistency consistency,
Durability durability)
throws ShellException {
storeHostname = host;
storePort = port;
kvstoreName = storeName;
if (timeout != null) {
setRequestTimeout(timeout);
}
if (consistency != null) {
setStoreConsistency(consistency);
}
if (durability != null) {
setStoreDurability(durability);
}
try {
getLoginHelper().updateStoreLogin(user, securityFile);
} catch (IllegalStateException ise) {
throw new ShellException(ise.getMessage());
} catch (IllegalArgumentException iae) {
output.println(iae.getMessage());
}
openStore();
}
String[] getHostPorts(List extraHostPorts) {
List hostports = new ArrayList<>();
if (storeHostname != null) {
hostports.add(storeHostname + ":" + storePort);
} else {
hostports.addAll(helperHosts);
}
if (extraHostPorts != null) {
hostports.addAll(extraHostPorts);
}
return hostports.toArray(new String[0]);
}
public void openStore() throws ShellException {
openStore(null);
}
/* Open the store. */
public void openStore(List extraHostPorts)
throws ShellException {
final String[] hostports = getHostPorts(extraHostPorts);
kvstoreConfig = new KVStoreConfig(kvstoreName, hostports);
final Durability durability = getStoreDurability();
kvstoreConfig.setDurability(durability);
final Consistency consistency = getStoreConsistency();
kvstoreConfig.setConsistency(consistency);
final int requestTimeout = getRequestTimeout();
kvstoreConfig.setRequestTimeout(requestTimeout, TimeUnit.MILLISECONDS);
/* Make sure socket timeout >= request timeout */
final long socketTimeout =
kvstoreConfig.getSocketReadTimeout(TimeUnit.MILLISECONDS);
if (socketTimeout < requestTimeout) {
kvstoreConfig.setSocketReadTimeout(requestTimeout,
TimeUnit.MILLISECONDS);
}
/*
* Disable async calls from the admin.
*
* TODO: Use async if the store has been upgraded to support it.
*/
kvstoreConfig.setUseAsync(false);
try {
store = getLoginHelper().getAuthenticatedStore(kvstoreConfig);
} catch (ShellException se) {
throw se;
} catch (Exception e) {
throw new ShellException("Cannot connect to " + kvstoreName +
" at " + (storeHostname != null ?
(storeHostname + ":" + storePort) :
joinHostsWithComma(hostports)),
e);
}
}
private String joinHostsWithComma(String[] hostports) {
StringBuilder sb = new StringBuilder();
for (String hp : hostports) {
if (sb.length() > 0) {
sb.append(", ");
}
sb.append(hp);
}
return sb.toString();
}
public void closeStore() {
if (store != null) {
store.close();
store = null;
}
}
public abstract class ShellParser extends CommandParser {
private List reqFlags;
/*
* The flag indicates that if there is a non-hidden argument
* provided.
*/
private boolean hasNonHiddenArg = false;
/*
* Hidden flags: -noprompt, -noconnect, -hidden, -verbose, -debug,
* -no-exit, help flag(-help, help, -?, ?)
*/
public ShellParser(String[] args,
String[] rcArgs,
String[] requiredFlags) {
/*
* The true argument tells CommandParser that this class will
* handle all flags, not just those unrecognized.
*/
super(args, rcArgs, true);
if (requiredFlags != null) {
reqFlags = new ArrayList<>();
reqFlags.addAll(Arrays.asList(requiredFlags));
}
}
@Override
protected void verifyArgs() {
/*
* If no argument except those hidden flags is provided, then
* don't try to connect to a store.
*/
if (!hasNonHiddenArg && !noconnect) {
noconnect = true;
}
if (!noconnect) {
if (reqFlags != null && reqFlags.size() > 0) {
usage("Missing required argument");
}
}
if ((commandToRun != null) &&
(nextCommandIdx < commandToRun.length)) {
usage("Flags may not follow commands");
}
}
/* Abstract function to get the usage of shell. */
public abstract String getShellUsage();
@Override
public void usage(String errorMsg) {
String error = "";
if (errorMsg != null) {
error += errorMsg + eol;
}
error += getShellUsage();
if (argArray != null &&
Shell.checkArg(argArray, CommandParser.JSON_FLAG)) {
String operation = "";
for (String arg: argArray) {
operation += arg + " ";
}
CommandResult result =
new CommandResult.CommandFails(
error, ErrorMessage.NOSQL_5100,
CommandResult.NO_CLEANUP_JOBS);
final boolean isJsonV1 =
Shell.checkArg(argArray, CommandParser.JSON_V1_FLAG);
if (isJsonV1) {
error = Shell.toJsonReport(operation, result);
} else {
error =
ShellCommandResult.toJsonReport(operation, result);
}
}
System.err.println(error);
System.exit(1);
}
public boolean checkExtraArg(@SuppressWarnings("unused") String arg) {
return false;
}
@Override
protected boolean checkArg(String arg) {
/*
* In order to allow an embedded command to use the same flags as
* the shell executable, if the commandToRun is set, just pass them
* through.
*/
if (checkHiddenFlags(arg)) {
return true;
}
if (commandToRun == null) {
checkRequiredFlag(arg);
if (HOST_FLAG.equals(arg)) {
storeHostname = nextArg(arg);
return true;
} else if (PORT_FLAG.equals(arg)) {
storePort = Integer.parseInt(nextArg(arg));
return true;
} else if (HELPER_HOSTS_FLAG.equals(arg)) {
addHelperHosts(nextArg(arg));
return true;
} else if (STORE_FLAG.equals(arg)) {
kvstoreName = nextArg(arg);
return true;
} else if (USER_FLAG.equals(arg)) {
storeUser = nextArg(arg);
return true;
} else if (SECURITY_FLAG.equals(arg)) {
storeSecurityFile = nextArg(arg);
return true;
} else if (TIMEOUT_FLAG.equals(arg)) {
storeTimeout = nextIntArg(arg);
if(storeTimeout <= 0) {
usage("Flag " + arg + " requires a positive integer");
}
return true;
} else if (CONSISTENCY_FLAG.equals(arg)) {
final String cname = nextArg(arg);
storeConsistency = getConsistency(cname);
if (storeConsistency == null) {
usage(CommandParser.getConsistencyUsage());
}
return true;
} else if (DURABILITY_FLAG.equals(arg)) {
final String dname = nextArg(arg);
storeDurability = getDurability(dname);
if (storeDurability == null) {
usage(CommandParser.getDurabilityUsage());
}
return true;
} else if (REG_OPEN_TIME_FLAG.equals(arg)) {
registryOpenTimeout = Integer.parseInt(nextArg(arg));
if(registryOpenTimeout <= 0) {
usage("Flag " + arg + " requires a positive integer");
}
return true;
} else if (REG_READ_TIME_FLAG.equals(arg)) {
registryReadTimeout = Integer.parseInt(nextArg(arg));
if(registryReadTimeout <= 0) {
usage("Flag " + arg + " requires a positive integer");
}
return true;
} else if (checkExtraArg(arg)) {
return true;
}
}
if (!isIgnoreUnknownArg()) {
addToCommand(arg);
}
return true;
}
/*
* Check if the input argument is one of the hidden flags:
* -noconnect, -noprompt, -verbose, -debug, -hidden or
* help flag (-help, help, -?, ?).
*
* If the argument is a help flag for shell but not for commandToRun,
* then print the usage message of shell and exit current program.
*/
private boolean checkHiddenFlags(final String arg) {
if (NOCONNECT_FLAG.equals(arg)) {
noconnect = true;
return true;
}
if (NOPROMPT_FLAG.equals(arg)) {
noprompt = true;
return true;
}
if (DONTEXIT_FLAG.equals(arg)) {
dontExit = true;
return true;
}
if (commandToRun == null && isHelpFlag(arg)) {
usage(null);
}
if (VERBOSE_FLAG.equals(arg)) {
setVerbose(true);
} else if (DEBUG_FLAG.equals(arg)) {
setDebug(true);
} else if (HIDDEN_FLAG.equals(arg)) {
setHidden(true);
} else if (JSON_FLAG.equals(arg)) {
setJson(true);
} else if (!checkExtraHiddenFlag(arg)) {
if (!hasNonHiddenArg) {
hasNonHiddenArg = true;
}
return false;
}
/* Some commands take this flag as well */
if (commandToRun != null) {
addToCommand(arg);
}
return true;
}
protected boolean checkExtraHiddenFlag(@SuppressWarnings("unused")
final String arg) {
return false;
}
private void checkRequiredFlag(String arg) {
if (reqFlags == null || reqFlags.isEmpty()) {
return;
}
if (reqFlags.contains(arg)) {
reqFlags.remove(arg);
}
}
private void addHelperHosts(String arg) {
helperHosts = new ArrayList<>();
String[] hostports = arg.split(",");
helperHosts.addAll(Arrays.asList(hostports));
}
/*
* Add unrecognized args to the commandToRun array.
*/
private void addToCommand(String arg) {
if (commandToRun == null) {
commandToRun = new String[getNRemainingArgs() + 1];
}
commandToRun[nextCommandIdx++] = arg;
}
@Override
public String getHostname() {
return storeHostname;
}
@Override
public int getRegistryPort() {
return storePort;
}
@Override
public String getStoreName() {
return kvstoreName;
}
@Override
public String getUserName() {
return storeUser;
}
@Override
public String getSecurityFile() {
return storeSecurityFile;
}
public List getHelperHosts() {
return helperHosts;
}
}
/**
* A helper class for client login of store.
*/
public static class LoginHelper implements CredentialsProvider {
protected final KVStoreLogin storeLogin = new KVStoreLogin();
private LoginCredentials storeCreds;
private boolean isSecuredStore;
/**
* Updates the login information of store.
*
* @param newUser new user name
* @param newLoginFile new login file path
*/
void updateStoreLogin(final String newUser,
final String newLoginFile) {
storeLogin.updateLoginInfo(newUser, newLoginFile);
isSecuredStore = storeLogin.foundTransportSettings();
storeCreds = null;
}
/**
* Returns a kvstore handler. If the store is secured, authentication
* will be conducted using login file or via user interaction.
*
* @param config the kvconfig specified by user
* @return kvstore handler
*/
protected KVStore getAuthenticatedStore(final KVStoreConfig config)
throws ShellException {
config.setSecurityProperties(storeLogin.getSecurityProperties());
try {
if (isSecuredStore && storeCreds == null) {
storeCreds = storeLogin.makeShellLoginCredentials();
}
return KVStoreFactory.getStore(config, storeCreds,
KVStoreLogin.makeReauthenticateHandler(this));
} catch (PasswordExpiredException pee) {
storeCreds = null;
String errorMsg = "Login failed: Password is expired. " +
"Log into the Admin CLI to renew your " +
"password.";
throw new ShellException(errorMsg, pee);
} catch (AuthenticationFailureException afe) {
storeCreds = null;
String errorMsg = "Login failed: " + afe.getMessage();
throw new ShellException(errorMsg, afe);
} catch (IOException ioe) {
throw new ShellException("Failed to get login credentials: " +
ioe.getMessage());
} catch (IllegalArgumentException iae) {
throw new ShellException(
"Login properties error: " + iae.getMessage());
}
}
@Override
public LoginCredentials getCredentials() {
return storeCreds;
}
}
/* ConnectStore command */
public static class ConnectStoreCommand extends ShellCommand {
static final String NAME = "connect";
public static final String CONNECT_STORE_COMMAND_DESC =
"Connects to a KVStore to perform data access functions." +
eolt + "If the instance is secured, you may need to provide " +
"login credentials.";
public static final String CONNECT_STORE_COMMAND_ARGUMENTS =
CommandParser.optional(CommandParser.getHostUsage()) + " " +
CommandParser.optional(CommandParser.getPortUsage()) + " " +
NAME_FLAG + " " + eolt +
CommandParser.optional(CommandParser.getTimeoutUsage()) + " " +
eolt +
CommandParser.optional(CommandParser.getConsistencyUsage()) +
eolt +
CommandParser.optional(CommandParser.getDurabilityUsage()) +
eolt +
CommandParser.optional(CommandParser.getUserUsage()) + " " +
CommandParser.optional(CommandParser.getSecurityUsage());
public static final String CONNECT_STORE_COMMAND_SYNTAX =
NAME + " " + CONNECT_STORE_COMMAND_ARGUMENTS;
public ConnectStoreCommand() {
super(NAME, 4);
}
@Override
public String execute(String[] args, Shell shell)
throws ShellException {
return execute(args, shell, new ArrayList());
}
public String execute(String[] args, Shell shell,
List extraHostports) throws ShellException {
Shell.checkHelp(args, this);
String hostname = null;
int port = 0;
String storeName = null;
String user = null;
String security = null;
Integer timeout = null;
Consistency consistency = null;
Durability durability = null;
for (int i = 1; i < args.length; i++) {
String arg = args[i];
if (CommandParser.HOST_FLAG.equals(arg)) {
hostname = Shell.nextArg(args, i++, this);
} else if (PORT_FLAG.equals(arg)) {
port = parseInt(Shell.nextArg(args, i++, this));
if (port < 1 || port > 65535) {
invalidArgument(arg);
}
} else if (NAME_FLAG.equals(arg)) {
storeName = Shell.nextArg(args, i++, this);
} else if (USER_FLAG.equals(arg)) {
user = Shell.nextArg(args, i++, this);
} else if (SECURITY_FLAG.equals(arg)) {
security = Shell.nextArg(args, i++, this);
} else if (TIMEOUT_FLAG.equals(arg)) {
timeout = parseInt(Shell.nextArg(args, i++, this));
if (timeout <= 0) {
invalidArgument(arg);
}
} else if (CONSISTENCY_FLAG.equals(arg)) {
final String cname = Shell.nextArg(args, i++, this);
consistency = getConsistency(cname);
if (consistency == null) {
invalidArgument(arg);
}
} else if (DURABILITY_FLAG.equals(arg)) {
final String dname = Shell.nextArg(args, i++, this);
durability = getDurability(dname);
if (durability == null) {
invalidArgument(arg);
}
} else {
shell.unknownArgument(arg, this);
}
}
if (storeName == null) {
shell.requiredArg(NAME_FLAG, this);
}
/* Close current store, open new one.*/
final CommonShell cshell = (CommonShell) shell;
cshell.closeStore();
List hostports = new ArrayList<>();
if (hostname != null && port != 0) {
hostports.add(new HostPort(hostname, port));
} else {
if (cshell.helperHosts != null) {
/*
* If a list of helperhost is used as argument of the shell,
* then -host and -port should be specified either both or
* not at all. Specifying only one of them cause the
* exception that miss the another argument.
*/
if (hostname == null && port != 0) {
shell.requiredArg(HOST_FLAG, this);
} else if (hostname != null && port == 0) {
shell.requiredArg(PORT_FLAG, this);
}
assert(hostname == null && port == 0);
for (String helperHost : cshell.helperHosts) {
hostports.add(HostPort.parse(helperHost));
}
} else {
if (hostname == null) {
hostname = cshell.storeHostname;
}
if (port == 0) {
port = cshell.storePort;
}
hostports.add(new HostPort(hostname, port));
}
if (extraHostports != null) {
hostports.addAll(extraHostports);
}
}
boolean connected = false;
for (HostPort hostPort : hostports) {
try {
hostname = hostPort.hostname();
port = hostPort.port();
cshell.openStore(hostname, port, storeName, user, security,
timeout, consistency, durability);
connected = true;
break;
} catch (ShellException ignored) {
}
}
if (!connected) {
String fmt = "Failed to connect to %s at %s" + eol +
"Warning: You are no longer connected to a store.";
String helperHosts = Arrays.toString(
hostports.toArray(new HostPort[hostports.size()]));
throw new ShellException(String.format(fmt, storeName,
helperHosts));
}
String ret = "Connected to " + storeName + " at " + hostname
+ ":" + port + ".";
if(timeout != null) {
ret += " Set timeout: " + timeout + "ms.";
}
if(consistency != null) {
ret += " Set consistency: " + consistency + ".";
}
if(durability != null) {
ret += " Set durability: " + durability + ".";
}
return ret;
}
@Override
protected String getCommandSyntax() {
return CONNECT_STORE_COMMAND_SYNTAX;
}
@Override
protected String getCommandDescription() {
return CONNECT_STORE_COMMAND_DESC;
}
}
/* Time command */
public static class TimeCommand extends ShellCommand {
private final static String NAME = "timer";
final static String SYNTAX = NAME + " " +
CommandParser.optional(ON_FLAG + " | " + OFF_FLAG);
final static String DESCRIPTION = "Turns the measurement and display " +
"of execution time for commands on or off.";
public TimeCommand() {
super(NAME, 5);
}
@Override
public String execute(String[] args, Shell shell)
throws ShellException {
Shell.checkHelp(args, this);
if (args.length > 2) {
shell.badArgCount(this);
} else if (args.length > 1) {
String arg = args[1];
if (ON_FLAG.equals(arg)) {
shell.setTimer(true);
} else if (OFF_FLAG.equals(arg)) {
shell.setTimer(false);
} else {
shell.unknownArgument(arg, this);
}
}
return "Timer is now " + (shell.getTimer() ? "on" : "off");
}
@Override
public String getCommandSyntax() {
return SYNTAX;
}
@Override
public String getCommandDescription() {
return DESCRIPTION;
}
}
/* Page command */
public static class PageCommand extends ShellCommand {
private final static String NAME = "page";
final static String SYNTAX = NAME + " " +
CommandParser.optional(ON_FLAG + " | | " + OFF_FLAG);
final static String DESCRIPTION =
"Turns query output paging on or off. If specified, n is used " +
"as the page" + eolt + "height. If n is 0, or 'on' is specified " +
"the default page height is used." + eolt + "'off' turns paging " +
"off.";
public PageCommand() {
super(NAME, 4);
}
@Override
public String execute(String[] args, Shell shell)
throws ShellException {
Shell.checkHelp(args, this);
final CommonShell comShell = (CommonShell)shell;
int height;
if (args.length > 2) {
shell.badArgCount(this);
} else if (args.length > 1) {
String arg = args[1];
if (ON_FLAG.equals(arg)) {
comShell.setPageHeight(0);
} else if (OFF_FLAG.equals(arg)) {
comShell.setPageHeight(-1);
} else {
height = parseInt(arg);
if (height < 1) {
invalidArgument(arg);
}
comShell.setPageHeight(height);
}
}
if (comShell.isPagingEnabled()) {
return "Paging mode is now on, height: " +
comShell.getPageHeight();
}
return "Paging mode is now off";
}
@Override
public String getCommandSyntax() {
return SYNTAX;
}
@Override
public String getCommandDescription() {
return DESCRIPTION;
}
}
/* History command */
public static class HistoryCommand extends ShellCommand {
final static String NAME = "history";
final static String SYNTAX = NAME + " " +
CommandParser.optional(LAST_FLAG + " ") + " " +
CommandParser.optional(FROM_FLAG + " ") + " " +
CommandParser.optional(TO_FLAG + " ");
final static String DESCRIPTION =
"Displays command history. By default all history is " +
"displayed." + eolt + "Optional flags are used to choose " +
"ranges for display";
public HistoryCommand() {
super(NAME, 4);
}
@Override
public String execute(String[] args, Shell shell)
throws ShellException {
Shell.checkHelp(args, this);
Shell.CommandHistory history = shell.getHistory();
int from = 0;
int to = history.getSize();
boolean isLast = false;
if (args.length > 1) {
for (int i = 1; i < args.length; i++) {
String arg = args[i];
if (LAST_FLAG.equals(arg)) {
from = parseInt(Shell.nextArg(args, i++, this));
isLast = true;
} else if (FROM_FLAG.equals(arg)) {
from = parseInt(Shell.nextArg(args, i++, this));
} else if (TO_FLAG.equals(arg)) {
to = parseInt(Shell.nextArg(args, i++, this));
} else {
shell.unknownArgument(arg, this);
}
}
if (isLast) {
from = history.getSize() - from + 1;
}
}
/*
* The index of command are shown as 1-based index in
* the output, so covert it to 0-based index when locating
* it in CommandHistory list.
*/
return history.dump(toZeroBasedIndex(from), toZeroBasedIndex(to));
}
private int toZeroBasedIndex(int index) {
return (index > 0) ? (index - 1) : 0;
}
@Override
protected String getCommandSyntax() {
return SYNTAX;
}
@Override
protected String getCommandDescription() {
return DESCRIPTION;
}
}
public static class DebugCommand extends ShellCommand {
private static String NAME = "debug";
final static String SYNTAX = NAME + " " +
CommandParser.optional(ON_FLAG + " | " + OFF_FLAG);
final static String DESCRIPTION =
"Toggles or sets the global debug setting. This property can " +
"also" + eolt + "be set per-command using the -debug flag.";
public DebugCommand() {
super(NAME, 4);
}
@Override
public boolean isHidden() {
return true;
}
@Override
public String execute(String[] args, Shell shell)
throws ShellException {
if (args.length > 2) {
shell.badArgCount(this);
} else if (args.length > 1) {
String arg = args[1];
if (ON_FLAG.equals(arg)) {
shell.setDebug(true);
} else if (OFF_FLAG.equals(arg)) {
shell.setDebug(false);
} else {
return "Invalid argument: " + arg + eolt +
getBriefHelp();
}
} else {
shell.toggleDebug();
}
return "Debug mode is now " + (shell.getDebug()? "on" : "off");
}
@Override
protected String getCommandSyntax() {
return SYNTAX;
}
@Override
public String getCommandDescription() {
return DESCRIPTION;
}
}
public static class VerboseCommand extends ShellCommand {
private final static String NAME = "verbose";
final static String SYNTAX = NAME + " " +
CommandParser.optional(ON_FLAG + " | " + OFF_FLAG);
final static String DESCRIPTION =
"Toggles or sets the global verbosity setting. This " +
"property can also" + eolt + "be set per-command using " +
"the -verbose flag.";
public VerboseCommand() {
super(NAME, 4);
}
@Override
public String execute(String[] args, Shell shell)
throws ShellException {
if (args.length > 2) {
shell.badArgCount(this);
} else if (args.length > 1) {
String arg = args[1];
if (ON_FLAG.equals(arg)) {
shell.setVerbose(true);
} else if (OFF_FLAG.equals(arg)) {
shell.setVerbose(false);
} else {
return "Invalid argument: " + arg + eolt +
getBriefHelp();
}
} else {
shell.toggleVerbose();
}
return "Verbose mode is now " + (shell.getVerbose()? "on" : "off");
}
@Override
protected String getCommandSyntax() {
return SYNTAX;
}
@Override
public String getCommandDescription() {
return DESCRIPTION;
}
}
public static class HiddenCommand extends ShellCommand {
private final static String NAME = "hidden";
final static String SYNTAX = NAME + " " +
CommandParser.optional(ON_FLAG + " | | " + OFF_FLAG);
final static String DESCRIPTION =
"Toggles visibility of commands and flags that are normally" +
eolt + "hidden. Use these only if advised to do so by Oracle " +
"Support.";
public HiddenCommand() {
super(NAME, 3);
}
@Override
protected boolean isHidden() {
return true;
}
@Override
public String execute(String[] args, Shell shell)
throws ShellException {
if (args.length > 2) {
shell.badArgCount(this);
} if (args.length > 1) {
String arg = args[1];
if (ON_FLAG.equals(arg)) {
shell.setHidden(true);
} else if (OFF_FLAG.equals(arg)) {
shell.setHidden(false);
} else {
return "Invalid argument: " + arg + eolt +
getBriefHelp();
}
} else {
shell.toggleHidden();
}
return "Hidden commands and parameters are " +
(shell.getHidden() ? "enabled" : "disabled");
}
@Override
protected String getCommandSyntax() {
return SYNTAX;
}
@Override
public String getCommandDescription() {
return DESCRIPTION;
}
}
/* Namespace command */
public static class NamespaceCommand extends ShellCommand {
final static String NAME = "namespace";
final static String SYNTAX = NAME + " " +
CommandParser.optional("namespace");
final static String DESCRIPTION =
"Sets or clears the default namespace to use for table " +
"operations and queries";
public NamespaceCommand() {
super(NAME, 3);
}
@Override
public String execute(String[] args, Shell shell)
throws ShellException {
Shell.checkHelp(args, this);
final CommonShell commonShell = ((CommonShell)shell);
if (args.length > 2) {
shell.badArgCount(this);
} else if (args.length > 1) {
commonShell.setNamespace(args[1]);
} else {
/* clear the namespace */
commonShell.setNamespace(null);
}
return ("Namespace is " +
NameUtils.switchToExternalUse(commonShell.getNamespace()));
}
@Override
public String getCommandSyntax() {
return SYNTAX;
}
@Override
public String getCommandDescription() {
return DESCRIPTION;
}
}
/**
* Display the result depending on its type and outcome. Operations that
* ended in error show their error messages and status info, operations
* like 'describe' and 'show' display their results, and operations that
* generate plan execution return status info.
*/
public String displayDDLResults(StatementResult result) {
if (result.getErrorMessage() != null) {
return result.getErrorMessage() + "\n" + result.getInfo();
}
/*
* Statement was successful, output for describes, shows, and noop
* should be displayed.
*/
if (result.isSuccessful()) {
if (result.getResult() != null) {
return result.getResult();
}
if (result.getInfo().equals(DdlJsonFormat.NOOP_STATUS)) {
return result.getInfo();
}
return "Statement completed successfully";
}
/*
* For now, all info is returned as unstructured text. In the future,
* when the execute option can specify json or not, we may return
* status info in json form.
*/
return "Statement did not complete successfully:\n" +
result.getInfo();
}
public String displayDMLResults(final OutputMode outputMode,
final StatementResult result)
throws ShellException {
return displayDMLResults(outputMode, result,
isPagingEnabled(), getOutput());
}
public String displayDMLResults(final OutputMode outputMode,
final StatementResult result,
final boolean isPagingEnabled,
final PrintStream queryOutput)
throws ShellException {
if (result.getErrorMessage() != null) {
return result.getErrorMessage() + "\n" + result.getInfo();
}
final ResultOutput resultOutput =
ResultOutputFactory.getOutput(outputMode, this, queryOutput,
result.getResultDef(),
result.iterator(),
isPagingEnabled,
getPageHeight());
try {
long num = resultOutput.outputResultSet();
return String.format("\n%d %s returned", num,
((num > 1) ? "rows" : "row"));
} catch (IllegalArgumentException iae) {
throw new ShellException("Failed to display result set: " +
iae.getMessage(), iae);
} catch (IOException ioe) {
throw new ShellException("Failed to display result set: " +
ioe.getMessage(), ioe);
}
}
public void start() {
init();
/*
* For testing, once exit code is set, give up following execution
* in order to output a single error message.
*/
if (getExitCode() != 0 && dontExit()) {
shutdown();
return;
}
try {
if (commandToRun != null) {
try {
String result = run(commandToRun[0], commandToRun);
output.println(result);
} catch (ShellException se) {
handleShellException(commandToRun[0], se);
} catch (Exception e) {
handleUnknownException(commandToRun[0], e);
}
} else {
loop();
}
} finally {
shutdown();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy