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 re...@apache.org on 2020/04/20 09:40:48 UTC
svn commit: r1876746 - in /jackrabbit/oak/trunk/oak-store-document/src:
main/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplier.java
test/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplierTest.java
Author: reschke
Date: Mon Apr 20 09:40:48 2020
New Revision: 1876746
URL: http://svn.apache.org/viewvc?rev=1876746&view=rev
Log:
OAK-9010: Standardize handling of system properties
Added:
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplier.java (with props)
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplierTest.java (with props)
Added: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplier.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplier.java?rev=1876746&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplier.java (added)
+++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplier.java Mon Apr 20 09:40:48 2020
@@ -0,0 +1,182 @@
+/*
+ * 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.plugins.document.util;
+
+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 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 String) {
+ return v -> (T) v;
+ } else {
+ throw new IllegalArgumentException(
+ String.format("expects a defaultValue of Boolean, Integer, or String, but got: %s", defaultValue.getClass()));
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplier.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplier.java
------------------------------------------------------------------------------
svn:executable = *
Added: jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplierTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplierTest.java?rev=1876746&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplierTest.java (added)
+++ jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplierTest.java Mon Apr 20 09:40:48 2020
@@ -0,0 +1,112 @@
+/*
+ * 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.plugins.document.util;
+
+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 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/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplierTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/util/SystemPropertySupplierTest.java
------------------------------------------------------------------------------
svn:executable = *