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 <[email protected]> AuthorDate: Mon Mar 21 18:52:17 2022 -0500 Refactor PluginManager usage to utilise Injector Signed-off-by: Matt Sicker <[email protected]> --- .../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 { /**
