mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-25 02:49:03 +00:00
Merge pull request #46410 from ppkarwasz
* pr/46410: Polish "Add runtime hints for Log4j Core 2" Add runtime hints for Log4j Core 2 Closes gh-46410
This commit is contained in:
+19
-11
@@ -90,44 +90,50 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem {
|
||||
|
||||
private static final String OPTIONAL_PREFIX = "optional:";
|
||||
|
||||
private static final String LOG4J_BRIDGE_HANDLER = "org.apache.logging.log4j.jul.Log4jBridgeHandler";
|
||||
/**
|
||||
* JUL handler that routes messages to the Log4j API (optional dependency).
|
||||
*/
|
||||
static final String LOG4J_BRIDGE_HANDLER = "org.apache.logging.log4j.jul.Log4jBridgeHandler";
|
||||
|
||||
private static final String LOG4J_LOG_MANAGER = "org.apache.logging.log4j.jul.LogManager";
|
||||
/**
|
||||
* JUL LogManager that routes messages to the Log4j API as the backend.
|
||||
*/
|
||||
static final String LOG4J_LOG_MANAGER = "org.apache.logging.log4j.jul.LogManager";
|
||||
|
||||
/**
|
||||
* JSON tree parser used by Log4j 2 (optional dependency).
|
||||
*/
|
||||
private static final String JSON_TREE_PARSER_V2 = "com.fasterxml.jackson.databind.ObjectMapper";
|
||||
static final String JSON_TREE_PARSER_V2 = "com.fasterxml.jackson.databind.ObjectMapper";
|
||||
|
||||
/**
|
||||
* JSON tree parser embedded in Log4j 3.
|
||||
*/
|
||||
private static final String JSON_TREE_PARSER_V3 = "org.apache.logging.log4j.kit.json.JsonReader";
|
||||
static final String JSON_TREE_PARSER_V3 = "org.apache.logging.log4j.kit.json.JsonReader";
|
||||
|
||||
/**
|
||||
* Configuration factory for properties files (Log4j 2).
|
||||
*/
|
||||
private static final String PROPS_CONFIGURATION_FACTORY_V2 = "org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory";
|
||||
static final String PROPS_CONFIGURATION_FACTORY_V2 = "org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory";
|
||||
|
||||
/**
|
||||
* Configuration factory for properties files (Log4j 3, optional dependency).
|
||||
*/
|
||||
private static final String PROPS_CONFIGURATION_FACTORY_V3 = "org.apache.logging.log4j.config.properties.JavaPropsConfigurationFactory";
|
||||
static final String PROPS_CONFIGURATION_FACTORY_V3 = "org.apache.logging.log4j.config.properties.JavaPropsConfigurationFactory";
|
||||
|
||||
/**
|
||||
* YAML tree parser used by Log4j 2 (optional dependency).
|
||||
*/
|
||||
private static final String YAML_TREE_PARSER_V2 = "com.fasterxml.jackson.dataformat.yaml.YAMLMapper";
|
||||
static final String YAML_TREE_PARSER_V2 = "com.fasterxml.jackson.dataformat.yaml.YAMLMapper";
|
||||
|
||||
/**
|
||||
* Configuration factory for YAML files (Log4j 2, embedded).
|
||||
*/
|
||||
private static final String YAML_CONFIGURATION_FACTORY_V2 = "org.apache.logging.log4j.core.config.yaml.YamlConfigurationFactory";
|
||||
static final String YAML_CONFIGURATION_FACTORY_V2 = "org.apache.logging.log4j.core.config.yaml.YamlConfigurationFactory";
|
||||
|
||||
/**
|
||||
* Configuration factory for YAML files (Log4j 3, optional dependency).
|
||||
*/
|
||||
private static final String YAML_CONFIGURATION_FACTORY_V3 = "org.apache.logging.log4j.config.yaml.YamlConfigurationFactory";
|
||||
static final String YAML_CONFIGURATION_FACTORY_V3 = "org.apache.logging.log4j.config.yaml.YamlConfigurationFactory";
|
||||
|
||||
private static final SpringEnvironmentPropertySource propertySource = new SpringEnvironmentPropertySource();
|
||||
|
||||
@@ -616,8 +622,10 @@ public class Log4J2LoggingSystem extends AbstractLoggingSystem {
|
||||
@Order(0)
|
||||
public static class Factory implements LoggingSystemFactory {
|
||||
|
||||
private static final boolean PRESENT = ClassUtils
|
||||
.isPresent("org.apache.logging.log4j.core.impl.Log4jContextFactory", Factory.class.getClassLoader());
|
||||
static final String LOG4J_CORE_CONTEXT_FACTORY = "org.apache.logging.log4j.core.impl.Log4jContextFactory";
|
||||
|
||||
private static final boolean PRESENT = ClassUtils.isPresent(LOG4J_CORE_CONTEXT_FACTORY,
|
||||
Factory.class.getClassLoader());
|
||||
|
||||
@Override
|
||||
public @Nullable LoggingSystem getLoggingSystem(ClassLoader classLoader) {
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.springframework.boot.logging.log4j2;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link RuntimeHintsRegistrar} implementation for {@link Log4J2LoggingSystem}.
|
||||
*
|
||||
* @author Piotr P. Karwasz
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class Log4J2RuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
if (ClassUtils.isPresent(Log4J2LoggingSystem.Factory.LOG4J_CORE_CONTEXT_FACTORY, classLoader)) {
|
||||
registerLog4j2Hints(hints, classLoader);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerLog4j2Hints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.Factory.LOG4J_CORE_CONTEXT_FACTORY);
|
||||
// Register default Log4j2 configuration files
|
||||
hints.resources().registerPattern("org/springframework/boot/logging/log4j2/log4j2.xml");
|
||||
hints.resources().registerPattern("org/springframework/boot/logging/log4j2/log4j2-file.xml");
|
||||
hints.resources().registerPattern("log4j2.springboot");
|
||||
// Declares the types that Log4j2LoggingSystem checks for existence reflectively.
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.JSON_TREE_PARSER_V2);
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.JSON_TREE_PARSER_V3);
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.PROPS_CONFIGURATION_FACTORY_V2);
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.PROPS_CONFIGURATION_FACTORY_V3);
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.YAML_TREE_PARSER_V2);
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.YAML_CONFIGURATION_FACTORY_V2);
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.YAML_CONFIGURATION_FACTORY_V3);
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.LOG4J_BRIDGE_HANDLER);
|
||||
hints.reflection().registerTypeIfPresent(classLoader, Log4J2LoggingSystem.LOG4J_LOG_MANAGER);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,6 +6,7 @@ org.springframework.boot.context.config.ConfigDataLocationRuntimeHints,\
|
||||
org.springframework.boot.context.config.ConfigDataPropertiesRuntimeHints,\
|
||||
org.springframework.boot.env.PropertySourceRuntimeHints,\
|
||||
org.springframework.boot.logging.java.JavaLoggingSystemRuntimeHints,\
|
||||
org.springframework.boot.logging.log4j2.Log4J2RuntimeHints,\
|
||||
org.springframework.boot.logging.logback.LogbackRuntimeHints,\
|
||||
org.springframework.boot.logging.structured.ElasticCommonSchemaProperties$ElasticCommonSchemaPropertiesRuntimeHints,\
|
||||
org.springframework.boot.logging.structured.GraylogExtendedLogFormatProperties$GraylogExtendedLogFormatPropertiesRuntimeHints,\
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2012-present the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.springframework.boot.logging.log4j2;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory;
|
||||
import org.apache.logging.log4j.core.config.yaml.YamlConfigurationFactory;
|
||||
import org.apache.logging.log4j.core.impl.Log4jContextFactory;
|
||||
import org.apache.logging.log4j.jul.Log4jBridgeHandler;
|
||||
import org.apache.logging.log4j.jul.LogManager;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.predicate.ReflectionHintsPredicates;
|
||||
import org.springframework.aot.hint.predicate.ResourceHintsPredicates;
|
||||
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link Log4J2RuntimeHints}.
|
||||
*
|
||||
* @author Piotr P. Karwasz
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class Log4J2RuntimeHintsTests {
|
||||
|
||||
private static final ReflectionHintsPredicates reflectionHints = RuntimeHintsPredicates.reflection();
|
||||
|
||||
private static final ResourceHintsPredicates resourceHints = RuntimeHintsPredicates.resource();
|
||||
|
||||
@Test
|
||||
void registersHintsForTypesCheckedByLog4J2LoggingSystem() {
|
||||
RuntimeHints runtimeHints = registerHints();
|
||||
assertThat(reflectionHints.onType(Log4jContextFactory.class)).accepts(runtimeHints);
|
||||
assertThat(reflectionHints.onType(Log4jBridgeHandler.class)).accepts(runtimeHints);
|
||||
assertThat(reflectionHints.onType(LogManager.class)).accepts(runtimeHints);
|
||||
assertThat(reflectionHints.onType(PropertiesConfigurationFactory.class)).accepts(runtimeHints);
|
||||
assertThat(reflectionHints.onType(YamlConfigurationFactory.class)).accepts(runtimeHints);
|
||||
}
|
||||
|
||||
@Test
|
||||
void registersHintsForLog4j2DefaultConfigurationFiles() {
|
||||
RuntimeHints runtimeHints = registerHints();
|
||||
assertThat(resourceHints.forResource("org/springframework/boot/logging/log4j2/log4j2.xml"))
|
||||
.accepts(runtimeHints);
|
||||
assertThat(resourceHints.forResource("org/springframework/boot/logging/log4j2/log4j2-file.xml"))
|
||||
.accepts(runtimeHints);
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotRegisterHintsWhenLog4jCoreIsNotAvailable() {
|
||||
RuntimeHints runtimeHints = new RuntimeHints();
|
||||
new Log4J2RuntimeHints().registerHints(runtimeHints, new HidePackagesClassLoader("org.apache.logging.log4j"));
|
||||
assertThat(runtimeHints.reflection().typeHints()).isEmpty();
|
||||
}
|
||||
|
||||
private RuntimeHints registerHints() {
|
||||
RuntimeHints hints = new RuntimeHints();
|
||||
new Log4J2RuntimeHints().registerHints(hints, getClass().getClassLoader());
|
||||
return hints;
|
||||
}
|
||||
|
||||
static final class HidePackagesClassLoader extends URLClassLoader {
|
||||
|
||||
private final String[] hiddenPackages;
|
||||
|
||||
HidePackagesClassLoader(String... hiddenPackages) {
|
||||
super(new URL[0], HidePackagesClassLoader.class.getClassLoader());
|
||||
this.hiddenPackages = hiddenPackages;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
if (Arrays.stream(this.hiddenPackages).anyMatch(name::startsWith)) {
|
||||
throw new ClassNotFoundException();
|
||||
}
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user