diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/status/StatusLoggerPropertiesUtilDoubleTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/status/StatusLoggerPropertiesUtilDoubleTest.java index 16feb542cca..94ad4903d28 100644 --- a/log4j-api-test/src/test/java/org/apache/logging/log4j/status/StatusLoggerPropertiesUtilDoubleTest.java +++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/status/StatusLoggerPropertiesUtilDoubleTest.java @@ -16,6 +16,7 @@ */ package org.apache.logging.log4j.status; +import static java.util.Collections.singletonMap; import static org.apache.logging.log4j.status.StatusLogger.PropertiesUtilsDouble.readAllAvailableProperties; import static org.apache.logging.log4j.status.StatusLogger.PropertiesUtilsDouble.readProperty; import static org.assertj.core.api.Assertions.assertThat; @@ -24,7 +25,9 @@ import java.util.Arrays; import java.util.Map; +import java.util.Properties; import java.util.stream.Stream; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.ResourceAccessMode; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.api.parallel.Resources; @@ -109,4 +112,11 @@ private static void verifyProperty(final TestCase testCase, final String expecte assertThat(actualValue).describedAs("" + testCase).isNull(); } } + + @Test + void properties_file_in_class_path_should_be_read() { + final String propertiesFileName = StatusLoggerPropertiesUtilDoubleTest.class.getSimpleName() + ".properties"; + final Properties actualProperties = StatusLogger.PropertiesUtilsDouble.readPropertiesFile(propertiesFileName); + assertThat(actualProperties).containsExactlyEntriesOf(singletonMap("foo", "bar")); + } } diff --git a/log4j-api-test/src/test/resources/StatusLoggerPropertiesUtilDoubleTest.properties b/log4j-api-test/src/test/resources/StatusLoggerPropertiesUtilDoubleTest.properties new file mode 100644 index 00000000000..923acfe587f --- /dev/null +++ b/log4j-api-test/src/test/resources/StatusLoggerPropertiesUtilDoubleTest.properties @@ -0,0 +1,22 @@ +# +# 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. +# + +# +# This file only exists to test if `StatusLogger.PropertiesUtilDouble` indeed loads the resource at the root directory. +# Hence, don't place this file under a subdirectory! +# +foo=bar diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java index 56d9ef98625..2355040066a 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java @@ -404,7 +404,7 @@ static String readProperty(final Map normalizedProperties, final static Map readAllAvailableProperties() { final Properties systemProperties = System.getProperties(); final Properties environmentProperties = readEnvironmentProperties(); - final Properties fileProvidedProperties = readPropertiesFile(); + final Properties fileProvidedProperties = readPropertiesFile(PROPERTIES_FILE_NAME); return normalizeProperties(systemProperties, environmentProperties, fileProvidedProperties); } @@ -419,16 +419,20 @@ private static Properties readEnvironmentProperties() { // Consequently, they would delegate to `LoaderUtil`, etc. // All these mechanisms expect a working `StatusLogger`. // Hence, in order to be self-sufficient, we cannot rely on them. - private static Properties readPropertiesFile() { + static Properties readPropertiesFile(final String propertiesFileName) { final Properties properties = new Properties(); - final URL url = StatusLogger.class.getResource(PROPERTIES_FILE_NAME); + // Unlike `ClassLoader#getResource()`, which takes absolute resource paths, `Class#getResource()` supports + // relative resource paths. Without a `/` prefix, the resource must be placed into JAR resources as + // `org/apache/logging/log4j/status/log4j2.StatusLogger.properties`. Hence, the `/` prefix. + final String resourceName = '/' + propertiesFileName; + final URL url = StatusLogger.class.getResource(resourceName); if (url == null) { return properties; } try (final InputStream stream = url.openStream()) { properties.load(stream); } catch (final IOException error) { - final String message = String.format("failed reading properties from `%s`", PROPERTIES_FILE_NAME); + final String message = String.format("failed reading properties from `%s`", propertiesFileName); final RuntimeException extendedError = new RuntimeException(message, error); // There is no logging system at this stage. // There is nothing we can do but simply dumping the failure. diff --git a/src/changelog/.2.x.x/fix_StatusLogger_properties_read.xml b/src/changelog/.2.x.x/fix_StatusLogger_properties_read.xml new file mode 100644 index 00000000000..809deee1608 --- /dev/null +++ b/src/changelog/.2.x.x/fix_StatusLogger_properties_read.xml @@ -0,0 +1,8 @@ + + + + Fix `StatusLogger` to correctly read `log4j2.StatusLogger.properties` resource +