You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2022/03/23 03:43:30 UTC
[logging-log4j2] 01/02: Refactor PluginManager usage to utilise Injector
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
commit f4c65158299eba194ca24e35482d25540593b795
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Mon Mar 21 18:52:17 2022 -0500
Refactor PluginManager usage to utilise Injector
Signed-off-by: Matt Sicker <ma...@apache.org>
---
.../java/org/apache/logging/log4j/core/Core.java | 6 +++
.../log4j/core/config/AbstractConfiguration.java | 34 ++++++++++-----
.../log4j/core/config/PropertiesPlugin.java | 22 +++++-----
.../logging/log4j/core/lookup/Interpolator.java | 45 ++++++++++++-------
.../logging/log4j/core/lookup/StrLookup.java | 5 +++
.../org/apache/logging/log4j/core/util/Loader.java | 50 +++-------------------
.../apache/logging/log4j/core/util/Watcher.java | 8 +++-
.../logging/log4j/core/util/WatcherFactory.java | 32 ++++----------
.../logging/log4j/plugins/di/BindingMap.java | 14 +++++-
.../logging/log4j/plugins/di/DefaultInjector.java | 16 ++++---
.../org/apache/logging/log4j/plugins/di/Key.java | 8 ++++
.../logging/log4j/plugins/util/PluginManager.java | 8 +++-
12 files changed, 130 insertions(+), 118 deletions(-)
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 6a26c04..0886a81 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
@@ -17,8 +17,14 @@
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;
+
public class Core {
public static final String CATEGORY_NAME = "Core";
+ public static final Key<PluginManager> PLUGIN_MANAGER_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 383ec1e..5acf726 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
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.config;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.Core;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
@@ -43,11 +44,11 @@ import org.apache.logging.log4j.core.script.ScriptManager;
import org.apache.logging.log4j.core.script.ScriptManagerFactory;
import org.apache.logging.log4j.core.time.NanoClock;
import org.apache.logging.log4j.core.util.Constants;
-import org.apache.logging.log4j.core.util.Loader;
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.core.util.WatcherFactory;
+import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.Node;
import org.apache.logging.log4j.plugins.di.DI;
import org.apache.logging.log4j.plugins.di.Injector;
@@ -56,6 +57,7 @@ import org.apache.logging.log4j.plugins.di.Keys;
import org.apache.logging.log4j.plugins.util.PluginManager;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.plugins.util.TypeUtil;
+import org.apache.logging.log4j.util.LazyValue;
import org.apache.logging.log4j.util.NameUtil;
import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.ServiceRegistry;
@@ -131,9 +133,9 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
private ConcurrentMap<String, LoggerConfig> loggerConfigs = new ConcurrentHashMap<>();
private List<CustomLevelConfig> customLevels = List.of();
private final ConcurrentMap<String, String> properties = new ConcurrentHashMap<>();
- private final StrLookup tempLookup = new Interpolator(properties);
- private final StrSubstitutor runtimeStrSubstitutor = new RuntimeStrSubstitutor(tempLookup);
- private final StrSubstitutor configurationStrSubstitutor = new ConfigurationStrSubstitutor(runtimeStrSubstitutor);
+ private final StrLookup tempLookup;
+ private final StrSubstitutor runtimeStrSubstitutor;
+ private final StrSubstitutor configurationStrSubstitutor;
private LoggerConfig root = new LoggerConfig();
private final ConcurrentMap<String, Object> componentMap = new ConcurrentHashMap<>();
private final ConfigurationSource configurationSource;
@@ -158,7 +160,10 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
injector.init();
}
componentMap.put(Configuration.CONTEXT_PROPERTIES, properties);
- pluginManager = new PluginManager(Node.CATEGORY);
+ tempLookup = new Interpolator(new PropertiesLookup(properties), this);
+ runtimeStrSubstitutor = new RuntimeStrSubstitutor(tempLookup);
+ configurationStrSubstitutor = new ConfigurationStrSubstitutor(runtimeStrSubstitutor);
+ pluginManager = injector.getInstance(Core.PLUGIN_MANAGER_KEY);
configurationScheduler = injector.getInstance(ConfigurationScheduler.class);
watchManager = injector.getInstance(WatchManager.class);
setState(State.INITIALIZING);
@@ -195,6 +200,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
public void setPluginManager(final PluginManager pluginManager) {
this.pluginManager = pluginManager;
+ injector.registerBinding(Core.PLUGIN_MANAGER_KEY, this::getPluginManager);
}
@Override
@@ -232,16 +238,17 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
configurationStrSubstitutor.setConfiguration(this);
initializeScriptManager();
pluginManager.collectPlugins(pluginPackages);
- final PluginManager levelPlugins = new PluginManager(Level.CATEGORY);
+ final PluginManager levelPlugins = injector.getInstance(new @Named(Level.CATEGORY) Key<>() {});
levelPlugins.collectPlugins(pluginPackages);
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.
- Loader.initializeClass(type.getPluginClass().getName(), type.getPluginClass().getClassLoader());
+ Class.forName(pluginClass.getName(), true, pluginClass.getClassLoader());
} catch (final Exception e) {
- LOGGER.error("Unable to initialize {} due to {}", type.getPluginClass().getName(), e.getClass()
+ LOGGER.error("Unable to initialize {} due to {}", pluginClass.getName(), e.getClass()
.getSimpleName(), e);
}
}
@@ -292,7 +299,14 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
private void monitorSource(final Reconfigurable reconfigurable, final ConfigurationSource configSource) {
if (configSource.getLastModified() > 0) {
final Source cfgSource = new Source(configSource);
- final Watcher watcher = WatcherFactory.getInstance(pluginPackages)
+ final Key<WatcherFactory> key = Key.forClass(WatcherFactory.class);
+ injector.registerBindingIfAbsent(key, new LazyValue<>(() -> {
+ final PluginManager pluginManager = injector.getInstance(Watcher.PLUGIN_MANAGER_KEY);
+ pluginManager.collectPlugins(pluginPackages);
+ final Map<String, PluginType<?>> watcherPlugins = pluginManager.getPlugins();
+ return new WatcherFactory(watcherPlugins);
+ }));
+ final Watcher watcher = injector.getInstance(key)
.newWatcher(cfgSource, this, reconfigurable, listeners, configSource.getLastModified());
if (watcher != null) {
watchManager.watch(cfgSource, watcher);
@@ -638,7 +652,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
} else {
final Map<String, String> map = this.getComponent(CONTEXT_PROPERTIES);
final StrLookup lookup = map == null ? null : new PropertiesLookup(map);
- Interpolator interpolator = new Interpolator(lookup, pluginPackages);
+ Interpolator interpolator = new Interpolator(lookup, this);
runtimeStrSubstitutor.setVariableResolver(interpolator);
configurationStrSubstitutor.setVariableResolver(interpolator);
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/PropertiesPlugin.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/PropertiesPlugin.java
index d027831..94fede4 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/PropertiesPlugin.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/PropertiesPlugin.java
@@ -16,10 +16,6 @@
*/
package org.apache.logging.log4j.core.config;
-import java.util.HashMap;
-import java.util.Map;
-
-
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
import org.apache.logging.log4j.core.lookup.Interpolator;
import org.apache.logging.log4j.core.lookup.PropertiesLookup;
@@ -29,6 +25,9 @@ import org.apache.logging.log4j.plugins.Plugin;
import org.apache.logging.log4j.plugins.PluginElement;
import org.apache.logging.log4j.plugins.PluginFactory;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Handles properties defined in the configuration.
*/
@@ -47,15 +46,16 @@ public final class PropertiesPlugin {
@PluginFactory
public static StrLookup configureSubstitutor(@PluginElement("Properties") final Property[] properties,
@PluginConfiguration final Configuration config) {
+ final Map<String, String> map;
if (properties == null) {
- return new Interpolator(config.getProperties());
- }
- final Map<String, String> map = new HashMap<>(config.getProperties());
+ map = config.getProperties();
+ } else {
+ map = new HashMap<>(config.getProperties());
- for (final Property prop : properties) {
- map.put(prop.getName(), prop.getValue());
+ for (final Property prop : properties) {
+ map.put(prop.getName(), prop.getValue());
+ }
}
-
- return new Interpolator(new PropertiesLookup(map), config.getPluginPackages());
+ return new Interpolator(new PropertiesLookup(map), config);
}
}
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 de48103..f05fa46 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
@@ -16,20 +16,21 @@
*/
package org.apache.logging.log4j.core.lookup;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationAware;
import org.apache.logging.log4j.core.util.Constants;
-import org.apache.logging.log4j.util.ReflectionUtil;
+import org.apache.logging.log4j.plugins.di.Key;
import org.apache.logging.log4j.plugins.util.PluginManager;
import org.apache.logging.log4j.plugins.util.PluginType;
import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.ReflectionUtil;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
/**
* Proxies other {@link StrLookup}s using a keys within ${} markers.
@@ -53,19 +54,14 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
private static final Logger LOGGER = StatusLogger.getLogger();
- private static final String JMX_LOOKUP = "org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup";
private static final String JNDI_LOOKUP = "org.apache.logging.log4j.jndi.lookup.JndiLookup";
- private static final String WEB_LOOKUP = "org.apache.logging.log4j.web.WebLookup";
- private static final String DOCKER_LOOKUP = "org.apache.logging.log4j.docker.DockerLookup";
- private static final String SPRING_LOOKUP = "org.apache.logging.log4j.spring.boot.SpringLookup";
- private static final String KUBERNETES_LOOKUP = "org.apache.logging.log4j.kubernetes.KubernetesLookup";
private final Map<String, StrLookup> strLookupMap = new HashMap<>();
private final StrLookup defaultLookup;
public Interpolator(final StrLookup defaultLookup) {
- this(defaultLookup, null);
+ this(defaultLookup, List.of());
}
/**
@@ -76,7 +72,7 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
* @since 2.1
*/
public Interpolator(final StrLookup defaultLookup, final List<String> pluginPackages) {
- this.defaultLookup = defaultLookup == null ? new PropertiesLookup(new HashMap<String, String>()) : defaultLookup;
+ this.defaultLookup = defaultLookup == null ? new PropertiesLookup(Map.of()) : defaultLookup;
final PluginManager manager = new PluginManager(CATEGORY);
manager.collectPlugins(pluginPackages);
final Map<String, PluginType<?>> plugins = manager.getPlugins();
@@ -93,18 +89,35 @@ public class Interpolator extends AbstractConfigurationAwareLookup {
}
}
+ public Interpolator(final StrLookup defaultLookup, final Configuration configuration) {
+ this.defaultLookup = defaultLookup == null ? new PropertiesLookup(Map.of()) : defaultLookup;
+ final PluginManager pluginManager = configuration.getComponent(StrLookup.PLUGIN_MANAGER_KEY);
+ pluginManager.collectPlugins(configuration.getPluginPackages());
+ for (final Map.Entry<String, PluginType<?>> entry : pluginManager.getPlugins().entrySet()) {
+ try {
+ final Class<? extends StrLookup> strLookupClass = entry.getValue().getPluginClass().asSubclass(StrLookup.class);
+ // TODO: this could use @RequiredProperty on JndiLookup instead
+ if (!strLookupClass.getName().equals(JNDI_LOOKUP) || Constants.JNDI_LOOKUP_ENABLED) {
+ strLookupMap.put(entry.getKey().toLowerCase(Locale.ROOT), configuration.getComponent(Key.forClass(strLookupClass)));
+ }
+ } catch (final Throwable t) {
+ handleError(entry.getKey(), t);
+ }
+ }
+ }
+
/**
* Create the default Interpolator.
*/
public Interpolator() {
- this((Map<String, String>) null);
+ this(Map.of());
}
/**
* Creates the default Interpolator with the provided properties.
*/
public Interpolator(final Map<String, String> properties) {
- this(new PropertiesLookup(properties), Collections.emptyList());
+ this(new PropertiesLookup(properties), List.of());
}
public StrLookup getDefaultLookup() {
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 cdef668..5ef6886 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
@@ -17,6 +17,9 @@
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;
/**
* Lookup a String key to a String value.
@@ -39,6 +42,8 @@ public interface StrLookup {
*/
String CATEGORY = "Lookup";
+ Key<PluginManager> PLUGIN_MANAGER_KEY = new @Named(CATEGORY) Key<>() {};
+
/**
* Looks up a String key to a String value.
* <p>
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
index f3f182f..4cbed02 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Loader.java
@@ -16,15 +16,15 @@
*/
package org.apache.logging.log4j.core.util;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URL;
-
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.LoaderUtil;
import org.apache.logging.log4j.util.PropertiesUtil;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+
/**
* Load resources (or images) from various sources.
*/
@@ -192,19 +192,6 @@ public final class Loader {
}
/**
- * Loads and initializes a named Class using a given ClassLoader.
- *
- * @param className The class name.
- * @param loader The class loader.
- * @return The class.
- * @throws ClassNotFoundException if the class could not be found.
- */
- public static Class<?> initializeClass(final String className, final ClassLoader loader)
- throws ClassNotFoundException {
- return Class.forName(className, true, loader);
- }
-
- /**
* Loads a named Class using a given ClassLoader.
*
* @param className The class name.
@@ -270,33 +257,6 @@ public final class Loader {
}
/**
- * Loads and instantiates a class given by a property name.
- *
- * @param propertyName The property name to look up a class name for.
- * @param clazz The class to cast it to.
- * @param <T> The type to cast it to.
- * @return new instance of the class given in the property or {@code null} if the property was unset.
- * @throws ClassNotFoundException if the class isn't available to the usual ClassLoaders
- * @throws IllegalAccessException if the class can't be instantiated through a public constructor
- * @throws InstantiationException if there was an exception whilst instantiating the class
- * @throws NoSuchMethodException if there isn't a no-args constructor on the class
- * @throws InvocationTargetException if there was an exception whilst constructing the class
- * @throws ClassCastException if the constructed object isn't type compatible with {@code T}
- */
- public static <T> T newCheckedInstanceOfProperty(final String propertyName, final Class<T> clazz)
- throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException,
- IllegalAccessException {
- final String className = PropertiesUtil.getProperties().getStringProperty(propertyName);
- final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(getClassLoader());
- return LoaderUtil.newCheckedInstanceOfProperty(propertyName, clazz);
- } finally {
- Thread.currentThread().setContextClassLoader(contextClassLoader);
- }
- }
-
- /**
* Loads and instantiates a Class using the default constructor.
*
* @param clazz The class.
@@ -337,7 +297,7 @@ public final class Loader {
}
/**
- * Loads a class by name. This method respects the {@link #IGNORE_TCCL_PROPERTY} Log4j property. If this property is
+ * Loads a class by name. This method respects the {@link LoaderUtil#IGNORE_TCCL_PROPERTY} Log4j property. If this property is
* specified and set to anything besides {@code false}, then the default ClassLoader will be used.
*
* @param className The class name.
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 61552a9..e02bb09 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
@@ -16,10 +16,13 @@
*/
package org.apache.logging.log4j.core.util;
-import java.util.List;
-
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 java.util.List;
/**
* Watches for changes in a Source and performs an action when it is modified.
@@ -29,6 +32,7 @@ import org.apache.logging.log4j.core.config.Reconfigurable;
public interface Watcher {
String CATEGORY = "Watcher";
+ Key<PluginManager> PLUGIN_MANAGER_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 cd4ec28..343815c 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
@@ -16,47 +16,31 @@
*/
package org.apache.logging.log4j.core.util;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
import org.apache.logging.log4j.Logger;
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.PluginManager;
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;
+
/**
* Creates Watchers of various types.
*/
public class WatcherFactory {
private static final Logger LOGGER = StatusLogger.getLogger();
- private static final PluginManager pluginManager = new PluginManager(Watcher.CATEGORY);
-
- private static volatile WatcherFactory factory;
private final Map<String, PluginType<?>> plugins;
- private WatcherFactory(final List<String> packages) {
- pluginManager.collectPlugins(packages);
- plugins = pluginManager.getPlugins();
- }
-
- public static WatcherFactory getInstance(final List<String> packages) {
- if (factory == null) {
- synchronized (pluginManager) {
- if (factory == null) {
- factory = new WatcherFactory(packages);
- }
- }
- }
- return factory;
+ public WatcherFactory(final Map<String, PluginType<?>> watcherPlugins) {
+ plugins = watcherPlugins;
}
public Watcher newWatcher(final Source source, final Configuration configuration, final Reconfigurable reconfigurable,
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/BindingMap.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/BindingMap.java
index 1fe03a6..2a58724 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/BindingMap.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/BindingMap.java
@@ -20,6 +20,7 @@ package org.apache.logging.log4j.plugins.di;
import org.apache.logging.log4j.plugins.util.TypeUtil;
+import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
@@ -35,8 +36,17 @@ class BindingMap {
this.bindings = new ConcurrentHashMap<>(bindings.bindings);
}
- public <T> Binding<T> get(final Key<T> key) {
- return TypeUtil.cast(bindings.get(key));
+ public <T> Binding<T> get(final Key<T> key, final Collection<String> aliases) {
+ var binding = bindings.get(key);
+ if (binding == null) {
+ for (final String alias : aliases) {
+ binding = bindings.get(key.withName(alias));
+ if (binding != null) {
+ break;
+ }
+ }
+ }
+ return TypeUtil.cast(binding);
}
public <T> void put(final Key<T> key, final Supplier<T> factory) {
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 7b70c8a..51bf172 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
@@ -20,6 +20,7 @@ package org.apache.logging.log4j.plugins.di;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.plugins.FactoryType;
import org.apache.logging.log4j.plugins.Inject;
+import org.apache.logging.log4j.plugins.Named;
import org.apache.logging.log4j.plugins.Node;
import org.apache.logging.log4j.plugins.PluginException;
import org.apache.logging.log4j.plugins.QualifierType;
@@ -28,6 +29,7 @@ import org.apache.logging.log4j.plugins.Singleton;
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.PluginType;
import org.apache.logging.log4j.plugins.util.TypeUtil;
import org.apache.logging.log4j.plugins.validation.Constraint;
@@ -192,15 +194,16 @@ class DefaultInjector implements Injector {
private <T> Supplier<T> getFactory(
final Key<T> key, final Collection<String> aliases, final Node node, final Set<Key<?>> chain) {
- final Binding<T> existing = bindingMap.get(key);
+ final Binding<T> existing = bindingMap.get(key, aliases);
if (existing != null) {
return existing.getSupplier();
}
- for (final String alias : aliases) {
- final Binding<T> binding = bindingMap.get(key.withName(alias));
- if (binding != null) {
- return binding.getSupplier();
- }
+ final Class<T> rawType = key.getRawType();
+ final Scope scope = getScopeForType(rawType);
+ if (rawType == PluginManager.class && key.getQualifierType() == Named.class) {
+ final Supplier<T> factory = () -> TypeUtil.cast(new PluginManager(key.getName()));
+ bindingMap.put(key, scope.get(key, factory));
+ return bindingMap.get(key, aliases).getSupplier();
}
final Supplier<T> instanceSupplier = () -> {
final StringBuilder debugLog = new StringBuilder();
@@ -208,7 +211,6 @@ class DefaultInjector implements Injector {
injectMembers(key, node, instance, chain, debugLog);
return instance;
};
- final Scope scope = getScopeForType(key.getRawType());
return bindingMap.bindIfAbsent(key, scope.get(key, instanceSupplier));
}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java
index 6c4bfc5..8368660 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Key.java
@@ -77,6 +77,10 @@ public class Key<T> {
hashCode = Objects.hash(type, qualifierType, name.toLowerCase(Locale.ROOT));
}
+ public Type getType() {
+ return type;
+ }
+
public final Class<T> getRawType() {
return rawType;
}
@@ -85,6 +89,10 @@ public class Key<T> {
return name;
}
+ public Class<? extends Annotation> getQualifierType() {
+ return qualifierType;
+ }
+
/**
* Returns a new key using the provided name and the same type and qualifier type as this instance.
*/
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
index b87e5a1..8360515 100644
--- 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
@@ -18,15 +18,21 @@
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.*;
+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 {
/**