This is an automated email from the ASF dual-hosted git repository. pkarwasz pushed a commit to branch fix/apply-property-environment in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit c646ed075f82dc7e3d1708808483428581d9c798 Author: Piotr P. Karwasz <[email protected]> AuthorDate: Mon Mar 4 13:12:25 2024 +0100 Generalize DI usage This commit ensures that: * an `InstanceFactory` is created in the Log4j `Provider`, * the same factory is injected as parameters to all the components of the chain `Log4jContextFactory`, `ContextSelector`, `LoggerContext` (child), `Configuration` (grand-child). * `DI.createInstanceFactory` is called only when strictly necessary. --- .../src/main/java/org/apache/log4j/Category.java | 2 +- .../org/apache/log4j/bridge/AppenderAdapter.java | 2 +- .../org/apache/log4j/bridge/LogEventAdapter.java | 13 ++ .../org/apache/log4j/bridge/LogEventWrapper.java | 8 + .../log4j/config/Log4j1ConfigurationFactory.java | 6 +- .../config/PropertiesConfigurationFactory.java | 10 +- .../apache/log4j/xml/XmlConfigurationFactory.java | 10 +- .../apache/log4j/BasicConfigurationFactory.java | 4 +- .../test/java/org/apache/log4j/CategoryTest.java | 35 ++++- .../test/java/org/apache/log4j/ListAppender.java | 7 +- .../config/PropertiesConfigurationFactoryTest.java | 4 +- .../log4j/config/XmlConfigurationFactoryTest.java | 4 +- .../properties/JavaPropsConfigurationFactory.java | 6 +- .../config/yaml/YamlConfigurationFactory.java | 6 +- .../log4j/core/test/BasicConfigurationFactory.java | 4 +- .../core/test/junit/ConfigurationFactoryType.java | 4 +- .../apache/logging/log4j/core/LoggerContext.java | 1 - .../core/config/AbstractConfigurationFactory.java | 172 +++++++++++++++++++++ .../log4j/core/config/ConfigurationSource.java | 14 +- .../apache/logging/log4j/core/config/Order.java | 2 +- .../core/config/json/JsonConfigurationFactory.java | 8 +- .../core/config/xml/XmlConfigurationFactory.java | 6 +- .../log4j/core/impl/SystemPropertyBundle.java | 4 +- .../osgi/tests/CustomConfigurationFactory.java | 6 +- .../config/builder/CustomConfigurationFactory.java | 6 +- 25 files changed, 280 insertions(+), 64 deletions(-) diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java index 7d3014b23f..3e5e34a09d 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java @@ -237,7 +237,7 @@ public class Category implements AppenderAttachable { */ public void callAppenders(final LoggingEvent event) { if (LogManager.isLog4jCorePresent()) { - CategoryUtil.log(logger, new LogEventWrapper(event)); + CategoryUtil.log(logger, LogEventWrapper.adapt(event)); return; } int writes = 0; diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/AppenderAdapter.java b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/AppenderAdapter.java index 411258e20f..297d9ae248 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/AppenderAdapter.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/AppenderAdapter.java @@ -85,7 +85,7 @@ public final class AppenderAdapter { @Override public void append(final LogEvent event) { - appender.doAppend(new LogEventAdapter(event)); + appender.doAppend(LogEventAdapter.adapt(event)); } @Override diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java index 40209ef813..8be75614d7 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventAdapter.java @@ -41,6 +41,10 @@ public class LogEventAdapter extends LoggingEvent { private final LogEvent event; + public static LoggingEvent adapt(final LogEvent event) { + return event instanceof final LogEventWrapper wrapper ? wrapper.getLoggingEvent() : new LogEventAdapter(event); + } + public LogEventAdapter(final LogEvent event) { this.event = event; } @@ -213,4 +217,13 @@ public class LogEventAdapter extends LoggingEvent { public Map getProperties() { return event.getContextData().toMap(); } + + public LoggingEvent toImmutable() { + final LogEvent immutable = event.toImmutable(); + return event == immutable ? this : adapt(immutable); + } + + LogEvent getLogEvent() { + return event; + } } diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventWrapper.java b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventWrapper.java index e0db478fa1..df63b8aa59 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventWrapper.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/bridge/LogEventWrapper.java @@ -49,6 +49,10 @@ public class LogEventWrapper implements LogEvent { private final MutableThreadContextStack contextStack; private Thread thread; + public static LogEvent adapt(final LoggingEvent event) { + return event instanceof final LogEventAdapter adapter ? adapter.getLogEvent() : new LogEventWrapper(event); + } + public LogEventWrapper(final LoggingEvent event) { this.event = event; this.contextData = new ContextDataMap(event.getProperties()); @@ -182,6 +186,10 @@ public class LogEventWrapper implements LogEvent { return 0; } + LoggingEvent getLoggingEvent() { + return event; + } + private static class ContextDataMap extends HashMap<String, String> implements ReadOnlyStringMap { ContextDataMap(final Map<String, String> map) { diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java index 5454ad7c0b..b4f2ff0e76 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java @@ -19,9 +19,9 @@ package org.apache.log4j.config; import java.io.IOException; import java.io.InputStream; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationException; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder; import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; @@ -35,7 +35,7 @@ import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; // // Best Value? // @Order(50) -public class Log4j1ConfigurationFactory extends ConfigurationFactory { +public class Log4j1ConfigurationFactory extends AbstractConfigurationFactory { private static final String[] SUFFIXES = {".properties"}; @@ -51,7 +51,7 @@ public class Log4j1ConfigurationFactory extends ConfigurationFactory { } @Override - protected String[] getSupportedTypes() { + public String[] getSupportedTypes() { return SUFFIXES; } } diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfigurationFactory.java b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfigurationFactory.java index 7ca6314c66..5286db9e24 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfigurationFactory.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfigurationFactory.java @@ -17,8 +17,8 @@ package org.apache.log4j.config; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Order; import org.apache.logging.log4j.plugins.Namespace; @@ -28,10 +28,10 @@ import org.apache.logging.log4j.util.PropertiesUtil; /** * Configures Log4j from a log4j 1 format properties file. */ -@Namespace(ConfigurationFactory.NAMESPACE) +@Namespace(AbstractConfigurationFactory.NAMESPACE) @Plugin("Log4j1PropertiesConfigurationFactory") @Order(2) -public class PropertiesConfigurationFactory extends ConfigurationFactory { +public class PropertiesConfigurationFactory extends AbstractConfigurationFactory { static final String FILE_EXTENSION = ".properties"; @@ -46,9 +46,9 @@ public class PropertiesConfigurationFactory extends ConfigurationFactory { protected static final String DEFAULT_PREFIX = "log4j"; @Override - protected String[] getSupportedTypes() { + public String[] getSupportedTypes() { if (!PropertiesUtil.getProperties() - .getBooleanProperty(ConfigurationFactory.LOG4J1_EXPERIMENTAL, Boolean.FALSE)) { + .getBooleanProperty(AbstractConfigurationFactory.LOG4J1_EXPERIMENTAL, Boolean.FALSE)) { return null; } return new String[] {FILE_EXTENSION}; diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfigurationFactory.java b/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfigurationFactory.java index 78d1cae463..5734304b60 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfigurationFactory.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfigurationFactory.java @@ -18,8 +18,8 @@ package org.apache.log4j.xml; import org.apache.log4j.config.Log4j1Configuration; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Order; import org.apache.logging.log4j.plugins.Namespace; @@ -29,10 +29,10 @@ import org.apache.logging.log4j.util.PropertiesUtil; /** * Constructs a Configuration usable in Log4j 2 from a Log4j 1 configuration file. */ -@Namespace(ConfigurationFactory.NAMESPACE) +@Namespace(AbstractConfigurationFactory.NAMESPACE) @Plugin("Log4j1XmlConfigurationFactory") @Order(2) -public class XmlConfigurationFactory extends ConfigurationFactory { +public class XmlConfigurationFactory extends AbstractConfigurationFactory { public static final String FILE_EXTENSION = ".xml"; @@ -47,9 +47,9 @@ public class XmlConfigurationFactory extends ConfigurationFactory { protected static final String DEFAULT_PREFIX = "log4j"; @Override - protected String[] getSupportedTypes() { + public String[] getSupportedTypes() { if (!PropertiesUtil.getProperties() - .getBooleanProperty(ConfigurationFactory.LOG4J1_EXPERIMENTAL, Boolean.FALSE)) { + .getBooleanProperty(AbstractConfigurationFactory.LOG4J1_EXPERIMENTAL, Boolean.FALSE)) { return null; } return new String[] {FILE_EXTENSION}; diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/BasicConfigurationFactory.java b/log4j-1.2-api/src/test/java/org/apache/log4j/BasicConfigurationFactory.java index fbf5ba1d5f..0c817d234c 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/BasicConfigurationFactory.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/BasicConfigurationFactory.java @@ -20,15 +20,15 @@ import java.net.URI; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.AbstractConfiguration; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.LoggerConfig; /** * */ -public class BasicConfigurationFactory extends ConfigurationFactory { +public class BasicConfigurationFactory extends AbstractConfigurationFactory { @Override protected String[] getSupportedTypes() { diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java index 0dc789bcf5..8beb7acb1d 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java @@ -16,6 +16,7 @@ */ package org.apache.log4j; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -334,7 +335,7 @@ public class CategoryTest { public void testAddAppender() { try { final Logger rootLogger = LogManager.getRootLogger(); - int count = version1Appender.getEvents().size(); + version1Appender.clear(); rootLogger.addAppender(version1Appender); final Logger logger = LogManager.getLogger(CategoryTest.class); final org.apache.log4j.ListAppender appender = new org.apache.log4j.ListAppender(); @@ -342,17 +343,35 @@ public class CategoryTest { logger.addAppender(appender); // Root logger rootLogger.info("testAddLogger"); - assertEquals(++count, version1Appender.getEvents().size(), "adding at root works"); - assertEquals(0, appender.getEvents().size(), "adding at child works"); + assertThat(version1Appender.getEvents()) + .as("check root logger events") + .extracting(LoggingEvent::getRenderedMessage) + .containsExactly("testAddLogger"); + assertThat(appender.getEvents()) + .as("check logger '%s' events", logger.getName()) + .isEmpty(); // Another logger logger.info("testAddLogger2"); - assertEquals(++count, version1Appender.getEvents().size(), "adding at root works"); - assertEquals(1, appender.getEvents().size(), "adding at child works"); + assertThat(version1Appender.getEvents()) + .as("check root logger events") + .extracting(LoggingEvent::getRenderedMessage) + .containsExactly("testAddLogger", "testAddLogger2"); + assertThat(appender.getEvents()) + .as("check logger '%s' events", logger.getName()) + .extracting(LoggingEvent::getRenderedMessage) + .containsExactly("testAddLogger2"); // Call appenders - final LoggingEvent event = new LoggingEvent(); + version1Appender.clear(); + appender.clear(); + class MyCustomEvent extends LoggingEvent {} + final LoggingEvent event = new MyCustomEvent(); logger.callAppenders(event); - assertEquals(++count, version1Appender.getEvents().size(), "callAppenders"); - assertEquals(2, appender.getEvents().size(), "callAppenders"); + assertThat(version1Appender.getEvents()) + .as("check root logger events") + .containsExactly(event); + assertThat(appender.getEvents()) + .as("check logger '%s' events", logger.getName()) + .containsExactly(event); } finally { LogManager.resetConfiguration(); } diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/ListAppender.java b/log4j-1.2-api/src/test/java/org/apache/log4j/ListAppender.java index cfc9fe49bc..efe01197ec 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/ListAppender.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/ListAppender.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; +import org.apache.log4j.bridge.LogEventAdapter; import org.apache.log4j.spi.LoggingEvent; /** @@ -45,13 +46,17 @@ public class ListAppender extends AppenderSkeleton { messages.add(result); } } else { - events.add(event); + events.add(event instanceof final LogEventAdapter adapter ? adapter.toImmutable() : event); } } @Override public void close() {} + public void clear() { + events.clear(); + } + @Override public boolean requiresLayout() { return false; diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationFactoryTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationFactoryTest.java index fc4fd25d0e..6d4a9b358a 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationFactoryTest.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationFactoryTest.java @@ -21,7 +21,7 @@ import static org.junit.Assert.assertTrue; import java.io.File; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; -import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.junit.BeforeClass; import org.junit.Test; @@ -33,7 +33,7 @@ public class PropertiesConfigurationFactoryTest { @BeforeClass public static void beforeClass() { System.setProperty( - ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY.getSystemKey(), + AbstractConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY.getSystemKey(), "target/test-classes/log4j1-file-1.properties"); } diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationFactoryTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationFactoryTest.java index 49bb5a7792..afa80683c4 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationFactoryTest.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationFactoryTest.java @@ -21,7 +21,7 @@ import static org.junit.Assert.assertTrue; import java.io.File; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; -import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.junit.BeforeClass; import org.junit.Test; @@ -33,7 +33,7 @@ public class XmlConfigurationFactoryTest { @BeforeClass public static void beforeClass() { System.setProperty( - ConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY.getSystemKey(), + AbstractConfigurationFactory.LOG4J1_CONFIGURATION_FILE_PROPERTY.getSystemKey(), "target/test-classes/log4j1-file.xml"); } diff --git a/log4j-config-properties/src/main/java/org/apache/logging/log4j/config/properties/JavaPropsConfigurationFactory.java b/log4j-config-properties/src/main/java/org/apache/logging/log4j/config/properties/JavaPropsConfigurationFactory.java index b585cdc6e5..b2e64d8070 100644 --- a/log4j-config-properties/src/main/java/org/apache/logging/log4j/config/properties/JavaPropsConfigurationFactory.java +++ b/log4j-config-properties/src/main/java/org/apache/logging/log4j/config/properties/JavaPropsConfigurationFactory.java @@ -17,17 +17,17 @@ package org.apache.logging.log4j.config.properties; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Order; import org.apache.logging.log4j.plugins.Namespace; import org.apache.logging.log4j.plugins.Plugin; -@Namespace(ConfigurationFactory.NAMESPACE) +@Namespace(AbstractConfigurationFactory.NAMESPACE) @Plugin @Order(8) -public class JavaPropsConfigurationFactory extends ConfigurationFactory { +public class JavaPropsConfigurationFactory extends AbstractConfigurationFactory { /** * The file extensions supported by this factory. diff --git a/log4j-config-yaml/src/main/java/org/apache/logging/log4j/config/yaml/YamlConfigurationFactory.java b/log4j-config-yaml/src/main/java/org/apache/logging/log4j/config/yaml/YamlConfigurationFactory.java index ae6c4d9503..fc61eccd0a 100644 --- a/log4j-config-yaml/src/main/java/org/apache/logging/log4j/config/yaml/YamlConfigurationFactory.java +++ b/log4j-config-yaml/src/main/java/org/apache/logging/log4j/config/yaml/YamlConfigurationFactory.java @@ -17,17 +17,17 @@ package org.apache.logging.log4j.config.yaml; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Order; import org.apache.logging.log4j.plugins.Namespace; import org.apache.logging.log4j.plugins.Plugin; -@Namespace(ConfigurationFactory.NAMESPACE) +@Namespace(AbstractConfigurationFactory.NAMESPACE) @Plugin("YamlConfigurationFactory") @Order(7) -public class YamlConfigurationFactory extends ConfigurationFactory { +public class YamlConfigurationFactory extends AbstractConfigurationFactory { /** * The file extensions supported by this factory. diff --git a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/BasicConfigurationFactory.java b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/BasicConfigurationFactory.java index 643b77741d..5dedf79ae8 100644 --- a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/BasicConfigurationFactory.java +++ b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/BasicConfigurationFactory.java @@ -20,8 +20,8 @@ import java.net.URI; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.AbstractConfiguration; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.logging.log4j.plugins.di.ConfigurableInstanceFactory; @@ -31,7 +31,7 @@ import org.apache.logging.log4j.util.PropertiesUtil; /** * */ -public class BasicConfigurationFactory extends ConfigurationFactory { +public class BasicConfigurationFactory extends AbstractConfigurationFactory { @Override public Configuration getConfiguration( diff --git a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/ConfigurationFactoryType.java b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/ConfigurationFactoryType.java index be40bc61b0..097265c178 100644 --- a/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/ConfigurationFactoryType.java +++ b/log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/ConfigurationFactoryType.java @@ -21,11 +21,11 @@ import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.URIConfigurationFactory; /** - * Specifies a particular {@link ConfigurationFactory} class to use for a test class or method instead of the default. + * Specifies a particular {@link AbstractConfigurationFactory} class to use for a test class or method instead of the default. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java index 6b2a2898c1..44f1849639 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java @@ -201,7 +201,6 @@ public class LoggerContext extends AbstractLifeCycle } } - @Override public PropertyEnvironment getEnvironment() { return environment; } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfigurationFactory.java new file mode 100644 index 0000000000..f1dd503d10 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfigurationFactory.java @@ -0,0 +1,172 @@ +/* + * 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.logging.log4j.core.config; + +import java.net.URI; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory; +import org.apache.logging.log4j.core.impl.Log4jPropertyKey; +import org.apache.logging.log4j.plugins.Namespace; +import org.apache.logging.log4j.plugins.di.ConfigurableInstanceFactory; +import org.apache.logging.log4j.plugins.di.Key; +import org.apache.logging.log4j.plugins.model.PluginNamespace; +import org.apache.logging.log4j.status.StatusLogger; +import org.apache.logging.log4j.util.LoaderUtil; +import org.apache.logging.log4j.util.PropertyKey; + +/** + * Factory class for parsed {@link Configuration} objects from a configuration file. + * ConfigurationFactory allows the configuration implementation to be + * dynamically chosen in 1 of 3 ways: + * <ol> + * <li>A system property named "log4j.configurationFactory" can be set with the + * name of the ConfigurationFactory to be used.</li> + * <li>A {@link ConfigurableInstanceFactory} binding for ConfigurationFactory may be registered.</li> + * <li> + * A ConfigurationFactory implementation can be added to the classpath and configured as a plugin in the + * {@link #NAMESPACE ConfigurationFactory} category. The {@link Order} annotation should be used to configure the + * factory to be the first one inspected. See + * {@linkplain org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory} for an example.</li> + * </ol> + * + * If the ConfigurationFactory that was added returns null on a call to + * getConfiguration then any other ConfigurationFactories found as plugins will + * be called in their respective order. DefaultConfiguration is always called + * last if no configuration has been returned. + */ +public abstract class AbstractConfigurationFactory extends ConfigurationBuilderFactory implements ConfigurationFactory { + + public static final PropertyKey LOG4J1_CONFIGURATION_FILE_PROPERTY = Log4jPropertyKey.CONFIG_V1_FILE_NAME; + + public static final PropertyKey LOG4J1_EXPERIMENTAL = Log4jPropertyKey.CONFIG_V1_COMPATIBILITY_ENABLED; + + /** + * Plugin category used to inject a ConfigurationFactory {@link org.apache.logging.log4j.plugins.Plugin} + * class. + * + * @since 2.1 + */ + public static final String NAMESPACE = "ConfigurationFactory"; + + public static final Key<ConfigurationFactory> KEY = new Key<>() {}; + + public static final Key<PluginNamespace> PLUGIN_NAMESPACE_KEY = new @Namespace(NAMESPACE) Key<>() {}; + + /** + * Allows subclasses access to the status logger without creating another instance. + */ + protected static final Logger LOGGER = StatusLogger.getLogger(); + + /** + * File name prefix for test configurations. + */ + protected static final String TEST_PREFIX = "log4j2-test"; + + /** + * File name prefix for standard configurations. + */ + protected static final String DEFAULT_PREFIX = "log4j2"; + + protected static final String LOG4J1_VERSION = "1"; + + protected static final String LOG4J2_VERSION = "2"; + /** + * The name of the classloader URI scheme. + */ + private static final String CLASS_LOADER_SCHEME = "classloader"; + + /** + * The name of the classpath URI scheme, synonymous with the classloader URI scheme. + */ + private static final String CLASS_PATH_SCHEME = "classpath"; + + @Override + public String getTestPrefix() { + return TEST_PREFIX; + } + + @Override + public String getDefaultPrefix() { + return DEFAULT_PREFIX; + } + + @Override + public String getVersion() { + return LOG4J2_VERSION; + } + + /** + * Returns the Configuration. + * @param loggerContext The logger context + * @param name The configuration name. + * @param configLocation The configuration location. + * @return The Configuration. + */ + @Override + public Configuration getConfiguration( + final LoggerContext loggerContext, final String name, final URI configLocation) { + if (configLocation != null) { + final ConfigurationSource source = ConfigurationSource.fromUri(configLocation); + if (source != null) { + return getConfiguration(loggerContext, source); + } + } + return null; + } + + /** + * Returns the Configuration obtained using a given ClassLoader. + * @param loggerContext The logger context + * @param name The configuration name. + * @param configLocation A URI representing the location of the configuration. + * @param loader The default ClassLoader to use. If this is {@code null}, then the + * {@linkplain LoaderUtil#getThreadContextClassLoader() default ClassLoader} will be used. + * + * @return The Configuration. + */ + @Override + public Configuration getConfiguration( + final LoggerContext loggerContext, final String name, final URI configLocation, final ClassLoader loader) { + if (loader == null) { + return getConfiguration(loggerContext, name, configLocation); + } + if (isClassLoaderUri(configLocation)) { + final String path = extractClassLoaderUriPath(configLocation); + final ConfigurationSource source = ConfigurationSource.fromResource(path, loader); + if (source != null) { + final Configuration configuration = getConfiguration(loggerContext, source); + if (configuration != null) { + return configuration; + } + } + } + return getConfiguration(loggerContext, name, configLocation); + } + + static boolean isClassLoaderUri(final URI uri) { + if (uri == null) { + return false; + } + final String scheme = uri.getScheme(); + return scheme == null || scheme.equals(CLASS_LOADER_SCHEME) || scheme.equals(CLASS_PATH_SCHEME); + } + + static String extractClassLoaderUriPath(final URI uri) { + return uri.getScheme() == null ? uri.getPath() : uri.getSchemeSpecificPart(); + } +} diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java index 86f932d888..15619d6b5c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java @@ -290,23 +290,23 @@ public class ConfigurationSource { try { return new ConfigurationSource(new FileInputStream(configFile), configFile); } catch (final FileNotFoundException ex) { - ConfigurationFactory.LOGGER.error("Cannot locate file {}", configLocation.getPath(), ex); + AbstractConfigurationFactory.LOGGER.error("Cannot locate file {}", configLocation.getPath(), ex); } } - if (ConfigurationFactory.isClassLoaderUri(configLocation)) { + if (AbstractConfigurationFactory.isClassLoaderUri(configLocation)) { final ClassLoader loader = LoaderUtil.getThreadContextClassLoader(); - final String path = ConfigurationFactory.extractClassLoaderUriPath(configLocation); + final String path = AbstractConfigurationFactory.extractClassLoaderUriPath(configLocation); return fromResource(path, loader); } if (!configLocation.isAbsolute()) { // LOG4J2-704 avoid confusing error message thrown by uri.toURL() - ConfigurationFactory.LOGGER.error( + AbstractConfigurationFactory.LOGGER.error( "File not found in file system or classpath: {}", configLocation.toString()); return null; } try { return getConfigurationSource(configLocation.toURL()); } catch (final MalformedURLException ex) { - ConfigurationFactory.LOGGER.error("Invalid URL {}", configLocation.toString(), ex); + AbstractConfigurationFactory.LOGGER.error("Invalid URL {}", configLocation.toString(), ex); } return null; } @@ -360,11 +360,11 @@ public class ConfigurationSource { urlConnection.getInputStream(), url, urlConnection.getLastModified()); } } catch (final FileNotFoundException ex) { - ConfigurationFactory.LOGGER.info("Unable to locate file {}, ignoring.", url.toString()); + AbstractConfigurationFactory.LOGGER.info("Unable to locate file {}, ignoring.", url.toString()); return null; } } catch (final IOException | URISyntaxException ex) { - ConfigurationFactory.LOGGER.warn( + AbstractConfigurationFactory.LOGGER.warn( "Error accessing {} due to {}, ignoring.", url.toString(), ex.getMessage()); return null; } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Order.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Order.java index 2421f42021..8fe1d7b4c9 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Order.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Order.java @@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Identifies the relative ordering of a {@link ConfigurationFactory} plugin. + * Identifies the relative ordering of a {@link AbstractConfigurationFactory} plugin. * * @see OrderComparator */ diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java index 048b0a9f62..d8147c12f5 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java @@ -17,17 +17,17 @@ package org.apache.logging.log4j.core.config.json; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Order; import org.apache.logging.log4j.plugins.Namespace; import org.apache.logging.log4j.plugins.Plugin; -@Namespace(ConfigurationFactory.NAMESPACE) +@Namespace(AbstractConfigurationFactory.NAMESPACE) @Plugin("JsonConfigurationFactory") @Order(6) -public class JsonConfigurationFactory extends ConfigurationFactory { +public class JsonConfigurationFactory extends AbstractConfigurationFactory { /** * The file extensions supported by this factory. @@ -35,7 +35,7 @@ public class JsonConfigurationFactory extends ConfigurationFactory { private static final String[] SUFFIXES = new String[] {".json", ".jsn"}; @Override - protected String[] getSupportedTypes() { + public String[] getSupportedTypes() { return SUFFIXES; } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java index 0e75d5cc20..fb7ebb9972 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java @@ -17,8 +17,8 @@ package org.apache.logging.log4j.core.config.xml; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Order; import org.apache.logging.log4j.plugins.Namespace; @@ -27,10 +27,10 @@ import org.apache.logging.log4j.plugins.Plugin; /** * Factory to construct an XmlConfiguration. */ -@Namespace(ConfigurationFactory.NAMESPACE) +@Namespace(AbstractConfigurationFactory.NAMESPACE) @Plugin("XmlConfigurationFactory") @Order(5) -public class XmlConfigurationFactory extends ConfigurationFactory { +public class XmlConfigurationFactory extends AbstractConfigurationFactory { /** * Valid file extensions for XML files. diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/SystemPropertyBundle.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/SystemPropertyBundle.java index fc9fba3fb3..22dc3c91e7 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/SystemPropertyBundle.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/SystemPropertyBundle.java @@ -19,7 +19,7 @@ package org.apache.logging.log4j.core.impl; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.ContextDataInjector; import org.apache.logging.log4j.core.annotation.ConditionalOnPropertyKey; -import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.composite.MergeStrategy; import org.apache.logging.log4j.core.selector.ContextSelector; import org.apache.logging.log4j.core.util.ShutdownCallbackRegistry; @@ -40,7 +40,7 @@ import org.apache.logging.log4j.util.PropertyKey; * @see Log4jPropertyKey * @see ContextSelector * @see ShutdownCallbackRegistry - * @see ConfigurationFactory + * @see AbstractConfigurationFactory * @see MergeStrategy * @see ContextDataInjector * @see LogEventFactory diff --git a/log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/CustomConfigurationFactory.java b/log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/CustomConfigurationFactory.java index 6ce34c37bc..08a7a8505c 100644 --- a/log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/CustomConfigurationFactory.java +++ b/log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/CustomConfigurationFactory.java @@ -18,8 +18,8 @@ package org.apache.logging.log4j.osgi.tests; import java.net.URI; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Order; import org.apache.logging.log4j.plugins.Namespace; @@ -28,10 +28,10 @@ import org.apache.logging.log4j.plugins.Plugin; /** * Factory to construct a CustomConfiguration. */ -@Namespace(ConfigurationFactory.NAMESPACE) +@Namespace(AbstractConfigurationFactory.NAMESPACE) @Plugin("CustomConfigurationFactory") @Order(50) -public final class CustomConfigurationFactory extends ConfigurationFactory { +public final class CustomConfigurationFactory extends AbstractConfigurationFactory { /** * Valid file extensions for XML files. diff --git a/log4j-script/src/test/java/org/apache/logging/log4j/script/config/builder/CustomConfigurationFactory.java b/log4j-script/src/test/java/org/apache/logging/log4j/script/config/builder/CustomConfigurationFactory.java index 441156af84..459d9839f9 100644 --- a/log4j-script/src/test/java/org/apache/logging/log4j/script/config/builder/CustomConfigurationFactory.java +++ b/log4j-script/src/test/java/org/apache/logging/log4j/script/config/builder/CustomConfigurationFactory.java @@ -21,8 +21,8 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.appender.ConsoleAppender; +import org.apache.logging.log4j.core.config.AbstractConfigurationFactory; import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder; import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder; @@ -35,7 +35,7 @@ import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; // @Category(ConfigurationFactory.CATEGORY) // @Plugin("CustomConfigurationFactory") // @Order(50) -public class CustomConfigurationFactory extends ConfigurationFactory { +public class CustomConfigurationFactory extends AbstractConfigurationFactory { public static Configuration addTestFixtures( final String name, final ConfigurationBuilder<BuiltConfiguration> builder) { @@ -77,7 +77,7 @@ public class CustomConfigurationFactory extends ConfigurationFactory { } @Override - protected String[] getSupportedTypes() { + public String[] getSupportedTypes() { return new String[] {"*"}; } }
