This is an automated email from the ASF dual-hosted git repository. reschke pushed a commit to branch OAK-12298 in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit a5f27495f8075ad2b5b715b136561c48932c3711 Author: Julian Reschke <[email protected]> AuthorDate: Mon Jul 6 12:20:37 2026 +0100 OAK-12298: SystemPropertySupplier: allow to signal that propery is not present (implies default value) --- .../commons/properties/SystemPropertySupplier.java | 54 ++++++++++++---------- .../oak/commons/properties/package-info.java | 2 +- .../properties/SystemPropertySupplierTest.java | 10 ++++ 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java index 0521172842..c1d16ae127 100644 --- a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java +++ b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java @@ -23,6 +23,7 @@ import java.util.function.Predicate; import java.util.function.Supplier; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,26 +50,34 @@ public class SystemPropertySupplier<T> implements Supplier<T> { private final String propName; private final T defaultValue; private final Function<String, T> parser; - private Logger log = LOG; private String successLogLevel = "INFO"; private boolean hideValue = false; - private Predicate<T> validator = (a) -> true; + private Predicate<T> validator = a -> true; private Function<String, String> sysPropReader = System::getProperty; private BiFunction<String, T, String> setMessageFormatter = (a, b) -> String.format("System property %s found to be '%s'", a, hideValue ? HIDDEN_REPLACEMENT : b); - private SystemPropertySupplier(@NotNull String propName, @NotNull T defaultValue) { + private SystemPropertySupplier(@NotNull String propName, @Nullable T defaultValue, @Nullable Class<T> clazz) { this.propName = Objects.requireNonNull(propName, "propertyName must be non-null"); - this.defaultValue = Objects.requireNonNull(defaultValue, "defaultValue must be non-null"); - this.parser = getValueParser(defaultValue); + this.defaultValue = defaultValue; + this.parser = getValueParser(defaultValue, clazz); } /** * Create it for a given property name and default value. */ public static <U> SystemPropertySupplier<U> create(@NotNull String propName, @NotNull U defaultValue) { - return new SystemPropertySupplier<>(propName, defaultValue); + return new SystemPropertySupplier<>(propName, + Objects.requireNonNull(defaultValue, "defaultValue must not be null"), null); + } + + /** + * Create it for a given property name and no default value (but expected {@linkplain Class}). + */ + public static <U> SystemPropertySupplier<U> create(@NotNull String propName, @NotNull Class<U> clazz) { + return new SystemPropertySupplier<>(propName, null, + Objects.requireNonNull(clazz, "clazz must not be null")); } /** @@ -100,18 +109,10 @@ public class SystemPropertySupplier<T> implements Supplier<T> { * Specify logging level to use for "success" message (defaults to "INFO") */ public SystemPropertySupplier<T> logSuccessAs(String successLogLevel) { - String newLevel; - switch (Objects.requireNonNull(successLogLevel)) { - case "DEBUG": - case "ERROR": - case "INFO": - case "TRACE": - case "WARN": - newLevel = successLogLevel; - break; - default: - throw new IllegalArgumentException("unsupported log level: " + successLogLevel); - } + String newLevel = switch (Objects.requireNonNull(successLogLevel)) { + case "DEBUG", "ERROR", "INFO", "TRACE", "WARN" -> successLogLevel; + default -> throw new IllegalArgumentException("unsupported log level: " + successLogLevel); + }; this.successLogLevel = newLevel; return this; } @@ -191,18 +192,21 @@ public class SystemPropertySupplier<T> implements Supplier<T> { } @SuppressWarnings("unchecked") - private static <T> Function<String, T> getValueParser(T defaultValue) { - if (defaultValue instanceof Boolean) { + private static <T> Function<String, T> getValueParser(T defaultValue, Class<T> type) { + Class<?> clazz = (defaultValue != null) ? defaultValue.getClass() : type; + + if (clazz == null) { + throw new IllegalArgumentException("Cannot determine type: defaultValue is null and no type provided."); + } else if (Boolean.class.isAssignableFrom(clazz)) { return v -> (T) Boolean.valueOf(v); - } else if (defaultValue instanceof Integer) { + } else if (Integer.class.isAssignableFrom(clazz)) { return v -> (T) Integer.valueOf(v); - } else if (defaultValue instanceof Long) { + } else if (Long.class.isAssignableFrom(clazz)) { return v -> (T) Long.valueOf(v); - } else if (defaultValue instanceof String) { + } else if (String.class.isAssignableFrom(clazz)) { return v -> (T) v; } else { - throw new IllegalArgumentException( - String.format("expects a defaultValue of Boolean, Integer, Long, or String, but got: %s", defaultValue.getClass())); + throw new IllegalArgumentException("Unsupported type: " + clazz.getName()); } } } diff --git a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java index 474329ac53..9c197aeb22 100644 --- a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java +++ b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java @@ -18,7 +18,7 @@ * <em>For Oak internal use only. Do not use outside Oak components.</em> */ @Internal(since = "1.1.0") -@Version("2.1.0") +@Version("2.2.0") package org.apache.jackrabbit.oak.commons.properties; import org.apache.jackrabbit.oak.commons.annotations.Internal; diff --git a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java index 69ed32d9d4..fea034e08c 100755 --- a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java +++ b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java @@ -17,6 +17,7 @@ package org.apache.jackrabbit.oak.commons.properties; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import org.apache.jackrabbit.oak.commons.junit.LogCustomizer; @@ -137,4 +138,13 @@ public class SystemPropertySupplierTest { } catch (IllegalArgumentException expected) { } } + + @Test + public void testCheckNullDefault() { + try { + assertNull(SystemPropertySupplier.create("foo", Boolean.class). + usingSystemPropertyReader((n) -> null).get()); + } catch (IllegalArgumentException expected) { + } + } }
