diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Preconditions.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Preconditions.java
index 0cded9a5e6..4b98797df3 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Preconditions.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/Preconditions.java
@@ -46,6 +46,8 @@ public final class Preconditions {
"The argument object is NULL";
private static final String CHECK_ARGUMENT_EX_MESSAGE =
"The argument expression is false";
+ private static final String CHECK_STATE_EX_MESSAGE =
+ "The state expression is false";
private Preconditions() {
}
@@ -240,6 +242,91 @@ public static void checkArgument(
}
}
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance
+ * without involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(final boolean expression) {
+ if (!expression) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance
+ * without involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @param errorMessage the exception message to use if the check fails; will be converted to a
+ * string using {@link String#valueOf(Object)}
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(final boolean expression, final Object errorMessage) {
+ if (!expression) {
+ throw new IllegalStateException(String.valueOf(errorMessage));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance
+ * without involving any parameters to the calling method.
+ *
+ *
The message of the exception is {@code String.format(f, m)}.
+ *
+ * @param expression a boolean expression
+ * @param errorMsg the {@link String#format(String, Object...)}
+ * exception message if valid. Otherwise,
+ * the message is {@link #CHECK_STATE_EX_MESSAGE}
+ * @param errorMsgArgs the optional values for the formatted exception message.
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(
+ final boolean expression,
+ final String errorMsg,
+ Object... errorMsgArgs) {
+ if (!expression) {
+ String msg;
+ try {
+ msg = String.format(errorMsg, errorMsgArgs);
+ } catch (Exception e) {
+ LOG.debug("Error formatting message", e);
+ msg = CHECK_STATE_EX_MESSAGE;
+ }
+ throw new IllegalStateException(msg);
+ }
+ }
+
+ /**
+ * Preconditions that the expression involving one or more parameters to the calling method.
+ *
+ * The message of the exception is {@code msgSupplier.get()}.
+ *
+ * @param expression a boolean expression
+ * @param msgSupplier the {@link Supplier#get()} set the
+ * exception message if valid. Otherwise,
+ * the message is {@link #CHECK_STATE_EX_MESSAGE}
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(
+ final boolean expression,
+ final Supplier msgSupplier) {
+ if (!expression) {
+ String msg;
+ try {
+ // note that we can get NPE evaluating the message itself;
+ // but we do not want this to override the actual NPE.
+ msg = msgSupplier.get();
+ } catch (Exception e) {
+ LOG.debug("Error formatting message", e);
+ msg = CHECK_STATE_EX_MESSAGE;
+ }
+ throw new IllegalStateException(msg);
+ }
+ }
+
/* @VisibleForTesting */
static String getDefaultNullMSG() {
return VALIDATE_IS_NOT_NULL_EX_MESSAGE;
@@ -249,4 +336,9 @@ static String getDefaultNullMSG() {
static String getDefaultCheckArgumentMSG() {
return CHECK_ARGUMENT_EX_MESSAGE;
}
+
+ /* @VisibleForTesting */
+ static String getDefaultCheckStateMSG() {
+ return CHECK_STATE_EX_MESSAGE;
+ }
}
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestPreconditions.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestPreconditions.java
index 47917662ad..4a11555535 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestPreconditions.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestPreconditions.java
@@ -221,4 +221,104 @@ public void testCheckArgumentWithFailure() throws Exception {
() -> Preconditions.checkArgument(false,
() -> String.format(NULL_FORMATTER, NON_NULL_STRING)));
}
+
+ @Test
+ public void testCheckStateWithSuccess() throws Exception {
+ // success
+ Preconditions.checkState(true);
+ // null supplier
+ Preconditions.checkState(true, null);
+ // null message
+ Preconditions.checkState(true, (String) null);
+ Preconditions.checkState(true, NON_NULL_STRING);
+ // null in string format
+ Preconditions.checkState(true, EXPECTED_ERROR_MSG_ARGS, null, null);
+ // illegalformat
+ Preconditions.checkState(true, EXPECTED_ERROR_MSG_ARGS, 1, 2);
+ // ill-formated string supplier
+ Preconditions.checkState(true, ()-> String.format("%d",
+ NON_INT_STRING));
+ // null pattern to string formatter
+ Preconditions.checkState(true, NULL_FORMATTER, null, 1);
+ // null arguments to string formatter
+ Preconditions.checkState(true, EXPECTED_ERROR_MSG_ARGS,
+ null, null);
+ // illegal format exception
+ Preconditions.checkState(true, "message %d %d",
+ NON_INT_STRING, 1);
+ // insufficient arguments
+ Preconditions.checkState(true, EXPECTED_ERROR_MSG_ARGS,
+ NON_INT_STRING);
+ // null format in string supplier
+ Preconditions.checkState(true,
+ () -> String.format(NULL_FORMATTER, NON_INT_STRING));
+ }
+
+ @Test
+ public void testCheckStateWithFailure() throws Exception {
+ // failure without message
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ () -> Preconditions.checkState(false));
+ errorMessage = null;
+ // failure with Null message
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ null,
+ () -> Preconditions.checkState(false, errorMessage));
+ // failure with message
+ errorMessage = EXPECTED_ERROR_MSG;
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ errorMessage,
+ () -> Preconditions.checkState(false, errorMessage));
+
+ // failure with message format
+ errorMessage = EXPECTED_ERROR_MSG + " %s";
+ String arg = "IllegalStaExcep";
+ String expectedMSG = String.format(errorMessage, arg);
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ expectedMSG,
+ () -> Preconditions.checkState(false, errorMessage, arg));
+
+ // failure with multiple arg message format
+ errorMessage = EXPECTED_ERROR_MSG_ARGS;
+ expectedMSG =
+ String.format(errorMessage, arg, 1);
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ expectedMSG,
+ () -> Preconditions.checkState(false, errorMessage, arg, 1));
+
+ // ignore illegal format will be thrown if the case is not handled correctly
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ Preconditions.getDefaultCheckStateMSG(),
+ () -> Preconditions.checkState(false,
+ errorMessage, 1, NON_INT_STRING));
+
+ // ignore illegal format will be thrown for insufficient Insufficient Args
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ Preconditions.getDefaultCheckStateMSG(),
+ () -> Preconditions.checkState(false, errorMessage, NON_NULL_STRING));
+
+ // failure with Null supplier
+ final Supplier nullSupplier = null;
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ null,
+ () -> Preconditions.checkState(false, nullSupplier));
+
+ // ignore illegal format in supplier
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ Preconditions.getDefaultCheckStateMSG(),
+ () -> Preconditions.checkState(false,
+ () -> String.format(errorMessage, 1, NON_INT_STRING)));
+
+ // ignore insufficient arguments in string Supplier
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ Preconditions.getDefaultCheckStateMSG(),
+ () -> Preconditions.checkState(false,
+ () -> String.format(errorMessage, NON_NULL_STRING)));
+
+ // ignore null formatter
+ LambdaTestUtils.intercept(IllegalStateException.class,
+ Preconditions.getDefaultCheckStateMSG(),
+ () -> Preconditions.checkState(false,
+ () -> String.format(NULL_FORMATTER, NON_NULL_STRING)));
+ }
}