This is an automated email from the ASF dual-hosted git repository. aherbert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-lang.git
commit 7f7d4b881d78dcb8d5a0149965f934df268919d7 Author: Piotr Stawirej <piotr.stawi...@gmail.com> AuthorDate: Wed Sep 21 21:26:34 2022 +0100 Handle error messages with special characters. Closes #953 --- .../java/org/apache/commons/lang3/Validate.java | 69 +++++++++++++--------- .../org/apache/commons/lang3/ValidateTest.java | 6 ++ 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/apache/commons/lang3/Validate.java b/src/main/java/org/apache/commons/lang3/Validate.java index 70b294bff..662d0b0cc 100644 --- a/src/main/java/org/apache/commons/lang3/Validate.java +++ b/src/main/java/org/apache/commons/lang3/Validate.java @@ -139,8 +139,7 @@ public class Validate { * primitive number or using your own custom validation expression. * * <pre> - * Validate.isTrue(i >= min && i <= max, "The value must be between %d and %d", min, max); - * Validate.isTrue(myObject.isOk(), "The object is not okay");</pre> + * Validate.isTrue(i >= min && i <= max, "The value must be between %d and %d", min, max);</pre> * * @param expression the boolean expression to check * @param message the {@link String#format(String, Object...)} exception message if invalid, not null @@ -152,7 +151,7 @@ public class Validate { */ public static void isTrue(final boolean expression, final String message, final Object... values) { if (!expression) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } } @@ -217,7 +216,7 @@ public class Validate { * @see Objects#requireNonNull(Object) */ public static <T> T notNull(final T object, final String message, final Object... values) { - return Objects.requireNonNull(object, () -> String.format(message, values)); + return Objects.requireNonNull(object, () -> getMessage(message, values)); } /** @@ -237,9 +236,9 @@ public class Validate { * @see #notEmpty(Object[]) */ public static <T> T[] notEmpty(final T[] array, final String message, final Object... values) { - Objects.requireNonNull(array, () -> String.format(message, values)); + Objects.requireNonNull(array, () -> getMessage(message, values)); if (array.length == 0) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } return array; } @@ -281,9 +280,9 @@ public class Validate { * @see #notEmpty(Object[]) */ public static <T extends Collection<?>> T notEmpty(final T collection, final String message, final Object... values) { - Objects.requireNonNull(collection, () -> String.format(message, values)); + Objects.requireNonNull(collection, () -> getMessage(message, values)); if (collection.isEmpty()) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } return collection; } @@ -325,9 +324,9 @@ public class Validate { * @see #notEmpty(Object[]) */ public static <T extends Map<?, ?>> T notEmpty(final T map, final String message, final Object... values) { - Objects.requireNonNull(map, () -> String.format(message, values)); + Objects.requireNonNull(map, () -> getMessage(message, values)); if (map.isEmpty()) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } return map; } @@ -369,9 +368,9 @@ public class Validate { * @see #notEmpty(CharSequence) */ public static <T extends CharSequence> T notEmpty(final T chars, final String message, final Object... values) { - Objects.requireNonNull(chars, () -> String.format(message, values)); + Objects.requireNonNull(chars, () -> getMessage(message, values)); if (chars.length() == 0) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } return chars; } @@ -417,9 +416,9 @@ public class Validate { * @since 3.0 */ public static <T extends CharSequence> T notBlank(final T chars, final String message, final Object... values) { - Objects.requireNonNull(chars, () -> String.format(message, values)); + Objects.requireNonNull(chars, () -> getMessage(message, values)); if (StringUtils.isBlank(chars)) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } return chars; } @@ -475,7 +474,7 @@ public class Validate { for (int i = 0; i < array.length; i++) { if (array[i] == null) { final Object[] values2 = ArrayUtils.add(values, Integer.valueOf(i)); - throw new IllegalArgumentException(String.format(message, values2)); + throw new IllegalArgumentException(getMessage(message, values2)); } } return array; @@ -535,7 +534,7 @@ public class Validate { for (final Iterator<?> it = iterable.iterator(); it.hasNext(); i++) { if (it.next() == null) { final Object[] values2 = ArrayUtils.addAll(values, Integer.valueOf(i)); - throw new IllegalArgumentException(String.format(message, values2)); + throw new IllegalArgumentException(getMessage(message, values2)); } } return iterable; @@ -590,7 +589,7 @@ public class Validate { public static <T> T[] validIndex(final T[] array, final int index, final String message, final Object... values) { Objects.requireNonNull(array, "array"); if (index < 0 || index >= array.length) { - throw new IndexOutOfBoundsException(String.format(message, values)); + throw new IndexOutOfBoundsException(getMessage(message, values)); } return array; } @@ -646,7 +645,7 @@ public class Validate { public static <T extends Collection<?>> T validIndex(final T collection, final int index, final String message, final Object... values) { Objects.requireNonNull(collection, "collection"); if (index < 0 || index >= collection.size()) { - throw new IndexOutOfBoundsException(String.format(message, values)); + throw new IndexOutOfBoundsException(getMessage(message, values)); } return collection; } @@ -700,7 +699,7 @@ public class Validate { public static <T extends CharSequence> T validIndex(final T chars, final int index, final String message, final Object... values) { Objects.requireNonNull(chars, "chars"); if (index < 0 || index >= chars.length()) { - throw new IndexOutOfBoundsException(String.format(message, values)); + throw new IndexOutOfBoundsException(getMessage(message, values)); } return chars; } @@ -776,7 +775,7 @@ public class Validate { */ public static void validState(final boolean expression, final String message, final Object... values) { if (!expression) { - throw new IllegalStateException(String.format(message, values)); + throw new IllegalStateException(getMessage(message, values)); } } @@ -822,7 +821,7 @@ public class Validate { public static void matchesPattern(final CharSequence input, final String pattern, final String message, final Object... values) { // TODO when breaking BC, consider returning input if (!Pattern.matches(pattern, input)) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } } @@ -861,7 +860,7 @@ public class Validate { */ public static void notNaN(final double value, final String message, final Object... values) { if (Double.isNaN(value)) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } } @@ -899,7 +898,7 @@ public class Validate { */ public static void finite(final double value, final String message, final Object... values) { if (Double.isNaN(value) || Double.isInfinite(value)) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } } @@ -946,7 +945,7 @@ public class Validate { public static <T> void inclusiveBetween(final T start, final T end, final Comparable<T> value, final String message, final Object... values) { // TODO when breaking BC, consider returning value if (value.compareTo(start) < 0 || value.compareTo(end) > 0) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } } @@ -1081,7 +1080,7 @@ public class Validate { public static <T> void exclusiveBetween(final T start, final T end, final Comparable<T> value, final String message, final Object... values) { // TODO when breaking BC, consider returning value if (value.compareTo(start) <= 0 || value.compareTo(end) >= 0) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } } @@ -1217,7 +1216,7 @@ public class Validate { public static void isInstanceOf(final Class<?> type, final Object obj, final String message, final Object... values) { // TODO when breaking BC, consider returning obj if (!type.isInstance(obj)) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } } @@ -1265,7 +1264,23 @@ public class Validate { public static void isAssignableFrom(final Class<?> superType, final Class<?> type, final String message, final Object... values) { // TODO when breaking BC, consider returning type if (!superType.isAssignableFrom(type)) { - throw new IllegalArgumentException(String.format(message, values)); + throw new IllegalArgumentException(getMessage(message, values)); } } + + /** + * Get the message using {@link String#format(String, Object...) String.format(message, values)} + * if the values are not empty, otherwise return the message unformatted. + * This method exists to allow validation methods declaring a String message and varargs parameters + * to be used without any message parameters when the message contains special characters, + * e.g. {@code Validate.isTrue(false, "%Failed%")}. + * + * @param message the {@link String#format(String, Object...)} exception message if invalid, not null + * @param values the optional values for the formatted message + * @return formatted message using {@link String#format(String, Object...) String.format(message, values)} + * if the values are not empty, otherwise return the unformatted message. + */ + private static String getMessage(final String message, final Object... values) { + return values.length == 0 ? message : String.format(message, values); + } } diff --git a/src/test/java/org/apache/commons/lang3/ValidateTest.java b/src/test/java/org/apache/commons/lang3/ValidateTest.java index 4ce3b4e84..1c9c0922b 100644 --- a/src/test/java/org/apache/commons/lang3/ValidateTest.java +++ b/src/test/java/org/apache/commons/lang3/ValidateTest.java @@ -73,6 +73,12 @@ public class ValidateTest extends AbstractLangTest { final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> Validate.isTrue(false, "MSG")); assertEquals("MSG", ex.getMessage()); } + + @Test + void shouldThrowExceptionWithGivenMessageContainingSpecialCharacterForFalseExpression() { + final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> Validate.isTrue(false, "%")); + assertEquals("%", ex.getMessage()); + } } @Nested