From ff11e21d73da7b5b1f0306106b94584d73e401bd Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Fri, 29 Aug 2025 11:06:28 +0200 Subject: [PATCH] Polish "Improve Log4j core configuration file detection for Log4j 3" See gh-46409 --- .../logging/log4j2/Log4J2LoggingSystem.java | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java b/core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java index 015ec1950bd..a3fdea3e978 100644 --- a/core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java +++ b/core/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java @@ -158,16 +158,21 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem { @Override protected String[] getStandardConfigLocations() { List locations = new ArrayList<>(); - // The `log4j2.configurationFile` and `log4j.configuration.location` properties - // should be checked first, as they can be set to a custom location. - for (String property : new String[] { "log4j2.configurationFile", "log4j.configuration.location" }) { + addLocationsFromProperties(locations); + addStandardLocations(locations); + return StringUtils.toStringArray(locations); + } + + private void addLocationsFromProperties(List locations) { + for (String property : List.of("log4j2.configurationFile", "log4j.configuration.location")) { String propertyDefinedLocation = PropertiesUtil.getProperties().getStringProperty(property); if (propertyDefinedLocation != null) { locations.add(propertyDefinedLocation); } } + } - // If no custom location is defined, we use the standard locations. + private void addStandardLocations(List locations) { LoggerContext loggerContext = getLoggerContext(); String contextName = loggerContext.getName(); List extensions = getStandardConfigExtensions(); @@ -175,34 +180,30 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem { extensions.forEach((e) -> locations.add("log4j2-test" + e)); extensions.forEach((e) -> locations.add("log4j2" + contextName + e)); extensions.forEach((e) -> locations.add("log4j2" + e)); - - return StringUtils.toStringArray(locations); } private List getStandardConfigExtensions() { List extensions = new ArrayList<>(); // These classes need to be visible by the classloader that loads Log4j Core. ClassLoader classLoader = LoggerContext.class.getClassLoader(); - // The order of the extensions corresponds to the order - // in which Log4j Core 2 and 3 will try to load them, - // in decreasing value of `@Order`. + // The order of the extensions corresponds to the order in which Log4j Core 2 and + // 3 will try to load them, in decreasing value of @Order. if (isClassAvailable(classLoader, PROPS_CONFIGURATION_FACTORY_V2) || isClassAvailable(classLoader, PROPS_CONFIGURATION_FACTORY_V3)) { extensions.add(".properties"); } - if (areClassesAvailable(classLoader, YAML_CONFIGURATION_FACTORY_V2, YAML_TREE_PARSER_V2) + if (areAllClassesAvailable(classLoader, YAML_CONFIGURATION_FACTORY_V2, YAML_TREE_PARSER_V2) || isClassAvailable(classLoader, YAML_CONFIGURATION_FACTORY_V3)) { Collections.addAll(extensions, ".yaml", ".yml"); } if (isClassAvailable(classLoader, JSON_TREE_PARSER_V2) || isClassAvailable(classLoader, JSON_TREE_PARSER_V3)) { Collections.addAll(extensions, ".json", ".jsn"); } - // We assume the `java.xml` module is always available. extensions.add(".xml"); return extensions; } - private boolean areClassesAvailable(ClassLoader classLoader, String... classNames) { + private boolean areAllClassesAvailable(ClassLoader classLoader, String... classNames) { for (String className : classNames) { if (!isClassAvailable(classLoader, className)) { return false; @@ -211,6 +212,11 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem { return true; } + @Deprecated(since = "4.0.0", forRemoval = true) + protected boolean isClassAvailable(String className) { + return ClassUtils.isPresent(className, getClassLoader()); + } + protected boolean isClassAvailable(ClassLoader classLoader, String className) { return ClassUtils.isPresent(className, classLoader); }