2021-03-27 14:08:26 +00:00
package com.termux.app.models ;
2021-03-23 22:48:24 +00:00
2021-03-25 04:20:09 +00:00
import android.app.Activity ;
2021-03-23 22:48:24 +00:00
import android.app.PendingIntent ;
import android.net.Uri ;
import androidx.annotation.NonNull ;
2021-04-07 06:31:30 +00:00
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_SERVICE ;
import com.termux.shared.logger.Logger ;
import com.termux.shared.markdown.MarkdownUtils ;
import com.termux.shared.data.DataUtils ;
2021-03-23 22:48:24 +00:00
import java.util.ArrayList ;
import java.util.List ;
public class ExecutionCommand {
/ *
The { @link ExecutionState # SUCCESS } and { @link ExecutionState # FAILED } is defined based on
successful execution of command without any internal errors or exceptions being raised .
The shell command { @link # exitCode } being non - zero * * does not * * mean that execution command failed .
Only the { @link # errCode } being non - zero means that execution command failed from the Termux app
perspective .
* /
/** The {@link Enum} that defines {@link ExecutionCommand} state. */
public enum ExecutionState {
PRE_EXECUTION ( " Pre-Execution " , 0 ) ,
EXECUTING ( " Executing " , 1 ) ,
EXECUTED ( " Executed " , 2 ) ,
SUCCESS ( " Success " , 3 ) ,
FAILED ( " Failed " , 4 ) ;
private final String name ;
private final int value ;
ExecutionState ( final String name , final int value ) {
this . name = name ;
this . value = value ;
}
public String getName ( ) {
return name ;
}
public int getValue ( ) {
return value ;
}
}
2021-03-25 04:20:09 +00:00
// Define errCode values
// TODO: Define custom values for different cases
public final static int RESULT_CODE_OK = Activity . RESULT_OK ;
public final static int RESULT_CODE_OK_MINOR_FAILURES = Activity . RESULT_FIRST_USER ;
public final static int RESULT_CODE_FAILED = Activity . RESULT_FIRST_USER + 1 ;
2021-03-23 22:48:24 +00:00
/** The optional unique id for the {@link ExecutionCommand}. */
public Integer id ;
/** The current state of the {@link ExecutionCommand}. */
2021-03-25 04:20:09 +00:00
private ExecutionState currentState = ExecutionState . PRE_EXECUTION ;
2021-03-23 22:48:24 +00:00
/** The previous state of the {@link ExecutionCommand}. */
2021-03-25 04:20:09 +00:00
private ExecutionState previousState = ExecutionState . PRE_EXECUTION ;
2021-03-23 22:48:24 +00:00
/** The executable for the {@link ExecutionCommand}. */
public String executable ;
/** The executable Uri for the {@link ExecutionCommand}. */
public Uri executableUri ;
/** The executable arguments array for the {@link ExecutionCommand}. */
public String [ ] arguments ;
/** The current working directory for the {@link ExecutionCommand}. */
public String workingDirectory ;
/** If the {@link ExecutionCommand} is a background or a foreground terminal session command. */
public boolean inBackground ;
/** If the {@link ExecutionCommand} is meant to start a failsafe terminal session. */
public boolean isFailsafe ;
/** The session action of foreground commands. */
public String sessionAction ;
/** The command label for the {@link ExecutionCommand}. */
public String commandLabel ;
/** The markdown text for the command description for the {@link ExecutionCommand}. */
public String commandDescription ;
/ * * The markdown text for the help of command for the { @link ExecutionCommand } . This can be used
* to provide useful info to the user if an internal error is raised . * /
public String commandHelp ;
/ * * Defines the markdown text for the help of the Termux plugin API that was used to start the
* { @link ExecutionCommand } . This can be used to provide useful info to the user if an internal
* error is raised . * /
public String pluginAPIHelp ;
2021-03-25 18:05:55 +00:00
/ * * Defines if { @link ExecutionCommand } was started because of an external plugin request
* like { @link TERMUX_SERVICE # ACTION_SERVICE_EXECUTE } intent or from within Termux app itself .
* /
2021-03-23 22:48:24 +00:00
public boolean isPluginExecutionCommand ;
/** Defines {@link PendingIntent} that should be sent if an external plugin requested the execution. */
public PendingIntent pluginPendingIntent ;
/** The stdout of shell command. */
public String stdout ;
2021-04-07 06:31:30 +00:00
/** The stderr of shell command. */
2021-03-23 22:48:24 +00:00
public String stderr ;
/** The exit code of shell command. */
public Integer exitCode ;
/** The internal error code of {@link ExecutionCommand}. */
2021-03-25 04:20:09 +00:00
public Integer errCode = RESULT_CODE_OK ;
2021-03-23 22:48:24 +00:00
/** The internal error message of {@link ExecutionCommand}. */
public String errmsg ;
/** The internal exceptions of {@link ExecutionCommand}. */
public List < Throwable > throwableList = new ArrayList < > ( ) ;
public ExecutionCommand ( ) {
}
public ExecutionCommand ( Integer id ) {
this . id = id ;
}
public ExecutionCommand ( Integer id , String executable , String [ ] arguments , String workingDirectory , boolean inBackground , boolean isFailsafe ) {
this . id = id ;
this . executable = executable ;
this . arguments = arguments ;
this . workingDirectory = workingDirectory ;
this . inBackground = inBackground ;
this . isFailsafe = isFailsafe ;
}
@NonNull
@Override
public String toString ( ) {
2021-04-06 12:17:12 +00:00
if ( ! hasExecuted ( ) )
2021-03-23 22:48:24 +00:00
return getExecutionInputLogString ( this , true ) ;
else {
return getExecutionOutputLogString ( this , true ) ;
}
}
/ * *
* Get a log friendly { @link String } for { @link ExecutionCommand } execution input parameters .
*
* @param executionCommand The { @link ExecutionCommand } to convert .
* @param ignoreNull Set to { @code true } if non - critical { @code null } values are to be ignored .
* @return Returns the log friendly { @link String } .
* /
2021-03-28 04:06:17 +00:00
public static String getExecutionInputLogString ( final ExecutionCommand executionCommand , boolean ignoreNull ) {
2021-03-23 22:48:24 +00:00
if ( executionCommand = = null ) return " null " ;
StringBuilder logString = new StringBuilder ( ) ;
2021-03-25 04:20:09 +00:00
logString . append ( executionCommand . getCommandIdAndLabelLogString ( ) ) . append ( " : " ) ;
2021-03-23 22:48:24 +00:00
2021-04-06 12:17:12 +00:00
if ( executionCommand . previousState ! = ExecutionState . PRE_EXECUTION )
2021-03-23 22:48:24 +00:00
logString . append ( " \ n " ) . append ( executionCommand . getPreviousStateLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getCurrentStateLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getExecutableLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getArgumentsLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getWorkingDirectoryLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getInBackgroundLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getIsFailsafeLogString ( ) ) ;
2021-04-06 12:17:12 +00:00
if ( ! ignoreNull | | executionCommand . sessionAction ! = null )
2021-03-23 22:48:24 +00:00
logString . append ( " \ n " ) . append ( executionCommand . getSessionActionLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getIsPluginExecutionCommandLogString ( ) ) ;
2021-04-06 12:17:12 +00:00
if ( ! ignoreNull | | executionCommand . isPluginExecutionCommand ) {
2021-03-23 22:48:24 +00:00
if ( ! ignoreNull | | executionCommand . pluginPendingIntent ! = null )
logString . append ( " \ n " ) . append ( executionCommand . getPendingIntentCreatorLogString ( ) ) ;
}
return logString . toString ( ) ;
}
/ * *
* Get a log friendly { @link String } for { @link ExecutionCommand } execution output parameters .
*
* @param executionCommand The { @link ExecutionCommand } to convert .
* @param ignoreNull Set to { @code true } if non - critical { @code null } values are to be ignored .
* @return Returns the log friendly { @link String } .
* /
2021-03-28 04:06:17 +00:00
public static String getExecutionOutputLogString ( final ExecutionCommand executionCommand , boolean ignoreNull ) {
2021-03-23 22:48:24 +00:00
if ( executionCommand = = null ) return " null " ;
StringBuilder logString = new StringBuilder ( ) ;
2021-03-25 04:20:09 +00:00
logString . append ( executionCommand . getCommandIdAndLabelLogString ( ) ) . append ( " : " ) ;
2021-03-23 22:48:24 +00:00
logString . append ( " \ n " ) . append ( executionCommand . getPreviousStateLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getCurrentStateLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getStdoutLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getStderrLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getExitCodeLogString ( ) ) ;
logString . append ( getExecutionErrLogString ( executionCommand , ignoreNull ) ) ;
return logString . toString ( ) ;
}
/ * *
* Get a log friendly { @link String } for { @link ExecutionCommand } execution error parameters .
*
* @param executionCommand The { @link ExecutionCommand } to convert .
* @param ignoreNull Set to { @code true } if non - critical { @code null } values are to be ignored .
* @return Returns the log friendly { @link String } .
* /
2021-03-28 04:06:17 +00:00
public static String getExecutionErrLogString ( final ExecutionCommand executionCommand , boolean ignoreNull ) {
2021-03-23 22:48:24 +00:00
StringBuilder logString = new StringBuilder ( ) ;
2021-04-06 12:17:12 +00:00
if ( ! ignoreNull | | ( executionCommand . isStateFailed ( ) ) ) {
2021-03-23 22:48:24 +00:00
logString . append ( " \ n " ) . append ( executionCommand . getErrCodeLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getErrmsgLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . geStackTracesLogString ( ) ) ;
} else {
logString . append ( " " ) ;
}
return logString . toString ( ) ;
}
/ * *
* Get a log friendly { @link String } for { @link ExecutionCommand } with more details .
*
* @param executionCommand The { @link ExecutionCommand } to convert .
* @return Returns the log friendly { @link String } .
* /
2021-03-28 04:06:17 +00:00
public static String getDetailedLogString ( final ExecutionCommand executionCommand ) {
2021-03-23 22:48:24 +00:00
if ( executionCommand = = null ) return " null " ;
StringBuilder logString = new StringBuilder ( ) ;
logString . append ( getExecutionInputLogString ( executionCommand , false ) ) ;
logString . append ( getExecutionOutputLogString ( executionCommand , false ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getCommandDescriptionLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getCommandHelpLogString ( ) ) ;
logString . append ( " \ n " ) . append ( executionCommand . getPluginAPIHelpLogString ( ) ) ;
return logString . toString ( ) ;
}
/ * *
* Get a markdown { @link String } for { @link ExecutionCommand } .
*
* @param executionCommand The { @link ExecutionCommand } to convert .
* @return Returns the markdown { @link String } .
* /
2021-03-28 04:06:17 +00:00
public static String getExecutionCommandMarkdownString ( final ExecutionCommand executionCommand ) {
2021-03-23 22:48:24 +00:00
if ( executionCommand = = null ) return " null " ;
if ( executionCommand . commandLabel = = null ) executionCommand . commandLabel = " Execution Command " ;
StringBuilder markdownString = new StringBuilder ( ) ;
2021-03-28 04:06:17 +00:00
markdownString . append ( " ## " ) . append ( executionCommand . commandLabel ) . append ( " \ n " ) ;
2021-03-23 22:48:24 +00:00
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " Previous State " , executionCommand . previousState . getName ( ) , " - " ) ) ;
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " Current State " , executionCommand . currentState . getName ( ) , " - " ) ) ;
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " Executable " , executionCommand . executable , " - " ) ) ;
markdownString . append ( " \ n " ) . append ( getArgumentsMarkdownString ( executionCommand . arguments ) ) ;
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " Working Directory " , executionCommand . workingDirectory , " - " ) ) ;
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " inBackground " , executionCommand . inBackground , " - " ) ) ;
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " isFailsafe " , executionCommand . isFailsafe , " - " ) ) ;
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " Session Action " , executionCommand . sessionAction , " - " ) ) ;
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " isPluginExecutionCommand " , executionCommand . isPluginExecutionCommand , " - " ) ) ;
if ( executionCommand . pluginPendingIntent ! = null )
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " Pending Intent Creator " , executionCommand . pluginPendingIntent . getCreatorPackage ( ) , " - " ) ) ;
else
markdownString . append ( " \ n " ) . append ( " **Pending Intent Creator:** - " ) ;
markdownString . append ( " \ n \ n " ) . append ( MarkdownUtils . getMultiLineMarkdownStringEntry ( " Stdout " , executionCommand . stdout , " - " ) ) ;
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getMultiLineMarkdownStringEntry ( " Stderr " , executionCommand . stderr , " - " ) ) ;
markdownString . append ( " \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " Exit Code " , executionCommand . exitCode , " - " ) ) ;
markdownString . append ( " \ n \ n " ) . append ( MarkdownUtils . getSingleLineMarkdownStringEntry ( " Err Code " , executionCommand . errCode , " - " ) ) ;
2021-03-28 04:08:45 +00:00
markdownString . append ( " \ n " ) . append ( " **Errmsg:** \ n " ) . append ( DataUtils . getDefaultIfNull ( executionCommand . errmsg , " - " ) ) ;
2021-03-23 22:48:24 +00:00
markdownString . append ( " \ n \ n " ) . append ( executionCommand . geStackTracesMarkdownString ( ) ) ;
2021-04-06 12:17:12 +00:00
if ( executionCommand . commandDescription ! = null | | executionCommand . commandHelp ! = null ) {
2021-03-23 22:48:24 +00:00
if ( executionCommand . commandDescription ! = null )
2021-03-28 04:06:17 +00:00
markdownString . append ( " \ n \ n### Command Description \ n \ n " ) . append ( executionCommand . commandDescription ) . append ( " \ n " ) ;
2021-03-23 22:48:24 +00:00
if ( executionCommand . commandHelp ! = null )
2021-03-28 04:06:17 +00:00
markdownString . append ( " \ n \ n### Command Help \ n \ n " ) . append ( executionCommand . commandHelp ) . append ( " \ n " ) ;
2021-03-23 22:48:24 +00:00
markdownString . append ( " \ n## \ n " ) ;
}
2021-04-06 12:17:12 +00:00
if ( executionCommand . pluginAPIHelp ! = null ) {
2021-03-28 04:06:17 +00:00
markdownString . append ( " \ n \ n### Plugin API Help \ n \ n " ) . append ( executionCommand . pluginAPIHelp ) ;
2021-03-23 22:48:24 +00:00
markdownString . append ( " \ n## \ n " ) ;
}
return markdownString . toString ( ) ;
}
public String getIdLogString ( ) {
2021-04-06 12:17:12 +00:00
if ( id ! = null )
2021-03-23 22:48:24 +00:00
return " ( " + id + " ) " ;
else
return " " ;
}
public String getCurrentStateLogString ( ) {
return " Current State: ` " + currentState . getName ( ) + " ` " ;
}
public String getPreviousStateLogString ( ) {
return " Previous State: ` " + previousState . getName ( ) + " ` " ;
}
public String getCommandLabelLogString ( ) {
if ( commandLabel ! = null & & ! commandLabel . isEmpty ( ) )
return commandLabel ;
else
return " Execution Command " ;
}
2021-03-25 04:20:09 +00:00
public String getCommandIdAndLabelLogString ( ) {
return getIdLogString ( ) + getCommandLabelLogString ( ) ;
}
2021-03-23 22:48:24 +00:00
public String getExecutableLogString ( ) {
return " Executable: ` " + executable + " ` " ;
}
public String getArgumentsLogString ( ) {
return getArgumentsLogString ( arguments ) ;
}
public String getWorkingDirectoryLogString ( ) {
return " Working Directory: ` " + workingDirectory + " ` " ;
}
public String getInBackgroundLogString ( ) {
return " inBackground: ` " + inBackground + " ` " ;
}
public String getIsFailsafeLogString ( ) {
return " isFailsafe: ` " + isFailsafe + " ` " ;
}
public String getIsPluginExecutionCommandLogString ( ) {
return " isPluginExecutionCommand: ` " + isPluginExecutionCommand + " ` " ;
}
public String getSessionActionLogString ( ) {
2021-04-05 18:21:13 +00:00
return Logger . getSingleLineLogStringEntry ( " Session Action " , sessionAction , " - " ) ;
2021-03-23 22:48:24 +00:00
}
public String getPendingIntentCreatorLogString ( ) {
if ( pluginPendingIntent ! = null )
return " Pending Intent Creator: ` " + pluginPendingIntent . getCreatorPackage ( ) + " ` " ;
else
return " Pending Intent Creator: - " ;
}
public String getCommandDescriptionLogString ( ) {
2021-04-05 18:21:13 +00:00
return Logger . getSingleLineLogStringEntry ( " Command Description " , commandDescription , " - " ) ;
2021-03-23 22:48:24 +00:00
}
public String getCommandHelpLogString ( ) {
2021-04-05 18:21:13 +00:00
return Logger . getSingleLineLogStringEntry ( " Command Help " , commandHelp , " - " ) ;
2021-03-23 22:48:24 +00:00
}
public String getPluginAPIHelpLogString ( ) {
2021-04-05 18:21:13 +00:00
return Logger . getSingleLineLogStringEntry ( " Plugin API Help " , pluginAPIHelp , " - " ) ;
2021-03-23 22:48:24 +00:00
}
public String getStdoutLogString ( ) {
2021-04-05 18:21:13 +00:00
return Logger . getMultiLineLogStringEntry ( " Stdout " , DataUtils . getTruncatedCommandOutput ( stdout , Logger . LOGGER_ENTRY_SIZE_LIMIT_IN_BYTES / 5 , false , false , true ) , " - " ) ;
2021-03-23 22:48:24 +00:00
}
public String getStderrLogString ( ) {
2021-04-05 18:21:13 +00:00
return Logger . getMultiLineLogStringEntry ( " Stderr " , DataUtils . getTruncatedCommandOutput ( stderr , Logger . LOGGER_ENTRY_SIZE_LIMIT_IN_BYTES / 5 , false , false , true ) , " - " ) ;
2021-03-23 22:48:24 +00:00
}
public String getExitCodeLogString ( ) {
2021-04-05 18:21:13 +00:00
return Logger . getSingleLineLogStringEntry ( " Exit Code " , exitCode , " - " ) ;
2021-03-23 22:48:24 +00:00
}
public String getErrCodeLogString ( ) {
2021-04-05 18:21:13 +00:00
return Logger . getSingleLineLogStringEntry ( " Err Code " , errCode , " - " ) ;
2021-03-23 22:48:24 +00:00
}
public String getErrmsgLogString ( ) {
2021-04-05 18:21:13 +00:00
return Logger . getMultiLineLogStringEntry ( " Errmsg " , errmsg , " - " ) ;
2021-03-23 22:48:24 +00:00
}
public String geStackTracesLogString ( ) {
return Logger . getStackTracesString ( " StackTraces: " , Logger . getStackTraceStringArray ( throwableList ) ) ;
}
public String geStackTracesMarkdownString ( ) {
Implement crash handler and reporting
Now whenever the Termux app crashes, the crash report (stacktrace, app and device info) will be logged to ~/crash_log.md file. When the user will reopen the app, a notification will be shown which when clicked will show the crash report content in the ReportActivity. The activity will have important links like email, reddit, github issues of termux app and packages at which the user can optionally report an issue if necessary after copying the crash report text. The ~/crash_log.md file will be moved to ~/crash_log-backup.md so that a notification is not shown again on next startup and can be viewed again via SAF, etc.
This will allow reports for bugs that are submitted to have complete and useful info, specially in markdown format, making lives of devs a tad bit easier. Also more bugs that are rare might be submitted since users will have the info to report with and know where to report at.
ToDo:
- The TermuxConstants.TERMUX_SUPPORT_EMAIL_URL needs to be updated with a valid support email once its set up. The TermuxUtils.getReportIssueMarkdownString() function currently also has "email" lines commented out which will need to be uncommented.
- Currently, crashes will only be handled for the main app thread, other threads will have to manually hooked into where necessary.
2021-04-06 11:15:00 +00:00
return Logger . getStackTracesMarkdownString ( " StackTraces " , Logger . getStackTraceStringArray ( throwableList ) ) ;
2021-03-23 22:48:24 +00:00
}
/ * *
* Get a markdown { @link String } for { @link String [ ] } argumentsArray .
* If argumentsArray are null or of size 0 , then ` * * Arguments : * * - ` is returned . Otherwise
* following format is returned :
*
* * * Arguments : * *
*
* * * Arg 1 : * *
* ` ` `
* value
* ` ` `
* * * Arg 2 : * *
* ` ` `
* value
* ` ` `
*
* @param argumentsArray The { @link String [ ] } argumentsArray to convert .
* @return Returns the markdown { @link String } .
* /
2021-03-28 04:06:17 +00:00
public static String getArgumentsMarkdownString ( final String [ ] argumentsArray ) {
2021-03-23 22:48:24 +00:00
StringBuilder argumentsString = new StringBuilder ( " **Arguments:** " ) ;
if ( argumentsArray ! = null & & argumentsArray . length ! = 0 ) {
argumentsString . append ( " \ n " ) ;
for ( int i = 0 ; i ! = argumentsArray . length ; i + + ) {
argumentsString . append ( MarkdownUtils . getMultiLineMarkdownStringEntry ( " Arg " + ( i + 1 ) , argumentsArray [ i ] , " - " ) ) . append ( " \ n " ) ;
}
} else {
2021-03-25 05:11:43 +00:00
argumentsString . append ( " - " ) ;
2021-03-23 22:48:24 +00:00
}
return argumentsString . toString ( ) ;
}
/ * *
* Get a log friendly { @link String } for { @link List < String > } argumentsArray .
* If argumentsArray are null or of size 0 , then ` Arguments : - ` is returned . Otherwise
* following format is returned :
*
* Arguments :
* ` ` `
* Arg 1 : ` value `
* Arg 2 : ' value `
* ` ` `
*
* @param argumentsArray The { @link String [ ] } argumentsArray to convert .
* @return Returns the log friendly { @link String } .
* /
2021-03-28 04:06:17 +00:00
public static String getArgumentsLogString ( final String [ ] argumentsArray ) {
2021-03-23 22:48:24 +00:00
StringBuilder argumentsString = new StringBuilder ( " Arguments: " ) ;
if ( argumentsArray ! = null & & argumentsArray . length ! = 0 ) {
argumentsString . append ( " \ n``` \ n " ) ;
for ( int i = 0 ; i ! = argumentsArray . length ; i + + ) {
2021-04-05 18:21:13 +00:00
argumentsString . append ( Logger . getSingleLineLogStringEntry ( " Arg " + ( i + 1 ) ,
DataUtils . getTruncatedCommandOutput ( argumentsArray [ i ] , Logger . LOGGER_ENTRY_SIZE_LIMIT_IN_BYTES / 5 , true , false , true ) ,
2021-03-25 04:20:09 +00:00
" - " ) ) . append ( " ` \ n " ) ;
2021-03-23 22:48:24 +00:00
}
argumentsString . append ( " ``` " ) ;
} else {
argumentsString . append ( " - " ) ;
}
return argumentsString . toString ( ) ;
}
2021-03-25 18:05:55 +00:00
public synchronized boolean setState ( ExecutionState newState ) {
2021-03-23 22:48:24 +00:00
// The state transition cannot go back or change if already at {@link ExecutionState#SUCCESS}
2021-04-06 12:17:12 +00:00
if ( newState . getValue ( ) < currentState . getValue ( ) | | currentState = = ExecutionState . SUCCESS ) {
2021-03-25 04:20:09 +00:00
Logger . logError ( " Invalid " + getCommandIdAndLabelLogString ( ) + " state transition from \" " + currentState . getName ( ) + " \" to " + " \" " + newState . getName ( ) + " \" " ) ;
2021-03-23 22:48:24 +00:00
return false ;
}
// The {@link ExecutionState#FAILED} can be set again, like to add more errors, but we don't update
// {@link #previousState} with the {@link #currentState} value if its at {@link ExecutionState#FAILED} to
// preserve the last valid state
2021-04-06 12:17:12 +00:00
if ( currentState ! = ExecutionState . FAILED )
2021-03-23 22:48:24 +00:00
previousState = currentState ;
currentState = newState ;
return true ;
}
2021-03-25 18:05:55 +00:00
public synchronized boolean setStateFailed ( int errCode , String errmsg , Throwable throwable ) {
2021-03-25 04:20:09 +00:00
if ( errCode > RESULT_CODE_OK ) {
this . errCode = errCode ;
} else {
Logger . logWarn ( " Ignoring invalid " + getCommandIdAndLabelLogString ( ) + " errCode value \" " + errCode + " \" . Force setting it to RESULT_CODE_FAILED \" " + RESULT_CODE_FAILED + " \" " ) ;
this . errCode = RESULT_CODE_FAILED ;
}
this . errmsg = errmsg ;
2021-03-23 22:48:24 +00:00
2021-04-06 12:17:12 +00:00
if ( ! setState ( ExecutionState . FAILED ) )
2021-03-23 22:48:24 +00:00
return false ;
2021-04-06 12:17:12 +00:00
if ( this . throwableList = = null )
2021-03-23 22:48:24 +00:00
this . throwableList = new ArrayList < > ( ) ;
2021-04-06 12:17:12 +00:00
if ( throwable ! = null )
2021-03-23 22:48:24 +00:00
this . throwableList . add ( throwable ) ;
return true ;
}
2021-03-25 18:05:55 +00:00
public synchronized boolean isStateFailed ( ) {
2021-04-06 12:17:12 +00:00
if ( currentState ! = ExecutionState . FAILED )
2021-03-25 04:20:09 +00:00
return false ;
2021-04-06 12:17:12 +00:00
if ( errCode < = RESULT_CODE_OK ) {
2021-03-25 04:20:09 +00:00
Logger . logWarn ( " The " + getCommandIdAndLabelLogString ( ) + " has an invalid errCode value \" " + errCode + " \" while having ExecutionState.FAILED state. " ) ;
return false ;
} else {
return true ;
}
}
2021-03-25 18:05:55 +00:00
public synchronized boolean hasExecuted ( ) {
2021-03-25 04:20:09 +00:00
return currentState . getValue ( ) > = ExecutionState . EXECUTED . getValue ( ) ;
}
2021-03-25 18:05:55 +00:00
public synchronized boolean isExecuting ( ) {
return currentState = = ExecutionState . EXECUTING ;
}
2021-03-23 22:48:24 +00:00
}