Repository: logging-log4j2 Updated Branches: refs/heads/master 2d16d346d -> 988ed5093
LOG4J2-494 working CompositeConfiguration Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/bb64f457 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/bb64f457 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/bb64f457 Branch: refs/heads/master Commit: bb64f457730864b70e3b932c2156c5522245d909 Parents: 4195c7b Author: Ralph Goers <[email protected]> Authored: Sat Apr 23 23:29:57 2016 -0700 Committer: Ralph Goers <[email protected]> Committed: Sat Apr 23 23:29:57 2016 -0700 ---------------------------------------------------------------------- .../apache/logging/log4j/util/LoaderUtil.java | 8 +- log4j-core/${filename} | 0 .../core/config/AbstractConfiguration.java | 26 +- .../log4j/core/config/ConfigurationFactory.java | 66 +++-- .../log4j/core/config/ConfigurationSource.java | 51 +++- .../core/config/ConfiguratonFileWatcher.java | 4 + .../logging/log4j/core/config/Configurator.java | 46 +++- .../composite/CompositeConfiguration.java | 168 +++++++++++++ .../config/composite/DefaultMergeStrategy.java | 252 +++++++++++++++++++ .../core/config/composite/MergeStrategy.java | 33 +++ .../core/config/composite/package-info.java | 21 ++ .../log4j/core/impl/Log4jContextFactory.java | 43 +++- .../logging/log4j/core/util/WatchManager.java | 9 + .../core/config/CompositeConfigurationTest.java | 149 +++++++++++ .../src/test/resources/log4j-comp-appender.json | 34 +++ .../src/test/resources/log4j-comp-appender.xml | 39 +++ .../src/test/resources/log4j-comp-filter.json | 9 + .../src/test/resources/log4j-comp-filter.xml | 34 +++ .../src/test/resources/log4j-comp-logger.json | 36 +++ .../src/test/resources/log4j-comp-logger.xml | 41 +++ .../test/resources/log4j-comp-properties.json | 16 ++ .../test/resources/log4j-comp-properties.xml | 34 +++ 22 files changed, 1072 insertions(+), 47 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java ---------------------------------------------------------------------- diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java index 096d945..c2d55a2 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java @@ -28,7 +28,7 @@ import java.util.Objects; /** * <em>Consider this class private.</em> Utility class for ClassLoaders. - * + * * @see ClassLoader * @see RuntimePermission * @see Thread#getContextClassLoader() @@ -135,14 +135,14 @@ public final class LoaderUtil { * @throws InvocationTargetException if there was an exception whilst constructing the class * @since 2.1 */ - public static Object newInstanceOf(final String className) throws ClassNotFoundException, IllegalAccessException, + public static <T> T newInstanceOf(final String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { final Class<?> clazz = loadClass(className); try { - return clazz.getConstructor().newInstance(); + return (T) clazz.getConstructor().newInstance(); } catch (final NoSuchMethodException ignored) { // FIXME: looking at the code for Class.newInstance(), this seems to do the same thing as above - return clazz.newInstance(); + return (T) clazz.newInstance(); } } http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/${filename} ---------------------------------------------------------------------- diff --git a/log4j-core/${filename} b/log4j-core/${filename} new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/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 00cd397..316381a 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 @@ -98,6 +98,11 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement protected boolean isShutdownHookEnabled = true; /** + * The Script manager. + */ + protected ScriptManager scriptManager; + + /** * The Advertiser which exposes appender configurations to external systems. */ private Advertiser advertiser = new DefaultAdvertiser(); @@ -113,7 +118,6 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement private LoggerConfig root = new LoggerConfig(); private final ConcurrentMap<String, Object> componentMap = new ConcurrentHashMap<>(); private final ConfigurationSource configurationSource; - private ScriptManager scriptManager; private final ConfigurationScheduler configurationScheduler = new ConfigurationScheduler(); private final WatchManager watchManager = new WatchManager(configurationScheduler); private AsyncLoggerConfigDisruptor asyncLoggerConfigDisruptor; @@ -151,6 +155,18 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement return scriptManager; } + public void setScriptManager(ScriptManager scriptManager) { + this.scriptManager = scriptManager; + } + + public PluginManager getPluginManager() { + return pluginManager; + } + + public void setPluginManager(PluginManager pluginManager) { + this.pluginManager = pluginManager; + } + @Override public WatchManager getWatchManager() { return watchManager; @@ -161,7 +177,11 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement return configurationScheduler; } - @Override + public Node getRootNode() { + return rootNode; + } + + @Override public AsyncLoggerConfigDelegate getAsyncLoggerConfigDelegate() { // lazily instantiate only when requested by AsyncLoggers: // loading AsyncLoggerConfigDisruptor requires LMAX Disruptor jar on classpath @@ -357,7 +377,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement return isShutdownHookEnabled; } - protected void setup() { + public void setup() { } protected Level getDefaultStatus() { http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/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 8f3d764..41f3571 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 @@ -36,6 +36,7 @@ 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; @@ -392,32 +393,21 @@ public abstract class ConfigurationFactory extends ConfigurationBuilderFactory { final String configLocationStr = this.substitutor.replace(PropertiesUtil.getProperties() .getStringProperty(CONFIGURATION_FILE_PROPERTY)); if (configLocationStr != null) { - 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("*") || configLocationStr.endsWith(type)) { - final Configuration config = factory.getConfiguration(source); - if (config != null) { - return config; - } - } - } + String[] sources = configLocationStr.split(","); + if (sources.length > 1) { + List<AbstractConfiguration> configs = new ArrayList<>(); + for (String sourceLocation : sources) { + Configuration config = getConfiguration(sourceLocation); + 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); } else { for (final ConfigurationFactory factory : getFactories()) { final String[] types = factory.getSupportedTypes(); @@ -468,6 +458,36 @@ public abstract class ConfigurationFactory extends ConfigurationBuilderFactory { return new DefaultConfiguration(); } + private Configuration getConfiguration(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("*") || 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(); http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java index edb2d75..f1627bb 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java @@ -23,6 +23,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.util.Objects; @@ -44,7 +46,7 @@ public class ConfigurationSource { /** * Constructs a new {@code ConfigurationSource} with the specified input stream that originated from the specified * file. - * + * * @param stream the input stream * @param file the file where the input stream originated */ @@ -59,7 +61,7 @@ public class ConfigurationSource { /** * Constructs a new {@code ConfigurationSource} with the specified input stream that originated from the specified * url. - * + * * @param stream the input stream * @param url the URL where the input stream originated */ @@ -74,7 +76,7 @@ public class ConfigurationSource { /** * Constructs a new {@code ConfigurationSource} with the specified input stream. Since the stream is the only source * of data, this constructor makes a copy of the stream contents. - * + * * @param stream the input stream * @throws IOException if an exception occurred reading from the specified stream */ @@ -92,7 +94,7 @@ public class ConfigurationSource { /** * Returns the contents of the specified {@code InputStream} as a byte array. - * + * * @param inputStream the stream to read * @return the contents of the specified stream * @throws IOException if a problem occurred reading from the stream @@ -113,7 +115,7 @@ public class ConfigurationSource { /** * Returns the file configuration source, or {@code null} if this configuration source is based on an URL or has * neither a file nor an URL. - * + * * @return the configuration source file, or {@code null} */ public File getFile() { @@ -123,7 +125,7 @@ public class ConfigurationSource { /** * Returns the configuration source URL, or {@code null} if this configuration source is based on a file or has * neither a file nor an URL. - * + * * @return the configuration source URL, or {@code null} */ public URL getURL() { @@ -131,9 +133,40 @@ public class ConfigurationSource { } /** + * Returns a URI representing the configuration resource or null if it cannot be determined. + * @return The URI. + */ + public URI getURI() { + URI sourceURI = null; + if (url != null) { + try { + sourceURI = url.toURI(); + } catch (URISyntaxException ex) { + /* Ignore the exception */ + } + } + if (sourceURI == null && file != null) { + sourceURI = file.toURI(); + } + if (sourceURI == null && location != null) { + try { + sourceURI = new URI(location); + } catch (URISyntaxException ex) { + // Assume the scheme was missing. + try { + sourceURI = new URI("file://" + location); + } catch (URISyntaxException uriEx) { + /* Ignore the exception */ + } + } + } + return sourceURI; + } + + /** * Returns a string describing the configuration source file or URL, or {@code null} if this configuration source * has neither a file nor an URL. - * + * * @return a string describing the configuration source file or URL, or {@code null} */ public String getLocation() { @@ -142,7 +175,7 @@ public class ConfigurationSource { /** * Returns the input stream that this configuration source was constructed with. - * + * * @return the input stream that this configuration source was constructed with. */ public InputStream getInputStream() { @@ -151,7 +184,7 @@ public class ConfigurationSource { /** * Returns a new {@code ConfigurationSource} whose input stream is reset to the beginning. - * + * * @return a new {@code ConfigurationSource} * @throws IOException if a problem occurred while opening the new input stream */ http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java index e268c54..82d06ab 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java @@ -35,6 +35,10 @@ public class ConfiguratonFileWatcher implements FileWatcher { this.listeners = listeners; } + public List<ConfigurationListener> getListeners() { + return listeners; + } + @Override public void fileModified(File file) { http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java index fe6a5d5..f0e462e 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java @@ -17,6 +17,8 @@ package org.apache.logging.log4j.core.config; import java.net.URI; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.apache.logging.log4j.Level; @@ -109,8 +111,24 @@ public final class Configurator { */ public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation, final Object externalContext) { - final URI uri = Strings.isBlank(configLocation) ? null : NetUtils.toURI(configLocation); - return initialize(name, loader, uri, externalContext); + if (Strings.isBlank(configLocation)) { + return initialize(name, loader, (URI) null, externalContext); + } + if (configLocation.contains(",")) { + String[] parts = configLocation.split(","); + String scheme = null; + List<URI> uris = new ArrayList<>(parts.length); + for (String part : parts) { + URI uri = NetUtils.toURI(scheme != null ? scheme + ":" + part : part); + if (scheme == null && uri.getScheme() != null) { + scheme = uri.getScheme(); + } + uris.add(uri); + } + return initialize(name, loader, uris, externalContext); + } else { + return initialize(name, loader, NetUtils.toURI(configLocation), externalContext); + } } /** @@ -146,6 +164,20 @@ public final class Configurator { return null; } + public static LoggerContext initialize(final String name, final ClassLoader loader, final List<URI> configLocations, + final Object externalContext) { + try { + final Log4jContextFactory factory = getFactory(); + return factory == null ? + null : + factory.getContext(FQCN, loader, externalContext, false, configLocations, name); + } catch (final Exception ex) { + LOGGER.error("There was a problem initializing the LoggerContext [{}] using configurations at [{}].", name, + configLocations, ex); + } + return null; + } + /** * Initializes the Logging Context. * @param name The Context name. @@ -202,7 +234,7 @@ public final class Configurator { public static void setAllLevels(final String parentLogger, final Level level) { // 1) get logger config // 2) if exact match, use it, if not, create it. - // 3) set level on logger config + // 3) set level on logger config // 4) update child logger configs with level // 5) update loggers final LoggerContext loggerContext = LoggerContext.getContext(false); @@ -225,10 +257,10 @@ public final class Configurator { } return set; } - + /** * Sets logger levels. - * + * * @param levelMap * a levelMap where keys are level names and values are new * Levels. @@ -249,7 +281,7 @@ public final class Configurator { /** * Sets a logger's level. - * + * * @param loggerName * the logger name * @param level @@ -283,7 +315,7 @@ public final class Configurator { /** * Sets the root logger's level. - * + * * @param level * the new level */ http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/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 new file mode 100644 index 0000000..8b416b3 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java @@ -0,0 +1,168 @@ +/* + * 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.composite; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.AbstractConfiguration; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.apache.logging.log4j.core.config.ConfigurationSource; +import org.apache.logging.log4j.core.config.ConfiguratonFileWatcher; +import org.apache.logging.log4j.core.config.Node; +import org.apache.logging.log4j.core.config.Reconfigurable; +import org.apache.logging.log4j.core.config.plugins.util.ResolverUtil; +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 org.apache.logging.log4j.core.util.WatchManager; +import org.apache.logging.log4j.util.LoaderUtil; +import org.apache.logging.log4j.util.PropertiesUtil; + +/** + * A Composite Configuration. + */ +public class CompositeConfiguration extends AbstractConfiguration implements Reconfigurable { + + /** + * Allow the ConfigurationFactory class to be specified as a system property. + */ + public static final String MERGE_STRATEGY_PROPERTY = "log4j.mergeStrategy"; + + private static final String[] VERBOSE_CLASSES = new String[] {ResolverUtil.class.getName()}; + + private List<? extends AbstractConfiguration> configurations; + + private MergeStrategy mergeStrategy; + + /** + * Construct the ComponsiteConfiguration. + * + * @param configurations The List of Configurations to merge. + */ + public CompositeConfiguration(List<? extends AbstractConfiguration> configurations) { + super(ConfigurationSource.NULL_SOURCE); + this.configurations = configurations; + String mergeStrategyClassName = PropertiesUtil.getProperties().getStringProperty(MERGE_STRATEGY_PROPERTY, + DefaultMergeStrategy.class.getName()); + try { + mergeStrategy = LoaderUtil.newInstanceOf(mergeStrategyClassName); + } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException | + InstantiationException ex) { + mergeStrategy = new DefaultMergeStrategy(); + } + } + + @Override + public void setup() { + AbstractConfiguration targetConfiguration = configurations.get(0); + staffChildConfiguration(targetConfiguration); + WatchManager watchManager = targetConfiguration.getWatchManager(); + rootNode = targetConfiguration.getRootNode(); + for (AbstractConfiguration sourceConfiguration : configurations.subList(1, configurations.size())) { + staffChildConfiguration(sourceConfiguration); + Node sourceRoot = sourceConfiguration.getRootNode(); + mergeStrategy.mergConfigurations(rootNode, sourceRoot, getPluginManager()); + if (LOGGER.isEnabled(Level.ALL)) { + StringBuilder sb = new StringBuilder(); + printNodes("", rootNode, sb); + System.out.println(sb.toString()); + } + int monitorInterval = sourceConfiguration.getWatchManager().getIntervalSeconds(); + if (monitorInterval > 0) { + if (monitorInterval < watchManager.getIntervalSeconds()) { + watchManager.setIntervalSeconds(monitorInterval); + } + WatchManager sourceWatchManager = sourceConfiguration.getWatchManager(); + Map<File, FileWatcher> watchers = sourceWatchManager.getWatchers(); + FileWatcher fileWatcher = new ConfiguratonFileWatcher(this, listeners); + for (Map.Entry<File, FileWatcher> entry : watchers.entrySet()) { + if (entry.getValue() instanceof ConfiguratonFileWatcher) { + watchManager.watchFile(entry.getKey(), fileWatcher); + } + } + } + } + final StatusConfiguration statusConfig = new StatusConfiguration().withVerboseClasses(VERBOSE_CLASSES) + .withStatus(getDefaultStatus()); + for (final Map.Entry<String, String> entry : rootNode.getAttributes().entrySet()) { + final String key = entry.getKey(); + final String value = getStrSubstitutor().replace(entry.getValue()); + if ("status".equalsIgnoreCase(key)) { + statusConfig.withStatus(value); + } else if ("dest".equalsIgnoreCase(key)) { + statusConfig.withDestination(value); + } else if ("shutdownHook".equalsIgnoreCase(key)) { + isShutdownHookEnabled = !"disable".equalsIgnoreCase(value); + } else if ("verbose".equalsIgnoreCase(key)) { + statusConfig.withVerbosity(value); + } else if ("packages".equalsIgnoreCase(key)) { + pluginPackages.addAll(Arrays.asList(value.split(Patterns.COMMA_SEPARATOR))); + } else if ("name".equalsIgnoreCase(key)) { + setName(value); + } + } + statusConfig.initialize(); + } + + @Override + public Configuration reconfigure() { + List<AbstractConfiguration> configs = new ArrayList<>(); + ConfigurationFactory factory = ConfigurationFactory.getInstance(); + for (AbstractConfiguration config : configurations) { + ConfigurationSource source = config.getConfigurationSource(); + URI sourceURI = source.getURI(); + Configuration currentConfig; + 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); + if (currentConfig == null) { + LOGGER.warn("Unable to reload configuration {}, changes to it will be ignored", config.getName()); + currentConfig = config; + } + } else { + currentConfig = config; + } + configs.add((AbstractConfiguration) currentConfig); + + } + + return new CompositeConfiguration(configs); + } + + private void staffChildConfiguration(AbstractConfiguration childConfiguration) { + childConfiguration.setPluginManager(pluginManager); + childConfiguration.setScriptManager(scriptManager); + childConfiguration.setup(); + } + + private void printNodes(String indent, Node node, StringBuilder sb) { + sb.append(indent).append(node.getName()).append(" type: ").append(node.getType()).append("\n"); + sb.append(indent).append(node.getAttributes().toString()).append("\n"); + for (Node child : node.getChildren()) { + printNodes(indent + " ", child, sb); + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java new file mode 100644 index 0000000..7b123a0 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java @@ -0,0 +1,252 @@ +/* + * 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.composite; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.config.Node; +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.filter.CompositeFilter; + +/** + * The default merge strategy for composite configurations. + * <p> + * The default merge strategy performs the merge according to the following rules: + * <ol> + * <li>Aggregates the global configuration attributes with those in later configurations replacing those in previous + * configurations with the exception that the highest status level and the lowest monitorInterval greater than 0 will + * be used.</li> + * <li>Properties from all configurations are aggregated. Duplicate properties replace those in previous + * configurations.</li> + * <li>Filters are aggregated under a CompositeFilter if more than one Filter is defined. Since Filters are not named + * duplicates may be present.</li> + * <li>Scripts and ScriptFile references are aggregated. Duplicate definiations replace those in previous + * configurations.</li> + * <li>Appenders are aggregated. Appenders with the same name are replaced by those in later configurations, including + * all of the Appender's subcomponents.</li> + * <li>Loggers are all aggregated. Logger attributes are individually merged with duplicates being replaced by those + * in later configurations. Appender references on a Logger are aggregated with duplicates being replaced by those in + * later configurations. Filters on a Logger are aggregated under a CompositeFilter if more than one Filter is defined. + * Since Filters are not named duplicates may be present. Filters under Appender references included or discarded + * depending on whether their parent Appender reference is kept or discarded.</li> + * </ol> + */ +public class DefaultMergeStrategy implements MergeStrategy { + + private static final String APPENDERS = "appenders"; + private static final String PROPERTIES = "properties"; + private static final String LOGGERS = "loggers"; + private static final String SCRIPTS = "scripts"; + private static final String FILTERS = "filters"; + private static final String STATUS = "status"; + private static final String NAME = "name"; + private static final String REF = "ref"; + + /** + * Merge the source Configuration into the target Configuration. + * + * @param target The target node to merge into. + * @param source The source node. + * @param pluginManager The PluginManager. + */ + public void mergConfigurations(Node target, Node source, PluginManager pluginManager) { + for (Map.Entry<String, String> attribute : source.getAttributes().entrySet()) { + boolean isFound = false; + for (Map.Entry<String, String> targetAttribute : target.getAttributes().entrySet()) { + if (targetAttribute.getKey().equalsIgnoreCase(attribute.getKey())) { + if (attribute.getKey().equalsIgnoreCase(STATUS)) { + Level targetLevel = Level.getLevel(targetAttribute.getValue()); + Level sourceLevel = Level.getLevel(attribute.getValue()); + if (targetLevel != null && sourceLevel != null) { + if (sourceLevel.isLessSpecificThan(targetLevel)) { + targetAttribute.setValue(attribute.getValue()); + } + } + } else { + if (attribute.getKey().equalsIgnoreCase("monitorInterval")) { + int sourceInterval = Integer.parseInt(attribute.getValue()); + int targetInterval = Integer.parseInt(targetAttribute.getValue()); + if (targetInterval == 0 || sourceInterval < targetInterval) { + targetAttribute.setValue(attribute.getValue()); + } + } else { + targetAttribute.setValue(attribute.getValue()); + } + } + isFound = true; + } + } + if (!isFound) { + target.getAttributes().put(attribute.getKey(), attribute.getValue()); + } + } + for (Node sourceChildNode : source.getChildren()) { + boolean isFilter = isFilterNode(sourceChildNode); + boolean isMerged = false; + for (Node targetChildNode : target.getChildren()) { + if (isFilter) { + if (isFilterNode(targetChildNode)) { + updateFilterNode(target, targetChildNode, sourceChildNode, pluginManager); + isMerged = true; + break; + } else { + continue; + } + } + + if (!targetChildNode.getName().equalsIgnoreCase(sourceChildNode.getName())) { + continue; + } + + switch (targetChildNode.getName().toLowerCase()) { + case PROPERTIES: + case SCRIPTS: + case APPENDERS: { + for (Node node : sourceChildNode.getChildren()) { + for (Node targetNode : targetChildNode.getChildren()) { + if (targetNode.getAttributes().get(NAME).equals(node.getAttributes().get(NAME))) { + targetChildNode.getChildren().remove(targetNode); + break; + } + } + targetChildNode.getChildren().add(node); + } + isMerged = true; + break; + } + case LOGGERS: { + Map<String, Node> targetLoggers = new HashMap<>(); + for (Node node : targetChildNode.getChildren()) { + targetLoggers.put(node.getName(), node); + } + for (Node node : sourceChildNode.getChildren()) { + Node targetNode = getLoggerNode(targetChildNode, node.getAttributes().get(NAME)); + Node loggerNode = new Node(targetChildNode, node.getName(), node.getType()); + if (targetNode != null) { + for (Node sourceLoggerChild : node.getChildren()) { + if (isFilterNode(sourceLoggerChild)) { + boolean foundFilter = false; + for (Node targetChild : targetNode.getChildren()) { + if (isFilterNode(targetChild)) { + updateFilterNode(loggerNode, targetChild, sourceLoggerChild, + pluginManager); + foundFilter = true; + break; + } + } + if (!foundFilter) { + Node childNode = new Node(loggerNode, sourceLoggerChild.getName(), + sourceLoggerChild.getType()); + targetNode.getChildren().add(childNode); + } + } else { + Node childNode = new Node(loggerNode, sourceLoggerChild.getName(), + sourceLoggerChild.getType()); + childNode.getAttributes().putAll(sourceLoggerChild.getAttributes()); + if (childNode.getName().equalsIgnoreCase("AppenderRef")) { + for (Node targetChild : targetNode.getChildren()) { + if (isSameReference(targetChild, childNode)) { + targetNode.getChildren().remove(targetChild); + break; + } + } + } else { + for (Node targetChild : targetNode.getChildren()) { + if (isSameName(targetChild, childNode)) { + targetNode.getChildren().remove(targetChild); + break; + } + } + } + + targetNode.getChildren().add(childNode); + } + } + } else { + loggerNode.getAttributes().putAll(node.getAttributes()); + loggerNode.getChildren().addAll(node.getChildren()); + targetChildNode.getChildren().add(loggerNode); + } + } + isMerged = true; + break; + } + default: { + targetChildNode.getChildren().addAll(sourceChildNode.getChildren()); + isMerged = true; + break; + } + + } + } + if (!isMerged) { + target.getChildren().add(sourceChildNode); + } + } + } + + private Node getLoggerNode(Node parentNode, String name) { + for (Node node : parentNode.getChildren()) { + String nodeName = node.getAttributes().get(NAME); + if (name == null && nodeName == null) { + return node; + } + if (nodeName != null && nodeName.equals(name)) { + return node; + } + } + return null; + } + + private void updateFilterNode(Node target, Node targetChildNode, Node sourceChildNode, + PluginManager pluginManager) { + if (CompositeFilter.class.isAssignableFrom(targetChildNode.getType().getPluginClass())) { + Node node = new Node(targetChildNode, sourceChildNode.getName(), sourceChildNode.getType()); + node.getChildren().addAll(sourceChildNode.getChildren()); + node.getAttributes().putAll(sourceChildNode.getAttributes()); + targetChildNode.getChildren().add(node); + } else { + PluginType pluginType = pluginManager.getPluginType(FILTERS); + Node filtersNode = new Node(targetChildNode, FILTERS, pluginType); + Node node = new Node(filtersNode, sourceChildNode.getName(), sourceChildNode.getType()); + node.getAttributes().putAll(sourceChildNode.getAttributes()); + List<Node> children = filtersNode.getChildren(); + children.add(targetChildNode); + children.add(node); + List<Node> nodes = target.getChildren(); + nodes.remove(targetChildNode); + nodes.add(filtersNode); + } + } + + private boolean isFilterNode(Node node) { + return Filter.class.isAssignableFrom(node.getType().getPluginClass()); + } + + private boolean isSameName(Node node1, Node node2) { + return node1.getAttributes().get(NAME).toLowerCase().equals(node2.getAttributes().get(NAME).toLowerCase()); + } + + private boolean isSameReference(Node node1, Node node2) { + return node1.getAttributes().get(REF).toLowerCase().equals(node2.getAttributes().get(REF).toLowerCase()); + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java new file mode 100644 index 0000000..130a6f0 --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java @@ -0,0 +1,33 @@ +/* + * 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.composite; + +import org.apache.logging.log4j.core.config.Node; +import org.apache.logging.log4j.core.config.plugins.util.PluginManager; + +/** + * Merges two configurations together + */ +public interface MergeStrategy { + + /** + * Merge the soure node tree into the target node tree. + * @param target The target Node tree. + * @param source The source Node tree. + */ + void mergConfigurations(Node target, Node source, PluginManager pluginManager); +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/package-info.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/package-info.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/package-info.java new file mode 100644 index 0000000..fd920fa --- /dev/null +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/package-info.java @@ -0,0 +1,21 @@ +/* + * 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. + */ + +/** + * Support for composite configurations. + */ +package org.apache.logging.log4j.core.config.composite; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java index c65a64f..b504838 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java @@ -17,10 +17,14 @@ package org.apache.logging.log4j.core.impl; import java.net.URI; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import org.apache.logging.log4j.core.LifeCycle; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AbstractConfiguration; +import org.apache.logging.log4j.core.config.composite.CompositeConfiguration; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; @@ -241,6 +245,43 @@ public class Log4jContextFactory implements LoggerContextFactory, ShutdownCallba return ctx; } + public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext, + final boolean currentContext, final List<URI> configLocations, final String name) { + final LoggerContext ctx = selector + .getContext(fqcn, loader, currentContext, null/*this probably needs to change*/); + if (externalContext != null && ctx.getExternalContext() == null) { + ctx.setExternalContext(externalContext); + } + if (name != null) { + ctx.setName(name); + } + if (ctx.getState() == LifeCycle.State.INITIALIZED) { + if ((configLocations != null && !configLocations.isEmpty())) { + ContextAnchor.THREAD_CONTEXT.set(ctx); + List<AbstractConfiguration> configurations = new ArrayList<>(configLocations.size()); + for (URI configLocation : configLocations) { + Configuration currentReadConfiguration = ConfigurationFactory.getInstance() + .getConfiguration(name, configLocation); + if (currentReadConfiguration instanceof AbstractConfiguration) { + configurations.add((AbstractConfiguration) currentReadConfiguration); + } else { + LOGGER.error( + "Found configuration {}, which is not an AbstractConfiguration and can't be handled by CompositeConfiguration", + configLocation); + } + } + CompositeConfiguration compositeConfiguration = new CompositeConfiguration(configurations); + LOGGER.debug("Starting LoggerContext[name={}] from configurations at {}", ctx.getName(), + configLocations); + ctx.start(compositeConfiguration); + ContextAnchor.THREAD_CONTEXT.remove(); + } else { + ctx.start(); + } + } + return ctx; + } + /** * Returns the ContextSelector. * @return The ContextSelector. @@ -251,7 +292,7 @@ public class Log4jContextFactory implements LoggerContextFactory, ShutdownCallba /** * Returns the ShutdownCallbackRegistry - * + * * @return the ShutdownCallbackRegistry * @since 2.4 */ http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java index 3750462..146bff7 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java @@ -17,6 +17,7 @@ package org.apache.logging.log4j.core.util; import java.io.File; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -78,6 +79,14 @@ public class WatchManager extends AbstractLifeCycle { } + public Map<File, FileWatcher> getWatchers() { + Map<File, FileWatcher> map = new HashMap<>(); + for (Map.Entry<File, FileMonitor> entry : watchers.entrySet()) { + map.put(entry.getKey(), entry.getValue().fileWatcher); + } + return map; + } + private class WatchWorker implements Runnable { @Override http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java new file mode 100644 index 0000000..f17c941 --- /dev/null +++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java @@ -0,0 +1,149 @@ +package org.apache.logging.log4j.core.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.appender.ConsoleAppender; +import org.apache.logging.log4j.core.appender.FileAppender; +import org.apache.logging.log4j.core.appender.RollingFileAppender; +import org.apache.logging.log4j.core.config.composite.CompositeConfiguration; +import org.apache.logging.log4j.core.filter.CompositeFilter; +import org.apache.logging.log4j.core.filter.ThresholdFilter; +import org.apache.logging.log4j.junit.LoggerContextRule; +import org.junit.Test; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +public class CompositeConfigurationTest +{ + + @Test + public void compositeConfigurationUsed() + { + final LoggerContextRule lcr = + new LoggerContextRule( "classpath:log4j-comp-appender.xml,log4j-comp-appender.json" ); + Statement test = new Statement() + { + @Override + public void evaluate() + throws Throwable + { + assertTrue( lcr.getConfiguration() instanceof CompositeConfiguration); + } + }; + runTest( lcr, test ); + } + + @Test + public void compositeProperties() + { + final LoggerContextRule lcr = + new LoggerContextRule( "classpath:log4j-comp-properties.xml,log4j-comp-properties.json" ); + Statement test = new Statement() + { + @Override + public void evaluate() + throws Throwable + { + CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration(); + assertEquals( "json", config.getStrSubstitutor().replace( "${propertyShared}" ) ); + assertEquals( "xml", config.getStrSubstitutor().replace( "${propertyXml}" ) ); + assertEquals( "json", config.getStrSubstitutor().replace( "${propertyJson}" ) ); + } + }; + runTest( lcr, test ); + } + + @Test + public void compositeAppenders() + { + final LoggerContextRule lcr = + new LoggerContextRule( "classpath:log4j-comp-appender.xml,log4j-comp-appender.json" ); + Statement test = new Statement() + { + @Override + public void evaluate() + throws Throwable + { + CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration(); + Map<String, Appender> appender = config.getAppenders(); + assertEquals( 3, appender.size() ); + assertTrue( appender.get( "STDOUT" ) instanceof ConsoleAppender ); + assertTrue( appender.get( "File" ) instanceof FileAppender ); + assertTrue( appender.get( "Override" ) instanceof RollingFileAppender ); + } + }; + runTest( lcr, test ); + } + + @Test + public void compositeLogger() + { + final LoggerContextRule lcr = new LoggerContextRule( "classpath:log4j-comp-logger.xml,log4j-comp-logger.json" ); + Statement test = new Statement() + { + @Override + public void evaluate() + throws Throwable + { + CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration(); + Map<String, Appender> appendersMap = config.getLogger( "cat1" ).getAppenders(); + assertEquals("Expected 2 Appender references for cat1 but got " + appendersMap.size(), 2, + appendersMap.size() ); + assertTrue( appendersMap.get( "STDOUT" ) instanceof ConsoleAppender ); + + appendersMap = config.getLogger( "cat2" ).getAppenders(); + assertEquals("Expected 1 Appender reference for cat2 but got " + appendersMap.size(), 1, + appendersMap.size() ); + assertTrue( appendersMap.get( "File" ) instanceof FileAppender ); + + appendersMap = config.getLogger( "cat3" ).getAppenders(); + assertEquals("Expected 1 Appender reference for cat3 but got " + appendersMap.size(), 1, + appendersMap.size() ); + assertTrue( appendersMap.get( "File" ) instanceof FileAppender ); + + appendersMap = config.getRootLogger().getAppenders(); + assertEquals("Expected 2 Appender references for the root logger but got " + appendersMap.size(), 2, + appendersMap.size() ); + assertTrue( appendersMap.get( "File" ) instanceof FileAppender ); + assertTrue( appendersMap.get( "STDOUT" ) instanceof ConsoleAppender ); + } + }; + runTest( lcr, test ); + } + + @Test + public void overrideFilter() + { + final LoggerContextRule lcr = new LoggerContextRule( "classpath:log4j-comp-filter.xml,log4j-comp-filter.json" ); + Statement test = new Statement() + { + @Override + public void evaluate() + throws Throwable + { + CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration(); + assertTrue( config.getFilter() instanceof CompositeFilter); + CompositeFilter filter = (CompositeFilter) config.getFilter(); + assertTrue( filter.getFiltersArray().length == 2); + } + }; + runTest( lcr, test ); + } + + private void runTest( LoggerContextRule rule, Statement statement ) + { + try + { + rule.apply( statement, Description.createTestDescription( getClass(), + Thread.currentThread().getStackTrace()[1].getMethodName() ) ).evaluate(); + } + catch ( Throwable throwable ) + { + throw new RuntimeException( throwable ); + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-appender.json ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-comp-appender.json b/log4j-core/src/test/resources/log4j-comp-appender.json new file mode 100644 index 0000000..1f0b02d --- /dev/null +++ b/log4j-core/src/test/resources/log4j-comp-appender.json @@ -0,0 +1,34 @@ +{ + "Configuration" : { + "status": "warn", + "name": "YAMLConfigTest", + "appenders": { + "Console": { + "name": "STDOUT", + "PatternLayout": { + "Pattern": "%m%n" + } + }, + "RollingFile": { + "name": "Override", + "fileName": "target/log4j-appender-override.log", + "filePattern": "target/log4j-appender-override-$${date:yyyy-MM}.log", + "PatternLayout": { + "Pattern": "%m%n" + }, + "SizeBasedTriggeringPolicy": { + "size": "500" + } + } + }, + "Loggers" : { + "Root" : { + "level" : "error", + "AppenderRef" : { + "ref" : "STDOUT" + } + + } + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-appender.xml ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-comp-appender.xml b/log4j-core/src/test/resources/log4j-comp-appender.xml new file mode 100644 index 0000000..7cd71a2 --- /dev/null +++ b/log4j-core/src/test/resources/log4j-comp-appender.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. + +--> +<Configuration status="ERROR" name="XMLConfigTest"> + <Appenders> + <File name="File" fileName="target/log4j-comp-appender.log" bufferedIO="false"> + <PatternLayout> + <Pattern>%d %p %C{1.} [%t] %m%n</Pattern> + </PatternLayout> + </File> + <File name="Override" fileName="target/log4j-comp-appender.log" bufferedIO="false"> + <PatternLayout> + <Pattern>%d %p %C{1.} [%t] %m%n</Pattern> + </PatternLayout> + </File> + </Appenders> + + <Loggers> + <Root level="ERROR"> + <AppenderRef ref="File"/> + </Root> + </Loggers> + +</Configuration> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-filter.json ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-comp-filter.json b/log4j-core/src/test/resources/log4j-comp-filter.json new file mode 100644 index 0000000..c010298 --- /dev/null +++ b/log4j-core/src/test/resources/log4j-comp-filter.json @@ -0,0 +1,9 @@ +{ + "Configuration" : { + "status": "warn", + "name": "YAMLConfigTest", + "thresholdFilter" : { + "level": "debug" + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-filter.xml ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-comp-filter.xml b/log4j-core/src/test/resources/log4j-comp-filter.xml new file mode 100644 index 0000000..553d448 --- /dev/null +++ b/log4j-core/src/test/resources/log4j-comp-filter.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. + +--> +<Configuration status="ERROR" name="XMLConfigTest"> + <BurstFilter level="INFO" rate="16" maxBurst="100"/> + + <Appenders> + <Console name="STDOUT"> + <PatternLayout pattern="%m%n"/> + </Console> + </Appenders> + + <Loggers> + <Root level="error"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> + +</Configuration> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-logger.json ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-comp-logger.json b/log4j-core/src/test/resources/log4j-comp-logger.json new file mode 100644 index 0000000..b2b08d7 --- /dev/null +++ b/log4j-core/src/test/resources/log4j-comp-logger.json @@ -0,0 +1,36 @@ +{ + "Configuration" : { + "status": "warn", + "name": "LoggerConfigTest", + "Loggers" : { + "logger" : [ + { + "name" : "cat1", + "level" : "debug", + "additivity" : false, + "AppenderRef" : { + "ref" : "STDOUT" + } + }, + { + "name" : "cat2", + "level" : "debug", + "additivity" : false, + "AppenderRef" : { + "ref" : "File" + } + + } + ], + "Root" : { + "level" : "error", + "AppenderRef" : [{ + "ref" : "STDOUT" + }, + { + "ref" : "File" + }] + } + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-logger.xml ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-comp-logger.xml b/log4j-core/src/test/resources/log4j-comp-logger.xml new file mode 100644 index 0000000..0934e94 --- /dev/null +++ b/log4j-core/src/test/resources/log4j-comp-logger.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. + +--> +<Configuration status="ERROR" name="LoggerConfigTest"> + <Appenders> + <Console name="STDOUT"> + <PatternLayout pattern="%m%n"/> + </Console> + <File name="File" fileName="${filename}" bufferedIO="false"> + <PatternLayout> + <Pattern>%d %p %C{1.} [%t] %m%n</Pattern> + </PatternLayout> + </File> + </Appenders> + + <Loggers> + <Logger name="cat1" level="debug" additivity="false"> + <AppenderRef ref="File"/> + </Logger> + + <Logger name="cat3" level="debug" additivity="false"> + <AppenderRef ref="File"/> + </Logger> + </Loggers> + +</Configuration> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-properties.json ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-comp-properties.json b/log4j-core/src/test/resources/log4j-comp-properties.json new file mode 100644 index 0000000..83c2d09 --- /dev/null +++ b/log4j-core/src/test/resources/log4j-comp-properties.json @@ -0,0 +1,16 @@ +{ + "Configuration" : { + "status": "warn", + "name": "YAMLConfigTest", + + "properties" : { + "property" : [{ + "name" : "propertyShared", + "value": "json" + },{ + "name" : "propertyJson", + "value": "json" + }] + } + } +} http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-properties.xml ---------------------------------------------------------------------- diff --git a/log4j-core/src/test/resources/log4j-comp-properties.xml b/log4j-core/src/test/resources/log4j-comp-properties.xml new file mode 100644 index 0000000..6fa9c6b --- /dev/null +++ b/log4j-core/src/test/resources/log4j-comp-properties.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. + +--> +<Configuration status="OFF" name="XMLConfigTest"> + <Properties> + <Property name="propertyShared">xml</Property> + <Property name="propertyXml">xml</Property> + </Properties> + <Appenders> + <Console name="STDOUT"> + <PatternLayout pattern="%m%n"/> + </Console> + </Appenders> + <Loggers> + <Root level="error"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> +</Configuration>
