com.sshtools.commands.CliCommand Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of command-utils Show documentation
Show all versions of command-utils Show documentation
Utility classes for creating SSH enabled commands with Maverick Synergy
The newest version!
package com.sshtools.commands;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import com.sshtools.common.util.Utils;
import com.sshtools.jaul.Phase;
import com.sshtools.sequins.Prompter.PromptContextBuilder;
import picocli.CommandLine;
public abstract class CliCommand extends SshCommand {
protected CliCommand(Optional defaultPhase) {
super(defaultPhase);
}
@Override
protected int runCommand() {
try {
int exitCode = 0;
if(startCLI()) {
do {
try {
var cmd = getTerminal().prompt(PromptContextBuilder.builder().withUse(getUsername()).build(), "{0} ", getPrompt());
if(cmd == null) {
getTerminal().getWriter().println();
break;
}
else if (cmd.length() > 0) {
exitCode = executeCommand(cmd);
}
} catch(Exception e) {
if(!isQuiet())
error("Operation failed.", e);
System.err.println(String.format("%s", e.getMessage()));
}
} while (!canExit());
}
return exitCode;
} catch (Exception e1) {
if(!isQuiet())
error("Failed.", e1);
return 1;
}
}
protected boolean startCLI() throws IOException, InterruptedException {
return true;
}
private int executeCommand(String cmd) throws IOException, InterruptedException {
var newargs = parseQuotedString(cmd);
newargs.removeIf(item -> item == null || "".equals(item));
var args = newargs.toArray(new String[0]);
if (args.length > 0) {
return spawn(args);
}
return 0;
}
protected int source(InputStream in) throws IOException, InterruptedException {
int exitCode = 0;
try(BufferedReader r = new BufferedReader(new InputStreamReader(in))) {
String line = null;
while ((line = r.readLine()) != null) {
if(line.startsWith("#") || Utils.isBlank(line)) {
continue;
}
exitCode = executeCommand(line);
}
} finally {
in.close();
}
return exitCode;
}
protected int spawn(String[] args) throws IOException, InterruptedException {
if(args[0].startsWith("!")) {
args[0] = args[0].substring(1);
var pb = new ProcessBuilder(Arrays.asList(args));
pb.directory(getLcwd());
pb.redirectErrorStream(true);
var p = pb.start();
try {
var thread = new Thread(() -> {
byte[] b = new byte[256];
var in = System.in;
var out = p.getOutputStream();
int r;
try {
while( ( r = in.read(b)) != -1) {
out.write(b, 0, r);
out.flush();
}
}
catch(Exception ioe) {
}
});
thread.start();
try {
p.getInputStream().transferTo(System.out);
}
finally {
thread.interrupt();
}
}
finally {
if(p.waitFor() != 0) {
System.err.println(String.format("%s exited with error code %d.", args[0], p.exitValue()));
}
}
return p.exitValue();
}
else {
var cl = new CommandLine(createInteractiveCommand());
cl.setTrimQuotes(true);
cl.setExecutionExceptionHandler(new ExceptionHandler(this));
cl.setUnmatchedArgumentsAllowed(true);
cl.setUnmatchedOptionsAllowedAsOptionParameters(true);
cl.setUnmatchedOptionsArePositionalParams(true);
return cl.execute(args);
}
}
protected abstract boolean canExit();
protected abstract void error(String string, Exception e);
protected abstract boolean isQuiet();
protected abstract Object createInteractiveCommand();
protected File getLcwd() {
try {
return new File(".").getCanonicalFile();
} catch (IOException e) {
return new File(System.getProperty("user.dir"));
}
}
/**
* Parse a space separated string into a list, treating portions quotes with
* single quotes as a single element. Single quotes themselves and spaces can be
* escaped with a backslash.
*
* @param command command to parse
* @return parsed command
*/
public static List parseQuotedString(String command) {
var args = new ArrayList();
var escaped = false;
var quoted = false;
var word = new StringBuilder();
for (int i = 0; i < command.length(); i++) {
char c = command.charAt(i);
if (c == '"' && !escaped) {
if (quoted) {
quoted = false;
} else {
quoted = true;
}
} else if (c == '\\' && !escaped) {
escaped = true;
} else if (c == ' ' && !escaped && !quoted) {
if (word.length() > 0) {
args.add(word.toString());
word.setLength(0);
;
}
} else {
word.append(c);
}
}
if (word.length() > 0)
args.add(word.toString());
return args;
}
protected String getPrompt() {
return String.format("%s>", getCommandName());
}
}