All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.batch.core.ExitStatus Maven / Gradle / Ivy

/*
 * Copyright 2006-2023 the original author or authors.
 *
 * Licensed 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
 *
 *      https://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 org.springframework.batch.core;

import org.springframework.util.StringUtils;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;

/**
 * Value object used to carry information about the status of a job or step execution.
 * 

* {@code ExitStatus} is immutable and, therefore, thread-safe. * * @author Dave Syer * */ @SuppressWarnings("serial") public class ExitStatus implements Serializable, Comparable { /** * Convenient constant value representing unknown state - assumed to not be * continuable. */ public static final ExitStatus UNKNOWN = new ExitStatus("UNKNOWN"); /** * Convenient constant value representing continuable state where processing is still * taking place, so no further action is required. Used for asynchronous execution * scenarios where the processing is happening in another thread or process and the * caller is not required to wait for the result. */ public static final ExitStatus EXECUTING = new ExitStatus("EXECUTING"); /** * Convenient constant value representing finished processing. */ public static final ExitStatus COMPLETED = new ExitStatus("COMPLETED"); /** * Convenient constant value representing a job that did no processing (for example, * because it was already complete). */ public static final ExitStatus NOOP = new ExitStatus("NOOP"); /** * Convenient constant value representing finished processing with an error. */ public static final ExitStatus FAILED = new ExitStatus("FAILED"); /** * Convenient constant value representing finished processing with interrupted status. */ public static final ExitStatus STOPPED = new ExitStatus("STOPPED"); private final String exitCode; private final String exitDescription; /** * Constructor that accepts the exit code and sets the exit description to an empty * {@link String}. * @param exitCode The exit code to be used for the {@link ExitStatus}. */ public ExitStatus(String exitCode) { this(exitCode, ""); } /** * Constructor that establishes the exit code and the exit description for the * {@link ExitStatus}. * @param exitCode The exit code to be used for the {@link ExitStatus}. * @param exitDescription The exit description to be used for the {@link ExitStatus}. */ public ExitStatus(String exitCode, String exitDescription) { super(); this.exitCode = exitCode; this.exitDescription = exitDescription == null ? "" : exitDescription; } /** * Getter for the exit code (defaults to blank). * @return the exit code. */ public String getExitCode() { return exitCode; } /** * Getter for the exit description (defaults to blank) * @return {@link String} containing the exit description. */ public String getExitDescription() { return exitDescription; } /** * Create a new {@link ExitStatus} with a logical combination of the exit code and a * concatenation of the descriptions. If either value has a higher severity, its exit * code is used in the result. In the case of equal severity, the exit code is * replaced if the new value is alphabetically greater.
*
* * Severity is defined by the exit code: *

    *
  • Codes beginning with EXECUTING have severity 1
  • *
  • Codes beginning with COMPLETED have severity 2
  • *
  • Codes beginning with NOOP have severity 3
  • *
  • Codes beginning with STOPPED have severity 4
  • *
  • Codes beginning with FAILED have severity 5
  • *
  • Codes beginning with UNKNOWN have severity 6
  • *
* Others have severity 7, so custom exit codes always win.
* * If the input is {@code null} just return this. * @param status An {@link ExitStatus} object to combine with this one. * @return a new {@link ExitStatus} combining the current value and the argument * provided. */ public ExitStatus and(ExitStatus status) { if (status == null) { return this; } ExitStatus result = addExitDescription(status.exitDescription); if (compareTo(status) < 0) { result = result.replaceExitCode(status.exitCode); } return result; } /** * @param status An {@link ExitStatus} to compare * @return greater than zero, 0, or less than zero, according to the severity and exit * code. * @see java.lang.Comparable */ @Override public int compareTo(ExitStatus status) { if (severity(status) > severity(this)) { return -1; } if (severity(status) < severity(this)) { return 1; } return this.getExitCode().compareTo(status.getExitCode()); } /** * Determines severity (an int between 1 and 7, inclusive) based on an * {@code ExitStatus} object. * @param status The {@code ExitStatus} object from which to determine the severity. * @return the severity number. */ private int severity(ExitStatus status) { if (status.exitCode.startsWith(EXECUTING.exitCode)) { return 1; } if (status.exitCode.startsWith(COMPLETED.exitCode)) { return 2; } if (status.exitCode.startsWith(NOOP.exitCode)) { return 3; } if (status.exitCode.startsWith(STOPPED.exitCode)) { return 4; } if (status.exitCode.startsWith(FAILED.exitCode)) { return 5; } if (status.exitCode.startsWith(UNKNOWN.exitCode)) { return 6; } return 7; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return String.format("exitCode=%s;exitDescription=%s", exitCode, exitDescription); } /** * Compare the fields, one by one. * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj == null) { return false; } return toString().equals(obj.toString()); } /** * Compatible with the equals implementation. * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return toString().hashCode(); } /** * Add an exit code to an existing {@link ExitStatus}. If there is already a code * present, it will be replaced. * @param code The code to add. * @return a new {@link ExitStatus} with the same properties but a new exit code. */ public ExitStatus replaceExitCode(String code) { return new ExitStatus(code, exitDescription); } /** * Check if this status represents a running process. * @return {@code true} if the exit code is {@code EXECUTING} or {@code UNKNOWN}. */ public boolean isRunning() { return "EXECUTING".equals(this.exitCode) || "UNKNOWN".equals(this.exitCode); } /** * Add an exit description to an existing {@link ExitStatus}. If there is already a * description present, the two are concatenated with a semicolon. * @param description The description to add. * @return a new {@link ExitStatus} with the same properties but a new exit * description. */ public ExitStatus addExitDescription(String description) { if (StringUtils.hasText(exitDescription)) { if (StringUtils.hasText(description) && !exitDescription.equals(description)) { StringBuilder buffer = new StringBuilder(description.length() + 2 + exitDescription.length()); buffer.append(exitDescription); buffer.append("; "); buffer.append(description); return new ExitStatus(exitCode, buffer.toString()); } return this; } else { return new ExitStatus(exitCode, description); } } /** * Extract the stack trace from the throwable provided and append it to the existing * description. * @param throwable A {@link Throwable} instance containing the stack trace. * @return a new ExitStatus with the stack trace appended. */ public ExitStatus addExitDescription(Throwable throwable) { StringWriter writer = new StringWriter(); throwable.printStackTrace(new PrintWriter(writer)); String message = writer.toString(); return addExitDescription(message); } /** * @param status The {@code ExitStatus} object containing the exit code to be * evaluated. * @return {@code true} if the value matches a known exit code. */ public static boolean isNonDefaultExitStatus(ExitStatus status) { return status == null || status.getExitCode() == null || status.getExitCode().equals(ExitStatus.COMPLETED.getExitCode()) || status.getExitCode().equals(ExitStatus.EXECUTING.getExitCode()) || status.getExitCode().equals(ExitStatus.FAILED.getExitCode()) || status.getExitCode().equals(ExitStatus.NOOP.getExitCode()) || status.getExitCode().equals(ExitStatus.STOPPED.getExitCode()) || status.getExitCode().equals(ExitStatus.UNKNOWN.getExitCode()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy