First commit for branch for [LOG4J2-1547] The Core AbstractConfiguration should track its LoggerContext.
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/85c5e81a Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/85c5e81a Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/85c5e81a Branch: refs/heads/LOG4J2-1010&LOG4J2-1447-injectable-contextdata&better-datastructure Commit: 85c5e81a4bca677bf02dc9be4f2dff3d1f0450c1 Parents: 24ebb9f Author: Gary Gregory <ggreg...@apache.org> Authored: Tue Aug 23 20:58:38 2016 -0700 Committer: Gary Gregory <ggreg...@apache.org> Committed: Tue Aug 23 20:58:38 2016 -0700 ---------------------------------------------------------------------- .../config/Log4j1ConfigurationFactory.java | 9 +- .../apache/log4j/BasicConfigurationFactory.java | 13 +- .../config/Log4j1ConfigurationFactoryTest.java | 4 +- .../logging/log4j/core/LoggerContext.java | 2 +- .../core/config/AbstractConfiguration.java | 14 +- .../log4j/core/config/Configuration.java | 8 + .../log4j/core/config/ConfigurationFactory.java | 1113 +++++++++--------- .../log4j/core/config/DefaultConfiguration.java | 2 +- .../log4j/core/config/NullConfiguration.java | 2 +- .../builder/api/ConfigurationBuilder.java | 8 + .../config/builder/impl/BuiltConfiguration.java | 5 +- .../impl/DefaultConfigurationBuilder.java | 29 +- .../composite/CompositeConfiguration.java | 4 +- .../core/config/json/JsonConfiguration.java | 14 +- .../config/json/JsonConfigurationFactory.java | 5 +- .../properties/PropertiesConfiguration.java | 8 +- .../PropertiesConfigurationBuilder.java | 16 +- .../PropertiesConfigurationFactory.java | 10 +- .../log4j/core/config/xml/XmlConfiguration.java | 7 +- .../config/xml/XmlConfigurationFactory.java | 5 +- .../core/config/yaml/YamlConfiguration.java | 7 +- .../config/yaml/YamlConfigurationFactory.java | 5 +- .../log4j/core/impl/Log4jContextFactory.java | 6 +- .../log4j/core/jmx/LoggerContextAdmin.java | 4 +- .../core/net/server/AbstractSocketServer.java | 7 +- .../log4j/core/BasicConfigurationFactory.java | 6 +- .../log4j/core/config/ConfigurationTest.java | 6 + .../builder/CustomConfigurationFactory.java | 11 +- .../configuration/CustomConfiguration.java | 13 +- .../CustomConfigurationFactory.java | 12 +- 30 files changed, 717 insertions(+), 638 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java index b1b2dfe..a974ed5 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/config/Log4j1ConfigurationFactory.java @@ -16,6 +16,10 @@ */ package org.apache.log4j.config; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationException; import org.apache.logging.log4j.core.config.ConfigurationFactory; @@ -23,9 +27,6 @@ import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder; import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; -import java.io.IOException; -import java.io.InputStream; - /** * Experimental ConfigurationFactory for Log4j 1.2 properties configuration files. */ @@ -39,7 +40,7 @@ public class Log4j1ConfigurationFactory extends ConfigurationFactory { private static final String[] SUFFIXES = {".properties"}; @Override - public Configuration getConfiguration(final ConfigurationSource source) { + public Configuration getConfiguration(LoggerContext loggerContext, final ConfigurationSource source) { final ConfigurationBuilder<BuiltConfiguration> builder; try (final InputStream configStream = source.getInputStream()) { builder = new Log4j1ConfigurationParser().buildConfigurationBuilder(configStream); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-1.2-api/src/test/java/org/apache/log4j/BasicConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/BasicConfigurationFactory.java b/log4j-1.2-api/src/test/java/org/apache/log4j/BasicConfigurationFactory.java index 49b2f82..aabc1c1 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/BasicConfigurationFactory.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/BasicConfigurationFactory.java @@ -19,6 +19,7 @@ package org.apache.log4j; import java.net.URI; import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.AbstractConfiguration; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; @@ -36,13 +37,13 @@ public class BasicConfigurationFactory extends ConfigurationFactory { } @Override - public Configuration getConfiguration(final ConfigurationSource source) { - return new BasicConfiguration(); + public Configuration getConfiguration(LoggerContext loggerContext, final ConfigurationSource source) { + return new BasicConfiguration(loggerContext); } @Override - public Configuration getConfiguration(final String name, final URI configLocation) { - return new BasicConfiguration(); + public Configuration getConfiguration(LoggerContext loggerContext, final String name, final URI configLocation) { + return new BasicConfiguration(loggerContext); } public class BasicConfiguration extends AbstractConfiguration { @@ -51,8 +52,8 @@ public class BasicConfigurationFactory extends ConfigurationFactory { private static final String DEFAULT_LEVEL = "org.apache.logging.log4j.level"; - public BasicConfiguration() { - super(ConfigurationSource.NULL_SOURCE); + public BasicConfiguration(final LoggerContext loggerContext) { + super(loggerContext, ConfigurationSource.NULL_SOURCE); final LoggerConfig root = getRootLogger(); setName("BasicConfiguration"); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-1.2-api/src/test/java/org/apache/log4j/config/Log4j1ConfigurationFactoryTest.java ---------------------------------------------------------------------- diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/Log4j1ConfigurationFactoryTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/Log4j1ConfigurationFactoryTest.java index 9f34563..c045415 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/Log4j1ConfigurationFactoryTest.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/Log4j1ConfigurationFactoryTest.java @@ -36,8 +36,8 @@ public class Log4j1ConfigurationFactoryTest { private Layout<?> testConsole(final String configResource) throws Exception { final URL configLocation = ClassLoader.getSystemResource(configResource); assertNotNull(configLocation); - final Configuration configuration = new Log4j1ConfigurationFactory().getConfiguration("test", - configLocation.toURI()); + final Configuration configuration = new Log4j1ConfigurationFactory().getConfiguration(null, + "test", configLocation.toURI()); assertNotNull(configuration); final ConsoleAppender appender = configuration.getAppender("Console"); assertNotNull(appender); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java index ce78615..7156b7c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java @@ -572,7 +572,7 @@ public class LoggerContext extends AbstractLifeCycle final ClassLoader cl = ClassLoader.class.isInstance(externalContext) ? (ClassLoader) externalContext : null; LOGGER.debug("Reconfiguration started for context[name={}] at URI {} ({}) with optional ClassLoader: {}", contextName, configURI, this, cl); - final Configuration instance = ConfigurationFactory.getInstance().getConfiguration(contextName, configURI, cl); + final Configuration instance = ConfigurationFactory.getInstance().getConfiguration(this, contextName, configURI, cl); if (instance == null) { LOGGER.error("Reconfiguration failed: No configuration found for '%s' at '%s' in '%s'", contextName, configURI, cl); } else { http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java ---------------------------------------------------------------------- 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 bc42d1f..64ead88 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 @@ -20,6 +20,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -39,6 +40,7 @@ import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.Layout; import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.appender.AsyncAppender; import org.apache.logging.log4j.core.appender.ConsoleAppender; import org.apache.logging.log4j.core.async.AsyncLoggerConfig; @@ -122,11 +124,14 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement private final WatchManager watchManager = new WatchManager(configurationScheduler); private AsyncLoggerConfigDisruptor asyncLoggerConfigDisruptor; private NanoClock nanoClock = new DummyNanoClock(); - + private WeakReference<LoggerContext> loggerContext; + /** * Constructor. */ - protected AbstractConfiguration(final ConfigurationSource configurationSource) { + protected AbstractConfiguration(LoggerContext loggerContext, final ConfigurationSource configurationSource) { + this.loggerContext = new WeakReference<>(loggerContext); + //this.loggerContext = new WeakReference(Objects.requireNonNull(loggerContext, "loggerContext is null")); this.configurationSource = Objects.requireNonNull(configurationSource, "configurationSource is null"); componentMap.put(Configuration.CONTEXT_PROPERTIES, properties); pluginManager = new PluginManager(Node.CATEGORY); @@ -787,6 +792,11 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement return root; } + @Override + public LoggerContext getLoggerContext() { + return loggerContext.get(); + } + /** * Returns the root Logger. * http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java index 678242c..88be74d 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configuration.java @@ -24,6 +24,7 @@ import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.async.AsyncLoggerConfigDelegate; import org.apache.logging.log4j.core.filter.Filterable; import org.apache.logging.log4j.core.lookup.StrSubstitutor; @@ -188,4 +189,11 @@ public interface Configuration extends Filterable { * @param nanoClock the new nano clock for this configuration. Must be non-null. */ void setNanoClock(NanoClock nanoClock); + + /** + * Gets the logger context. + * + * @return the logger context. + */ + LoggerContext getLoggerContext(); } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java ---------------------------------------------------------------------- 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 7452dfa..806451d 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 @@ -1,553 +1,560 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache license, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the license for the specific language governing permissions and - * limitations under the license. - */ -package org.apache.logging.log4j.core.config; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory; -import org.apache.logging.log4j.core.config.composite.CompositeConfiguration; -import org.apache.logging.log4j.core.config.plugins.util.PluginManager; -import org.apache.logging.log4j.core.config.plugins.util.PluginType; -import org.apache.logging.log4j.core.lookup.Interpolator; -import org.apache.logging.log4j.core.lookup.StrSubstitutor; -import org.apache.logging.log4j.core.util.FileUtils; -import org.apache.logging.log4j.core.util.Loader; -import org.apache.logging.log4j.core.util.NetUtils; -import org.apache.logging.log4j.core.util.ReflectionUtil; -import org.apache.logging.log4j.status.StatusLogger; -import org.apache.logging.log4j.util.LoaderUtil; -import org.apache.logging.log4j.util.PropertiesUtil; -import org.apache.logging.log4j.util.Strings; - -/** - * Factory class for parsed {@link Configuration} objects from a configuration file. - * ConfigurationFactory allows the configuration implementation to be - * dynamically chosen in 1 of 3 ways: - * <ol> - * <li>A system property named "log4j.configurationFactory" can be set with the - * name of the ConfigurationFactory to be used.</li> - * <li> - * {@linkplain #setConfigurationFactory(ConfigurationFactory)} can be called - * with the instance of the ConfigurationFactory to be used. This must be called - * before any other calls to Log4j.</li> - * <li> - * A ConfigurationFactory implementation can be added to the classpath and configured as a plugin in the - * {@link #CATEGORY ConfigurationFactory} category. The {@link Order} annotation should be used to configure the - * factory to be the first one inspected. See - * {@linkplain org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory} for an example.</li> - * </ol> - * - * If the ConfigurationFactory that was added returns null on a call to - * getConfiguration then any other ConfigurationFactories found as plugins will - * be called in their respective order. DefaultConfiguration is always called - * last if no configuration has been returned. - */ -public abstract class ConfigurationFactory extends ConfigurationBuilderFactory { - - /** - * Allows the ConfigurationFactory class to be specified as a system property. - */ - public static final String CONFIGURATION_FACTORY_PROPERTY = "log4j.configurationFactory"; - - /** - * Allows the location of the configuration file to be specified as a system property. - */ - public static final String CONFIGURATION_FILE_PROPERTY = "log4j.configurationFile"; - - /** - * Plugin category used to inject a ConfigurationFactory {@link org.apache.logging.log4j.core.config.plugins.Plugin} - * class. - * - * @since 2.1 - */ - public static final String CATEGORY = "ConfigurationFactory"; - - /** - * Allows subclasses access to the status logger without creating another instance. - */ - protected static final Logger LOGGER = StatusLogger.getLogger(); - - /** - * File name prefix for test configurations. - */ - protected static final String TEST_PREFIX = "log4j2-test"; - - /** - * File name prefix for standard configurations. - */ - protected static final String DEFAULT_PREFIX = "log4j2"; - - /** - * The name of the classloader URI scheme. - */ - private static final String CLASS_LOADER_SCHEME = "classloader"; - - /** - * The name of the classpath URI scheme, synonymous with the classloader URI scheme. - */ - private static final String CLASS_PATH_SCHEME = "classpath"; - - private static volatile List<ConfigurationFactory> factories = null; - - private static ConfigurationFactory configFactory = new Factory(); - - protected final StrSubstitutor substitutor = new StrSubstitutor(new Interpolator()); - - private static final Lock LOCK = new ReentrantLock(); - - /** - * Returns the ConfigurationFactory. - * @return the ConfigurationFactory. - */ - public static ConfigurationFactory getInstance() { - // volatile works in Java 1.6+, so double-checked locking also works properly - //noinspection DoubleCheckedLocking - if (factories == null) { - LOCK.lock(); - try { - if (factories == null) { - final List<ConfigurationFactory> list = new ArrayList<>(); - final String factoryClass = PropertiesUtil.getProperties().getStringProperty(CONFIGURATION_FACTORY_PROPERTY); - if (factoryClass != null) { - addFactory(list, factoryClass); - } - final PluginManager manager = new PluginManager(CATEGORY); - manager.collectPlugins(); - final Map<String, PluginType<?>> plugins = manager.getPlugins(); - final List<Class<? extends ConfigurationFactory>> ordered = new ArrayList<>(plugins.size()); - for (final PluginType<?> type : plugins.values()) { - try { - ordered.add(type.getPluginClass().asSubclass(ConfigurationFactory.class)); - } catch (final Exception ex) { - LOGGER.warn("Unable to add class {}", type.getPluginClass(), ex); - } - } - Collections.sort(ordered, OrderComparator.getInstance()); - for (final Class<? extends ConfigurationFactory> clazz : ordered) { - addFactory(list, clazz); - } - // see above comments about double-checked locking - //noinspection NonThreadSafeLazyInitialization - factories = Collections.unmodifiableList(list); - } - } finally { - LOCK.unlock(); - } - } - - LOGGER.debug("Using configurationFactory {}", configFactory); - return configFactory; - } - - private static void addFactory(final Collection<ConfigurationFactory> list, final String factoryClass) { - try { - addFactory(list, LoaderUtil.loadClass(factoryClass).asSubclass(ConfigurationFactory.class)); - } catch (final Exception ex) { - LOGGER.error("Unable to load class {}", factoryClass, ex); - } - } - - private static void addFactory(final Collection<ConfigurationFactory> list, - final Class<? extends ConfigurationFactory> factoryClass) { - try { - list.add(ReflectionUtil.instantiate(factoryClass)); - } catch (final Exception ex) { - LOGGER.error("Unable to create instance of {}", factoryClass.getName(), ex); - } - } - - /** - * Sets the configuration factory. This method is not intended for general use and may not be thread safe. - * @param factory the ConfigurationFactory. - */ - public static void setConfigurationFactory(final ConfigurationFactory factory) { - configFactory = factory; - } - - /** - * Resets the ConfigurationFactory to the default. This method is not intended for general use and may - * not be thread safe. - */ - public static void resetConfigurationFactory() { - configFactory = new Factory(); - } - - /** - * Removes the ConfigurationFactory. This method is not intended for general use and may not be thread safe. - * @param factory The factory to remove. - */ - public static void removeConfigurationFactory(final ConfigurationFactory factory) { - if (configFactory == factory) { - configFactory = new Factory(); - } - } - - protected abstract String[] getSupportedTypes(); - - protected boolean isActive() { - return true; - } - - public abstract Configuration getConfiguration(ConfigurationSource source); - - /** - * Returns the Configuration. - * @param name The configuration name. - * @param configLocation The configuration location. - * @return The Configuration. - */ - public Configuration getConfiguration(final String name, final URI configLocation) { - if (!isActive()) { - return null; - } - if (configLocation != null) { - final ConfigurationSource source = getInputFromUri(configLocation); - if (source != null) { - return getConfiguration(source); - } - } - return null; - } - - /** - * Returns the Configuration obtained using a given ClassLoader. - * - * @param name The configuration name. - * @param configLocation A URI representing the location of the configuration. - * @param loader The default ClassLoader to use. If this is {@code null}, then the - * {@linkplain LoaderUtil#getThreadContextClassLoader() default ClassLoader} will be used. - * @return The Configuration. - * @since 2.1 - */ - public Configuration getConfiguration(final String name, final URI configLocation, final ClassLoader loader) { - if (!isActive()) { - return null; - } - if (loader == null) { - return getConfiguration(name, configLocation); - } - if (isClassLoaderUri(configLocation)) { - final String path = extractClassLoaderUriPath(configLocation); - final ConfigurationSource source = getInputFromResource(path, loader); - if (source != null) { - final Configuration configuration = getConfiguration(source); - if (configuration != null) { - return configuration; - } - } - } - return getConfiguration(name, configLocation); - } - - /** - * Loads the configuration from a URI. - * @param configLocation A URI representing the location of the configuration. - * @return The ConfigurationSource for the configuration. - */ - protected ConfigurationSource getInputFromUri(final URI configLocation) { - final File configFile = FileUtils.fileFromUri(configLocation); - if (configFile != null && configFile.exists() && configFile.canRead()) { - try { - return new ConfigurationSource(new FileInputStream(configFile), configFile); - } catch (final FileNotFoundException ex) { - LOGGER.error("Cannot locate file {}", configLocation.getPath(), ex); - } - } - if (isClassLoaderUri(configLocation)) { - final ClassLoader loader = LoaderUtil.getThreadContextClassLoader(); - final String path = extractClassLoaderUriPath(configLocation); - final ConfigurationSource source = getInputFromResource(path, loader); - if (source != null) { - return source; - } - } - if (!configLocation.isAbsolute()) { // LOG4J2-704 avoid confusing error message thrown by uri.toURL() - LOGGER.error("File not found in file system or classpath: {}", configLocation.toString()); - return null; - } - try { - return new ConfigurationSource(configLocation.toURL().openStream(), configLocation.toURL()); - } catch (final MalformedURLException ex) { - LOGGER.error("Invalid URL {}", configLocation.toString(), ex); - } catch (final Exception ex) { - LOGGER.error("Unable to access {}", configLocation.toString(), ex); - } - return null; - } - - private static boolean isClassLoaderUri(final URI uri) { - if (uri == null) { - return false; - } - final String scheme = uri.getScheme(); - return scheme == null || scheme.equals(CLASS_LOADER_SCHEME) || scheme.equals(CLASS_PATH_SCHEME); - } - - private static String extractClassLoaderUriPath(final URI uri) { - return uri.getScheme() == null ? uri.getPath() : uri.getSchemeSpecificPart(); - } - - /** - * Loads the configuration from the location represented by the String. - * @param config The configuration location. - * @param loader The default ClassLoader to use. - * @return The InputSource to use to read the configuration. - */ - protected ConfigurationSource getInputFromString(final String config, final ClassLoader loader) { - try { - final URL url = new URL(config); - return new ConfigurationSource(url.openStream(), FileUtils.fileFromUri(url.toURI())); - } catch (final Exception ex) { - final ConfigurationSource source = getInputFromResource(config, loader); - if (source == null) { - try { - final File file = new File(config); - return new ConfigurationSource(new FileInputStream(file), file); - } catch (final FileNotFoundException fnfe) { - // Ignore the exception - LOGGER.catching(Level.DEBUG, fnfe); - } - } - return source; - } - } - - /** - * Retrieves the configuration via the ClassLoader. - * @param resource The resource to load. - * @param loader The default ClassLoader to use. - * @return The ConfigurationSource for the configuration. - */ - protected ConfigurationSource getInputFromResource(final String resource, final ClassLoader loader) { - final URL url = Loader.getResource(resource, loader); - if (url == null) { - return null; - } - InputStream is = null; - try { - is = url.openStream(); - } catch (final IOException ioe) { - LOGGER.catching(Level.DEBUG, ioe); - return null; - } - if (is == null) { - return null; - } - - if (FileUtils.isFile(url)) { - try { - return new ConfigurationSource(is, FileUtils.fileFromUri(url.toURI())); - } catch (final URISyntaxException ex) { - // Just ignore the exception. - LOGGER.catching(Level.DEBUG, ex); - } - } - return new ConfigurationSource(is, url); - } - - /** - * Default Factory. - */ - private static class Factory extends ConfigurationFactory { - - private static final String ALL_TYPES = "*"; - - /** - * Default Factory Constructor. - * @param name The configuration name. - * @param configLocation The configuration location. - * @return The Configuration. - */ - @Override - public Configuration getConfiguration(final String name, final URI configLocation) { - - if (configLocation == null) { - final String configLocationStr = this.substitutor.replace(PropertiesUtil.getProperties() - .getStringProperty(CONFIGURATION_FILE_PROPERTY)); - if (configLocationStr != null) { - final String[] sources = configLocationStr.split(","); - if (sources.length > 1) { - final List<AbstractConfiguration> configs = new ArrayList<>(); - for (final String sourceLocation : sources) { - final Configuration config = getConfiguration(sourceLocation.trim()); - if (config != null && config instanceof AbstractConfiguration) { - configs.add((AbstractConfiguration) config); - } else { - LOGGER.error("Failed to created configuration at {}", sourceLocation); - return null; - } - } - return new CompositeConfiguration(configs); - } - return getConfiguration(configLocationStr); - } - for (final ConfigurationFactory factory : getFactories()) { - final String[] types = factory.getSupportedTypes(); - if (types != null) { - for (final String type : types) { - if (type.equals(ALL_TYPES)) { - final Configuration config = factory.getConfiguration(name, configLocation); - if (config != null) { - return config; - } - } - } - } - } - } else { - // configLocation != null - final String configLocationStr = configLocation.toString(); - for (final ConfigurationFactory factory : getFactories()) { - final String[] types = factory.getSupportedTypes(); - if (types != null) { - for (final String type : types) { - if (type.equals(ALL_TYPES) || configLocationStr.endsWith(type)) { - final Configuration config = factory.getConfiguration(name, configLocation); - if (config != null) { - return config; - } - } - } - } - } - } - - Configuration config = getConfiguration(true, name); - if (config == null) { - config = getConfiguration(true, null); - if (config == null) { - config = getConfiguration(false, name); - if (config == null) { - config = getConfiguration(false, null); - } - } - } - if (config != null) { - return config; - } - LOGGER.error("No log4j2 configuration file found. Using default configuration: logging only errors to the console."); - return new DefaultConfiguration(); - } - - private Configuration getConfiguration(final String configLocationStr) { - ConfigurationSource source = null; - try { - source = getInputFromUri(NetUtils.toURI(configLocationStr)); - } catch (final Exception ex) { - // Ignore the error and try as a String. - LOGGER.catching(Level.DEBUG, ex); - } - if (source == null) { - final ClassLoader loader = LoaderUtil.getThreadContextClassLoader(); - source = getInputFromString(configLocationStr, loader); - } - if (source != null) { - for (final ConfigurationFactory factory : getFactories()) { - final String[] types = factory.getSupportedTypes(); - if (types != null) { - for (final String type : types) { - if (type.equals(ALL_TYPES) || configLocationStr.endsWith(type)) { - final Configuration config = factory.getConfiguration(source); - if (config != null) { - return config; - } - } - } - } - } - } - return null; - } - - private Configuration getConfiguration(final boolean isTest, final String name) { - final boolean named = Strings.isNotEmpty(name); - final ClassLoader loader = LoaderUtil.getThreadContextClassLoader(); - for (final ConfigurationFactory factory : getFactories()) { - String configName; - final String prefix = isTest ? TEST_PREFIX : DEFAULT_PREFIX; - final String [] types = factory.getSupportedTypes(); - if (types == null) { - continue; - } - - for (final String suffix : types) { - if (suffix.equals(ALL_TYPES)) { - continue; - } - configName = named ? prefix + name + suffix : prefix + suffix; - - final ConfigurationSource source = getInputFromResource(configName, loader); - if (source != null) { - return factory.getConfiguration(source); - } - } - } - return null; - } - - @Override - public String[] getSupportedTypes() { - return null; - } - - @Override - public Configuration getConfiguration(final ConfigurationSource source) { - if (source != null) { - final String config = source.getLocation(); - for (final ConfigurationFactory factory : getFactories()) { - final String[] types = factory.getSupportedTypes(); - if (types != null) { - for (final String type : types) { - if (type.equals(ALL_TYPES) || config != null && config.endsWith(type)) { - final Configuration c = factory.getConfiguration(source); - if (c != null) { - LOGGER.debug("Loaded configuration from {}", source); - return c; - } - LOGGER.error("Cannot determine the ConfigurationFactory to use for {}", config); - return null; - } - } - } - } - } - LOGGER.error("Cannot process configuration, input source is null"); - return null; - } - } - - static List<ConfigurationFactory> getFactories() { - return factories; - } -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache license, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license for the specific language governing permissions and + * limitations under the license. + */ +package org.apache.logging.log4j.core.config; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory; +import org.apache.logging.log4j.core.config.composite.CompositeConfiguration; +import org.apache.logging.log4j.core.config.plugins.util.PluginManager; +import org.apache.logging.log4j.core.config.plugins.util.PluginType; +import org.apache.logging.log4j.core.lookup.Interpolator; +import org.apache.logging.log4j.core.lookup.StrSubstitutor; +import org.apache.logging.log4j.core.util.FileUtils; +import org.apache.logging.log4j.core.util.Loader; +import org.apache.logging.log4j.core.util.NetUtils; +import org.apache.logging.log4j.core.util.ReflectionUtil; +import org.apache.logging.log4j.status.StatusLogger; +import org.apache.logging.log4j.util.LoaderUtil; +import org.apache.logging.log4j.util.PropertiesUtil; +import org.apache.logging.log4j.util.Strings; + +/** + * Factory class for parsed {@link Configuration} objects from a configuration file. + * ConfigurationFactory allows the configuration implementation to be + * dynamically chosen in 1 of 3 ways: + * <ol> + * <li>A system property named "log4j.configurationFactory" can be set with the + * name of the ConfigurationFactory to be used.</li> + * <li> + * {@linkplain #setConfigurationFactory(ConfigurationFactory)} can be called + * with the instance of the ConfigurationFactory to be used. This must be called + * before any other calls to Log4j.</li> + * <li> + * A ConfigurationFactory implementation can be added to the classpath and configured as a plugin in the + * {@link #CATEGORY ConfigurationFactory} category. The {@link Order} annotation should be used to configure the + * factory to be the first one inspected. See + * {@linkplain org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory} for an example.</li> + * </ol> + * + * If the ConfigurationFactory that was added returns null on a call to + * getConfiguration then any other ConfigurationFactories found as plugins will + * be called in their respective order. DefaultConfiguration is always called + * last if no configuration has been returned. + */ +public abstract class ConfigurationFactory extends ConfigurationBuilderFactory { + + public ConfigurationFactory() { + super(); + // TEMP For breakpoints + } + + /** + * Allows the ConfigurationFactory class to be specified as a system property. + */ + public static final String CONFIGURATION_FACTORY_PROPERTY = "log4j.configurationFactory"; + + /** + * Allows the location of the configuration file to be specified as a system property. + */ + public static final String CONFIGURATION_FILE_PROPERTY = "log4j.configurationFile"; + + /** + * Plugin category used to inject a ConfigurationFactory {@link org.apache.logging.log4j.core.config.plugins.Plugin} + * class. + * + * @since 2.1 + */ + public static final String CATEGORY = "ConfigurationFactory"; + + /** + * Allows subclasses access to the status logger without creating another instance. + */ + protected static final Logger LOGGER = StatusLogger.getLogger(); + + /** + * File name prefix for test configurations. + */ + protected static final String TEST_PREFIX = "log4j2-test"; + + /** + * File name prefix for standard configurations. + */ + protected static final String DEFAULT_PREFIX = "log4j2"; + + /** + * The name of the classloader URI scheme. + */ + private static final String CLASS_LOADER_SCHEME = "classloader"; + + /** + * The name of the classpath URI scheme, synonymous with the classloader URI scheme. + */ + private static final String CLASS_PATH_SCHEME = "classpath"; + + private static volatile List<ConfigurationFactory> factories = null; + + private static ConfigurationFactory configFactory = new Factory(); + + protected final StrSubstitutor substitutor = new StrSubstitutor(new Interpolator()); + + private static final Lock LOCK = new ReentrantLock(); + + /** + * Returns the ConfigurationFactory. + * @return the ConfigurationFactory. + */ + public static ConfigurationFactory getInstance() { + // volatile works in Java 1.6+, so double-checked locking also works properly + //noinspection DoubleCheckedLocking + if (factories == null) { + LOCK.lock(); + try { + if (factories == null) { + final List<ConfigurationFactory> list = new ArrayList<>(); + final String factoryClass = PropertiesUtil.getProperties().getStringProperty(CONFIGURATION_FACTORY_PROPERTY); + if (factoryClass != null) { + addFactory(list, factoryClass); + } + final PluginManager manager = new PluginManager(CATEGORY); + manager.collectPlugins(); + final Map<String, PluginType<?>> plugins = manager.getPlugins(); + final List<Class<? extends ConfigurationFactory>> ordered = new ArrayList<>(plugins.size()); + for (final PluginType<?> type : plugins.values()) { + try { + ordered.add(type.getPluginClass().asSubclass(ConfigurationFactory.class)); + } catch (final Exception ex) { + LOGGER.warn("Unable to add class {}", type.getPluginClass(), ex); + } + } + Collections.sort(ordered, OrderComparator.getInstance()); + for (final Class<? extends ConfigurationFactory> clazz : ordered) { + addFactory(list, clazz); + } + // see above comments about double-checked locking + //noinspection NonThreadSafeLazyInitialization + factories = Collections.unmodifiableList(list); + } + } finally { + LOCK.unlock(); + } + } + + LOGGER.debug("Using configurationFactory {}", configFactory); + return configFactory; + } + + private static void addFactory(final Collection<ConfigurationFactory> list, final String factoryClass) { + try { + addFactory(list, LoaderUtil.loadClass(factoryClass).asSubclass(ConfigurationFactory.class)); + } catch (final Exception ex) { + LOGGER.error("Unable to load class {}", factoryClass, ex); + } + } + + private static void addFactory(final Collection<ConfigurationFactory> list, + final Class<? extends ConfigurationFactory> factoryClass) { + try { + list.add(ReflectionUtil.instantiate(factoryClass)); + } catch (final Exception ex) { + LOGGER.error("Unable to create instance of {}", factoryClass.getName(), ex); + } + } + + /** + * Sets the configuration factory. This method is not intended for general use and may not be thread safe. + * @param factory the ConfigurationFactory. + */ + public static void setConfigurationFactory(final ConfigurationFactory factory) { + configFactory = factory; + } + + /** + * Resets the ConfigurationFactory to the default. This method is not intended for general use and may + * not be thread safe. + */ + public static void resetConfigurationFactory() { + configFactory = new Factory(); + } + + /** + * Removes the ConfigurationFactory. This method is not intended for general use and may not be thread safe. + * @param factory The factory to remove. + */ + public static void removeConfigurationFactory(final ConfigurationFactory factory) { + if (configFactory == factory) { + configFactory = new Factory(); + } + } + + protected abstract String[] getSupportedTypes(); + + protected boolean isActive() { + return true; + } + + public abstract Configuration getConfiguration(LoggerContext loggerContext, ConfigurationSource source); + + /** + * Returns the Configuration. + * @param loggerContext The logger context + * @param name The configuration name. + * @param configLocation The configuration location. + * @return The Configuration. + */ + public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) { + if (!isActive()) { + return null; + } + if (configLocation != null) { + final ConfigurationSource source = getInputFromUri(configLocation); + if (source != null) { + return getConfiguration(loggerContext, source); + } + } + return null; + } + + /** + * Returns the Configuration obtained using a given ClassLoader. + * @param loggerContext TODO + * @param name The configuration name. + * @param configLocation A URI representing the location of the configuration. + * @param loader The default ClassLoader to use. If this is {@code null}, then the + * {@linkplain LoaderUtil#getThreadContextClassLoader() default ClassLoader} will be used. + * + * @return The Configuration. + */ + public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation, final ClassLoader loader) { + if (!isActive()) { + return null; + } + if (loader == null) { + return getConfiguration(loggerContext, name, configLocation); + } + if (isClassLoaderUri(configLocation)) { + final String path = extractClassLoaderUriPath(configLocation); + final ConfigurationSource source = getInputFromResource(path, loader); + if (source != null) { + final Configuration configuration = getConfiguration(loggerContext, source); + if (configuration != null) { + return configuration; + } + } + } + return getConfiguration(loggerContext, name, configLocation); + } + + /** + * Loads the configuration from a URI. + * @param configLocation A URI representing the location of the configuration. + * @return The ConfigurationSource for the configuration. + */ + protected ConfigurationSource getInputFromUri(final URI configLocation) { + final File configFile = FileUtils.fileFromUri(configLocation); + if (configFile != null && configFile.exists() && configFile.canRead()) { + try { + return new ConfigurationSource(new FileInputStream(configFile), configFile); + } catch (final FileNotFoundException ex) { + LOGGER.error("Cannot locate file {}", configLocation.getPath(), ex); + } + } + if (isClassLoaderUri(configLocation)) { + final ClassLoader loader = LoaderUtil.getThreadContextClassLoader(); + final String path = extractClassLoaderUriPath(configLocation); + final ConfigurationSource source = getInputFromResource(path, loader); + if (source != null) { + return source; + } + } + if (!configLocation.isAbsolute()) { // LOG4J2-704 avoid confusing error message thrown by uri.toURL() + LOGGER.error("File not found in file system or classpath: {}", configLocation.toString()); + return null; + } + try { + return new ConfigurationSource(configLocation.toURL().openStream(), configLocation.toURL()); + } catch (final MalformedURLException ex) { + LOGGER.error("Invalid URL {}", configLocation.toString(), ex); + } catch (final Exception ex) { + LOGGER.error("Unable to access {}", configLocation.toString(), ex); + } + return null; + } + + private static boolean isClassLoaderUri(final URI uri) { + if (uri == null) { + return false; + } + final String scheme = uri.getScheme(); + return scheme == null || scheme.equals(CLASS_LOADER_SCHEME) || scheme.equals(CLASS_PATH_SCHEME); + } + + private static String extractClassLoaderUriPath(final URI uri) { + return uri.getScheme() == null ? uri.getPath() : uri.getSchemeSpecificPart(); + } + + /** + * Loads the configuration from the location represented by the String. + * @param config The configuration location. + * @param loader The default ClassLoader to use. + * @return The InputSource to use to read the configuration. + */ + protected ConfigurationSource getInputFromString(final String config, final ClassLoader loader) { + try { + final URL url = new URL(config); + return new ConfigurationSource(url.openStream(), FileUtils.fileFromUri(url.toURI())); + } catch (final Exception ex) { + final ConfigurationSource source = getInputFromResource(config, loader); + if (source == null) { + try { + final File file = new File(config); + return new ConfigurationSource(new FileInputStream(file), file); + } catch (final FileNotFoundException fnfe) { + // Ignore the exception + LOGGER.catching(Level.DEBUG, fnfe); + } + } + return source; + } + } + + /** + * Retrieves the configuration via the ClassLoader. + * @param resource The resource to load. + * @param loader The default ClassLoader to use. + * @return The ConfigurationSource for the configuration. + */ + protected ConfigurationSource getInputFromResource(final String resource, final ClassLoader loader) { + final URL url = Loader.getResource(resource, loader); + if (url == null) { + return null; + } + InputStream is = null; + try { + is = url.openStream(); + } catch (final IOException ioe) { + LOGGER.catching(Level.DEBUG, ioe); + return null; + } + if (is == null) { + return null; + } + + if (FileUtils.isFile(url)) { + try { + return new ConfigurationSource(is, FileUtils.fileFromUri(url.toURI())); + } catch (final URISyntaxException ex) { + // Just ignore the exception. + LOGGER.catching(Level.DEBUG, ex); + } + } + return new ConfigurationSource(is, url); + } + + /** + * Default Factory. + */ + private static class Factory extends ConfigurationFactory { + + private static final String ALL_TYPES = "*"; + + /** + * Default Factory Constructor. + * @param name The configuration name. + * @param configLocation The configuration location. + * @return The Configuration. + */ + @Override + public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) { + + if (configLocation == null) { + final String configLocationStr = this.substitutor.replace(PropertiesUtil.getProperties() + .getStringProperty(CONFIGURATION_FILE_PROPERTY)); + if (configLocationStr != null) { + final String[] sources = configLocationStr.split(","); + if (sources.length > 1) { + final List<AbstractConfiguration> configs = new ArrayList<>(); + for (final String sourceLocation : sources) { + final Configuration config = getConfiguration(loggerContext, sourceLocation.trim()); + if (config != null && config instanceof AbstractConfiguration) { + configs.add((AbstractConfiguration) config); + } else { + LOGGER.error("Failed to created configuration at {}", sourceLocation); + return null; + } + } + return new CompositeConfiguration(configs); + } + return getConfiguration(loggerContext, configLocationStr); + } + for (final ConfigurationFactory factory : getFactories()) { + final String[] types = factory.getSupportedTypes(); + if (types != null) { + for (final String type : types) { + if (type.equals(ALL_TYPES)) { + final Configuration config = factory.getConfiguration(loggerContext, name, configLocation); + if (config != null) { + return config; + } + } + } + } + } + } else { + // configLocation != null + final String configLocationStr = configLocation.toString(); + for (final ConfigurationFactory factory : getFactories()) { + final String[] types = factory.getSupportedTypes(); + if (types != null) { + for (final String type : types) { + if (type.equals(ALL_TYPES) || configLocationStr.endsWith(type)) { + final Configuration config = factory.getConfiguration(loggerContext, name, configLocation); + if (config != null) { + return config; + } + } + } + } + } + } + + Configuration config = getConfiguration(loggerContext, true, name); + if (config == null) { + config = getConfiguration(loggerContext, true, null); + if (config == null) { + config = getConfiguration(loggerContext, false, name); + if (config == null) { + config = getConfiguration(loggerContext, false, null); + } + } + } + if (config != null) { + return config; + } + LOGGER.error("No log4j2 configuration file found. Using default configuration: logging only errors to the console."); + return new DefaultConfiguration(); + } + + private Configuration getConfiguration(final LoggerContext loggerContext, final String configLocationStr) { + ConfigurationSource source = null; + try { + source = getInputFromUri(NetUtils.toURI(configLocationStr)); + } catch (final Exception ex) { + // Ignore the error and try as a String. + LOGGER.catching(Level.DEBUG, ex); + } + if (source == null) { + final ClassLoader loader = LoaderUtil.getThreadContextClassLoader(); + source = getInputFromString(configLocationStr, loader); + } + if (source != null) { + for (final ConfigurationFactory factory : getFactories()) { + final String[] types = factory.getSupportedTypes(); + if (types != null) { + for (final String type : types) { + if (type.equals(ALL_TYPES) || configLocationStr.endsWith(type)) { + final Configuration config = factory.getConfiguration(loggerContext, source); + if (config != null) { + return config; + } + } + } + } + } + } + return null; + } + + private Configuration getConfiguration(final LoggerContext loggerContext, final boolean isTest, final String name) { + final boolean named = Strings.isNotEmpty(name); + final ClassLoader loader = LoaderUtil.getThreadContextClassLoader(); + for (final ConfigurationFactory factory : getFactories()) { + String configName; + final String prefix = isTest ? TEST_PREFIX : DEFAULT_PREFIX; + final String [] types = factory.getSupportedTypes(); + if (types == null) { + continue; + } + + for (final String suffix : types) { + if (suffix.equals(ALL_TYPES)) { + continue; + } + configName = named ? prefix + name + suffix : prefix + suffix; + + final ConfigurationSource source = getInputFromResource(configName, loader); + if (source != null) { + return factory.getConfiguration(loggerContext, source); + } + } + } + return null; + } + + @Override + public String[] getSupportedTypes() { + return null; + } + + @Override + public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) { + if (source != null) { + final String config = source.getLocation(); + for (final ConfigurationFactory factory : getFactories()) { + final String[] types = factory.getSupportedTypes(); + if (types != null) { + for (final String type : types) { + if (type.equals(ALL_TYPES) || config != null && config.endsWith(type)) { + final Configuration c = factory.getConfiguration(loggerContext, source); + if (c != null) { + LOGGER.debug("Loaded configuration from {}", source); + return c; + } + LOGGER.error("Cannot determine the ConfigurationFactory to use for {}", config); + return null; + } + } + } + } + } + LOGGER.error("Cannot process configuration, input source is null"); + return null; + } + } + + static List<ConfigurationFactory> getFactories() { + return factories; + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfiguration.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfiguration.java index e186c44..cbedf7c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfiguration.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/DefaultConfiguration.java @@ -43,7 +43,7 @@ public class DefaultConfiguration extends AbstractConfiguration { * Constructor to create the default configuration. */ public DefaultConfiguration() { - super(ConfigurationSource.NULL_SOURCE); + super(null, ConfigurationSource.NULL_SOURCE); setToDefault(); } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/NullConfiguration.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/NullConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/NullConfiguration.java index 9b04b50..db6f779 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/NullConfiguration.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/NullConfiguration.java @@ -29,7 +29,7 @@ public class NullConfiguration extends AbstractConfiguration { public static final String NULL_NAME = "Null"; public NullConfiguration() { - super(ConfigurationSource.NULL_SOURCE); + super(null, ConfigurationSource.NULL_SOURCE); setName(NULL_NAME); final LoggerConfig root = getRootLogger(); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java index 1fbfa01..0cc9ae8 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java @@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.config.builder.api; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.util.Builder; @@ -391,6 +392,12 @@ public interface ConfigurationBuilder<T extends Configuration> extends Builder<T ConfigurationBuilder<T> setDestination(String destination); /** + * Sets the logger context. + * @param loggerContext the logger context. + */ + void setLoggerContext(LoggerContext loggerContext); + + /** * Add the properties for the root node. * @param key The property key. * @param value The property value. @@ -405,4 +412,5 @@ public interface ConfigurationBuilder<T extends Configuration> extends Builder<T * @return The constructed Configuration. */ T build(boolean initialize); + } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/BuiltConfiguration.java ---------------------------------------------------------------------- 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 029caf2..ca35d12 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 @@ -22,6 +22,7 @@ import java.io.InputStream; import java.util.Arrays; import java.util.List; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.AbstractConfiguration; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.ConfiguratonFileWatcher; @@ -53,8 +54,8 @@ public class BuiltConfiguration extends AbstractConfiguration { private Component scriptsComponent; private String contentType = "text"; - public BuiltConfiguration(final ConfigurationSource source, final Component rootComponent) { - super(source); + public BuiltConfiguration(LoggerContext loggerContext, final ConfigurationSource source, final Component rootComponent) { + super(loggerContext, source); statusConfig = new StatusConfiguration().withVerboseClasses(VERBOSE_CLASSES).withStatus(getDefaultStatus()); for (final Component component : rootComponent.getComponents()) { switch (component.getPluginType()) { http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java index b455100..000da5d 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java @@ -21,6 +21,7 @@ import java.util.List; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationException; import org.apache.logging.log4j.core.config.ConfigurationSource; @@ -53,15 +54,15 @@ public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implement private Component scripts; private final Class<T> clazz; private ConfigurationSource source; - private int monitorInterval = 0; - private Level level = null; - private String verbosity = null; - private String destination = null; - private String packages = null; - private String shutdownFlag = null; - private String advertiser = null; - - private String name = null; + private int monitorInterval; + private Level level; + private String verbosity; + private String destination; + private String packages; + private String shutdownFlag; + private String advertiser; + private LoggerContext loggerContext; + private String name; @SuppressWarnings("unchecked") public DefaultConfigurationBuilder() { @@ -152,8 +153,8 @@ public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implement if (source == null) { source = ConfigurationSource.NULL_SOURCE; } - final Constructor<T> constructor = clazz.getConstructor(ConfigurationSource.class, Component.class); - configuration = constructor.newInstance(source, root); + final Constructor<T> constructor = clazz.getConstructor(LoggerContext.class, ConfigurationSource.class, Component.class); + configuration = constructor.newInstance(loggerContext, source, root); configuration.setMonitorInterval(monitorInterval); configuration.getRootNode().getAttributes().putAll(root.getAttributes()); if (name != null) { @@ -400,8 +401,14 @@ public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implement } @Override + public void setLoggerContext(LoggerContext loggerContext) { + this.loggerContext = loggerContext; + } + + @Override public ConfigurationBuilder<T> addRootProperty(final String key, final String value) { root.getAttributes().put(key, value); return this; } + } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java ---------------------------------------------------------------------- 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 f272fc1..a1f1557 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 @@ -62,7 +62,7 @@ public class CompositeConfiguration extends AbstractConfiguration implements Rec * @param configurations The List of Configurations to merge. */ public CompositeConfiguration(final List<? extends AbstractConfiguration> configurations) { - super(ConfigurationSource.NULL_SOURCE); + super(null, ConfigurationSource.NULL_SOURCE); rootNode = configurations.get(0).getRootNode(); this.configurations = configurations; final String mergeStrategyClassName = PropertiesUtil.getProperties().getStringProperty(MERGE_STRATEGY_PROPERTY, @@ -152,7 +152,7 @@ public class CompositeConfiguration extends AbstractConfiguration implements Rec if (sourceURI != null) { LOGGER.warn("Unable to determine URI for configuration {}, changes to it will be ignored", config.getName()); - currentConfig = factory.getConfiguration(config.getName(), sourceURI); + currentConfig = factory.getConfiguration(getLoggerContext(), config.getName(), sourceURI); if (currentConfig == null) { LOGGER.warn("Unable to reload configuration {}, changes to it will be ignored", config.getName()); currentConfig = config; http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfiguration.java ---------------------------------------------------------------------- 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 427fa6d..0d87268 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 @@ -26,9 +26,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.AbstractConfiguration; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationSource; @@ -42,6 +40,10 @@ import org.apache.logging.log4j.core.config.status.StatusConfiguration; import org.apache.logging.log4j.core.util.FileWatcher; import org.apache.logging.log4j.core.util.Patterns; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + /** * Creates a Node hierarchy from a JSON file. */ @@ -51,8 +53,8 @@ public class JsonConfiguration extends AbstractConfiguration implements Reconfig private final List<Status> status = new ArrayList<>(); private JsonNode root; - public JsonConfiguration(final ConfigurationSource configSource) { - super(configSource); + public JsonConfiguration(final LoggerContext loggerContext, final ConfigurationSource configSource) { + super(loggerContext, configSource); final File configFile = configSource.getFile(); byte[] buffer; try { @@ -140,7 +142,7 @@ public class JsonConfiguration extends AbstractConfiguration implements Reconfig if (source == null) { return null; } - return new JsonConfiguration(source); + return new JsonConfiguration(getLoggerContext(), source); } catch (final IOException ex) { LOGGER.error("Cannot locate file {}", getConfigurationSource(), ex); } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java index 7b45cf9..d802e0e 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java @@ -16,6 +16,7 @@ */ package org.apache.logging.log4j.core.config.json; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; @@ -60,11 +61,11 @@ public class JsonConfigurationFactory extends ConfigurationFactory { } @Override - public Configuration getConfiguration(final ConfigurationSource source) { + public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) { if (!isActive) { return null; } - return new JsonConfiguration(source); + return new JsonConfiguration(loggerContext, source); } @Override http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java index a5eaae9..b89b30c 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java @@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.config.properties; import java.io.IOException; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Reconfigurable; @@ -30,8 +31,9 @@ import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; */ public class PropertiesConfiguration extends BuiltConfiguration implements Reconfigurable { - public PropertiesConfiguration(final ConfigurationSource source, final Component root) { - super(source, root); + // ctor is called through reflection. + public PropertiesConfiguration(LoggerContext loggerContext, final ConfigurationSource source, final Component root) { + super(loggerContext, source, root); } @Override @@ -42,7 +44,7 @@ public class PropertiesConfiguration extends BuiltConfiguration implements Recon return null; } final PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory(); - final PropertiesConfiguration config = factory.getConfiguration(source); + final PropertiesConfiguration config = factory.getConfiguration(getLoggerContext(), source); return config == null || config.getState() != State.INITIALIZING ? null : config; } catch (final IOException ex) { LOGGER.error("Cannot locate file {}: {}", getConfigurationSource(), ex); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java index d9245ad..9a676a0 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Properties; import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.ConfigurationException; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.LoggerConfig; @@ -61,6 +62,7 @@ public class PropertiesConfigurationBuilder extends ConfigurationBuilderFactory private static final String CONFIG_TYPE = "type"; private final ConfigurationBuilder<PropertiesConfiguration> builder; + private LoggerContext loggerContext; private Properties rootProperties; public PropertiesConfigurationBuilder() { @@ -79,7 +81,6 @@ public class PropertiesConfigurationBuilder extends ConfigurationBuilderFactory @Override public PropertiesConfiguration build() { - final Map<String, String> rootProps = new HashMap<>(); for (final String key : rootProperties.stringPropertyNames()) { if (!key.contains(".")) { builder.addRootProperty(key, rootProperties.getProperty(key)); @@ -179,7 +180,9 @@ public class PropertiesConfigurationBuilder extends ConfigurationBuilderFactory if (props.size() > 0) { builder.add(createRootLogger(props)); } - + + builder.setLoggerContext(loggerContext); + return builder.build(false); } @@ -366,4 +369,13 @@ public class PropertiesConfigurationBuilder extends ConfigurationBuilderFactory } return loggerBuilder; } + + public PropertiesConfigurationBuilder setLoggerContext(LoggerContext loggerContext) { + this.loggerContext = loggerContext; + return this; + } + + public LoggerContext getLoggerContext() { + return loggerContext; + } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationFactory.java index 1098e8f..2263267 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationFactory.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Properties; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.ConfigurationException; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; @@ -41,14 +42,17 @@ public class PropertiesConfigurationFactory extends ConfigurationFactory { } @Override - public PropertiesConfiguration getConfiguration(final ConfigurationSource source) { + public PropertiesConfiguration getConfiguration(LoggerContext loggerContext, final ConfigurationSource source) { final Properties properties = new Properties(); try (final InputStream configStream = source.getInputStream()) { properties.load(configStream); } catch (final IOException ioe) { throw new ConfigurationException("Unable to load " + source.toString(), ioe); } - return new PropertiesConfigurationBuilder().setConfigurationSource(source) - .setRootProperties(properties).build(); + return new PropertiesConfigurationBuilder() + .setConfigurationSource(source) + .setRootProperties(properties) + .setLoggerContext(loggerContext) + .build(); } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfiguration.java ---------------------------------------------------------------------- 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 799a49e..2608552 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 @@ -35,6 +35,7 @@ import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.AbstractConfiguration; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationSource; @@ -75,8 +76,8 @@ public class XmlConfiguration extends AbstractConfiguration implements Reconfigu private boolean strict; private String schemaResource; - public XmlConfiguration(final ConfigurationSource configSource) { - super(configSource); + public XmlConfiguration(final LoggerContext loggerContext, final ConfigurationSource configSource) { + super(loggerContext, configSource); final File configFile = configSource.getFile(); byte[] buffer = null; @@ -255,7 +256,7 @@ public class XmlConfiguration extends AbstractConfiguration implements Reconfigu if (source == null) { return null; } - final XmlConfiguration config = new XmlConfiguration(source); + final XmlConfiguration config = new XmlConfiguration(getLoggerContext(), source); return config.rootElement == null ? null : config; } catch (final IOException ex) { LOGGER.error("Cannot locate file {}", getConfigurationSource(), ex); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/85c5e81a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java index 1c3e919..9de84aa 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java @@ -16,6 +16,7 @@ */ package org.apache.logging.log4j.core.config.xml; +import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; @@ -40,8 +41,8 @@ public class XmlConfigurationFactory extends ConfigurationFactory { * @return The Configuration. */ @Override - public Configuration getConfiguration(final ConfigurationSource source) { - return new XmlConfiguration(source); + public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) { + return new XmlConfiguration(loggerContext, source); } /**