You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by st...@apache.org on 2021/02/18 12:55:24 UTC

svn commit: r1886661 - in /jackrabbit/oak/branches/1.22/oak-commons/src: main/java/org/apache/jackrabbit/oak/commons/properties/ test/java/org/apache/jackrabbit/oak/commons/properties/

Author: stefanegli
Date: Thu Feb 18 12:55:23 2021
New Revision: 1886661

URL: http://svn.apache.org/viewvc?rev=1886661&view=rev
Log:
OAK-9352 : merged 1886654 and 1886657 from trunk albeit manually since SystemPropertySupplier didnt exist in 1.22 branch yet at all

Added:
    jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/
    jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java   (with props)
    jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java   (with props)
    jackrabbit/oak/branches/1.22/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/
    jackrabbit/oak/branches/1.22/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java   (with props)

Added: jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java?rev=1886661&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java (added)
+++ jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java Thu Feb 18 12:55:23 2021
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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.apache.jackrabbit.oak.commons.properties;
+
+import java.util.Objects;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
+
+/**
+ * Utility class for consistent handling of system properties.
+ * <p>
+ * It provides for:
+ * <ul>
+ * <li>TRACE level logging of getting the system property
+ * <li>ERROR level logging when value does not parse or is invalid (where
+ * validity can be checked by a {@link Predicate})
+ * <li>(default) INFO level logging when value differs from default (log level
+ * and message format can be overridden)
+ * </ul>
+ * <p>
+ * The supported types are: {@link Boolean}, {@link Integer},  {@link Long}, {@link String}
+ */
+public class SystemPropertySupplier<T> implements Supplier<T> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SystemPropertySupplier.class);
+
+    private final String propName;
+    private final T defaultValue;
+    private final Function<String, T> parser;
+
+    private Logger log = LOG;
+    private Level successLogLevel = Level.INFO;
+    private Predicate<T> validator = (a) -> true;
+    private Function<String, String> sysPropReader = System::getProperty;
+    private BiFunction<String, T, String> setMessageFormatter = (a, b) -> {
+        return String.format("System property %s found to be '%s'", a, b);
+    };
+
+    private SystemPropertySupplier(@NotNull String propName, @NotNull T defaultValue) throws IllegalArgumentException {
+        this.propName = Objects.requireNonNull(propName, "propertyName must be non-null");
+        this.defaultValue = Objects.requireNonNull(defaultValue, "defaultValue must be non-null");
+        this.parser = getValueParser(defaultValue);
+    }
+
+    /**
+     * Create it for a given property name and default value.
+     */
+    public static <U> SystemPropertySupplier<U> create(@NotNull String propName, @NotNull U defaultValue)
+            throws IllegalArgumentException {
+        return new SystemPropertySupplier<U>(propName, defaultValue);
+    }
+
+    /**
+     * Specify the {@link Logger} to log to (defaults to this classes logger otherwise).
+     */
+    public SystemPropertySupplier<T> loggingTo(@NotNull Logger log) {
+        this.log = Objects.requireNonNull(log);
+        return this;
+    }
+
+    /**
+     * Specify a validation expression.
+     */
+    public SystemPropertySupplier<T> validateWith(@NotNull Predicate<T> validator) {
+        this.validator = Objects.requireNonNull(validator);
+        return this;
+    }
+
+    /**
+     * Specify a formatter for the "success" log message to be used when the
+     * returned property value differs from the default.
+     */
+    public SystemPropertySupplier<T> formatSetMessage(@NotNull BiFunction<String, T, String> setMessageFormatter) {
+        this.setMessageFormatter = Objects.requireNonNull(setMessageFormatter);
+        return this;
+    }
+
+    /**
+     * Specify {@link Level} to use for "success" message.
+     */
+    public SystemPropertySupplier<T> logSuccessAs(Level successLogLevel) {
+        this.successLogLevel = Objects.requireNonNull(successLogLevel);
+        return this;
+    }
+
+    /**
+     * <em>For unit testing</em>: specify a function to read system properties
+     * (overriding default of {@code System.getProperty(String}).
+     */
+    protected SystemPropertySupplier<T> usingSystemPropertyReader(@NotNull Function<String, String> sysPropReader) {
+        this.sysPropReader = Objects.requireNonNull(sysPropReader);
+        return this;
+    }
+
+    /**
+     * Obtains the value of a system property, optionally generating
+     * diagnostics.
+     * 
+     * @return value of system property
+     */
+    public T get() {
+
+        T ret = defaultValue;
+
+        String value = sysPropReader.apply(propName);
+        if (value == null) {
+            log.trace("System property {} not set", propName);
+        } else {
+            log.trace("System property {} set to '{}'", propName, value);
+            try {
+                T v = parser.apply(value);
+                if (!validator.test(v)) {
+                    log.error("Ignoring invalid value '{}' for system property {}", value, propName);
+                } else {
+                    ret = v;
+                }
+            } catch (NumberFormatException ex) {
+                log.error("Ignoring malformed value '{}' for system property {}", value, propName);
+            }
+
+            if (!ret.equals(defaultValue)) {
+                String msg = setMessageFormatter.apply(propName, ret);
+                switch (successLogLevel) {
+                    case INFO:
+                        log.info(msg);
+                        break;
+                    case DEBUG:
+                        log.debug(msg);
+                        break;
+                    case ERROR:
+                        log.error(msg);
+                        break;
+                    case TRACE:
+                        log.trace(msg);
+                        break;
+                    case WARN:
+                        log.warn(msg);
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Function<String, T> getValueParser(T defaultValue) {
+        if (defaultValue instanceof Boolean) {
+            return v -> (T) Boolean.valueOf(v);
+        } else if (defaultValue instanceof Integer) {
+            return v -> (T) Integer.valueOf(v);
+        } else if (defaultValue instanceof Long) {
+            return v -> (T) Long.valueOf(v);
+        } else if (defaultValue instanceof String) {
+            return v -> (T) v;
+        } else {
+            throw new IllegalArgumentException(
+                    String.format("expects a defaultValue of Boolean, Integer, Long, or String, but got: %s", defaultValue.getClass()));
+        }
+    }
+}

Propchange: jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplier.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java?rev=1886661&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java (added)
+++ jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java Thu Feb 18 12:55:23 2021
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *     http://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.
+ */
+@Version("1.0.0")
+package org.apache.jackrabbit.oak.commons.properties;
+
+import org.osgi.annotation.versioning.Version;

Propchange: jackrabbit/oak/branches/1.22/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/properties/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/branches/1.22/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.22/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java?rev=1886661&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.22/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java (added)
+++ jackrabbit/oak/branches/1.22/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java Thu Feb 18 12:55:23 2021
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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.apache.jackrabbit.oak.commons.properties;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
+
+public class SystemPropertySupplierTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SystemPropertySupplierTest.class);
+
+    @Test
+    public void testBoolean() {
+        assertEquals(Boolean.TRUE, SystemPropertySupplier.create("foo", Boolean.TRUE).usingSystemPropertyReader((n) -> null).get());
+        assertEquals(Boolean.FALSE,
+                SystemPropertySupplier.create("foo", Boolean.FALSE).usingSystemPropertyReader((n) -> null).get());
+        assertEquals(Boolean.TRUE,
+                SystemPropertySupplier.create("foo", Boolean.FALSE).usingSystemPropertyReader((n) -> "true").get());
+        assertEquals(Boolean.FALSE,
+                SystemPropertySupplier.create("foo", Boolean.FALSE).usingSystemPropertyReader((n) -> "false").get());
+    }
+
+    @Test
+    public void testInteger() {
+        assertEquals(Integer.valueOf(123),
+                SystemPropertySupplier.create("foo", Integer.valueOf(123)).usingSystemPropertyReader((n) -> null).get());
+        assertEquals(Integer.valueOf(1742),
+                SystemPropertySupplier.create("foo", Integer.valueOf(123)).usingSystemPropertyReader((n) -> "1742").get());
+    }
+
+    @Test
+    public void testLong() {
+        long big = Long.MAX_VALUE;
+        assertEquals(Long.valueOf(big),
+                SystemPropertySupplier.create("foo", Long.valueOf(big)).usingSystemPropertyReader((n) -> null).get());
+        assertEquals(Long.valueOf(1742),
+                SystemPropertySupplier.create("foo", Long.valueOf(big)).usingSystemPropertyReader((n) -> "1742").get());
+    }
+
+    @Test
+    public void testString() {
+        assertEquals("bar", SystemPropertySupplier.create("foo", "bar").usingSystemPropertyReader((n) -> null).get());
+        assertEquals("", SystemPropertySupplier.create("foo", "bar").usingSystemPropertyReader((n) -> "").get());
+    }
+
+    @Test
+    public void testFilter() {
+        LogCustomizer logCustomizer = LogCustomizer.forLogger(SystemPropertySupplierTest.class.getName()).enable(Level.ERROR)
+                .contains("Ignoring invalid value").create();
+        logCustomizer.starting();
+
+        try {
+            int positive = SystemPropertySupplier.create("foo", Integer.valueOf(123)).loggingTo(LOG)
+                    .usingSystemPropertyReader((n) -> "-1").validateWith(n -> n >= 0).get();
+            assertEquals(123, positive);
+            assertEquals(1, logCustomizer.getLogs().size());
+        } finally {
+            logCustomizer.finished();
+        }
+    }
+
+    @Test
+    public void testNonParseable() {
+        LogCustomizer logCustomizer = LogCustomizer.forLogger(SystemPropertySupplierTest.class.getName()).enable(Level.ERROR)
+                .contains("Ignoring malformed value").create();
+        logCustomizer.starting();
+
+        try {
+            int positive = SystemPropertySupplier.create("foo", Integer.valueOf(123)).loggingTo(LOG)
+                    .usingSystemPropertyReader((n) -> "abc").validateWith(n -> n >= 0).get();
+            assertEquals(123, positive);
+            assertEquals(1, logCustomizer.getLogs().size());
+        } finally {
+            logCustomizer.finished();
+        }
+    }
+
+    @Test
+    public void testRedirectSuccess() {
+        Logger local = LoggerFactory.getLogger(SystemPropertySupplierTest.class.getName() + "-FOO");
+        LogCustomizer logCustomizer = LogCustomizer.forLogger(SystemPropertySupplierTest.class.getName() + "-FOO")
+                .enable(Level.TRACE).create();
+        logCustomizer.starting();
+
+        try {
+            int positive = SystemPropertySupplier.create("foo", Integer.valueOf(123)).loggingTo(local)
+                    .usingSystemPropertyReader((n) -> "4217").get();
+            assertEquals(4217, positive);
+            assertEquals(2, logCustomizer.getLogs().size());
+        } finally {
+            logCustomizer.finished();
+        }
+    }
+
+    @Test
+    public void testUnsupportedType() {
+        try {
+            SystemPropertySupplier.create("foo", new Object());
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+}

Propchange: jackrabbit/oak/branches/1.22/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/branches/1.22/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/properties/SystemPropertySupplierTest.java
------------------------------------------------------------------------------
    svn:executable = *