This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/master by this push:
new 6802596386 LOG4J2-857 - Support PluginOrder annotation and cleanups
6802596386 is described below
commit 68025963868f1e17e7eab293112abfd67c5e2a67
Author: Matt Sicker <[email protected]>
AuthorDate: Sat May 14 13:16:33 2022 -0500
LOG4J2-857 - Support PluginOrder annotation and cleanups
- PluginManager is effectively renamed to PluginCategory with plugin
collection logic moved to PluginRegistry
- PluginBundle replaces a map of category names to plugin type lists
- PluginOrder added for a generic plugin ordering annotation
- MergeStrategy updated to be injectable
Signed-off-by: Matt Sicker <[email protected]>
---
.../org/apache/log4j/builders/BuilderManager.java | 13 +-
.../validators/RequiredValidatorTest.java | 6 +-
.../validators/ValidHostValidatorTest.java | 6 +-
.../validators/ValidPortValidatorTest.java | 6 +-
.../ValidatingPluginWithFailoverTest.java | 10 +-
.../ValidatingPluginWithGenericBuilderTest.java | 6 +-
...ngPluginWithGenericSubclassFoo1BuilderTest.java | 6 +-
.../ValidatingPluginWithTypedBuilderTest.java | 6 +-
.../java/org/apache/logging/log4j/core/Core.java | 4 +-
.../log4j/core/config/AbstractConfiguration.java | 45 +++---
.../log4j/core/config/ConfigurationFactory.java | 8 +-
.../core/config/DefaultConfigurationFactory.java | 60 ++++---
.../config/builder/impl/BuiltConfiguration.java | 8 +-
.../config/composite/CompositeConfiguration.java | 20 +--
.../config/composite/DefaultMergeStrategy.java | 32 ++--
.../log4j/core/config/composite/MergeStrategy.java | 13 +-
.../log4j/core/config/jason/JsonConfiguration.java | 4 +-
.../log4j/core/config/json/JsonConfiguration.java | 4 +-
.../log4j/core/config/xml/XmlConfiguration.java | 2 +-
.../logging/log4j/core/impl/DefaultCallback.java | 8 +-
.../logging/log4j/core/lookup/Interpolator.java | 12 +-
.../logging/log4j/core/lookup/StrLookup.java | 4 +-
.../logging/log4j/core/pattern/PatternParser.java | 14 +-
.../logging/log4j/core/util/SecretKeyProvider.java | 4 +-
.../apache/logging/log4j/core/util/Watcher.java | 4 +-
.../logging/log4j/core/util/WatcherFactory.java | 6 +-
.../flume/appender/FlumePersistentManager.java | 11 +-
.../json/resolver/TemplateResolverFactories.java | 25 ++-
.../json/resolver/TemplateResolverFactory.java | 4 +-
.../json/resolver/TemplateResolverInterceptor.java | 4 +-
.../resolver/TemplateResolverInterceptors.java | 26 ++--
.../log4j/plugin/processor/package-info.java | 3 +-
.../plugin/processor/PluginProcessorTest.java | 54 +++----
.../apache/logging/log4j/plugins/PluginOrder.java | 57 +++++++
.../log4j/plugins/convert/TypeConverter.java | 4 +-
.../logging/log4j/plugins/di/DefaultInjector.java | 23 +--
.../apache/logging/log4j/plugins/di/Injector.java | 1 +
.../logging/log4j/plugins/di/LookupSelector.java | 25 ---
.../logging/log4j/plugins/osgi/Activator.java | 17 +-
.../log4j/plugins/processor/PluginService.java | 26 ++--
.../logging/log4j/plugins/util/PluginBundle.java | 88 +++++++++++
.../logging/log4j/plugins/util/PluginCategory.java | 173 +++++++++++++++++++++
.../logging/log4j/plugins/util/PluginManager.java | 167 --------------------
.../logging/log4j/plugins/util/PluginRegistry.java | 134 ++++++++--------
.../logging/log4j/plugins/util/PluginType.java | 5 +-
src/site/asciidoc/manual/plugins.adoc | 27 +---
46 files changed, 639 insertions(+), 546 deletions(-)
diff --git
a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
index 249ca940fd..29a71bae85 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java
@@ -34,13 +34,13 @@ import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.status.StatusLogger;
import org.w3c.dom.Element;
import java.util.Locale;
-import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.function.Function;
@@ -56,18 +56,18 @@ public class BuilderManager {
public static final Filter INVALID_FILTER = new FilterWrapper(null);
public static final Layout INVALID_LAYOUT = new LayoutWrapper(null);
public static final RewritePolicy INVALID_REWRITE_POLICY = new
RewritePolicyWrapper(null);
- public static final Key<PluginManager> PLUGIN_MANAGER_KEY = new
@Named(CATEGORY) Key<>() {};
+ public static final Key<PluginCategory> PLUGIN_CATEGORY_KEY = new
@Named(CATEGORY) Key<>() {};
private static final Logger LOGGER = StatusLogger.getLogger();
private static final Class<?>[] CONSTRUCTOR_PARAMS = new Class[] {
String.class, Properties.class };
private final Injector injector;
- private final Map<String, PluginType<?>> plugins;
+ private final PluginCategory plugins;
/**
* Constructs a new instance.
*/
public BuilderManager(final Injector injector) {
this.injector = injector;
- plugins = injector.getInstance(PLUGIN_MANAGER_KEY).getPlugins();
+ plugins = injector.getInstance(PLUGIN_CATEGORY_KEY);
}
private <T extends Builder<U>, U> T createBuilder(final PluginType<T>
plugin, final String prefix, final Properties props) {
@@ -92,7 +92,6 @@ public class BuilderManager {
}
}
- @SuppressWarnings("unchecked")
private <T> PluginType<T> getPlugin(final String className) {
Objects.requireNonNull(plugins, "plugins");
Objects.requireNonNull(className, "className");
@@ -101,7 +100,7 @@ public class BuilderManager {
if (pluginType == null) {
LOGGER.warn("Unable to load plugin class name {} with key {}",
className, key);
}
- return (PluginType<T>) pluginType;
+ return TypeUtil.cast(pluginType);
}
private <T extends Builder<U>, U> U newInstance(final PluginType<T>
plugin, final Function<T, U> consumer,
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/RequiredValidatorTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/RequiredValidatorTest.java
index 68f513750b..4d28b88ef9 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/RequiredValidatorTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/RequiredValidatorTest.java
@@ -23,7 +23,7 @@ import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
import org.apache.logging.log4j.plugins.di.Keys;
import org.apache.logging.log4j.plugins.test.validation.ValidatingPlugin;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.test.junit.StatusLoggerLevel;
import org.junit.jupiter.api.BeforeEach;
@@ -41,8 +41,8 @@ public class RequiredValidatorTest {
@BeforeEach
public void setUp() throws Exception {
- final PluginManager pluginManager = injector.getInstance(new
@Named("Test") Key<>() {});
- final PluginType<?> pluginType =
pluginManager.getPluginType("Validator");
+ final PluginCategory category = injector.getInstance(new
@Named("Test") Key<>() {});
+ final PluginType<?> pluginType = category.get("Validator");
assertNotNull(pluginType, "Rebuild this module to make sure annotation
processing kicks in.");
node = new Node(null, "Validator", pluginType);
}
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidHostValidatorTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidHostValidatorTest.java
index 3b152f19ab..6a3be20e34 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidHostValidatorTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidHostValidatorTest.java
@@ -23,7 +23,7 @@ import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
import org.apache.logging.log4j.plugins.di.Keys;
import org.apache.logging.log4j.plugins.test.validation.HostAndPort;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.test.junit.StatusLoggerLevel;
import org.junit.jupiter.api.BeforeEach;
@@ -41,8 +41,8 @@ public class ValidHostValidatorTest {
@BeforeEach
public void setUp() throws Exception {
- final PluginManager pluginManager = injector.getInstance(new
@Named("Test") Key<>() {});
- PluginType<?> plugin = pluginManager.getPluginType("HostAndPort");
+ final PluginCategory category = injector.getInstance(new
@Named("Test") Key<>() {});
+ PluginType<?> plugin = category.get("HostAndPort");
assertNotNull(plugin, "Rebuild this module to ensure annotation
processing has been done.");
node = new Node(null, "HostAndPort", plugin);
}
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidPortValidatorTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidPortValidatorTest.java
index 3df06e9b70..1a17bb1ca9 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidPortValidatorTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidPortValidatorTest.java
@@ -22,7 +22,7 @@ import org.apache.logging.log4j.plugins.di.DI;
import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
import org.apache.logging.log4j.plugins.di.Keys;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.test.junit.StatusLoggerLevel;
import org.junit.jupiter.api.BeforeEach;
@@ -40,8 +40,8 @@ public class ValidPortValidatorTest {
@BeforeEach
public void setUp() throws Exception {
- final PluginManager pluginManager = injector.getInstance(new
@Named("Test") Key<>() {});
- PluginType<?> plugin = pluginManager.getPluginType("HostAndPort");
+ final PluginCategory category = injector.getInstance(new
@Named("Test") Key<>() {});
+ PluginType<?> plugin = category.get("HostAndPort");
assertNotNull(plugin, "Rebuild this module to ensure annotation
processing has been done.");
node = new Node(null, "HostAndPort", plugin);
node.getAttributes().put("host", "localhost");
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithFailoverTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithFailoverTest.java
index a619c0144b..b2e0b3d0dc 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithFailoverTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithFailoverTest.java
@@ -28,7 +28,7 @@ import org.apache.logging.log4j.plugins.di.DI;
import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
import org.apache.logging.log4j.plugins.di.Keys;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.status.StatusData;
import org.apache.logging.log4j.status.StatusListener;
@@ -51,14 +51,14 @@ public class ValidatingPluginWithFailoverTest {
@BeforeEach
public void setUp() throws Exception {
- final PluginManager pluginManager =
injector.getInstance(Core.PLUGIN_MANAGER_KEY);
- PluginType<?> plugin = pluginManager.getPluginType("Failover");
+ final PluginCategory category =
injector.getInstance(Core.PLUGIN_CATEGORY_KEY);
+ PluginType<?> plugin = category.get("Failover");
assertNotNull(plugin, "Rebuild this module to make sure annotation
processing kicks in.");
AppenderRef appenderRef = AppenderRef.createAppenderRef("List",
Level.ALL, null);
node = new Node(null, "failover", plugin);
- Node failoversNode = new Node(node, "Failovers",
pluginManager.getPluginType("Failovers"));
- Node appenderRefNode = new Node(failoversNode, "appenderRef",
pluginManager.getPluginType("appenderRef"));
+ Node failoversNode = new Node(node, "Failovers",
category.get("Failovers"));
+ Node appenderRefNode = new Node(failoversNode, "appenderRef",
category.get("appenderRef"));
appenderRefNode.getAttributes().put("ref", "file");
appenderRefNode.setObject(appenderRef);
failoversNode.getChildren().add(appenderRefNode);
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithGenericBuilderTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithGenericBuilderTest.java
index bf5fc57dfc..cd3fbd0b6c 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithGenericBuilderTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithGenericBuilderTest.java
@@ -23,7 +23,7 @@ import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
import org.apache.logging.log4j.plugins.di.Keys;
import
org.apache.logging.log4j.plugins.test.validation.ValidatingPluginWithGenericBuilder;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.test.junit.StatusLoggerLevel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -40,8 +40,8 @@ public class ValidatingPluginWithGenericBuilderTest {
@BeforeEach
public void setUp() throws Exception {
- final PluginManager pluginManager = injector.getInstance(new
@Named("Test") Key<>() {});
- final var plugin =
pluginManager.getPluginType("ValidatingPluginWithGenericBuilder");
+ final PluginCategory category = injector.getInstance(new
@Named("Test") Key<>() {});
+ final var plugin = category.get("ValidatingPluginWithGenericBuilder");
assertNotNull(plugin, "Rebuild this module to make sure annotation
processing kicks in.");
node = new Node(null, "Validator", plugin);
}
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithGenericSubclassFoo1BuilderTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithGenericSubclassFoo1BuilderTest.java
index 313ea56724..25c5d1ca43 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithGenericSubclassFoo1BuilderTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithGenericSubclassFoo1BuilderTest.java
@@ -23,7 +23,7 @@ import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
import org.apache.logging.log4j.plugins.di.Keys;
import
org.apache.logging.log4j.plugins.test.validation.PluginWithGenericSubclassFoo1Builder;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.test.junit.StatusLoggerLevel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -40,8 +40,8 @@ public class
ValidatingPluginWithGenericSubclassFoo1BuilderTest {
@BeforeEach
public void setUp() throws Exception {
- final PluginManager pluginManager = injector.getInstance(new
@Named("Test") Key<>() {});
- final var plugin =
pluginManager.getPluginType("PluginWithGenericSubclassFoo1Builder");
+ final PluginCategory category = injector.getInstance(new
@Named("Test") Key<>() {});
+ final var plugin =
category.get("PluginWithGenericSubclassFoo1Builder");
assertNotNull(plugin, "Rebuild this module to make sure annotation
processing kicks in.");
node = new Node(null, "Validator", plugin);
}
diff --git
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithTypedBuilderTest.java
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithTypedBuilderTest.java
index 6e284c7ad4..2a4b536d97 100644
---
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithTypedBuilderTest.java
+++
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/validation/validators/ValidatingPluginWithTypedBuilderTest.java
@@ -23,7 +23,7 @@ import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
import org.apache.logging.log4j.plugins.di.Keys;
import
org.apache.logging.log4j.plugins.test.validation.ValidatingPluginWithTypedBuilder;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.test.junit.StatusLoggerLevel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -40,8 +40,8 @@ public class ValidatingPluginWithTypedBuilderTest {
@BeforeEach
public void setUp() throws Exception {
- final PluginManager pluginManager = injector.getInstance(new
@Named("Test") Key<>() {});
- final var plugin =
pluginManager.getPluginType("ValidatingPluginWithTypedBuilder");
+ final PluginCategory category = injector.getInstance(new
@Named("Test") Key<>() {});
+ final var plugin = category.get("ValidatingPluginWithTypedBuilder");
assertNotNull(plugin, "Rebuild this module to make sure annotation
processing kicks in.");
node = new Node(null, "Validator", plugin);
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/Core.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/Core.java
index 0886a81337..831db35bab 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/Core.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/Core.java
@@ -19,12 +19,12 @@ package org.apache.logging.log4j.core;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
public class Core {
public static final String CATEGORY_NAME = "Core";
- public static final Key<PluginManager> PLUGIN_MANAGER_KEY = new
@Named(CATEGORY_NAME) Key<>() {};
+ public static final Key<PluginCategory> PLUGIN_CATEGORY_KEY = new
@Named(CATEGORY_NAME) Key<>() {};
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index c575b45bd3..a3b00119e2 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -57,7 +57,7 @@ import org.apache.logging.log4j.plugins.di.DI;
import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
import org.apache.logging.log4j.plugins.di.Keys;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.util.LazyValue;
@@ -106,9 +106,9 @@ public abstract class AbstractConfiguration extends
AbstractFilterable implement
protected final List<String> pluginPackages = new ArrayList<>();
/**
- * The plugin manager.
+ * Core plugins.
*/
- protected PluginManager pluginManager;
+ protected PluginCategory corePlugins;
/**
* Shutdown hook is enabled by default.
@@ -200,13 +200,13 @@ public abstract class AbstractConfiguration extends
AbstractFilterable implement
injector.registerBinding(ScriptManager.KEY, this::getScriptManager);
}
- public PluginManager getPluginManager() {
- return pluginManager;
+ public PluginCategory getCorePlugins() {
+ return corePlugins;
}
- public void setPluginManager(final PluginManager pluginManager) {
- this.pluginManager = pluginManager;
- injector.registerBinding(Core.PLUGIN_MANAGER_KEY,
this::getPluginManager);
+ public void setCorePlugins(final PluginCategory corePlugins) {
+ this.corePlugins = corePlugins;
+ injector.registerBinding(Core.PLUGIN_CATEGORY_KEY,
this::getCorePlugins);
}
@Override
@@ -249,21 +249,18 @@ public abstract class AbstractConfiguration extends
AbstractFilterable implement
configurationStrSubstitutor.setConfiguration(this);
initializeScriptManager();
injector.registerBindingIfAbsent(Keys.PLUGIN_PACKAGES_KEY,
this::getPluginPackages);
- pluginManager = injector.getInstance(Core.PLUGIN_MANAGER_KEY);
- final PluginManager levelPlugins = injector.getInstance(new
@Named(Level.CATEGORY) Key<>() {});
- final Map<String, PluginType<?>> plugins = levelPlugins.getPlugins();
- if (plugins != null) {
- for (final PluginType<?> type : plugins.values()) {
- final Class<?> pluginClass = type.getPluginClass();
- try {
- // Cause the class to be initialized if it isn't already.
- Class.forName(pluginClass.getName(), true,
pluginClass.getClassLoader());
- } catch (final Exception e) {
- LOGGER.error("Unable to initialize {} due to {}",
pluginClass.getName(), e.getClass()
- .getSimpleName(), e);
- }
+ corePlugins = injector.getInstance(Core.PLUGIN_CATEGORY_KEY);
+ final PluginCategory levelPlugins = injector.getInstance(new
@Named(Level.CATEGORY) Key<>() {});
+ levelPlugins.forEach(type -> {
+ final Class<?> pluginClass = type.getPluginClass();
+ try {
+ // Cause the class to be initialized if it isn't already.
+ Class.forName(pluginClass.getName(), true,
pluginClass.getClassLoader());
+ } catch (final Exception e) {
+ LOGGER.error("Unable to initialize {} due to {}",
pluginClass.getName(), e.getClass()
+ .getSimpleName(), e);
}
- }
+ });
setup();
setupAdvertisement();
doConfigure();
@@ -312,7 +309,7 @@ public abstract class AbstractConfiguration extends
AbstractFilterable implement
final Source cfgSource = new Source(configSource);
final Key<WatcherFactory> key = Key.forClass(WatcherFactory.class);
injector.registerBindingIfAbsent(key, LazyValue.from(() ->
- new
WatcherFactory(injector.getInstance(Watcher.PLUGIN_MANAGER_KEY).getPlugins())));
+ new
WatcherFactory(injector.getInstance(Watcher.PLUGIN_CATEGORY_KEY))));
final Watcher watcher = injector.getInstance(key)
.newWatcher(cfgSource, this, reconfigurable, listeners,
configSource.getLastModified());
if (watcher != null) {
@@ -512,7 +509,7 @@ public abstract class AbstractConfiguration extends
AbstractFilterable implement
private void setupAdvertisement() {
if (advertiserNode != null) {
final String nodeName = advertiserNode.getName();
- final PluginType<?> type = pluginManager.getPluginType(nodeName);
+ final PluginType<?> type = corePlugins.get(nodeName);
if (type != null) {
advertiser =
injector.getInstance(type.getPluginClass().asSubclass(Advertiser.class));
advertisement =
advertiser.advertise(advertiserNode.getAttributes());
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
index e764231c0e..c856a5c97e 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
@@ -16,8 +16,6 @@
*/
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;
@@ -28,11 +26,13 @@ import org.apache.logging.log4j.plugins.Inject;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.LoaderUtil;
import org.apache.logging.log4j.util.PropertiesUtil;
+import java.net.URI;
+
/**
* Factory class for parsed {@link Configuration} objects from a configuration
file.
* ConfigurationFactory allows the configuration implementation to be
@@ -84,7 +84,7 @@ public abstract class ConfigurationFactory extends
ConfigurationBuilderFactory {
public static final Key<ConfigurationFactory> KEY = new Key<>() {};
- public static final Key<PluginManager> PLUGIN_MANAGER_KEY = new
@Named(CATEGORY) Key<>() {};
+ public static final Key<PluginCategory> PLUGIN_CATEGORY_KEY = new
@Named(CATEGORY) Key<>() {};
/**
* Allows subclasses access to the status logger without creating another
instance.
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfigurationFactory.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfigurationFactory.java
index 3f0a7902f0..bdcad7fb94 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfigurationFactory.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfigurationFactory.java
@@ -37,8 +37,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
/**
* Default factory for using a plugin selected based on the configuration
source.
@@ -294,44 +292,38 @@ public class DefaultConfigurationFactory extends
ConfigurationFactory {
}
private static List<ConfigurationFactory> loadConfigurationFactories(final
Injector injector) {
- final Stream<? extends ConfigurationFactory>
primaryConfigurationFactoryStream =
-
Optional.ofNullable(PropertiesUtil.getProperties().getStringProperty(CONFIGURATION_FACTORY_PROPERTY))
-
.flatMap(DefaultConfigurationFactory::tryLoadFactoryClass)
- .map(clazz -> {
- try {
- return injector.getInstance(clazz);
- } catch (final Exception ex) {
- LOGGER.error("Unable to create instance of
{}", clazz, ex);
- return null;
- }
- })
- .stream();
+ final List<ConfigurationFactory> factories = new ArrayList<>();
- final Stream<? extends ConfigurationFactory>
pluginConfigurationFactoryStream = injector.getInstance(PLUGIN_MANAGER_KEY)
- .getPlugins()
- .values()
- .stream()
- .flatMap(type -> {
- try {
- final Class<? extends ConfigurationFactory> clazz =
-
type.getPluginClass().asSubclass(ConfigurationFactory.class);
- return Stream.of(clazz);
- } catch (final Exception ex) {
- LOGGER.warn("Unable to add class {}",
type.getPluginClass(), ex);
- return Stream.empty();
- }
- })
- .sorted(OrderComparator.getInstance())
- .flatMap(clazz -> {
+
Optional.ofNullable(PropertiesUtil.getProperties().getStringProperty(CONFIGURATION_FACTORY_PROPERTY))
+ .flatMap(DefaultConfigurationFactory::tryLoadFactoryClass)
+ .map(clazz -> {
try {
- return Stream.of(injector.getInstance(clazz));
+ return injector.getInstance(clazz);
} catch (final Exception ex) {
LOGGER.error("Unable to create instance of {}", clazz,
ex);
- return Stream.empty();
+ return null;
}
- });
+ })
+ .ifPresent(factories::add);
+
+ final List<Class<? extends ConfigurationFactory>>
configurationFactoryPluginClasses = new ArrayList<>();
+ injector.getInstance(PLUGIN_CATEGORY_KEY).forEach(type -> {
+ try {
+
configurationFactoryPluginClasses.add(type.getPluginClass().asSubclass(ConfigurationFactory.class));
+ } catch (final Exception ex) {
+ LOGGER.warn("Unable to add class {}", type.getPluginClass(),
ex);
+ }
+ });
+ configurationFactoryPluginClasses.sort(OrderComparator.getInstance());
+ configurationFactoryPluginClasses.forEach(clazz -> {
+ try {
+ factories.add(injector.getInstance(clazz));
+ } catch (final Exception ex) {
+ LOGGER.error("Unable to create instance of {}", clazz, ex);
+ }
+ });
- return Stream.concat(primaryConfigurationFactoryStream,
pluginConfigurationFactoryStream).collect(Collectors.toList());
+ return factories;
}
private static Optional<Class<? extends ConfigurationFactory>>
tryLoadFactoryClass(final String factoryClass) {
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/BuiltConfiguration.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/BuiltConfiguration.java
index 7ee1d71876..76b27ad0e9 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/BuiltConfiguration.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/BuiltConfiguration.java
@@ -24,7 +24,6 @@ import
org.apache.logging.log4j.core.config.builder.api.Component;
import org.apache.logging.log4j.core.config.status.StatusConfiguration;
import org.apache.logging.log4j.core.util.Patterns;
import org.apache.logging.log4j.plugins.Node;
-import org.apache.logging.log4j.plugins.util.PluginManager;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.plugins.util.ResolverUtil;
@@ -154,14 +153,9 @@ public class BuiltConfiguration extends
AbstractConfiguration {
}
}
- @Override
- public PluginManager getPluginManager() {
- return pluginManager;
- }
-
protected Node convertToNode(final Node parent, final Component component)
{
final String name = component.getPluginType();
- final PluginType<?> pluginType = pluginManager.getPluginType(name);
+ final PluginType<?> pluginType = corePlugins.get(name);
final Node node = new Node(parent, name, pluginType);
node.getAttributes().putAll(component.getAttributes());
node.setValue(component.getValue());
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
index 3a947d3a2f..536101d223 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
@@ -23,16 +23,13 @@ import
org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Reconfigurable;
import org.apache.logging.log4j.core.config.status.StatusConfiguration;
-import org.apache.logging.log4j.core.util.Loader;
import org.apache.logging.log4j.core.util.Patterns;
import org.apache.logging.log4j.core.util.Source;
import org.apache.logging.log4j.core.util.WatchManager;
import org.apache.logging.log4j.core.util.Watcher;
import org.apache.logging.log4j.plugins.Node;
import org.apache.logging.log4j.plugins.util.ResolverUtil;
-import org.apache.logging.log4j.util.PropertiesUtil;
-import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
@@ -53,7 +50,7 @@ public class CompositeConfiguration extends
AbstractConfiguration implements Rec
private final List<? extends AbstractConfiguration> configurations;
- private MergeStrategy mergeStrategy;
+ private final MergeStrategy mergeStrategy;
/**
* Construct the CompositeConfiguration.
@@ -64,14 +61,7 @@ public class CompositeConfiguration extends
AbstractConfiguration implements Rec
super(configurations.get(0).getLoggerContext(),
ConfigurationSource.COMPOSITE_SOURCE);
rootNode = configurations.get(0).getRootNode();
this.configurations = configurations;
- final String mergeStrategyClassName =
PropertiesUtil.getProperties().getStringProperty(MERGE_STRATEGY_PROPERTY,
- DefaultMergeStrategy.class.getName());
- try {
- mergeStrategy = Loader.newInstanceOf(mergeStrategyClassName);
- } catch (final ClassNotFoundException | IllegalAccessException |
InvocationTargetException |
- InstantiationException ex) {
- mergeStrategy = new DefaultMergeStrategy();
- }
+ mergeStrategy = getComponent(MergeStrategy.KEY);
for (final AbstractConfiguration config : configurations) {
mergeStrategy.mergeRootProperties(rootNode, config);
}
@@ -116,7 +106,7 @@ public class CompositeConfiguration extends
AbstractConfiguration implements Rec
for (final AbstractConfiguration sourceConfiguration :
configurations.subList(1, configurations.size())) {
staffChildConfiguration(sourceConfiguration);
final Node sourceRoot = sourceConfiguration.getRootNode();
- mergeStrategy.mergeConfigurations(rootNode, sourceRoot,
getPluginManager());
+ mergeStrategy.mergeConfigurations(rootNode, sourceRoot,
corePlugins);
if (LOGGER.isEnabled(Level.ALL)) {
final StringBuilder sb = new StringBuilder();
printNodes("", rootNode, sb);
@@ -164,7 +154,7 @@ public class CompositeConfiguration extends
AbstractConfiguration implements Rec
}
private void staffChildConfiguration(final AbstractConfiguration
childConfiguration) {
- childConfiguration.setPluginManager(pluginManager);
+ childConfiguration.setCorePlugins(corePlugins);
childConfiguration.setScriptManager(scriptManager);
childConfiguration.setup();
}
@@ -181,7 +171,7 @@ public class CompositeConfiguration extends
AbstractConfiguration implements Rec
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode()) +
" [configurations=" + configurations
+ ", mergeStrategy=" + mergeStrategy + ", rootNode=" +
rootNode + ", listeners=" + listeners
- + ", pluginPackages=" + pluginPackages + ", pluginManager=" +
pluginManager + ", isShutdownHookEnabled="
+ + ", pluginPackages=" + pluginPackages + ", corePlugins=" +
corePlugins + ", isShutdownHookEnabled="
+ isShutdownHookEnabled + ", shutdownTimeoutMillis=" +
shutdownTimeoutMillis + ", scriptManager="
+ scriptManager + "]";
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
index 343d315f67..c040343fb1 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
@@ -16,19 +16,19 @@
*/
package org.apache.logging.log4j.core.config.composite;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.config.AbstractConfiguration;
import org.apache.logging.log4j.core.filter.CompositeFilter;
import org.apache.logging.log4j.plugins.Node;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
/**
* The default merge strategy for composite configurations.
* <p>
@@ -108,19 +108,19 @@ public class DefaultMergeStrategy implements
MergeStrategy {
/**
* Merge the source Configuration into the target Configuration.
*
- * @param target The target node to merge into.
- * @param source The source node.
- * @param pluginManager The PluginManager.
+ * @param target The target node to merge into.
+ * @param source The source node.
+ * @param corePlugins The Core plugins to use.
*/
@Override
- public void mergeConfigurations(final Node target, final Node source,
final PluginManager pluginManager) {
+ public void mergeConfigurations(final Node target, final Node source,
final PluginCategory corePlugins) {
for (final Node sourceChildNode : source.getChildren()) {
final boolean isFilter = isFilterNode(sourceChildNode);
boolean isMerged = false;
for (final Node targetChildNode : target.getChildren()) {
if (isFilter) {
if (isFilterNode(targetChildNode)) {
- updateFilterNode(target, targetChildNode,
sourceChildNode, pluginManager);
+ updateFilterNode(target, targetChildNode,
sourceChildNode, corePlugins);
isMerged = true;
break;
}
@@ -163,7 +163,7 @@ public class DefaultMergeStrategy implements MergeStrategy {
for (final Node targetChild :
targetNode.getChildren()) {
if (isFilterNode(targetChild)) {
updateFilterNode(loggerNode,
targetChild, sourceLoggerChild,
- pluginManager);
+ corePlugins);
foundFilter = true;
break;
}
@@ -240,14 +240,14 @@ public class DefaultMergeStrategy implements
MergeStrategy {
}
private void updateFilterNode(final Node target, final Node
targetChildNode, final Node sourceChildNode,
- final PluginManager pluginManager) {
+ final PluginCategory corePlugins) {
if
(CompositeFilter.class.isAssignableFrom(targetChildNode.getType().getPluginClass()))
{
final Node node = new Node(targetChildNode,
sourceChildNode.getName(), sourceChildNode.getType());
node.getChildren().addAll(sourceChildNode.getChildren());
node.getAttributes().putAll(sourceChildNode.getAttributes());
targetChildNode.getChildren().add(node);
} else {
- final PluginType pluginType = pluginManager.getPluginType(FILTERS);
+ final PluginType<?> pluginType = corePlugins.get(FILTERS);
final Node filtersNode = new Node(targetChildNode, FILTERS,
pluginType);
final Node node = new Node(filtersNode, sourceChildNode.getName(),
sourceChildNode.getType());
node.getAttributes().putAll(sourceChildNode.getAttributes());
@@ -266,11 +266,11 @@ public class DefaultMergeStrategy implements
MergeStrategy {
private boolean isSameName(final Node node1, final Node node2) {
final String value = node1.getAttributes().get(NAME);
- return value != null &&
value.toLowerCase().equals(node2.getAttributes().get(NAME).toLowerCase());
+ return value != null &&
value.equalsIgnoreCase(node2.getAttributes().get(NAME));
}
private boolean isSameReference(final Node node1, final Node node2) {
final String value = node1.getAttributes().get(REF);
- return value != null &&
value.toLowerCase().equals(node2.getAttributes().get(REF).toLowerCase());
+ return value != null &&
value.equalsIgnoreCase(node2.getAttributes().get(REF));
}
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
index 415c1de138..bb3014b572 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
@@ -18,13 +18,16 @@ package org.apache.logging.log4j.core.config.composite;
import org.apache.logging.log4j.core.config.AbstractConfiguration;
import org.apache.logging.log4j.plugins.Node;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.di.Key;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
/**
* Merges two configurations together
*/
public interface MergeStrategy {
+ Key<MergeStrategy> KEY = new Key<>() {};
+
/**
* Merge the root node properties into the configuration.
* @param rootNode The composite root node.
@@ -34,8 +37,10 @@ public interface MergeStrategy {
/**
* Merge the source node tree into the target node tree.
- * @param target The target Node tree.
- * @param source The source Node tree.
+ *
+ * @param target The target Node tree.
+ * @param source The source Node tree.
+ * @param corePlugins The Core plugins to merge.
*/
- void mergeConfigurations(Node target, Node source, PluginManager
pluginManager);
+ void mergeConfigurations(Node target, Node source, PluginCategory
corePlugins);
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/jason/JsonConfiguration.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/jason/JsonConfiguration.java
index c50c156d92..d18ba75862 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/jason/JsonConfiguration.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/jason/JsonConfiguration.java
@@ -113,7 +113,7 @@ public class JsonConfiguration extends
AbstractConfiguration implements Reconfig
}
private Node constructNode(final String key, final Node parent, final
Map<String, Object> value) {
- final PluginType<?> pluginType = pluginManager.getPluginType(key);
+ final PluginType<?> pluginType = corePlugins.get(key);
final Node node = new Node(parent, key, pluginType);
processAttributes(node, value);
final List<Node> children = node.getChildren();
@@ -133,7 +133,7 @@ public class JsonConfiguration extends
AbstractConfiguration implements Reconfig
if (object instanceof Map<?, ?>) {
final Map<String, Object> map = TypeUtil.cast(object);
final String type = getType(map).orElse(k);
- final PluginType<?> entryType =
pluginManager.getPluginType(type);
+ final PluginType<?> entryType = corePlugins.get(type);
final Node child = new Node(node, k, entryType);
processAttributes(child, map);
if (type.equalsIgnoreCase(k)) {
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfiguration.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfiguration.java
index 7406448c68..268c2bbdd5 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfiguration.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfiguration.java
@@ -144,7 +144,7 @@ public class JsonConfiguration extends
AbstractConfiguration implements Reconfig
}
private Node constructNode(final String name, final Node parent, final
JsonNode jsonNode) {
- final PluginType<?> type = pluginManager.getPluginType(name);
+ final PluginType<?> type = corePlugins.get(name);
final Node node = new Node(parent, name, type);
processAttributes(node, jsonNode);
final Iterator<Map.Entry<String, JsonNode>> iter = jsonNode.fields();
@@ -160,7 +160,7 @@ public class JsonConfiguration extends
AbstractConfiguration implements Reconfig
LOGGER.debug("Processing node for array {}",
entry.getKey());
for (int i = 0; i < n.size(); ++i) {
final String pluginType = getType(n.get(i),
entry.getKey());
- final PluginType<?> entryType =
pluginManager.getPluginType(pluginType);
+ final PluginType<?> entryType =
corePlugins.get(pluginType);
final Node item = new Node(node, entry.getKey(),
entryType);
processAttributes(item, n.get(i));
if (pluginType.equals(entry.getKey())) {
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfiguration.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfiguration.java
index 9440ec1d98..25ae2a715e 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfiguration.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfiguration.java
@@ -287,7 +287,7 @@ public class XmlConfiguration extends AbstractConfiguration
implements Reconfigu
if (w3cNode instanceof Element) {
final Element child = (Element) w3cNode;
final String name = getType(child);
- final PluginType<?> type = pluginManager.getPluginType(name);
+ final PluginType<?> type = corePlugins.get(name);
final Node childNode = new Node(node, name, type);
constructHierarchy(childNode, child);
if (type == null) {
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
index aa83f153d5..d1872e5d86 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/DefaultCallback.java
@@ -23,6 +23,9 @@ import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.ContextDataInjector;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.DefaultConfigurationFactory;
+import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
+import org.apache.logging.log4j.core.config.composite.DefaultMergeStrategy;
+import org.apache.logging.log4j.core.config.composite.MergeStrategy;
import org.apache.logging.log4j.core.lookup.Interpolator;
import org.apache.logging.log4j.core.lookup.InterpolatorFactory;
import org.apache.logging.log4j.core.lookup.StrLookup;
@@ -126,10 +129,13 @@ public class DefaultCallback implements InjectorCallback {
DefaultLogEventFactory.class))
.registerBindingIfAbsent(Key.forClass(InterpolatorFactory.class),
() -> defaultLookup -> new Interpolator(defaultLookup,
-
injector.getInstance(StrLookup.PLUGIN_MANAGER_KEY).getPlugins(),
injector::getInstance))
+
injector.getInstance(StrLookup.PLUGIN_CATEGORY_KEY), injector::getInstance))
.registerBindingIfAbsent(Key.forClass(StrSubstitutor.class),
() -> new
StrSubstitutor(injector.getInstance(InterpolatorFactory.class).newInterpolator(null)))
.registerBindingIfAbsent(ConfigurationFactory.KEY,
injector.getFactory(DefaultConfigurationFactory.class))
+ .registerBindingIfAbsent(MergeStrategy.KEY,
+ () ->
loader.getInstance(CompositeConfiguration.MERGE_STRATEGY_PROPERTY,
MergeStrategy.class,
+ () -> DefaultMergeStrategy.class))
.registerBindingIfAbsent(Constants.DEFAULT_STATUS_LEVEL_KEY,
() -> {
final String statusLevel =
properties.getStringProperty(Constants.LOG4J_DEFAULT_STATUS_LEVEL,
Level.ERROR.name());
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
index 387b0e0969..561e596ed1 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
@@ -22,7 +22,7 @@ import
org.apache.logging.log4j.core.config.ConfigurationAware;
import org.apache.logging.log4j.plugins.di.DI;
import org.apache.logging.log4j.plugins.di.Injector;
import org.apache.logging.log4j.plugins.di.Keys;
-import org.apache.logging.log4j.plugins.util.PluginType;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.LazyValue;
@@ -75,12 +75,10 @@ public class Interpolator extends
AbstractConfigurationAwareLookup {
this.defaultLookup = defaultLookup == null ? new
PropertiesLookup(Map.of()) : defaultLookup;
final Injector injector = DI.createInjector();
injector.registerBinding(Keys.PLUGIN_PACKAGES_KEY, () ->
pluginPackages);
- injector.getInstance(PLUGIN_MANAGER_KEY)
- .getPlugins()
+ injector.getInstance(PLUGIN_CATEGORY_KEY)
.forEach((key, value) -> {
try {
- strLookups.put(key.toLowerCase(Locale.ROOT),
-
injector.getFactory(value.getPluginClass().asSubclass(StrLookup.class)));
+ strLookups.put(key,
injector.getFactory(value.getPluginClass().asSubclass(StrLookup.class)));
} catch (final Throwable t) {
handleError(key, t);
}
@@ -88,13 +86,13 @@ public class Interpolator extends
AbstractConfigurationAwareLookup {
}
public Interpolator(
- final StrLookup defaultLookup, final Map<String, PluginType<?>>
strLookupPlugins,
+ final StrLookup defaultLookup, final PluginCategory
strLookupPlugins,
final Function<Class<? extends StrLookup>, StrLookup>
pluginLoader) {
this.defaultLookup = defaultLookup == null ? new
PropertiesLookup(Map.of()) : defaultLookup;
strLookupPlugins.forEach((key, value) -> {
try {
final Class<? extends StrLookup> strLookupClass =
value.getPluginClass().asSubclass(StrLookup.class);
- strLookups.put(key.toLowerCase(Locale.ROOT), LazyValue.from(()
-> pluginLoader.apply(strLookupClass)));
+ strLookups.put(key, LazyValue.from(() ->
pluginLoader.apply(strLookupClass)));
} catch (final Throwable t) {
handleError(key, t);
}
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrLookup.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrLookup.java
index 5ef6886964..f5e571085f 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrLookup.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/StrLookup.java
@@ -19,7 +19,7 @@ package org.apache.logging.log4j.core.lookup;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
/**
* Lookup a String key to a String value.
@@ -42,7 +42,7 @@ public interface StrLookup {
*/
String CATEGORY = "Lookup";
- Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY) Key<>() {};
+ Key<PluginCategory> PLUGIN_CATEGORY_KEY = new @Named(CATEGORY) Key<>() {};
/**
* Looks up a String key to a String value.
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
index 03627b6f44..9b6713b5ff 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
@@ -22,7 +22,7 @@ import org.apache.logging.log4j.core.time.SystemNanoClock;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.di.DI;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.Strings;
@@ -88,7 +88,7 @@ public final class PatternParser {
private static final int DECIMAL = 10;
- private static final Key<PluginManager> PLUGIN_MANAGER_KEY =
Key.forClass(PluginManager.class).withQualifierType(Named.class);
+ private static final Key<PluginCategory> PLUGIN_CATEGORY_KEY =
Key.forClass(PluginCategory.class).withQualifierType(Named.class);
private final Configuration config;
@@ -133,17 +133,17 @@ public final class PatternParser {
public PatternParser(final Configuration config, final String
converterKey, final Class<?> expectedClass,
final Class<?> filterClass) {
this.config = config;
- final Map<String, PluginType<?>> plugins;
- final Key<PluginManager> pluginManagerKey =
PLUGIN_MANAGER_KEY.withName(converterKey);
+ final PluginCategory plugins;
+ final Key<PluginCategory> pluginCategoryKey =
PLUGIN_CATEGORY_KEY.withName(converterKey);
if (config == null) {
- plugins =
DI.createInjector().getInstance(pluginManagerKey).getPlugins();
+ plugins = DI.createInjector().getInstance(pluginCategoryKey);
} else {
- plugins = config.getComponent(pluginManagerKey).getPlugins();
+ plugins = config.getComponent(pluginCategoryKey);
}
final Map<String, Class<? extends PatternConverter>> converters = new
LinkedHashMap<>();
- for (final PluginType<?> type : plugins.values()) {
+ for (final PluginType<?> type : plugins) {
try {
final Class<? extends PatternConverter> clazz =
type.getPluginClass().asSubclass(PatternConverter.class);
if (filterClass != null &&
!filterClass.isAssignableFrom(clazz)) {
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/SecretKeyProvider.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/SecretKeyProvider.java
index 58dae4bda6..66a87ec586 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/SecretKeyProvider.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/SecretKeyProvider.java
@@ -18,7 +18,7 @@ package org.apache.logging.log4j.core.util;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import javax.crypto.SecretKey;
@@ -29,7 +29,7 @@ public interface SecretKeyProvider {
String CATEGORY = "KeyProvider";
- Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY) Key<>() {};
+ Key<PluginCategory> PLUGIN_CATEGORY_KEY = new @Named(CATEGORY) Key<>() {};
/**
* Returns this SecretKey.
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Watcher.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Watcher.java
index e02bb09fc0..b4d2be06a7 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Watcher.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Watcher.java
@@ -20,7 +20,7 @@ import
org.apache.logging.log4j.core.config.ConfigurationListener;
import org.apache.logging.log4j.core.config.Reconfigurable;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import java.util.List;
@@ -32,7 +32,7 @@ import java.util.List;
public interface Watcher {
String CATEGORY = "Watcher";
- Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY) Key<>() {};
+ Key<PluginCategory> PLUGIN_CATEGORY_KEY = new @Named(CATEGORY) Key<>() {};
String ELEMENT_TYPE = "watcher";
/**
diff --git
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatcherFactory.java
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatcherFactory.java
index 343815ce8a..e692a9f2b9 100644
---
a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatcherFactory.java
+++
b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatcherFactory.java
@@ -21,13 +21,13 @@ import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFileWatcher;
import org.apache.logging.log4j.core.config.ConfigurationListener;
import org.apache.logging.log4j.core.config.Reconfigurable;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.status.StatusLogger;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
/**
@@ -37,9 +37,9 @@ public class WatcherFactory {
private static final Logger LOGGER = StatusLogger.getLogger();
- private final Map<String, PluginType<?>> plugins;
+ private final PluginCategory plugins;
- public WatcherFactory(final Map<String, PluginType<?>> watcherPlugins) {
+ public WatcherFactory(final PluginCategory watcherPlugins) {
plugins = watcherPlugins;
}
diff --git
a/log4j-flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumePersistentManager.java
b/log4j-flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumePersistentManager.java
index 8ddf166315..bb58c0ad0c 100644
---
a/log4j-flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumePersistentManager.java
+++
b/log4j-flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumePersistentManager.java
@@ -39,6 +39,7 @@ import org.apache.logging.log4j.core.util.Log4jThread;
import org.apache.logging.log4j.core.util.Log4jThreadFactory;
import org.apache.logging.log4j.core.util.SecretKeyProvider;
import org.apache.logging.log4j.plugins.di.Injector;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.util.Strings;
@@ -433,14 +434,14 @@ public class FlumePersistentManager extends
FlumeAvroManager {
}
if (key != null) {
final Injector injector = data.injector;
- final Map<String, PluginType<?>> plugins =
-
injector.getInstance(SecretKeyProvider.PLUGIN_MANAGER_KEY).getPlugins();
+ final PluginCategory plugins =
+
injector.getInstance(SecretKeyProvider.PLUGIN_CATEGORY_KEY);
if (plugins != null) {
boolean found = false;
- for (final Map.Entry<String, PluginType<?>> entry :
plugins.entrySet()) {
- if (entry.getKey().equalsIgnoreCase(key)) {
+ for (final PluginType<?> type : plugins) {
+ if (key.equalsIgnoreCase(type.getKey())) {
found = true;
- final Class<?> cl =
entry.getValue().getPluginClass();
+ final Class<?> cl = type.getPluginClass();
try {
final SecretKeyProvider provider =
injector.getInstance(cl.asSubclass(SecretKeyProvider.class));
diff --git
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.java
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.java
index 2afa8449a9..57c0187143 100644
---
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.java
+++
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.java
@@ -19,12 +19,13 @@ package
org.apache.logging.log4j.layout.template.json.resolver;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.plugins.di.Key;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.status.StatusLogger;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.Set;
/**
* Utility class for {@link TemplateResolverFactory}.
@@ -47,24 +48,24 @@ public final class TemplateResolverFactories {
final Class<C> contextClass) {
// Populate template resolver factories.
- final Map<String, PluginType<?>> pluginTypeByName =
-
configuration.getComponent(TemplateResolverFactory.PLUGIN_MANAGER_KEY).getPlugins();
+ final PluginCategory factoryPlugins =
+
configuration.getComponent(TemplateResolverFactory.PLUGIN_CATEGORY_KEY);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"found {} plugins of category \"{}\": {}",
- pluginTypeByName.size(),
+ factoryPlugins.size(),
TemplateResolverFactory.CATEGORY,
- pluginTypeByName.keySet());
+ factoryPlugins.getPluginKeys());
}
// Filter matching resolver factories.
final Map<String, F> factoryByName =
- populateFactoryByName(pluginTypeByName, configuration,
valueClass, contextClass);
+ populateFactoryByName(factoryPlugins, configuration,
valueClass, contextClass);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"matched {} resolver factories out of {} for value class
{} and context class {}: {}",
factoryByName.size(),
- pluginTypeByName.size(),
+ factoryPlugins.size(),
valueClass,
contextClass,
factoryByName.keySet());
@@ -74,14 +75,12 @@ public final class TemplateResolverFactories {
}
private static <V, C extends TemplateResolverContext<V, C>, F extends
TemplateResolverFactory<V, C>> Map<String, F> populateFactoryByName(
- final Map<String, PluginType<?>> pluginTypeByName,
+ final PluginCategory factoryPlugins,
final Configuration configuration,
final Class<V> valueClass,
final Class<C> contextClass) {
final Map<String, F> factoryByName = new LinkedHashMap<>();
- final Set<String> pluginNames = pluginTypeByName.keySet();
- for (final String pluginName : pluginNames) {
- final PluginType<?> pluginType = pluginTypeByName.get(pluginName);
+ for (final PluginType<?> pluginType : factoryPlugins) {
final Class<?> pluginClass = pluginType.getPluginClass();
final boolean pluginClassMatched =
TemplateResolverFactory.class.isAssignableFrom(pluginClass);
@@ -111,9 +110,7 @@ public final class TemplateResolverFactories {
final boolean factoryContextClassMatched =
contextClass.isAssignableFrom(factoryContextClass);
if (factoryValueClassMatched && factoryContextClassMatched) {
- @SuppressWarnings("unchecked")
- final F typedFactory = (F) factory;
- return typedFactory;
+ return TypeUtil.cast(factory);
}
return null;
}
diff --git
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactory.java
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactory.java
index 2553f07fe3..170bc46378 100644
---
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactory.java
+++
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactory.java
@@ -18,7 +18,7 @@ package
org.apache.logging.log4j.layout.template.json.resolver;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
/**
* {@link TemplateResolver} factory.
@@ -33,7 +33,7 @@ public interface TemplateResolverFactory<V, C extends
TemplateResolverContext<V,
*/
String CATEGORY = "JsonTemplateResolverFactory";
- Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY) Key<>() {};
+ Key<PluginCategory> PLUGIN_CATEGORY_KEY = new @Named(CATEGORY) Key<>() {};
/**
* The targeted value class.
diff --git
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptor.java
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptor.java
index d11178ea1d..ad30d684d4 100644
---
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptor.java
+++
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptor.java
@@ -18,7 +18,7 @@ package
org.apache.logging.log4j.layout.template.json.resolver;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
/**
* Main {@link TemplateResolver} compilation interception interface.
@@ -33,7 +33,7 @@ public interface TemplateResolverInterceptor<V, C extends
TemplateResolverContex
*/
String CATEGORY = "JsonTemplateResolverInterceptor";
- Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY) Key<>() {};
+ Key<PluginCategory> PLUGIN_CATEGORY_KEY = new @Named(CATEGORY) Key<>() {};
/**
* The targeted value class.
diff --git
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptors.java
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptors.java
index 340d3cd1c8..d793c8f139 100644
---
a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptors.java
+++
b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverInterceptors.java
@@ -19,13 +19,13 @@ package
org.apache.logging.log4j.layout.template.json.resolver;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.plugins.di.Key;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.status.StatusLogger;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
/**
* Utility class for {@link TemplateResolverInterceptor}.
@@ -48,23 +48,23 @@ public class TemplateResolverInterceptors {
final Class<C> contextClass) {
// Populate interceptors.
- final Map<String, PluginType<?>> pluginTypeByName =
-
configuration.getComponent(TemplateResolverInterceptor.PLUGIN_MANAGER_KEY).getPlugins();
+ final PluginCategory interceptorPlugins =
+
configuration.getComponent(TemplateResolverInterceptor.PLUGIN_CATEGORY_KEY);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"found {} plugins of category \"{}\": {}",
- pluginTypeByName.size(),
+ interceptorPlugins.size(),
TemplateResolverInterceptor.CATEGORY,
- pluginTypeByName.keySet());
+ interceptorPlugins.getPluginKeys());
}
// Filter matching interceptors.
final List<I> interceptors =
- populateInterceptors(pluginTypeByName, configuration,
valueClass, contextClass);
+ populateInterceptors(interceptorPlugins, configuration,
valueClass, contextClass);
LOGGER.debug(
"{} interceptors matched out of {} for value class {} and
context class {}",
interceptors.size(),
- pluginTypeByName.size(),
+ interceptorPlugins.size(),
valueClass,
contextClass);
return interceptors;
@@ -72,14 +72,12 @@ public class TemplateResolverInterceptors {
}
private static <V, C extends TemplateResolverContext<V, C>, I extends
TemplateResolverInterceptor<V, C>> List<I> populateInterceptors(
- final Map<String, PluginType<?>> pluginTypeByName,
+ final PluginCategory interceptorPlugins,
final Configuration configuration,
final Class<V> valueClass,
final Class<C> contextClass) {
final List<I> interceptors = new LinkedList<>();
- final Set<String> pluginNames = pluginTypeByName.keySet();
- for (final String pluginName : pluginNames) {
- final PluginType<?> pluginType = pluginTypeByName.get(pluginName);
+ for (final PluginType<?> pluginType : interceptorPlugins) {
final Class<?> pluginClass = pluginType.getPluginClass();
final boolean pluginClassMatched =
TemplateResolverInterceptor.class.isAssignableFrom(pluginClass);
@@ -110,9 +108,7 @@ public class TemplateResolverInterceptors {
final boolean interceptorContextClassMatched =
contextClass.isAssignableFrom(interceptorContextClass);
if (interceptorValueClassMatched && interceptorContextClassMatched) {
- @SuppressWarnings({"unchecked"})
- final I typedInterceptor = (I) interceptor;
- return typedInterceptor;
+ return TypeUtil.cast(interceptor);
}
return null;
}
diff --git
a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/package-info.java
b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/package-info.java
index b67bf604e0..5e4b0ae449 100644
---
a/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/package-info.java
+++
b/log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/package-info.java
@@ -16,7 +16,6 @@
*/
/**
- * Java annotation processor for pre-scanning Log4j 2 plugins. This is
provided as an alternative to using the
- * executable {@link org.apache.logging.log4j.plugins.util.PluginManager}
class in your build process.
+ * Java annotation processor for pre-scanning Log4j 2 plugins.
*/
package org.apache.logging.log4j.plugin.processor;
diff --git
a/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugin/processor/PluginProcessorTest.java
b/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugin/processor/PluginProcessorTest.java
index 8d8f02e97a..c3e03c468b 100644
---
a/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugin/processor/PluginProcessorTest.java
+++
b/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugin/processor/PluginProcessorTest.java
@@ -19,7 +19,6 @@ package org.apache.logging.log4j.plugin.processor;
import org.apache.logging.log4j.plugins.Plugin;
import org.apache.logging.log4j.plugins.PluginAliases;
-import org.apache.logging.log4j.plugins.processor.PluginEntry;
import org.apache.logging.log4j.plugins.processor.PluginService;
import org.apache.logging.log4j.plugins.test.validation.FakePlugin;
import org.apache.logging.log4j.plugins.test.validation.plugins.Log4jPlugins;
@@ -29,8 +28,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-import java.util.List;
-
import static org.junit.Assert.*;
@RunWith(JUnit4.class)
@@ -48,7 +45,7 @@ public class PluginProcessorTest {
@Test
public void testTestCategoryFound() throws Exception {
assertNotNull("No plugin annotation on FakePlugin.", p);
- final List<PluginType<?>> testCategory =
pluginService.getCategory(p.category());
+ final var testCategory = pluginService.getCategory(p.category());
assertNotEquals("No plugins were found.", 0, pluginService.size());
assertNotNull("The category '" + p.category() + "' was not found.",
testCategory);
assertFalse(testCategory.isEmpty());
@@ -56,56 +53,47 @@ public class PluginProcessorTest {
@Test
public void testFakePluginFoundWithCorrectInformation() throws Exception {
- final List<PluginType<?>> list =
pluginService.getCategory(p.category());
- assertNotNull(list);
- final PluginEntry fake = getEntry(list, p.name());
- assertNotNull(fake);
- verifyFakePluginEntry(p.name(), fake);
+ final var testCategory = pluginService.getCategory(p.category());
+ assertNotNull(testCategory);
+ final PluginType<?> type = testCategory.get(p.name());
+ assertNotNull(type);
+ verifyFakePluginEntry(p.name(), type);
}
@Test
public void testFakePluginAliasesContainSameInformation() throws Exception
{
final PluginAliases aliases =
FakePlugin.class.getAnnotation(PluginAliases.class);
for (final String alias : aliases.value()) {
- final List<PluginType<?>> list =
pluginService.getCategory(p.category());
- assertNotNull(list);
- final PluginEntry fake = getEntry(list, alias);
- assertNotNull(fake);
- verifyFakePluginEntry(alias, fake);
+ final var testCategory = pluginService.getCategory(p.category());
+ assertNotNull(testCategory);
+ final PluginType<?> type = testCategory.get(alias);
+ assertNotNull(type);
+ verifyFakePluginEntry(alias, type);
}
}
- private void verifyFakePluginEntry(final String name, final PluginEntry
fake) {
+ private void verifyFakePluginEntry(final String name, final PluginType<?>
fake) {
assertNotNull("The plugin '" + name.toLowerCase() + "' was not
found.", fake);
- assertEquals(FakePlugin.class.getName(), fake.getClassName());
+ assertEquals(FakePlugin.class.getName(),
fake.getPluginEntry().getClassName());
assertEquals(name.toLowerCase(), fake.getKey());
assertEquals(Plugin.EMPTY, p.elementType());
assertEquals(name, fake.getName());
- assertEquals(p.printObject(), fake.isPrintable());
- assertEquals(p.deferChildren(), fake.isDefer());
+ assertEquals(p.printObject(), fake.isObjectPrintable());
+ assertEquals(p.deferChildren(), fake.isDeferChildren());
}
@Test
public void testNestedPlugin() throws Exception {
final Plugin p = FakePlugin.Nested.class.getAnnotation(Plugin.class);
- final List<PluginType<?>> list =
pluginService.getCategory(p.category());
- assertNotNull(list);
- final PluginEntry nested = getEntry(list, p.name());
+ final var testCategory = pluginService.getCategory(p.category());
+ assertNotNull(testCategory);
+ final PluginType<?> nested = testCategory.get(p.name());
assertNotNull(nested);
assertEquals(p.name().toLowerCase(), nested.getKey());
- assertEquals(FakePlugin.Nested.class.getName(), nested.getClassName());
+ assertEquals(FakePlugin.Nested.class.getName(),
nested.getPluginEntry().getClassName());
assertEquals(p.name(), nested.getName());
assertEquals(Plugin.EMPTY, p.elementType());
- assertEquals(p.printObject(), nested.isPrintable());
- assertEquals(p.deferChildren(), nested.isDefer());
- }
-
- private PluginEntry getEntry(List<PluginType<?>> list, String name) {
- for (PluginType<?> type : list) {
- if (type.getPluginEntry().getName().equalsIgnoreCase(name)) {
- return type.getPluginEntry();
- }
- }
- return null;
+ assertEquals(p.printObject(), nested.isObjectPrintable());
+ assertEquals(p.deferChildren(), nested.isDeferChildren());
}
}
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginOrder.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginOrder.java
new file mode 100644
index 0000000000..f8bb60afee
--- /dev/null
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/PluginOrder.java
@@ -0,0 +1,57 @@
+/*
+ * 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.plugins;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Comparator;
+
+/**
+ * Specifies the order in which the annotated class should be considered in
when processing plugins.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface PluginOrder {
+ int value();
+
+ int FIRST = Integer.MIN_VALUE;
+
+ int LAST = Integer.MAX_VALUE;
+
+ Comparator<Class<?>> COMPARATOR = (lhs, rhs) -> {
+ if (lhs == rhs) {
+ return 0;
+ }
+ final PluginOrder lhsOrder = lhs.getAnnotation(PluginOrder.class);
+ final PluginOrder rhsOrder = rhs.getAnnotation(PluginOrder.class);
+ if (lhsOrder != null && rhsOrder != null) {
+ return Integer.compare(lhsOrder.value(), rhsOrder.value());
+ } else if (lhsOrder != null) {
+ return -1;
+ } else if (rhsOrder != null) {
+ return 1;
+ } else {
+ // natural ordering
+ return -1;
+ }
+ };
+}
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverter.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverter.java
index 781f32118e..271150150d 100644
---
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverter.java
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverter.java
@@ -20,7 +20,7 @@ package org.apache.logging.log4j.plugins.convert;
import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.Plugin;
import org.apache.logging.log4j.plugins.di.Key;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.status.StatusLogger;
@@ -38,7 +38,7 @@ public interface TypeConverter<T> {
*/
String CATEGORY = "TypeConverter";
- Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY) Key<>() {};
+ Key<PluginCategory> PLUGIN_CATEGORY_KEY = new @Named(CATEGORY) Key<>() {};
/**
* Converts a String to a given type.
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
index 4ed098f61f..2ae9342a63 100644
---
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
@@ -29,7 +29,8 @@ import org.apache.logging.log4j.plugins.convert.TypeConverter;
import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
import org.apache.logging.log4j.plugins.util.AnnotationUtil;
-import org.apache.logging.log4j.plugins.util.PluginManager;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
+import org.apache.logging.log4j.plugins.util.PluginRegistry;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.plugins.validation.Constraint;
@@ -81,7 +82,7 @@ class DefaultInjector implements Injector {
DefaultInjector() {
bindingMap = new BindingMap();
- bindingMap.put(Key.forClass(Injector.class), () -> this);
+ bindingMap.put(KEY, () -> this);
scopes.put(Singleton.class, new SingletonScope());
}
@@ -249,12 +250,16 @@ class DefaultInjector implements Injector {
}
final Class<T> rawType = key.getRawType();
final Scope scope = getScopeForType(rawType);
- if (rawType == PluginManager.class && key.getQualifierType() ==
Named.class) {
+ if (rawType == PluginCategory.class && key.getQualifierType() ==
Named.class) {
final Supplier<T> factory = () -> {
- final var manager = new PluginManager(key.getName());
+ final String categoryName = key.getName();
final Binding<List<String>> pluginPackagesBinding =
bindingMap.get(Keys.PLUGIN_PACKAGES_KEY, List.of());
- manager.collectPlugins(pluginPackagesBinding != null ?
pluginPackagesBinding.getSupplier().get() : List.of());
- return TypeUtil.cast(manager);
+ final List<String> pluginPackages = pluginPackagesBinding !=
null ? pluginPackagesBinding.getSupplier().get() : List.of();
+ // TODO: can this be a bean, too? might be tricky in OSGi
+ final var registry = PluginRegistry.getInstance();
+ // Then, iterate over packages registered in PluginManager
+ final var category = registry.getCategory(categoryName,
pluginPackages);
+ return TypeUtil.cast(category);
};
bindingMap.put(key, scope.get(key, factory));
return bindingMap.get(key, aliases).getSupplier();
@@ -298,13 +303,13 @@ class DefaultInjector implements Injector {
}
private void initializeTypeConverters() {
- final PluginManager manager =
getInstance(TypeConverter.PLUGIN_MANAGER_KEY);
- for (final PluginType<?> knownType : manager.getPlugins().values()) {
+ final PluginCategory category =
getInstance(TypeConverter.PLUGIN_CATEGORY_KEY);
+ category.forEach(knownType -> {
final Class<?> pluginClass = knownType.getPluginClass();
final Type type = getTypeConverterSupportedType(pluginClass);
final TypeConverter<?> converter =
getInstance(pluginClass.asSubclass(TypeConverter.class));
registerTypeConverter(type, converter);
- }
+ });
registerTypeConverter(Boolean.class, Boolean::valueOf);
registerTypeAlias(Boolean.class, Boolean.TYPE);
registerTypeConverter(Byte.class, Byte::valueOf);
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
index 24a0ee9478..a98d78042a 100644
---
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
@@ -31,6 +31,7 @@ import java.util.function.Supplier;
* {@linkplain #init() initialized} with {@link InjectorCallback} services.
*/
public interface Injector {
+ Key<Injector> KEY = new Key<>() {};
/**
* Initializes this Injector with all registered {@link InjectorCallback}
services in
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/LookupSelector.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/LookupSelector.java
deleted file mode 100644
index 59df5a634d..0000000000
---
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/LookupSelector.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.plugins.di;
-
-import java.lang.invoke.MethodHandles;
-
-@FunctionalInterface
-public interface LookupSelector {
- MethodHandles.Lookup in(final Class<?> clazz) throws
IllegalAccessException;
-}
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/osgi/Activator.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/osgi/Activator.java
index 2364aa9ae9..ea7b76be3f 100644
---
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/osgi/Activator.java
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/osgi/Activator.java
@@ -17,17 +17,23 @@
package org.apache.logging.log4j.plugins.osgi;
-import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.plugins.processor.PluginService;
import org.apache.logging.log4j.plugins.util.PluginRegistry;
import org.apache.logging.log4j.status.StatusLogger;
-import org.osgi.framework.*;
+import org.osgi.framework.AdaptPermission;
+import org.osgi.framework.AdminPermission;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.SynchronousBundleListener;
import org.osgi.framework.wiring.BundleWiring;
import java.security.Permission;
import java.util.Collection;
-import java.util.Hashtable;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -54,11 +60,12 @@ public final class Activator implements BundleActivator,
SynchronousBundleListen
}
private void loadPlugins(final BundleContext bundleContext) {
+ final PluginRegistry pluginRegistry = PluginRegistry.getInstance();
try {
final Collection<ServiceReference<PluginService>>
serviceReferences = bundleContext.getServiceReferences(PluginService.class,
null);
for (final ServiceReference<PluginService> serviceReference :
serviceReferences) {
final PluginService pluginService =
bundleContext.getService(serviceReference);
-
PluginRegistry.getInstance().loadFromBundle(pluginService.getCategories(),
bundleContext.getBundle().getBundleId());
+ pluginRegistry.loadFromBundle(pluginService.getBundle(),
bundleContext.getBundle().getBundleId());
}
} catch (final InvalidSyntaxException ex) {
LOGGER.error("Error accessing Plugins", ex);
@@ -122,7 +129,7 @@ public final class Activator implements BundleActivator,
SynchronousBundleListen
final long bundleId = bundle.getBundleId();
// LOG4J2-920: don't scan system bundle for plugins
if (bundle.getState() == Bundle.ACTIVE && bundleId != 0) {
- LOGGER.trace("Scanning bundle [{}, id=%d] for plugins.",
bundle.getSymbolicName(), bundleId);
+ LOGGER.trace("Scanning bundle [{}, id={}] for plugins.",
bundle.getSymbolicName(), bundleId);
PluginRegistry.getInstance().loadFromBundle(bundleId,
bundle.adapt(BundleWiring.class).getClassLoader());
}
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
index 00d8a7cf5d..69233c64d4 100644
---
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/processor/PluginService.java
@@ -16,14 +16,10 @@
*/
package org.apache.logging.log4j.plugins.processor;
+import org.apache.logging.log4j.plugins.util.PluginBundle;
+import org.apache.logging.log4j.plugins.util.PluginCategory;
import org.apache.logging.log4j.plugins.util.PluginType;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
/**
* Provides {@linkplain PluginEntry plugin metadata} for a module.
Implementation classes are typically generated by
* {@code PluginProcessor} in log4j-plugin-processor.
@@ -32,31 +28,29 @@ import java.util.Map;
*/
public abstract class PluginService {
- private final Map<String, List<PluginType<?>>> categories = new
LinkedHashMap<>();
+ private final PluginBundle bundle = new PluginBundle();
public PluginService() {
PluginEntry[] entries = getEntries();
ClassLoader classLoader = getClass().getClassLoader();
for (PluginEntry entry : entries) {
- String category = entry.getCategory().toLowerCase();
- List<PluginType<?>> list = categories.computeIfAbsent(category,
ignored -> new ArrayList<>());
- PluginType<?> type = new PluginType<>(entry, classLoader);
- list.add(type);
+ final PluginType<?> pluginType = new PluginType<>(entry,
classLoader);
+ bundle.add(pluginType);
}
}
public abstract PluginEntry[] getEntries();
- public Map<String, List<PluginType<?>>> getCategories() {
- return Collections.unmodifiableMap(categories);
+ public PluginBundle getBundle() {
+ return bundle;
}
- public List<PluginType<?>> getCategory(String category) {
- return
Collections.unmodifiableList(categories.get(category.toLowerCase()));
+ public PluginCategory getCategory(String category) {
+ return bundle.get(category);
}
public long size() {
- return categories.size();
+ return bundle.size();
}
}
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginBundle.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginBundle.java
new file mode 100644
index 0000000000..a1a3271cae
--- /dev/null
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginBundle.java
@@ -0,0 +1,88 @@
+/*
+ * 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.plugins.util;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+/**
+ * Bundles plugins by category from a plugin source.
+ */
+public class PluginBundle {
+ private final Map<String, PluginCategory> categories = new
LinkedHashMap<>();
+
+ public int size() {
+ return categories.size();
+ }
+
+ public boolean isEmpty() {
+ return categories.isEmpty();
+ }
+
+ public void put(final String category, final List<PluginType<?>>
pluginTypes) {
+ final var pluginCategory = new PluginCategory(category);
+ pluginCategory.putAll(pluginTypes);
+ categories.put(pluginCategory.getKey(), pluginCategory);
+ }
+
+ public void put(final PluginCategory category) {
+ categories.put(category.getKey(), category);
+ }
+
+ public int merge(final PluginCategory category) {
+ final PluginCategory existingCategory = getOrCreate(category.getKey());
+ final AtomicInteger addedCount = new AtomicInteger();
+ category.forEach((key, plugin) -> {
+ final var merged = existingCategory.merge(key, plugin);
+ if (merged == plugin) {
+ addedCount.incrementAndGet();
+ }
+ });
+ return addedCount.get();
+ }
+
+ public void add(final PluginType<?> pluginType) {
+ getOrCreate(pluginType.getCategory()).put(pluginType);
+ }
+
+ public void addAll(final String category, final Collection<PluginType<?>>
pluginTypes) {
+ getOrCreate(category).putAll(pluginTypes);
+ }
+
+ public PluginCategory get(final String category) {
+ return categories.get(category.toLowerCase(Locale.ROOT));
+ }
+
+ public PluginCategory getOrCreate(final String category) {
+ return categories.computeIfAbsent(category.toLowerCase(Locale.ROOT),
key -> new PluginCategory(key, category));
+ }
+
+ public void forEach(final Consumer<? super PluginCategory> consumer) {
+ categories.values().forEach(consumer);
+ }
+
+ public void forEach(final BiConsumer<? super String, ? super
PluginCategory> biConsumer) {
+ categories.forEach(biConsumer);
+ }
+}
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginCategory.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginCategory.java
new file mode 100644
index 0000000000..63a7dae8e2
--- /dev/null
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginCategory.java
@@ -0,0 +1,173 @@
+/*
+ * 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.plugins.util;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.plugins.PluginOrder;
+import org.apache.logging.log4j.plugins.Singleton;
+import org.apache.logging.log4j.status.StatusLogger;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
+
+/**
+ * Plugin categories are mappings of plugin keys to plugin classes where
plugin keys are lower-cased
+ * versions of plugin names.
+ */
+@Singleton
+public class PluginCategory implements Iterable<PluginType<?>> {
+ private static final Logger LOGGER = StatusLogger.getLogger();
+
+ private final String key;
+ private final String name;
+ private final Map<String, PluginType<?>> plugins = new LinkedHashMap<>();
+
+ public PluginCategory(final String name) {
+ this(name.toLowerCase(Locale.ROOT), name);
+ }
+
+ PluginCategory(final String key, final String name) {
+ this.key = key;
+ this.name = name;
+ }
+
+ /**
+ * Returns the key corresponding to this plugin category. These keys are
lowercase versions of the category name.
+ */
+ public String getKey() {
+ return key;
+ }
+
+ /**
+ * Returns the name of this plugin category.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the number of plugins in this category.
+ */
+ public int size() {
+ return plugins.size();
+ }
+
+ /**
+ * Indicates if this category has no plugins.
+ */
+ public boolean isEmpty() {
+ return plugins.isEmpty();
+ }
+
+ /**
+ * Returns an unmodifiable set of plugin keys in this category.
+ */
+ public Set<String> getPluginKeys() {
+ return Collections.unmodifiableSet(plugins.keySet());
+ }
+
+ /**
+ * Returns an unmodifiable collection of plugin types in this category.
+ */
+ public Collection<PluginType<?>> getPluginTypes() {
+ return Collections.unmodifiableCollection(plugins.values());
+ }
+
+ /**
+ * Returns an unmodifiable map of plugin keys to plugin types in this
category.
+ */
+ public Map<String, PluginType<?>> asMap() {
+ return Collections.unmodifiableMap(plugins);
+ }
+
+ /**
+ * Gets the plugin type for the provided plugin name (case-insensitive) if
available or {@code null}.
+ */
+ public PluginType<?> get(final String name) {
+ return plugins.get(name.toLowerCase(Locale.ROOT));
+ }
+
+ /**
+ * Puts all the provided plugin types into this category.
+ */
+ public void putAll(final Collection<PluginType<?>> pluginTypes) {
+ pluginTypes.forEach(this::put);
+ }
+
+ /**
+ * Puts the provided plugin type into this category.
+ */
+ public void put(final PluginType<?> pluginType) {
+ put(pluginType.getKey(), pluginType);
+ }
+
+ /**
+ * Puts the provided plugin type into this category using the given key.
+ */
+ public void put(final String key, final PluginType<?> pluginType) {
+ plugins.put(key, pluginType);
+ LOGGER.trace("Put PluginCategory[{}][{}] = {}", name, key, pluginType);
+ }
+
+ /**
+ * Merges the provided plugin type into this category using the given key
and returns the merged result.
+ * Merging is done by preferring plugins according to {@link PluginOrder}
where a conflict occurs with the
+ * same key.
+ */
+ public PluginType<?> merge(final String key, final PluginType<?>
pluginType) {
+ final PluginType<?> result = plugins.merge(key, pluginType, (lhs, rhs)
-> {
+ final int compare =
PluginOrder.COMPARATOR.compare(lhs.getPluginClass(), rhs.getPluginClass());
+ LOGGER.debug("PluginCategory merge for key {} with comparison
result {}", key, compare);
+ return compare <= 0 ? lhs : rhs;
+ });
+ LOGGER.trace("Merged PluginCategory[{}][{}] = {}", name, key, result);
+ return result;
+ }
+
+ public int mergeAll(final PluginCategory category) {
+ if (category != null) {
+ final AtomicInteger addedCount = new AtomicInteger();
+ category.forEach((pluginKey, pluginType) -> {
+ if (pluginType == merge(pluginKey, pluginType)) {
+ addedCount.incrementAndGet();
+ }
+ });
+ return addedCount.get();
+ }
+ return 0;
+ }
+
+ @Override
+ public Iterator<PluginType<?>> iterator() {
+ return plugins.values().iterator();
+ }
+
+ /**
+ * Performs the given action on all the plugin types in this category.
+ */
+ public void forEach(final BiConsumer<? super String, ? super
PluginType<?>> biConsumer) {
+ plugins.forEach(biConsumer);
+ }
+}
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginManager.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginManager.java
deleted file mode 100644
index 8360515116..0000000000
---
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginManager.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.plugins.util;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.plugins.Singleton;
-import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.Strings;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * Loads and manages all the plugins.
- */
-@Singleton
-public class PluginManager {
-
- /**
- * The location of the plugin cache data file. This file is written to by
this processor, and read from by
- * {@link org.apache.logging.log4j.plugins.util.PluginManager}.
- */
- public static final String PLUGIN_CACHE_FILE =
-
"META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat";
- private static final CopyOnWriteArrayList<String> PACKAGES = new
CopyOnWriteArrayList<>();
- private static final String LOG4J_PACKAGES =
"org.apache.logging.log4j.core";
-
- private static final Logger LOGGER = StatusLogger.getLogger();
-
- private Map<String, PluginType<?>> plugins = new HashMap<>();
- private final String category;
-
- /**
- * Constructs a PluginManager for the plugin category name given.
- *
- * @param category The plugin category name.
- */
- public PluginManager(final String category) {
- this.category = category;
- }
-
- /**
- * Adds a package name to be scanned for plugins. Must be invoked prior to
plugins being collected.
- *
- * @param p The package name. Ignored if {@code null} or empty.
- */
- public static void addPackage(final String p) {
- if (Strings.isBlank(p)) {
- return;
- }
- PACKAGES.addIfAbsent(p);
- }
-
- /**
- * Adds a list of package names to be scanned for plugins. Convenience
method for {@link #addPackage(String)}.
- *
- * @param packages collection of package names to add. Empty and null
package names are ignored.
- */
- public static void addPackages(final Collection<String> packages) {
- for (final String pkg : packages) {
- if (Strings.isNotBlank(pkg)) {
- PACKAGES.addIfAbsent(pkg);
- }
- }
- }
-
- /**
- * Returns the type of a specified plugin.
- *
- * @param name The name of the plugin.
- * @return The plugin's type.
- */
- public PluginType<?> getPluginType(final String name) {
- return plugins.get(name.toLowerCase());
- }
-
- /**
- * Returns all the matching plugins.
- *
- * @return A Map containing the name of the plugin and its type.
- */
- public Map<String, PluginType<?>> getPlugins() {
- return plugins;
- }
-
- /**
- * Locates all the plugins.
- */
- public void collectPlugins() {
- collectPlugins(null);
- }
-
- /**
- * Locates all the plugins including search of specific packages. Warns
about name collisions.
- *
- * @param packages the list of packages to scan for plugins
- * @since 2.1
- */
- public void collectPlugins(final List<String> packages) {
- final String categoryLowerCase = category.toLowerCase();
- final Map<String, PluginType<?>> newPlugins = new LinkedHashMap<>();
-
- // First, iterate the Log4j2Plugin.dat files found in the main
CLASSPATH
- Map<String, List<PluginType<?>>> builtInPlugins =
PluginRegistry.getInstance().loadFromMainClassLoader();
- if (builtInPlugins.isEmpty()) {
- // If we didn't find any plugins above, someone must have messed
with the log4j-core.jar.
- // Search the standard package in the hopes we can find our core
plugins.
- builtInPlugins =
PluginRegistry.getInstance().loadFromPackage(LOG4J_PACKAGES);
- }
- mergeByName(newPlugins, builtInPlugins.get(categoryLowerCase));
-
- // Next, iterate any Log4j2Plugin.dat files from OSGi Bundles
- for (final Map<String, List<PluginType<?>>> pluginsByCategory :
PluginRegistry.getInstance().getPluginsByCategoryByBundleId().values()) {
- mergeByName(newPlugins, pluginsByCategory.get(categoryLowerCase));
- }
-
- // Next iterate any packages passed to the static addPackage method.
- for (final String pkg : PACKAGES) {
- mergeByName(newPlugins,
PluginRegistry.getInstance().loadFromPackage(pkg).get(categoryLowerCase));
- }
- // Finally iterate any packages provided in the configuration (note
these can be changed at runtime).
- if (packages != null) {
- for (final String pkg : packages) {
- mergeByName(newPlugins,
PluginRegistry.getInstance().loadFromPackage(pkg).get(categoryLowerCase));
- }
- }
-
- LOGGER.debug("PluginManager '{}' found {} plugins", category,
newPlugins.size());
-
- plugins = newPlugins;
- }
-
- private static void mergeByName(final Map<String, PluginType<?>>
newPlugins, final List<PluginType<?>> plugins) {
- if (plugins == null) {
- return;
- }
- for (final PluginType<?> pluginType : plugins) {
- final String key = pluginType.getKey();
- final PluginType<?> existing = newPlugins.get(key);
- if (existing == null) {
- newPlugins.put(key, pluginType);
- } else if
(!existing.getPluginClass().equals(pluginType.getPluginClass())) {
- LOGGER.warn("Plugin [{}] is already mapped to {}, ignoring {}",
- key, existing.getPluginClass(),
pluginType.getPluginClass());
- }
- }
- }
-}
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
index e68bfdb2a4..09762c4a0e 100644
---
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginRegistry.java
@@ -32,19 +32,14 @@ import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Locale;
-import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
import java.util.function.Supplier;
/**
@@ -52,6 +47,11 @@ import java.util.function.Supplier;
*/
public class PluginRegistry {
+ /**
+ * The location of the plugin cache data file for compatibility with Log4j
2.x plugins.
+ */
+ private static final String PLUGIN_CACHE_FILE =
+
"META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat";
private static final Logger LOGGER = StatusLogger.getLogger();
private static final Supplier<PluginRegistry> INSTANCE = new
LazyValue<>(PluginRegistry::new);
@@ -59,20 +59,17 @@ public class PluginRegistry {
/**
* Contains plugins found in Log4j2Plugins.dat cache files in the main
CLASSPATH.
*/
- private final AtomicReference<Map<String, List<PluginType<?>>>>
pluginsByCategoryRef =
- new AtomicReference<>();
+ private final AtomicReference<PluginBundle> pluginsByCategoryRef = new
AtomicReference<>();
/**
* Contains plugins found in Log4j2Plugins.dat cache files in OSGi Bundles.
*/
- private final ConcurrentMap<Long, Map<String, List<PluginType<?>>>>
pluginsByCategoryByBundleId =
- new ConcurrentHashMap<>();
+ private final ConcurrentMap<Long, PluginBundle>
pluginsByCategoryByBundleId = new ConcurrentHashMap<>();
/**
* Contains plugins found by searching for annotated classes at runtime.
*/
- private final ConcurrentMap<String, Map<String, List<PluginType<?>>>>
pluginsByCategoryByPackage =
- new ConcurrentHashMap<>();
+ private final ConcurrentMap<String, PluginBundle>
pluginsByCategoryByPackage = new ConcurrentHashMap<>();
private PluginRegistry() {
}
@@ -96,13 +93,8 @@ public class PluginRegistry {
pluginsByCategoryByBundleId.clear();
}
- /**
- * Retrieve plugins by their category and bundle id.
- * @return The Map of plugin maps.
- * @since 2.1
- */
- public Map<Long, Map<String, List<PluginType<?>>>>
getPluginsByCategoryByBundleId() {
- return pluginsByCategoryByBundleId;
+ public void forEachOsgiPluginBundle(final Consumer<? super PluginBundle>
consumer) {
+ pluginsByCategoryByBundleId.values().forEach(consumer);
}
/**
@@ -110,13 +102,13 @@ public class PluginRegistry {
* @return Map of the List of PluginTypes by category.
* @since 2.1
*/
- public Map<String, List<PluginType<?>>> loadFromMainClassLoader() {
- final Map<String, List<PluginType<?>>> existing =
pluginsByCategoryRef.get();
+ public PluginBundle loadFromMainClassLoader() {
+ final var existing = pluginsByCategoryRef.get();
if (existing != null) {
// already loaded
return existing;
}
- final Map<String, List<PluginType<?>>> newPluginsByCategory =
decodeCacheFiles(LoaderUtil.getClassLoader());
+ final PluginBundle newPluginsByCategory =
decodeCacheFiles(LoaderUtil.getClassLoader());
loadPlugins(newPluginsByCategory);
// Note multiple threads could be calling this method concurrently.
Both will do the work,
@@ -144,13 +136,13 @@ public class PluginRegistry {
* @return the Map of Lists of plugins organized by category.
* @since 2.1
*/
- public Map<String, List<PluginType<?>>> loadFromBundle(final long
bundleId, final ClassLoader loader) {
- Map<String, List<PluginType<?>>> existing =
pluginsByCategoryByBundleId.get(bundleId);
+ public PluginBundle loadFromBundle(final long bundleId, final ClassLoader
loader) {
+ PluginBundle existing = pluginsByCategoryByBundleId.get(bundleId);
if (existing != null) {
// already loaded from this classloader
return existing;
}
- final Map<String, List<PluginType<?>>> newPluginsByCategory =
decodeCacheFiles(loader);
+ final PluginBundle newPluginsByCategory = decodeCacheFiles(loader);
loadPlugins(loader, newPluginsByCategory);
// Note multiple threads could be calling this method concurrently.
Both will do the work,
@@ -169,15 +161,8 @@ public class PluginRegistry {
* @param bundleId The bundle Id.
* @since 3.0
*/
- public void loadFromBundle(Map<String, List<PluginType<?>>> categories,
Long bundleId) {
+ public void loadFromBundle(PluginBundle categories, Long bundleId) {
pluginsByCategoryByBundleId.put(bundleId, categories);
- for (Map.Entry<String, List<PluginType<?>>> entry:
categories.entrySet()) {
- if (!categories.containsKey(entry.getKey())) {
-
- categories.put(entry.getKey(), new LinkedList<>());
- }
- categories.get(entry.getKey()).addAll(entry.getValue());
- }
}
/**
@@ -185,7 +170,7 @@ public class PluginRegistry {
* @param map The Map of the lists of plugins organized by category.
* @since 3.0
*/
- public void loadPlugins(Map<String, List<PluginType<?>>> map) {
+ public void loadPlugins(PluginBundle map) {
Throwable throwable = null;
ClassLoader errorClassLoader = null;
boolean allFail = true;
@@ -208,18 +193,15 @@ public class PluginRegistry {
/**
* Load plugins from a specific ClassLoader.
* @param classLoader The ClassLoader.
- * @param map The Map of the list of plugin types organized by category.
+ * @param bundle The PluginBundle to merge discovered plugins to
* @since 3.0
*/
- public void loadPlugins(ClassLoader classLoader, Map<String,
List<PluginType<?>>> map) {
+ public void loadPlugins(ClassLoader classLoader, PluginBundle bundle) {
final long startTime = System.nanoTime();
final ServiceLoader<PluginService> serviceLoader =
ServiceLoader.load(PluginService.class, classLoader);
final AtomicInteger pluginCount = new AtomicInteger();
for (final PluginService pluginService : serviceLoader) {
- pluginService.getCategories().forEach((category, plugins) -> {
- map.computeIfAbsent(category.toLowerCase(Locale.ROOT), ignored
-> new ArrayList<>()).addAll(plugins);
- pluginCount.addAndGet(plugins.size());
- });
+ pluginService.getBundle().forEach((category, plugins) ->
pluginCount.addAndGet(bundle.merge(plugins)));
}
final int numPlugins = pluginCount.get();
LOGGER.debug(() -> {
@@ -230,11 +212,11 @@ public class PluginRegistry {
});
}
- private Map<String, List<PluginType<?>>> decodeCacheFiles(final
ClassLoader classLoader) {
+ private PluginBundle decodeCacheFiles(final ClassLoader classLoader) {
final long startTime = System.nanoTime();
final PluginCache cache = new PluginCache();
try {
- final Enumeration<URL> resources =
classLoader.getResources(PluginManager.PLUGIN_CACHE_FILE);
+ final Enumeration<URL> resources =
classLoader.getResources(PLUGIN_CACHE_FILE);
if (resources == null) {
LOGGER.info("Plugin preloads not available from class loader
{}", classLoader);
} else {
@@ -243,20 +225,15 @@ public class PluginRegistry {
} catch (final IOException ioe) {
LOGGER.warn("Unable to preload plugins", ioe);
}
- final Map<String, List<PluginType<?>>> newPluginsByCategory = new
HashMap<>();
- int pluginCount = 0;
- for (final Map.Entry<String, Map<String, PluginEntry>> outer :
cache.getAllCategories().entrySet()) {
- final String categoryLowerCase = outer.getKey();
- final List<PluginType<?>> types = new
ArrayList<>(outer.getValue().size());
- newPluginsByCategory.put(categoryLowerCase, types);
- for (final Map.Entry<String, PluginEntry> inner :
outer.getValue().entrySet()) {
- final PluginEntry entry = inner.getValue();
- final PluginType<?> type = new PluginType<>(entry,
classLoader);
- types.add(type);
- ++pluginCount;
- }
- }
- final int numPlugins = pluginCount;
+ final PluginBundle newPluginsByCategory = new PluginBundle();
+ final AtomicInteger pluginCount = new AtomicInteger();
+ cache.getAllCategories().forEach((key, outer) ->
+ outer.values().forEach(entry -> {
+ final PluginType<?> type = new PluginType<>(entry,
classLoader);
+ newPluginsByCategory.add(type);
+ pluginCount.incrementAndGet();
+ }));
+ final int numPlugins = pluginCount.get();
LOGGER.debug(() -> {
final long endTime = System.nanoTime();
final DecimalFormat numFormat = new DecimalFormat("#0.000000");
@@ -272,12 +249,12 @@ public class PluginRegistry {
* @return A Map of the lists of plugin types organized by category.
* @since 2.1
*/
- public Map<String, List<PluginType<?>>> loadFromPackage(final String pkg) {
+ public PluginBundle loadFromPackage(final String pkg) {
if (Strings.isBlank(pkg)) {
// happens when splitting an empty string
- return Collections.emptyMap();
+ return new PluginBundle();
}
- Map<String, List<PluginType<?>>> existing =
pluginsByCategoryByPackage.get(pkg);
+ PluginBundle existing = pluginsByCategoryByPackage.get(pkg);
if (existing != null) {
// already loaded this package
return existing;
@@ -291,11 +268,9 @@ public class PluginRegistry {
}
resolver.findInPackage(new PluginTest(), pkg);
- final Map<String, List<PluginType<?>>> newPluginsByCategory = new
HashMap<>();
+ final PluginBundle newPluginsByCategory = new PluginBundle();
for (final Class<?> clazz : resolver.getClasses()) {
final Plugin plugin = clazz.getAnnotation(Plugin.class);
- final String categoryLowerCase = plugin.category().toLowerCase();
- List<PluginType<?>> list =
newPluginsByCategory.computeIfAbsent(categoryLowerCase, k -> new ArrayList<>());
final PluginEntry mainEntry = new PluginEntry();
final String mainElementName = plugin.elementType().equals(
Plugin.EMPTY) ? plugin.name() : plugin.elementType();
@@ -306,7 +281,7 @@ public class PluginRegistry {
mainEntry.setPrintable(plugin.printObject());
mainEntry.setDefer(plugin.deferChildren());
final PluginType<?> mainType = new PluginType<>(mainEntry, clazz,
mainElementName);
- list.add(mainType);
+ newPluginsByCategory.add(mainType);
final PluginAliases pluginAliases =
clazz.getAnnotation(PluginAliases.class);
if (pluginAliases != null) {
for (final String alias : pluginAliases.value()) {
@@ -320,7 +295,7 @@ public class PluginRegistry {
aliasEntry.setPrintable(plugin.printObject());
aliasEntry.setDefer(plugin.deferChildren());
final PluginType<?> aliasType = new
PluginType<>(aliasEntry, clazz, aliasElementName);
- list.add(aliasType);
+ newPluginsByCategory.add(aliasType);
}
}
}
@@ -341,6 +316,37 @@ public class PluginRegistry {
return newPluginsByCategory;
}
+ /**
+ * Gets the registered plugins for the given category. If additional scan
packages are provided, then plugins
+ * are scanned and loaded from there as well.
+ */
+ public PluginCategory getCategory(final String categoryName, List<String>
additionalScanPackages) {
+ final var category = new PluginCategory(categoryName);
+ // First, iterate the PluginService services and legacy
Log4j2Plugin.dat files found in the main CLASSPATH
+ PluginBundle builtInPlugins = loadFromMainClassLoader();
+ if (builtInPlugins.isEmpty()) {
+ // If we didn't find any plugins above, someone must have messed
with the log4j-core.jar.
+ // Search the standard package in the hopes we can find our core
plugins.
+ builtInPlugins = loadFromPackage("org.apache.logging.log4j.core");
+ }
+ final AtomicInteger addedCount = new
AtomicInteger(category.mergeAll(builtInPlugins.get(categoryName)));
+
+ // Next, iterate OSGi modules that provide plugins as OSGi services
+ forEachOsgiPluginBundle(bundle ->
+
addedCount.addAndGet(category.mergeAll(bundle.get(categoryName))));
+
+ // Finally, iterate over additional packages from configuration
+ if (additionalScanPackages != null) {
+ for (final String pkg : additionalScanPackages) {
+
addedCount.addAndGet(category.mergeAll(loadFromPackage(pkg).get(categoryName)));
+ }
+ }
+
+ LOGGER.debug("Discovered {} new plugins in category '{}'",
addedCount.get(), categoryName);
+
+ return category;
+ }
+
/**
* A Test that checks to see if each class is annotated with the 'Plugin'
annotation. If it
* is, then the test returns true, otherwise false.
diff --git
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
index f1ab067e48..f934936356 100644
---
a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
+++
b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/util/PluginType.java
@@ -65,7 +65,6 @@ public class PluginType<T> {
this.elementName = pluginEntry.getName();
}
-
public PluginEntry getPluginEntry() {
return this.pluginEntry;
}
@@ -104,6 +103,10 @@ public class PluginType<T> {
return this.pluginEntry.getCategory();
}
+ public String getName() {
+ return pluginEntry.getName();
+ }
+
@Override
public String toString() {
return "PluginType [pluginClass=" + pluginClass.get() +
diff --git a/src/site/asciidoc/manual/plugins.adoc
b/src/site/asciidoc/manual/plugins.adoc
index 88c64599e9..f198c86934 100644
--- a/src/site/asciidoc/manual/plugins.adoc
+++ b/src/site/asciidoc/manual/plugins.adoc
@@ -30,7 +30,7 @@
link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/Configuration.ht
will invoke the
link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/plugins/util/PluginManager.html[`PluginManager`]
to load the built-in Log4j plugins as well as any custom plugins. The
-`PluginManager` locates plugins by looking in five places:
+`Injector` locates plugins by looking in five places:
1. Plugin collection classes on the classpath that are loaded by
java.util.ServiceLoader.
These classes are generated automatically during the build (more details
below).
@@ -40,30 +40,19 @@ new bundles after `log4j-plugins` has started. Bundles must
register their plugi
class as an OSGi service.
3. A comma-separated list of packages specified by the
`log4j.plugin.packages` system property.
-4. Packages passed to the static `PluginManager.addPackages` method
-(before Log4j configuration occurs).
+4. Packages from the `@Named("PluginPackages") List<String>` binding in
`Injector` (if provided before configuration occurs).
5. The link:./configuration.html#ConfigurationSyntax[packages] declared
in your log4j2 configuration file.
6. Serialized plugin listing files on the classpath. These files were
generated by
the plugin annotation processor in Log4j 2 2.x. These are processed to allow
compatibility.
-If multiple Plugins specify the same (case-insensitive) `name`, then the
-load order above determines which one will be used. For example, to
-override the `File` plugin which is provided by the built-in
-`FileAppender` class, you would need to place your plugin in a JAR file
-in the CLASSPATH ahead of`log4j-core.jar`. This is not recommended;
-plugin name collisions will cause a warning to be emitted. Note that in
-an OSGi environment, the order that bundles are scanned for plugins
-generally follows the same order that bundles were installed into the
-framework. See
-http://www.osgi.org/javadoc/r5/core/org/osgi/framework/BundleContext.html#getBundles()[`getBundles()`]
-and
-http://www.osgi.org/javadoc/r5/core/org/osgi/framework/SynchronousBundleListener.html[`SynchronousBundleListener`].
-In short, name collisions are even more unpredictable in an OSGi environment.
-////
-TODO: in future, plugins will be able to be annotated with @Order which can
override priorities
-////
+When multiple plugins use the same case-insensitive `name` within the same
plugin category, then which one is selected is determined first by the presence
of `@PluginOrder` annotations and then by the previously described plugin
loading order.
+For example, to override the `File` plugin which is provided by the built-in
`FileAppender` class, you would need to place your plugin in a JAR file in the
CLASSPATH ahead of`log4j-core.jar`.
+This is not recommended; plugin name collisions will cause a warning to be
emitted.
+Note that in an OSGi environment, the order that bundles are scanned for
plugins generally follows the same order that bundles were installed into the
framework.
+See
https://www.osgi.org/javadoc/r5/core/org/osgi/framework/BundleContext.html#getBundles()[`getBundles()`]
and
https://www.osgi.org/javadoc/r5/core/org/osgi/framework/SynchronousBundleListener.html[`SynchronousBundleListener`].
+In short, name collisions are even more unpredictable in an OSGi environment
without additional `@PluginOrder` usage.
Plugin collection classes are generated by an annotation processor contained
in the log4j-plugins artifact which will automatically scan your code for