public class CmdExecuter
extends java.lang.Object
implements java.io.Closeable
ProcessBuilder
)
and call of JZtxtcmdScript
sub routines (which may call internally command lines).
It is especially proper for graphic applications:
The execution of complex callbacks on graphical buttons should not be done in the graphic thread!Modifier and Type | Class and Description |
---|---|
static class |
CmdExecuter.CmdQueueEntry |
static interface |
CmdExecuter.ExecuteAfterFinish
An implementation of this interface can be evaluate the output of the process after finish.
|
(package private) class |
CmdExecuter.InThread |
(package private) class |
CmdExecuter.OutThread |
Modifier and Type | Field and Description |
---|---|
(package private) boolean |
bRunThreads
True for ever so long this class is used, it maybe so long this application runs.
|
private java.nio.charset.Charset |
charsetCmd
A maybe special charset for Input and output stream.
|
(package private) java.util.concurrent.ConcurrentLinkedQueue<CmdExecuter.CmdQueueEntry> |
cmdQueue |
private java.lang.Appendable |
echoCmd
Can be set especially for debug the commands.
|
private CmdExecuter.OutThread |
errThread
Both thread instances runs for ever so long bRunThreads is true.
|
private CmdExecuter.ExecuteAfterFinish |
executeAfterCmd
Set with an execute invocation, set to null if it was processed.
|
private JZtxtcmdExecuter |
jzcmdExecuter
|
private CmdExecuter.OutThread |
outThread
Both thread instances runs for ever so long bRunThreads is true.
|
private java.lang.Process |
process
The running process or null.
|
private java.lang.ProcessBuilder |
processBuilder
Composite instance of the java.lang.ProcessBuilder.
|
(package private) java.lang.String[] |
sConsoleInvocation |
(package private) java.lang.Thread |
threadExecError |
(package private) java.lang.Thread |
threadExecIn |
(package private) java.lang.Thread |
threadExecOut
True if a process is started, false if it is finished.
|
static java.lang.String |
version
Version, License and History:
2022-01-21 Hartmut new
setEnvIgnoreCase(String, String) : The Problem is that windows does not distinguish upper/lower case. |
Constructor and Description |
---|
CmdExecuter()
Constructs the class and starts the threads to getting output and error stream
and putting the input stream to a process.
|
Modifier and Type | Method and Description |
---|---|
boolean |
abortAllCmds() |
boolean |
abortCmd()
Aborts the running cmd.
|
void |
addCmd(JZtxtcmdScript.Subroutine jzsub,
java.util.List<DataAccess.Variable<java.lang.Object>> args,
java.lang.Appendable out,
java.io.File currDir)
Same as
addCmd(org.vishia.cmd.JZtxtcmdScript.Subroutine, List, Appendable, File, ExecuteAfterFinish)
but without execFinish |
void |
addCmd(JZtxtcmdScript.Subroutine jzsub,
java.util.List<DataAccess.Variable<java.lang.Object>> args,
java.lang.Appendable out,
java.io.File currDir,
CmdExecuter.ExecuteAfterFinish execFinish)
Adds a Subroutine of an jzTc script to execute.
|
void |
addCmd(java.lang.String[] cmdArgs,
java.lang.String input,
java.util.List<java.lang.Appendable> outputs,
java.util.List<java.lang.Appendable> errors,
java.io.File currentDir,
CmdExecuter.ExecuteAfterFinish executeAfterCmd) |
void |
addCmd(java.lang.String cmdline,
java.lang.String input,
java.lang.Appendable output,
java.io.File currentDir,
CmdExecuter.ExecuteAfterFinish executeAfterCmd) |
void |
clearCmdQueue() |
void |
close()
Closes the functionality, finished the threads.
|
java.util.Map<java.lang.String,java.lang.String> |
environment()
Returns the environment map for the internal
ProcessBuilder . |
int |
execute(java.lang.String[] cmdArgs,
boolean donotwait,
java.lang.String input,
java.util.List<java.lang.Appendable> outputs,
java.util.List<java.lang.Appendable> errors,
CmdExecuter.ExecuteAfterFinish executeAfterCmd)
Executes a command with arguments and maybe waits for its finishing.
|
int |
execute(java.lang.String[] cmdArgs,
java.lang.String input,
java.lang.Appendable output,
java.lang.Appendable error)
Executes a command with arguments and maybe waits for its finishing.
|
int |
execute(java.lang.String[] cmdArgs,
java.lang.String input,
java.util.List<java.lang.Appendable> outputs,
java.util.List<java.lang.Appendable> errors)
Same as
#execute(String[], String, Appendable, Appendable, boolean)
but do not wait for finish if both outputs and errors are null. |
int |
execute(java.lang.String cmdLine,
java.lang.String input,
java.lang.Appendable output,
java.lang.Appendable error)
Executes a command with arguments and waits for its finishing.
|
int |
execute(java.lang.String cmdLine,
java.lang.String input,
java.lang.Appendable output,
java.lang.Appendable error,
boolean useShell)
Executes a command with arguments and waits for its finishing.
|
CmdExecuter.CmdQueueEntry |
executeCmdQueue(boolean abortOnError)
Executes the commands stored with
#addCmd(String[], String, List, List, ExecuteAfterFinish) . |
void |
finalize()
Stops the threads to get output.
|
private java.lang.String |
getRemoveEnv(java.lang.String name) |
boolean |
hasEntries()
Returns true if the associated queue has at least on entry.
|
void |
initJZcmdExecuter(JZtxtcmdScript script,
java.lang.String sCurrdir,
LogMessage log) |
static void |
main(java.lang.String[] args)
A test main programm only for class test espesically in debug mode.
|
void |
outAllEnvironment(java.lang.Appendable out)
Outputs all environment variables in a sorted form
|
java.lang.String |
prefixEnv(java.lang.String name,
java.lang.String value)
Adds a prefix or sets an environment variable, especially usable for PATH.
|
java.lang.String |
prefixEnvIgnoreCase(java.lang.String name,
java.lang.String value)
Adds a prefix or sets an environment variable, especially usable for PATH.
|
void |
setCharsetForOutput(java.lang.String nameCharset) |
void |
setCurrentDir(java.io.File dir)
Sets the current directory for the next execution.
|
void |
setEchoCmdOut(java.lang.Appendable echo)
Possible to use for debugging which commands are executed.
|
java.lang.String |
setEnv(java.lang.String name,
java.lang.String value)
Sets an environment variable.
|
java.lang.String |
setEnvIgnoreCase(java.lang.String name,
java.lang.String value)
Sets an environment variable.
|
void |
specifyConsoleInvocation(java.lang.String cmd) |
static java.lang.String[] |
splitArgs(java.lang.String line)
Splits command line arguments.
|
static java.lang.String[] |
splitArgs(java.lang.String line,
int npreArgs,
int npostArgs)
Splits command line arguments.
|
static java.lang.String[] |
splitArgs(java.lang.String line,
java.lang.String[] preArgs,
java.lang.String[] postArgs)
Splits command line arguments with given pre- and post arg array.
|
(package private) void |
stop() |
public static final java.lang.String version
setEnvIgnoreCase(String, String)
: The Problem is that windows does not distinguish upper/lower case.
If an environment variable is existing, and the same with other case is set in the Map from Java's ProcessBuilder.environment()
,
then this variable is twice, with all following catastrophics. This routine repairs, as also prefixEnvIgnoreCase(String, String)
.
splitArgs(String, int, int)
now regards also '' as quotation, for inner quotation.
Using: myCmd -arg="'partial arg' second": Firstly 'partial arg' second is stored, and this is split after them with this operation.
setEchoCmdOut(Appendable)
hasEntries()
addCmd(org.vishia.cmd.JZtxtcmdScript.Subroutine, List, Appendable, File, ExecuteAfterFinish)
.
setCharsetForOutput(String)
: git outputs its status etc. in UTF-8.
JZtxtcmdExecuter#execSub(org.vishia.cmd.JZtxtcmdScript.Subroutine, List, boolean, Appendable, File)
can be invoked by a #add The JZcmdExecuter may invoke an command process and uses this CmdExecuter too in the main thread. Therefore it is proper
to join both invocation variants. The old class org.vishia.cmd.CmdQueue is obsolete then.
addCmd(String[], String, List, List, File, ExecuteAfterFinish)
and executeCmdQueue(boolean)
.
That is a new feature to store simple system commands. The class CmdQueue
may be over-engineered for some applications.
execute(String[], boolean, String, List, List, ExecuteAfterFinish)
have the argument CmdExecuter.ExecuteAfterFinish
.
This method is executed in the outThread
after finishing the command and can evaluate the output of the command with a Java routine.
The interface CmdExecuter.ExecuteAfterFinish
can be overridden in any application for that appoach.
splitArgs(String, String[], String[])
with pre- and post-arguments.
Therewith both the invocation of a batch in Windows with "cmd.exe" can be organized as a Linux cmd with "sh.exe" can be invoked.
The possibility execute(String, String, Appendable, Appendable, boolean)
with "useShell=true" is not the favor
because it is only one of the necessities. Nevertheless it works now with initial setting of sConsoleInvocation
.
execute(String[], String, Appendable, Appendable)
etc. the error can be the same
as the output. It is equate to error=null, only one output instance is used.
#execute(String[], boolean, String, List, List)
now with donotwait
execute(String[], String, List, List)
for more as one output or error.
It is nice to write a process output similar to the System.out and to a internal buffer while the process runs.
Catching in a buffer and write to System.out after the process is finished is not fine if the process needs some time or hangs.
splitArgs(String)
.
abortCmd()
: There was a situation were in CmdExecuter.OutThread.run()
readline() hangs,
though the process
was destroyed. It isn't solved yet. Test whether it may be better
to read the InputStream direct without wrapping with an BufferedReader.
CmdExecuter.OutThread.bProcessIsRunning
set to false to abort waiting.
close()
to stop threads.
execute(String, String, Appendable, Appendable)
because it has the capability of no-wait too.
abortCmd()
. experience: On windows the output getting thread may block.
execute(String[], String, Appendable, Appendable)
waits until
all outputs are gotten in the outThread
and errThread. Extra class CmdExecuter.OutThread
for both errThread and outThread.
MainCmd.executeCmdLine(String[], ProcessBuilder, int, Appendable, String)
.
private final java.lang.ProcessBuilder processBuilder
private java.lang.Process process
private CmdExecuter.ExecuteAfterFinish executeAfterCmd
private java.lang.Appendable echoCmd
private java.nio.charset.Charset charsetCmd
boolean bRunThreads
private final CmdExecuter.OutThread outThread
private final CmdExecuter.OutThread errThread
final java.lang.Thread threadExecOut
final java.lang.Thread threadExecIn
final java.lang.Thread threadExecError
java.util.concurrent.ConcurrentLinkedQueue<CmdExecuter.CmdQueueEntry> cmdQueue
private JZtxtcmdExecuter jzcmdExecuter
JZtxtcmdScript.Subroutine
. It is created on demand if necessity.java.lang.String[] sConsoleInvocation
public CmdExecuter()
finalize()
is called manually.
public void initJZcmdExecuter(JZtxtcmdScript script, java.lang.String sCurrdir, LogMessage log) throws java.lang.Throwable
java.lang.Throwable
public void setCurrentDir(java.io.File dir)
dir
- any directory in the users file system.public void setCharsetForOutput(java.lang.String nameCharset)
public java.util.Map<java.lang.String,java.lang.String> environment()
ProcessBuilder
. The returned Map can be modified,
its modified content will be used on the next execute(...) invocation. The modification is valid for all following executes.
ProcessBuilder.environment()
will be called.private java.lang.String getRemoveEnv(java.lang.String name)
public java.lang.String setEnv(java.lang.String name, java.lang.String value)
name
- Note: For MS-Windows use setEnvIgnoreCase(String, String)
value
- public java.lang.String setEnvIgnoreCase(java.lang.String name, java.lang.String value)
name
- If a variable with abbreviating case exists, this will be deleted.value
- public java.lang.String prefixEnv(java.lang.String name, java.lang.String value)
name
- Note: For MS-Windows use prefixEnvIgnoreCase(String, String)
value
- add as prefix to existing value, or the new value if not exists.public java.lang.String prefixEnvIgnoreCase(java.lang.String name, java.lang.String value)
name
- If a variable with abbreviating case exists, this will be deleted.value
- add as prefix to existing value, or the new value if not exists.public void outAllEnvironment(java.lang.Appendable out) throws java.io.IOException
out
- java.io.IOException
public void specifyConsoleInvocation(java.lang.String cmd)
public void setEchoCmdOut(java.lang.Appendable echo)
echo
- Write the cmd and args to echo before execution.
It writes in form: >cmdExecuter>cmd <args> <args>public void addCmd(java.lang.String cmdline, java.lang.String input, java.lang.Appendable output, java.io.File currentDir, CmdExecuter.ExecuteAfterFinish executeAfterCmd)
public void addCmd(java.lang.String[] cmdArgs, java.lang.String input, java.util.List<java.lang.Appendable> outputs, java.util.List<java.lang.Appendable> errors, java.io.File currentDir, CmdExecuter.ExecuteAfterFinish executeAfterCmd)
public void addCmd(JZtxtcmdScript.Subroutine jzsub, java.util.List<DataAccess.Variable<java.lang.Object>> args, java.lang.Appendable out, java.io.File currDir)
addCmd(org.vishia.cmd.JZtxtcmdScript.Subroutine, List, Appendable, File, ExecuteAfterFinish)
but without execFinishjzsub
- args
- out
- currDir
- public void addCmd(JZtxtcmdScript.Subroutine jzsub, java.util.List<DataAccess.Variable<java.lang.Object>> args, java.lang.Appendable out, java.io.File currDir, CmdExecuter.ExecuteAfterFinish execFinish)
JZtxtcmdExecuter
knows this.
initJZcmdExecuter(JZtxtcmdScript, String, LogMessage)
with that script
which contains the sub routine before call this operation.
executeCmdQueue(boolean)
. Hint: It can be done for example by the main thread in a graphical application.
The execution of complex callbacks on graphical buttons should not be done in the graphic thread!jzsub
- The dedicated subroutine from the script given with initJZcmdExecuter(JZtxtcmdScript, String, LogMessage)
args
- proper argumentsout
- The <:>...<.> text output is written intocurrDir
- current directory for script executionexecFinish
- maybe null, this operation is called on finishing the subroutine.
Maybe the text output on out should be append to an graphical window or such other,
or the resulting files are used.public void clearCmdQueue()
public boolean hasEntries()
executeCmdQueue(boolean)
for example also for a specific breakpoint in an application:public CmdExecuter.CmdQueueEntry executeCmdQueue(boolean abortOnError)
#addCmd(String[], String, List, List, ExecuteAfterFinish)
.
This can be invoked in a specific thread with the following pattern: Thread cmdThread = new Thread("gitGui-Cmd") {
abortOnError
- stops execution if a command does not return 0.public int execute(java.lang.String cmdLine, java.lang.String input, java.lang.Appendable output, java.lang.Appendable error)
cmdLine
- The command and its arguments in one line.
To separate the command and its argument the method splitArgs(String)
is used.input
- The input stream of the command. TODO not used yet.output
- Will be filled with the output of the command.error
- Will be filled with the error output of the command.
Maybe null or equal output, then the error output will be written to output with the same output thread.public int execute(java.lang.String cmdLine, java.lang.String input, java.lang.Appendable output, java.lang.Appendable error, boolean useShell)
#setConsoleInvocation(String)
.cmdLine
- The command and its arguments in one line.
To separate the command and its argument the method splitArgs(String)
is used.input
- The input stream of the command. TODO not used yet.output
- Will be filled with the output of the command.error
- Will be filled with the error output of the command.
Maybe null or equal output, then the error output will be written to output with the same output thread.public int execute(java.lang.String[] cmdArgs, java.lang.String input, java.lang.Appendable output, java.lang.Appendable error)
cmdArgs
- The command and its arguments. The command is cmdArgs[0].
Any argument have to be given with one element of this String array.input
- The input stream of the command. TODO not used yet.output
- Will be filled with the output of the command.
If output ==null then no output is expected and the end of command execution is not awaited.
But in this case error should not be ==null because errors of command invocation are written there.error
- Will be filled with the error output of the command.
Maybe null or equal output, then the error output will be written to output with the same output thread.public int execute(java.lang.String[] cmdArgs, java.lang.String input, java.util.List<java.lang.Appendable> outputs, java.util.List<java.lang.Appendable> errors)
#execute(String[], String, Appendable, Appendable, boolean)
but do not wait for finish if both outputs and errors are null.cmdArgs
- input
- outputs
- errors
- public int execute(java.lang.String[] cmdArgs, boolean donotwait, java.lang.String input, java.util.List<java.lang.Appendable> outputs, java.util.List<java.lang.Appendable> errors, CmdExecuter.ExecuteAfterFinish executeAfterCmd)
cmdArgs
- The command and its arguments. The command is cmdArgs[0].
Any argument have to be given with one element of this String array.donotwait
- true and all outputs, errors and input == null, then starts the process without wait.
If one of input, outputs and errors is not null, the execution should wait in this thread because
the threads for input, output and error should be running to capture that data. Then this flag is not used.input
- The input stream of the command. TODO not used yet.outputs
- Will be filled with the output of the command.
If output ==null then no output is expected and the end of command execution is not awaited.
But in this case error should not be ==null because errors of command invocation are written there.errors
- Will be filled with the error output of the command.
Maybe null, then the error output will be written to outputexecuteAfterCmd
- maybe null, will be executing if given. If the process waits it waits on end of this method.public boolean abortCmd()
public boolean abortAllCmds()
public static java.lang.String[] splitArgs(java.lang.String line)
splitArgs(String, String[], String[])
, without preArgs and postArgs.public static java.lang.String[] splitArgs(java.lang.String line, int npreArgs, int npostArgs)
line
- The line or more as one line with argumentsnpreArgs
- maybe 0, some arguments before them from line.npostArgs
- maybe 0, some arguments after them from line.public static java.lang.String[] splitArgs(java.lang.String line, java.lang.String[] preArgs, java.lang.String[] postArgs)
splitArgs(String, int, int)
.line
- The line or more as one line with argumentspreArgs
- maybe null, some arguments before them from line.postArgs
- maybe null, some arguments after them from line.void stop()
public void close()
close
in interface java.io.Closeable
close
in interface java.lang.AutoCloseable
public void finalize()
finalize
in class java.lang.Object
Object.finalize()
public static final void main(java.lang.String[] args)
args
- not used.