diff --git a/log4j-1.2-api/pom.xml b/log4j-1.2-api/pom.xml index 08f30772593..6e38bbee4e0 100644 --- a/log4j-1.2-api/pom.xml +++ b/log4j-1.2-api/pom.xml @@ -23,7 +23,6 @@ ${revision} ../log4j-parent - log4j-1.2-api jar Apache Log4j 1.x Compatibility API @@ -86,12 +85,6 @@ commons-lang3 test - - - org.hamcrest - hamcrest - test - com.fasterxml.jackson.dataformat jackson-dataformat-xml @@ -107,6 +100,7 @@ junit-jupiter-params test + org.junit.vintage junit-vintage-engine diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java index aa925bfcc77..7d3014b23f1 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java @@ -30,8 +30,6 @@ import org.apache.log4j.helpers.AppenderAttachableImpl; import org.apache.log4j.helpers.NullEnumeration; import org.apache.log4j.legacy.core.CategoryUtil; -import org.apache.log4j.or.ObjectRenderer; -import org.apache.log4j.or.RendererMap; import org.apache.log4j.spi.AppenderAttachable; import org.apache.log4j.spi.HierarchyEventListener; import org.apache.log4j.spi.LoggerRepository; @@ -144,8 +142,6 @@ public static void shutdown() { */ protected volatile Level level; - private RendererMap rendererMap; - /** * The parent of this category. All categories have at least one ancestor which is the root category. */ @@ -172,7 +168,6 @@ public static void shutdown() { protected Category(final LoggerContext context, final String name) { this.name = name; this.logger = context.getLogger(name); - this.repository = LogManager.getLoggerRepository(); } Category(final org.apache.logging.log4j.Logger logger) { @@ -345,21 +340,6 @@ public void forcedLog(final String fqcn, final Priority level, final Object mess } } - private ObjectRenderer get(final Class clazz) { - ObjectRenderer renderer = null; - for (Class c = clazz; c != null; c = c.getSuperclass()) { - renderer = rendererMap.get(c); - if (renderer != null) { - return renderer; - } - renderer = searchInterfaces(c); - if (renderer != null) { - return renderer; - } - } - return null; - } - public boolean getAdditivity() { return LogManager.isLog4jCorePresent() ? CategoryUtil.isAdditive(logger) : false; } @@ -471,8 +451,12 @@ public final Category getParent() { return null; } final ConcurrentMap loggers = Hierarchy.getLoggersMap(loggerContext); - final Logger parentLogger = loggers.get(parent.getName()); - return parentLogger == null ? new Category(parent) : parentLogger; + Category parentLogger = loggers.get(parent.getName()); + if (parentLogger == null) { + parentLogger = new Category(parent); + parentLogger.setHierarchy(getLoggerRepository()); + } + return parentLogger; } public final Level getPriority() { @@ -653,21 +637,6 @@ public void removeAppender(final String name) { } } - ObjectRenderer searchInterfaces(final Class c) { - ObjectRenderer renderer = rendererMap.get(c); - if (renderer != null) { - return renderer; - } - final Class[] ia = c.getInterfaces(); - for (final Class clazz : ia) { - renderer = searchInterfaces(clazz); - if (renderer != null) { - return renderer; - } - } - return null; - } - public void setAdditivity(final boolean additivity) { if (LogManager.isLog4jCorePresent()) { CategoryUtil.setAdditivity(logger, additivity); diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/Hierarchy.java b/log4j-1.2-api/src/main/java/org/apache/log4j/Hierarchy.java index 518b58f9fe5..6c3214836e9 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/Hierarchy.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/Hierarchy.java @@ -96,16 +96,24 @@ static LoggerContext getContext() { return PrivateLogManager.getContext(); } - static Logger getInstance(final LoggerContext context, final String name) { + private Logger getInstance(final LoggerContext context, final String name) { return getInstance(context, name, LOGGER_ADAPTER); } - static Logger getInstance(final LoggerContext context, final String name, final LoggerFactory factory) { - return getLoggersMap(context).computeIfAbsent(name, k -> factory.makeNewLoggerInstance(name)); + private Logger getInstance(final LoggerContext context, final String name, final LoggerFactory factory) { + return getLoggersMap(context).computeIfAbsent(name, k -> { + final Logger logger = factory.makeNewLoggerInstance(name); + logger.setHierarchy(this); + return logger; + }); } - static Logger getInstance(final LoggerContext context, final String name, final PrivateLoggerAdapter factory) { - return getLoggersMap(context).computeIfAbsent(name, k -> factory.newLogger(name, context)); + private Logger getInstance(final LoggerContext context, final String name, final PrivateLoggerAdapter factory) { + return getLoggersMap(context).computeIfAbsent(name, k -> { + final Logger logger = factory.newLogger(name, context); + logger.setHierarchy(this); + return logger; + }); } static ConcurrentMap getLoggersMap(final LoggerContext context) { @@ -114,10 +122,6 @@ static ConcurrentMap getLoggersMap(final LoggerContext context) } } - static Logger getRootLogger(final LoggerContext context) { - return getInstance(context, org.apache.logging.log4j.LogManager.ROOT_LOGGER_NAME); - } - private final LoggerFactory defaultFactory; private final Vector listeners; Hashtable ht; diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/WriterAppender.java b/log4j-1.2-api/src/main/java/org/apache/log4j/WriterAppender.java index 5603338ded3..23f731077bc 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/WriterAppender.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/WriterAppender.java @@ -20,6 +20,7 @@ import java.io.InterruptedIOException; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; import java.io.Writer; import org.apache.log4j.helpers.QuietWriter; import org.apache.log4j.spi.ErrorHandler; @@ -235,12 +236,8 @@ protected OutputStreamWriter createWriter(final OutputStream os) { if (enc != null) { try { retval = new OutputStreamWriter(os, enc); - } catch (IOException e) { - if (e instanceof InterruptedIOException) { - Thread.currentThread().interrupt(); - } - LOGGER.warn("Error initializing output writer."); - LOGGER.warn("Unsupported encoding?"); + } catch (final UnsupportedEncodingException e) { + LOGGER.warn("Error initializing output writer: encoding {} is not supported.", enc, e); } } if (retval == null) { diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/AbstractBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/AbstractBuilder.java index 7f3bdbdaffa..dfd4319b409 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/AbstractBuilder.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/AbstractBuilder.java @@ -24,6 +24,7 @@ import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import org.apache.log4j.bridge.FilterAdapter; import org.apache.log4j.bridge.FilterWrapper; @@ -121,6 +122,19 @@ public int getIntegerProperty(final String key, final int defaultValue) { return defaultValue; } + public long getLongProperty(final String key, final long defaultValue) { + String value = null; + try { + value = getProperty(key); + if (value != null) { + return Long.parseLong(value); + } + } catch (final Exception ex) { + LOGGER.warn("Error converting value {} of {} to a long: {}", value, key, ex.getMessage()); + } + return defaultValue; + } + protected String getNameAttribute(final Element element) { return element.getAttribute(NAME_ATTR); } @@ -202,6 +216,25 @@ protected void set(final String name, final Element element, final AtomicInteger } } + protected void set(final String name, final Element element, final AtomicLong ref) { + final String value = getValueAttribute(element); + if (value == null) { + LOGGER.warn("No value for {} parameter, using default {}", name, ref); + } else { + try { + ref.set(Long.parseLong(value)); + } catch (NumberFormatException e) { + LOGGER.warn( + "{} parsing {} parameter, using default {}: {}", + e.getClass().getName(), + name, + ref, + e.getMessage(), + e); + } + } + } + protected void set(final String name, final Element element, final AtomicReference ref) { final String value = getValueAttribute(element); if (value == null) { diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java index 4f04d23f33e..86b63b17b4d 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/BuilderManager.java @@ -31,11 +31,13 @@ import org.apache.log4j.builders.filter.FilterBuilder; import org.apache.log4j.builders.layout.LayoutBuilder; import org.apache.log4j.builders.rewrite.RewritePolicyBuilder; +import org.apache.log4j.builders.rolling.TriggeringPolicyBuilder; import org.apache.log4j.config.PropertiesConfiguration; import org.apache.log4j.rewrite.RewritePolicy; import org.apache.log4j.spi.Filter; import org.apache.log4j.xml.XmlConfiguration; import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; import org.apache.logging.log4j.plugins.Inject; import org.apache.logging.log4j.plugins.Namespace; import org.apache.logging.log4j.plugins.di.ConfigurableInstanceFactory; @@ -67,7 +69,7 @@ public class BuilderManager { */ @Inject public BuilderManager( - final ConfigurableInstanceFactory instanceFactory, @Namespace(NAMESPACE) PluginNamespace plugins) { + final ConfigurableInstanceFactory instanceFactory, @Namespace(NAMESPACE) final PluginNamespace plugins) { this.instanceFactory = instanceFactory; this.plugins = plugins; } @@ -124,7 +126,7 @@ public

, T> T parse( final String prefix, final Properties props, final PropertiesConfiguration config, - T invalidValue) { + final T invalidValue) { final P parser = createBuilder(getPlugin(className), prefix, props); if (parser != null) { final T value = parser.parse(config); @@ -174,4 +176,12 @@ public RewritePolicy parseRewritePolicy( b -> b.parse(rewriteElement, config), INVALID_REWRITE_POLICY); } + + public TriggeringPolicy parseTriggeringPolicy( + final String className, final Element policyElement, final XmlConfiguration config) { + return newInstance( + this.getPlugin(className), + b -> b.parse(policyElement, config), + (TriggeringPolicy) null); + } } diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/EnhancedRollingFileAppenderBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/EnhancedRollingFileAppenderBuilder.java new file mode 100644 index 00000000000..2c97bf170af --- /dev/null +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/EnhancedRollingFileAppenderBuilder.java @@ -0,0 +1,295 @@ +/* + * 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.log4j.builders.appender; + +import static org.apache.log4j.builders.BuilderManager.NAMESPACE; +import static org.apache.log4j.config.Log4j1Configuration.THRESHOLD_PARAM; +import static org.apache.log4j.xml.XmlConfiguration.FILTER_TAG; +import static org.apache.log4j.xml.XmlConfiguration.LAYOUT_TAG; +import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG; +import static org.apache.log4j.xml.XmlConfiguration.forEachElement; + +import java.util.Properties; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import org.apache.log4j.Appender; +import org.apache.log4j.Layout; +import org.apache.log4j.bridge.AppenderWrapper; +import org.apache.log4j.bridge.LayoutAdapter; +import org.apache.log4j.builders.AbstractBuilder; +import org.apache.log4j.config.PropertiesConfiguration; +import org.apache.log4j.spi.Filter; +import org.apache.log4j.xml.XmlConfiguration; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.appender.RollingFileAppender; +import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy; +import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy; +import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.plugins.Namespace; +import org.apache.logging.log4j.plugins.Plugin; +import org.apache.logging.log4j.status.StatusLogger; +import org.w3c.dom.Element; + +/** + * Build a File Appender + */ +@Plugin("org.apache.log4j.rolling.RollingFileAppender") +@Namespace(NAMESPACE) +public class EnhancedRollingFileAppenderBuilder extends AbstractBuilder implements AppenderBuilder { + + private static final String TIME_BASED_ROLLING_POLICY = "org.apache.log4j.rolling.TimeBasedRollingPolicy"; + private static final String FIXED_WINDOW_ROLLING_POLICY = "org.apache.log4j.rolling.FixedWindowRollingPolicy"; + private static final Logger LOGGER = StatusLogger.getLogger(); + private static final String TRIGGERING_TAG = "triggeringPolicy"; + private static final String ROLLING_TAG = "rollingPolicy"; + private static final int DEFAULT_MIN_INDEX = 1; + private static final int DEFAULT_MAX_INDEX = 7; + private static final String ACTIVE_FILE_PARAM = "ActiveFileName"; + private static final String FILE_PATTERN_PARAM = "FileNamePattern"; + private static final String MIN_INDEX_PARAM = "MinIndex"; + private static final String MAX_INDEX_PARAM = "MaxIndex"; + + public EnhancedRollingFileAppenderBuilder() {} + + public EnhancedRollingFileAppenderBuilder(final String prefix, final Properties properties) { + super(prefix, properties); + } + + private void parseRollingPolicy( + final Element element, + final XmlConfiguration configuration, + final AtomicReference rollingPolicyClassName, + final AtomicReference activeFileName, + final AtomicReference fileNamePattern, + final AtomicInteger minIndex, + final AtomicInteger maxIndex) { + rollingPolicyClassName.set(configuration.subst(element.getAttribute("class"), getProperties())); + forEachElement(element.getChildNodes(), currentElement -> { + switch (currentElement.getTagName()) { + case PARAM_TAG: + switch (getNameAttributeKey(currentElement)) { + case ACTIVE_FILE_PARAM: + set(ACTIVE_FILE_PARAM, currentElement, activeFileName); + break; + case FILE_PATTERN_PARAM: + set(FILE_PATTERN_PARAM, currentElement, fileNamePattern); + break; + case MIN_INDEX_PARAM: + set(MIN_INDEX_PARAM, currentElement, minIndex); + break; + case MAX_INDEX_PARAM: + set(MAX_INDEX_PARAM, currentElement, maxIndex); + } + } + }); + } + + @Override + public Appender parseAppender(final Element element, final XmlConfiguration configuration) { + // FileAppender + final String name = getNameAttribute(element); + final AtomicReference layout = new AtomicReference<>(); + final AtomicReference filter = new AtomicReference<>(); + final AtomicReference fileName = new AtomicReference<>(); + final AtomicReference level = new AtomicReference<>(); + final AtomicBoolean immediateFlush = new AtomicBoolean(true); + final AtomicBoolean append = new AtomicBoolean(true); + final AtomicBoolean bufferedIo = new AtomicBoolean(); + final AtomicInteger bufferSize = new AtomicInteger(8192); + // specific to RollingFileAppender + final AtomicReference rollingPolicyClassName = new AtomicReference<>(); + final AtomicReference activeFileName = new AtomicReference<>(); + final AtomicReference fileNamePattern = new AtomicReference<>(); + final AtomicInteger minIndex = new AtomicInteger(DEFAULT_MIN_INDEX); + final AtomicInteger maxIndex = new AtomicInteger(DEFAULT_MAX_INDEX); + final AtomicReference triggeringPolicy = new AtomicReference<>(); + forEachElement(element.getChildNodes(), currentElement -> { + switch (currentElement.getTagName()) { + case ROLLING_TAG: + parseRollingPolicy( + currentElement, + configuration, + rollingPolicyClassName, + activeFileName, + fileNamePattern, + minIndex, + maxIndex); + break; + case TRIGGERING_TAG: + triggeringPolicy.set(configuration.parseTriggeringPolicy(currentElement)); + break; + case LAYOUT_TAG: + layout.set(configuration.parseLayout(currentElement)); + break; + case FILTER_TAG: + configuration.addFilter(filter, currentElement); + break; + case PARAM_TAG: + switch (getNameAttributeKey(currentElement)) { + case FILE_PARAM: + set(FILE_PARAM, currentElement, fileName); + break; + case APPEND_PARAM: + set(APPEND_PARAM, currentElement, append); + break; + case BUFFERED_IO_PARAM: + set(BUFFERED_IO_PARAM, currentElement, bufferedIo); + break; + case BUFFER_SIZE_PARAM: + set(BUFFER_SIZE_PARAM, currentElement, bufferSize); + break; + case THRESHOLD_PARAM: + set(THRESHOLD_PARAM, currentElement, level); + break; + case IMMEDIATE_FLUSH_PARAM: + set(IMMEDIATE_FLUSH_PARAM, currentElement, immediateFlush); + break; + } + break; + } + }); + return createAppender( + name, + layout.get(), + filter.get(), + fileName.get(), + level.get(), + immediateFlush.get(), + append.get(), + bufferedIo.get(), + bufferSize.get(), + rollingPolicyClassName.get(), + activeFileName.get(), + fileNamePattern.get(), + minIndex.get(), + maxIndex.get(), + triggeringPolicy.get(), + configuration); + } + + @Override + public Appender parseAppender( + final String name, + final String appenderPrefix, + final String layoutPrefix, + final String filterPrefix, + final Properties props, + final PropertiesConfiguration configuration) { + final Layout layout = configuration.parseLayout(layoutPrefix, name, props); + final Filter filter = configuration.parseAppenderFilters(props, filterPrefix, name); + final String level = getProperty(THRESHOLD_PARAM); + final String fileName = getProperty(FILE_PARAM); + final boolean append = getBooleanProperty(APPEND_PARAM, true); + final boolean immediateFlush = getBooleanProperty(IMMEDIATE_FLUSH_PARAM, true); + final boolean bufferedIo = getBooleanProperty(BUFFERED_IO_PARAM, false); + final int bufferSize = Integer.parseInt(getProperty(BUFFER_SIZE_PARAM, "8192")); + final String rollingPolicyClassName = getProperty(ROLLING_TAG); + final int minIndex = getIntegerProperty(ROLLING_TAG + "." + MIN_INDEX_PARAM, DEFAULT_MIN_INDEX); + final int maxIndex = getIntegerProperty(ROLLING_TAG + "." + MAX_INDEX_PARAM, DEFAULT_MAX_INDEX); + final String activeFileName = getProperty(ROLLING_TAG + "." + ACTIVE_FILE_PARAM); + final String fileNamePattern = getProperty(ROLLING_TAG + "." + FILE_PATTERN_PARAM); + final TriggeringPolicy triggeringPolicy = + configuration.parseTriggeringPolicy(props, appenderPrefix + "." + TRIGGERING_TAG); + return createAppender( + name, + layout, + filter, + fileName, + level, + immediateFlush, + append, + bufferedIo, + bufferSize, + rollingPolicyClassName, + activeFileName, + fileNamePattern, + minIndex, + maxIndex, + triggeringPolicy, + configuration); + } + + private Appender createAppender( + final String name, + final Layout layout, + final Filter filter, + final String fileName, + final String level, + final boolean immediateFlush, + final boolean append, + final boolean bufferedIo, + final int bufferSize, + final String rollingPolicyClassName, + final String activeFileName, + final String fileNamePattern, + final int minIndex, + final int maxIndex, + final TriggeringPolicy triggeringPolicy, + final Configuration configuration) { + final org.apache.logging.log4j.core.Layout fileLayout = LayoutAdapter.adapt(layout); + final boolean actualImmediateFlush = bufferedIo ? false : immediateFlush; + final org.apache.logging.log4j.core.Filter fileFilter = buildFilters(level, filter); + if (rollingPolicyClassName == null) { + LOGGER.error("Unable to create RollingFileAppender, no rolling policy provided."); + return null; + } + final String actualFileName = activeFileName != null ? activeFileName : fileName; + if (actualFileName == null) { + LOGGER.error("Unable to create RollingFileAppender, no file name provided."); + return null; + } + if (fileNamePattern == null) { + LOGGER.error("Unable to create RollingFileAppender, no file name pattern provided."); + return null; + } + final DefaultRolloverStrategy.Builder rolloverStrategyBuilder = DefaultRolloverStrategy.newBuilder(); + switch (rollingPolicyClassName) { + case FIXED_WINDOW_ROLLING_POLICY: + rolloverStrategyBuilder.setMin(Integer.toString(minIndex)).setMax(Integer.toString(maxIndex)); + break; + case TIME_BASED_ROLLING_POLICY: + break; + default: + LOGGER.warn("Unsupported rolling policy: {}", rollingPolicyClassName); + } + final TriggeringPolicy actualTriggeringPolicy; + if (triggeringPolicy != null) { + actualTriggeringPolicy = triggeringPolicy; + } else if (rollingPolicyClassName.equals(TIME_BASED_ROLLING_POLICY)) { + actualTriggeringPolicy = TimeBasedTriggeringPolicy.newBuilder().build(); + } else { + LOGGER.error("Unable to create RollingFileAppender, no triggering policy provided."); + return null; + } + return AppenderWrapper.adapt(RollingFileAppender.newBuilder() + .setAppend(append) + .setBufferedIo(bufferedIo) + .setBufferSize(bufferedIo ? bufferSize : 0) + .setConfiguration(configuration) + .setFileName(actualFileName) + .setFilePattern(fileNamePattern) + .setFilter(fileFilter) + .setImmediateFlush(actualImmediateFlush) + .setLayout(fileLayout) + .setName(name) + .setPolicy(actualTriggeringPolicy) + .setStrategy(rolloverStrategyBuilder.build()) + .build()); + } +} diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RollingFileAppenderBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RollingFileAppenderBuilder.java index 770cd991b36..897d7d598f4 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RollingFileAppenderBuilder.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/appender/RollingFileAppenderBuilder.java @@ -42,8 +42,6 @@ import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy; import org.apache.logging.log4j.core.appender.rolling.RolloverStrategy; import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy; -import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy; -import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; import org.apache.logging.log4j.core.time.Clock; import org.apache.logging.log4j.plugins.Namespace; import org.apache.logging.log4j.plugins.Plugin; @@ -193,10 +191,6 @@ private Appender createAppender( return null; } final String filePattern = fileName + ".%i"; - final TriggeringPolicy timePolicy = TimeBasedTriggeringPolicy.newBuilder() - .setClock(clock) - .setModulate(true) - .build(); final SizeBasedTriggeringPolicy sizePolicy = SizeBasedTriggeringPolicy.createPolicy(maxSize); final CompositeTriggeringPolicy policy = CompositeTriggeringPolicy.createPolicy(sizePolicy); final RolloverStrategy strategy = DefaultRolloverStrategy.newBuilder() diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilder.java index 3d5ef21c3ae..781665ab1bb 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilder.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilder.java @@ -66,7 +66,7 @@ public Filter parse(final Element filterElement, final XmlConfiguration config) levelMax.set(getValueAttribute(currentElement)); break; case LEVEL_MIN: - levelMax.set(getValueAttribute(currentElement)); + levelMin.set(getValueAttribute(currentElement)); break; case ACCEPT_ON_MATCH: acceptOnMatch.set(getBooleanValueAttribute(currentElement)); @@ -86,21 +86,23 @@ public Filter parse(final PropertiesConfiguration config) { } private Filter createFilter(final String levelMax, final String levelMin, final boolean acceptOnMatch) { - Level max = Level.FATAL; - Level min = Level.TRACE; + Level max = Level.OFF; + Level min = Level.ALL; if (levelMax != null) { - max = OptionConverter.toLevel(levelMax, org.apache.log4j.Level.FATAL) - .getVersion2Level(); + max = OptionConverter.toLevel(levelMax, org.apache.log4j.Level.OFF).getVersion2Level(); } if (levelMin != null) { - min = OptionConverter.toLevel(levelMin, org.apache.log4j.Level.DEBUG) - .getVersion2Level(); + min = OptionConverter.toLevel(levelMin, org.apache.log4j.Level.ALL).getVersion2Level(); } final org.apache.logging.log4j.core.Filter.Result onMatch = acceptOnMatch ? org.apache.logging.log4j.core.Filter.Result.ACCEPT : org.apache.logging.log4j.core.Filter.Result.NEUTRAL; + // XXX: LOG4J2-2315 + // log4j1 order: ALL < TRACE < DEBUG < ... < FATAL < OFF + // log4j2 order: ALL > TRACE > DEBUG > ... > FATAL > OFF + // So we create as LevelRangeFilter.createFilter(minLevel=max, maxLevel=min, ...) return FilterWrapper.adapt( - LevelRangeFilter.createFilter(min, max, onMatch, org.apache.logging.log4j.core.Filter.Result.DENY)); + LevelRangeFilter.createFilter(max, min, onMatch, org.apache.logging.log4j.core.Filter.Result.DENY)); } } diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/XmlLayoutBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/XmlLayoutBuilder.java index 541e0ce03f1..37b8da819bb 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/XmlLayoutBuilder.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/layout/XmlLayoutBuilder.java @@ -28,7 +28,7 @@ import org.apache.log4j.config.PropertiesConfiguration; import org.apache.log4j.layout.Log4j1XmlLayout; import org.apache.log4j.xml.XmlConfiguration; -import org.apache.logging.log4j.core.config.DefaultConfiguration; +import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.plugins.Namespace; import org.apache.logging.log4j.plugins.Plugin; import org.w3c.dom.Element; @@ -60,17 +60,17 @@ public Layout parse(final Element layoutElement, final XmlConfiguration config) locationInfo.set(getBooleanValueAttribute(currentElement)); } }); - return createLayout(properties.get(), locationInfo.get()); + return createLayout(config, properties.get(), locationInfo.get()); } @Override public Layout parse(final PropertiesConfiguration config) { final boolean properties = getBooleanProperty(PROPERTIES); final boolean locationInfo = getBooleanProperty(LOCATION_INFO); - return createLayout(properties, locationInfo); + return createLayout(config, properties, locationInfo); } - private Layout createLayout(final boolean properties, final boolean locationInfo) { - return LayoutWrapper.adapt(Log4j1XmlLayout.createLayout(new DefaultConfiguration(), locationInfo, properties)); + private Layout createLayout(final Configuration config, final boolean properties, final boolean locationInfo) { + return LayoutWrapper.adapt(Log4j1XmlLayout.createLayout(config, locationInfo, properties)); } } diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/CompositeTriggeringPolicyBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/CompositeTriggeringPolicyBuilder.java new file mode 100644 index 00000000000..1eeab59d405 --- /dev/null +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/CompositeTriggeringPolicyBuilder.java @@ -0,0 +1,75 @@ +/* + * 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.log4j.builders.rolling; + +import static org.apache.log4j.builders.BuilderManager.NAMESPACE; +import static org.apache.log4j.xml.XmlConfiguration.forEachElement; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import org.apache.log4j.builders.AbstractBuilder; +import org.apache.log4j.config.PropertiesConfiguration; +import org.apache.log4j.xml.XmlConfiguration; +import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy; +import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; +import org.apache.logging.log4j.plugins.Namespace; +import org.apache.logging.log4j.plugins.Plugin; +import org.w3c.dom.Element; + +@Plugin("org.apache.log4j.rolling.CompositeTriggeringPolicy") +@Namespace(NAMESPACE) +public class CompositeTriggeringPolicyBuilder extends AbstractBuilder + implements TriggeringPolicyBuilder { + + private static final TriggeringPolicy[] EMPTY_TRIGGERING_POLICIES = new TriggeringPolicy[0]; + private static final String POLICY_TAG = "triggeringPolicy"; + + public CompositeTriggeringPolicyBuilder() { + super(); + } + + public CompositeTriggeringPolicyBuilder(final String prefix, final Properties props) { + super(prefix, props); + } + + @Override + public CompositeTriggeringPolicy parse(final Element element, final XmlConfiguration configuration) { + final List policies = new ArrayList<>(); + forEachElement(element.getChildNodes(), currentElement -> { + switch (currentElement.getTagName()) { + case POLICY_TAG: + final TriggeringPolicy policy = configuration.parseTriggeringPolicy(currentElement); + if (policy != null) { + policies.add(policy); + } + break; + } + }); + return createTriggeringPolicy(policies); + } + + @Override + public CompositeTriggeringPolicy parse(final PropertiesConfiguration configuration) { + return createTriggeringPolicy(Collections.emptyList()); + } + + private CompositeTriggeringPolicy createTriggeringPolicy(final List policies) { + return CompositeTriggeringPolicy.createPolicy(policies.toArray(EMPTY_TRIGGERING_POLICIES)); + } +} diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/SizeBasedTriggeringPolicyBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/SizeBasedTriggeringPolicyBuilder.java new file mode 100644 index 00000000000..fc531d5c9a5 --- /dev/null +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/SizeBasedTriggeringPolicyBuilder.java @@ -0,0 +1,76 @@ +/* + * 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.log4j.builders.rolling; + +import static org.apache.log4j.builders.BuilderManager.NAMESPACE; +import static org.apache.log4j.xml.XmlConfiguration.PARAM_TAG; +import static org.apache.log4j.xml.XmlConfiguration.forEachElement; + +import java.util.Properties; +import java.util.concurrent.atomic.AtomicLong; +import org.apache.log4j.builders.AbstractBuilder; +import org.apache.log4j.config.PropertiesConfiguration; +import org.apache.log4j.xml.XmlConfiguration; +import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy; +import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; +import org.apache.logging.log4j.plugins.Namespace; +import org.apache.logging.log4j.plugins.Plugin; +import org.w3c.dom.Element; + +@Plugin("org.apache.log4j.rolling.SizeBasedTriggeringPolicy") +@Namespace(NAMESPACE) +public class SizeBasedTriggeringPolicyBuilder extends AbstractBuilder + implements TriggeringPolicyBuilder { + + private static final String MAX_SIZE_PARAM = "MaxFileSize"; + private static final long DEFAULT_MAX_SIZE = 10 * 1024 * 1024; + + public SizeBasedTriggeringPolicyBuilder() { + super(); + } + + public SizeBasedTriggeringPolicyBuilder(final String prefix, final Properties props) { + super(prefix, props); + } + + @Override + public SizeBasedTriggeringPolicy parse(final Element element, final XmlConfiguration configuration) { + final AtomicLong maxSize = new AtomicLong(DEFAULT_MAX_SIZE); + forEachElement(element.getChildNodes(), currentElement -> { + switch (currentElement.getTagName()) { + case PARAM_TAG: + switch (getNameAttributeKey(currentElement)) { + case MAX_SIZE_PARAM: + set(MAX_SIZE_PARAM, currentElement, maxSize); + break; + } + break; + } + }); + return createTriggeringPolicy(maxSize.get()); + } + + @Override + public SizeBasedTriggeringPolicy parse(final PropertiesConfiguration configuration) { + final long maxSize = getLongProperty(MAX_SIZE_PARAM, DEFAULT_MAX_SIZE); + return createTriggeringPolicy(maxSize); + } + + private SizeBasedTriggeringPolicy createTriggeringPolicy(final long maxSize) { + return SizeBasedTriggeringPolicy.createPolicy(Long.toString(maxSize)); + } +} diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/TimeBasedRollingPolicyBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/TimeBasedRollingPolicyBuilder.java new file mode 100644 index 00000000000..c53e9ace482 --- /dev/null +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/TimeBasedRollingPolicyBuilder.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.log4j.builders.rolling; + +import static org.apache.log4j.builders.BuilderManager.NAMESPACE; + +import java.util.Properties; +import org.apache.log4j.builders.AbstractBuilder; +import org.apache.log4j.config.PropertiesConfiguration; +import org.apache.log4j.xml.XmlConfiguration; +import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy; +import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; +import org.apache.logging.log4j.plugins.Namespace; +import org.apache.logging.log4j.plugins.Plugin; +import org.w3c.dom.Element; + +@Plugin("org.apache.log4j.rolling.TimeBasedRollingPolicy") +@Namespace(NAMESPACE) +public class TimeBasedRollingPolicyBuilder extends AbstractBuilder + implements TriggeringPolicyBuilder { + + public TimeBasedRollingPolicyBuilder(final String prefix, final Properties props) { + super(prefix, props); + } + + public TimeBasedRollingPolicyBuilder() { + super(); + } + + @Override + public TimeBasedTriggeringPolicy parse(final Element element, final XmlConfiguration configuration) { + return createTriggeringPolicy(); + } + + @Override + public TimeBasedTriggeringPolicy parse(final PropertiesConfiguration configuration) { + return createTriggeringPolicy(); + } + + private TimeBasedTriggeringPolicy createTriggeringPolicy() { + return TimeBasedTriggeringPolicy.newBuilder().build(); + } +} diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/TriggeringPolicyBuilder.java b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/TriggeringPolicyBuilder.java new file mode 100644 index 00000000000..931ad08b405 --- /dev/null +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/builders/rolling/TriggeringPolicyBuilder.java @@ -0,0 +1,24 @@ +/* + * 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.log4j.builders.rolling; + +import org.apache.log4j.builders.Parser; +import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; + +public interface TriggeringPolicyBuilder extends Parser { + // NOP +} diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java index f3ed60377b3..5ee7bc06fa1 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/config/PropertiesConfiguration.java @@ -41,6 +41,7 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Filter.Result; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.LoggerConfig; @@ -612,6 +613,14 @@ private Filter buildFilter(final String className, final String appenderName, fi return filter; } + public TriggeringPolicy parseTriggeringPolicy(final Properties props, final String policyPrefix) { + final String policyClass = OptionConverter.findAndSubst(policyPrefix, props); + if (policyClass == null) { + return null; + } + return manager.parse(policyClass, policyPrefix, props, this, null); + } + private static T newInstanceOf(final String className, final String type) { try { return LoaderUtil.newInstanceOf(className); diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java b/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java index eea6bc673d7..b354d183058 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/helpers/OptionConverter.java @@ -41,7 +41,7 @@ /** * A convenience class to convert property values to specific types. */ -public class OptionConverter { +public final class OptionConverter { private static class CharMap { final char key; diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/layout/Log4j1XmlLayout.java b/log4j-1.2-api/src/main/java/org/apache/log4j/layout/Log4j1XmlLayout.java index 0b2c45b9e11..ccb57282f81 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/layout/Log4j1XmlLayout.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/layout/Log4j1XmlLayout.java @@ -55,7 +55,7 @@ public final class Log4j1XmlLayout extends AbstractStringLayout { @PluginFactory public static Log4j1XmlLayout createLayout( // @formatter:off - @PluginConfiguration Configuration configuration, + @PluginConfiguration final Configuration configuration, @PluginAttribute(value = "locationInfo") final boolean locationInfo, @PluginAttribute(value = "properties") final boolean properties // @formatter:on diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/pattern/Log4j1LevelPatternConverter.java b/log4j-1.2-api/src/main/java/org/apache/log4j/pattern/Log4j1LevelPatternConverter.java index ce38b4b0479..f93c9f8de2b 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/pattern/Log4j1LevelPatternConverter.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/pattern/Log4j1LevelPatternConverter.java @@ -30,7 +30,7 @@ @Namespace(PatternConverter.CATEGORY) @Plugin("Log4j1LevelPatternConverter") @ConverterKeys({"v1Level"}) -public class Log4j1LevelPatternConverter extends LogEventPatternConverter { +public final class Log4j1LevelPatternConverter extends LogEventPatternConverter { private static final Log4j1LevelPatternConverter INSTANCE = new Log4j1LevelPatternConverter(); diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.java b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.java index 1519bf37e94..d705b856f55 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.java @@ -18,6 +18,7 @@ import java.io.Serializable; import java.util.Objects; +import org.apache.logging.log4j.core.util.Integers; /** * The internal representation of caller location information. @@ -101,35 +102,40 @@ public LocationInfo(final Throwable throwable, final String fqnOfCallingClass) { prevClass = thisClass; } } - this.stackTraceElement = new StackTraceElement(declaringClass, methodName, file, Integer.parseInt(line)); - this.fullInfo = stackTraceElement.toString(); + if (declaringClass != null && methodName != null) { + this.stackTraceElement = new StackTraceElement(declaringClass, methodName, file, Integers.parseInt(line)); + this.fullInfo = stackTraceElement.toString(); + } else { + this.stackTraceElement = null; + this.fullInfo = null; + } } /** * Gets the fully qualified class name of the caller making the logging request. */ public String getClassName() { - return stackTraceElement.getClassName(); + return stackTraceElement != null ? stackTraceElement.getClassName() : NA; } /** * Gets the file name of the caller. */ public String getFileName() { - return stackTraceElement.getFileName(); + return stackTraceElement != null ? stackTraceElement.getFileName() : NA; } /** * Gets the line number of the caller. */ public String getLineNumber() { - return Integer.toString(stackTraceElement.getLineNumber()); + return stackTraceElement != null ? Integer.toString(stackTraceElement.getLineNumber()) : NA; } /** * Gets the method name of the caller. */ public String getMethodName() { - return stackTraceElement.getMethodName(); + return stackTraceElement != null ? stackTraceElement.getMethodName() : NA; } } diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfiguration.java b/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfiguration.java index 25f81f01db1..daa0903ba03 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfiguration.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/xml/XmlConfiguration.java @@ -42,6 +42,7 @@ import org.apache.log4j.spi.Filter; import org.apache.logging.log4j.core.Filter.Result; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.LoggerConfig; @@ -663,6 +664,12 @@ private Layout buildLayout(final String className, final Element layout_element) return null; } + public TriggeringPolicy parseTriggeringPolicy(final Element policyElement) { + final String className = subst(policyElement.getAttribute(CLASS_ATTR)); + LOGGER.debug("Parsing triggering policy of class: \"{}\"", className); + return manager.parseTriggeringPolicy(className, policyElement, this); + } + /** * Used internally to parse a level element. */ diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java index a1001d2aa5f..0dc789bcf5a 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/CategoryTest.java @@ -89,6 +89,7 @@ public void testExist() { public void testForcedLog() { final MockCategory category = new MockCategory("org.example.foo"); category.setAdditivity(false); + category.setHierarchy(LogManager.getHierarchy()); ((org.apache.logging.log4j.core.Logger) category.getLogger()).addAppender(appender); // Logging a String category.info("Hello, World"); diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilderTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilderTest.java new file mode 100644 index 00000000000..79a4354406b --- /dev/null +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/builders/filter/LevelRangeFilterBuilderTest.java @@ -0,0 +1,209 @@ +/* + * 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.log4j.builders.filter; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.StringReader; +import java.util.Properties; +import java.util.stream.Stream; +import javax.xml.parsers.DocumentBuilderFactory; +import org.apache.log4j.bridge.FilterWrapper; +import org.apache.log4j.spi.Filter; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Filter.Result; +import org.apache.logging.log4j.core.filter.LevelRangeFilter; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +public class LevelRangeFilterBuilderTest { + + @ParameterizedTest + @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class) + public void testAcceptOnMatchTrue(TestLevelRangeFilterBuilder builder) throws Exception { + LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, Level.ERROR, true); + + assertResult(Result.DENY, levelRangeFilter, Level.ALL); + assertResult(Result.DENY, levelRangeFilter, Level.DEBUG); + assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO); + assertResult(Result.ACCEPT, levelRangeFilter, Level.WARN); + assertResult(Result.ACCEPT, levelRangeFilter, Level.ERROR); + assertResult(Result.DENY, levelRangeFilter, Level.FATAL); + assertResult(Result.DENY, levelRangeFilter, Level.OFF); + } + + @ParameterizedTest + @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class) + public void testAcceptOnMatchFalse(TestLevelRangeFilterBuilder builder) throws Exception { + LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, Level.ERROR, false); + + assertResult(Result.DENY, levelRangeFilter, Level.ALL); + assertResult(Result.DENY, levelRangeFilter, Level.DEBUG); + assertResult(Result.NEUTRAL, levelRangeFilter, Level.INFO); + assertResult(Result.NEUTRAL, levelRangeFilter, Level.WARN); + assertResult(Result.NEUTRAL, levelRangeFilter, Level.ERROR); + assertResult(Result.DENY, levelRangeFilter, Level.FATAL); + assertResult(Result.DENY, levelRangeFilter, Level.OFF); + } + + @ParameterizedTest + @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class) + public void testAcceptOnMatchNull(TestLevelRangeFilterBuilder builder) throws Exception { + LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, Level.ERROR, null); + + assertResult(Result.DENY, levelRangeFilter, Level.ALL); + assertResult(Result.DENY, levelRangeFilter, Level.DEBUG); + assertResult(Result.NEUTRAL, levelRangeFilter, Level.INFO); + assertResult(Result.NEUTRAL, levelRangeFilter, Level.WARN); + assertResult(Result.NEUTRAL, levelRangeFilter, Level.ERROR); + assertResult(Result.DENY, levelRangeFilter, Level.FATAL); + assertResult(Result.DENY, levelRangeFilter, Level.OFF); + } + + @ParameterizedTest + @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class) + public void testMinLevelNull(TestLevelRangeFilterBuilder builder) throws Exception { + LevelRangeFilter levelRangeFilter = builder.build(null, Level.ERROR, true); + + assertResult(Result.ACCEPT, levelRangeFilter, Level.ALL); + assertResult(Result.ACCEPT, levelRangeFilter, Level.DEBUG); + assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO); + assertResult(Result.ACCEPT, levelRangeFilter, Level.WARN); + assertResult(Result.ACCEPT, levelRangeFilter, Level.ERROR); + assertResult(Result.DENY, levelRangeFilter, Level.FATAL); + assertResult(Result.DENY, levelRangeFilter, Level.OFF); + } + + @ParameterizedTest + @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class) + public void testMaxLevelNull(TestLevelRangeFilterBuilder builder) throws Exception { + LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, null, true); + + assertResult(Result.DENY, levelRangeFilter, Level.ALL); + assertResult(Result.DENY, levelRangeFilter, Level.DEBUG); + assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO); + assertResult(Result.ACCEPT, levelRangeFilter, Level.WARN); + assertResult(Result.ACCEPT, levelRangeFilter, Level.ERROR); + assertResult(Result.ACCEPT, levelRangeFilter, Level.FATAL); + assertResult(Result.ACCEPT, levelRangeFilter, Level.OFF); + } + + @ParameterizedTest + @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class) + public void testMinMaxLevelSame(TestLevelRangeFilterBuilder builder) throws Exception { + LevelRangeFilter levelRangeFilter = builder.build(Level.INFO, Level.INFO, true); + + assertResult(Result.DENY, levelRangeFilter, Level.ALL); + assertResult(Result.DENY, levelRangeFilter, Level.DEBUG); + assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO); + assertResult(Result.DENY, levelRangeFilter, Level.WARN); + assertResult(Result.DENY, levelRangeFilter, Level.ERROR); + assertResult(Result.DENY, levelRangeFilter, Level.FATAL); + assertResult(Result.DENY, levelRangeFilter, Level.OFF); + } + + @ParameterizedTest + @ArgumentsSource(TestLevelRangeFilterBuilderProvider.class) + public void testMinMaxLevelNull(TestLevelRangeFilterBuilder builder) throws Exception { + LevelRangeFilter levelRangeFilter = builder.build(null, null, true); + + assertResult(Result.ACCEPT, levelRangeFilter, Level.ALL); + assertResult(Result.ACCEPT, levelRangeFilter, Level.DEBUG); + assertResult(Result.ACCEPT, levelRangeFilter, Level.INFO); + assertResult(Result.ACCEPT, levelRangeFilter, Level.WARN); + assertResult(Result.ACCEPT, levelRangeFilter, Level.ERROR); + assertResult(Result.ACCEPT, levelRangeFilter, Level.FATAL); + assertResult(Result.ACCEPT, levelRangeFilter, Level.OFF); + } + + private static void assertResult(Result expected, LevelRangeFilter filter, Level level) { + assertSame(expected, filter.filter(null, level, null, (Object) null, null)); + } + + private static class TestLevelRangeFilterBuilderProvider implements ArgumentsProvider { + + @Override + public Stream provideArguments(ExtensionContext extensionContext) { + return Stream.of( + Arguments.of(new TestLevelRangeFilterFromXmlBuilder()), + Arguments.of(new TestLevelRangeFilterFromPropertyBuilder())); + } + } + + private interface TestLevelRangeFilterBuilder { + + LevelRangeFilter build(Level levelMin, Level levelMax, Boolean acceptOnMatch) throws Exception; + } + + private static class TestLevelRangeFilterFromXmlBuilder implements TestLevelRangeFilterBuilder { + + @Override + public LevelRangeFilter build(Level levelMin, Level levelMax, Boolean acceptOnMatch) throws Exception { + LevelRangeFilterBuilder builder = new LevelRangeFilterBuilder(); + Filter filter = builder.parse(generateTestXml(levelMin, levelMax, acceptOnMatch), null); + org.apache.logging.log4j.core.Filter wrappedFilter = ((FilterWrapper) filter).getFilter(); + return (LevelRangeFilter) wrappedFilter; + } + + private static Element generateTestXml(Level levelMin, Level levelMax, Boolean acceptOnMatch) throws Exception { + + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + if (levelMin != null) { + sb.append(String.format("\n", levelMin)); + } + if (levelMax != null) { + sb.append(String.format("\n", levelMax)); + } + if (acceptOnMatch != null) { + sb.append(String.format("\n", acceptOnMatch)); + } + sb.append(""); + + return DocumentBuilderFactory.newInstance() + .newDocumentBuilder() + .parse(new InputSource(new StringReader(sb.toString()))) + .getDocumentElement(); + } + } + + private static class TestLevelRangeFilterFromPropertyBuilder implements TestLevelRangeFilterBuilder { + + @Override + public LevelRangeFilter build(Level levelMin, Level levelMax, Boolean acceptOnMatch) { + Properties properties = new Properties(); + if (levelMin != null) { + properties.setProperty("foobar.levelMin", levelMin.name()); + } + if (levelMax != null) { + properties.setProperty("foobar.levelMax", levelMax.name()); + } + if (acceptOnMatch != null) { + properties.setProperty("foobar.acceptOnMatch", acceptOnMatch.toString()); + } + LevelRangeFilterBuilder builder = new LevelRangeFilterBuilder("foobar", properties); + Filter filter = builder.parse(null); + org.apache.logging.log4j.core.Filter wrappedFilter = ((FilterWrapper) filter).getFilter(); + return (LevelRangeFilter) wrappedFilter; + } + } +} diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java index 48996f99bef..946bd7b042a 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/AbstractLog4j1ConfigurationTest.java @@ -26,6 +26,7 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -71,6 +72,12 @@ public abstract class AbstractLog4j1ConfigurationTest { abstract Configuration getConfiguration(String configResourcePrefix) throws URISyntaxException, IOException; + protected InputStream getResourceAsStream(final String configResource) throws IOException { + final InputStream is = getClass().getClassLoader().getResourceAsStream(configResource); + assertNotNull(is); + return is; + } + protected LoggerContext configure(final String configResourcePrefix) throws URISyntaxException, IOException { Configurator.reconfigure(getConfiguration(configResourcePrefix)); return (LoggerContext) org.apache.logging.log4j.LogManager.getContext(false); @@ -550,4 +557,101 @@ public void testGlobalThreshold() throws Exception { assertEquals(1, legacyAppender.getEvents().size()); } } + + protected void testEnhancedRollingFileAppender(final Configuration configuration) { + Appender appender; + TriggeringPolicy policy; + RolloverStrategy strategy; + DefaultRolloverStrategy defaultRolloverStrategy; + // Time policy with default attributes + appender = configuration.getAppender("DEFAULT_TIME"); + assertTrue("is RollingFileAppender", appender instanceof RollingFileAppender); + final RollingFileAppender defaultTime = (RollingFileAppender) appender; + assertEquals("append", true, defaultTime.getManager().isAppend()); + assertEquals("bufferSize", 8192, defaultTime.getManager().getBufferSize()); + assertEquals("immediateFlush", true, defaultTime.getImmediateFlush()); + assertEquals("fileName", "target/EnhancedRollingFileAppender/defaultTime.log", defaultTime.getFileName()); + assertEquals( + "filePattern", + "target/EnhancedRollingFileAppender/defaultTime.%d{yyyy-MM-dd}.log", + defaultTime.getFilePattern()); + policy = defaultTime.getTriggeringPolicy(); + assertTrue("is TimeBasedTriggeringPolicy", policy instanceof TimeBasedTriggeringPolicy); + // Size policy with default attributes + appender = configuration.getAppender("DEFAULT_SIZE"); + assertTrue("is RollingFileAppender", appender instanceof RollingFileAppender); + final RollingFileAppender defaultSize = (RollingFileAppender) appender; + assertEquals("append", true, defaultSize.getManager().isAppend()); + assertEquals("bufferSize", 8192, defaultSize.getManager().getBufferSize()); + assertEquals("immediateFlush", true, defaultSize.getImmediateFlush()); + assertEquals("fileName", "target/EnhancedRollingFileAppender/defaultSize.log", defaultSize.getFileName()); + assertEquals( + "filePattern", "target/EnhancedRollingFileAppender/defaultSize.%i.log", defaultSize.getFilePattern()); + policy = defaultSize.getTriggeringPolicy(); + assertTrue("is SizeBasedTriggeringPolicy", policy instanceof SizeBasedTriggeringPolicy); + assertEquals(10 * 1024 * 1024L, ((SizeBasedTriggeringPolicy) policy).getMaxFileSize()); + strategy = defaultSize.getManager().getRolloverStrategy(); + assertTrue("is DefaultRolloverStrategy", strategy instanceof DefaultRolloverStrategy); + defaultRolloverStrategy = (DefaultRolloverStrategy) strategy; + assertEquals(1, defaultRolloverStrategy.getMinIndex()); + assertEquals(7, defaultRolloverStrategy.getMaxIndex()); + // Time policy with custom attributes + appender = configuration.getAppender("TIME"); + assertTrue("is RollingFileAppender", appender instanceof RollingFileAppender); + final RollingFileAppender time = (RollingFileAppender) appender; + assertEquals("append", false, time.getManager().isAppend()); + assertEquals("bufferSize", 1000, time.getManager().getBufferSize()); + assertEquals("immediateFlush", false, time.getImmediateFlush()); + assertEquals("fileName", "target/EnhancedRollingFileAppender/time.log", time.getFileName()); + assertEquals( + "filePattern", "target/EnhancedRollingFileAppender/time.%d{yyyy-MM-dd}.log", time.getFilePattern()); + policy = time.getTriggeringPolicy(); + assertTrue("is TimeBasedTriggeringPolicy", policy instanceof TimeBasedTriggeringPolicy); + // Size policy with custom attributes + appender = configuration.getAppender("SIZE"); + assertTrue("is RollingFileAppender", appender instanceof RollingFileAppender); + final RollingFileAppender size = (RollingFileAppender) appender; + assertEquals("append", false, size.getManager().isAppend()); + assertEquals("bufferSize", 1000, size.getManager().getBufferSize()); + assertEquals("immediateFlush", false, size.getImmediateFlush()); + assertEquals("fileName", "target/EnhancedRollingFileAppender/size.log", size.getFileName()); + assertEquals("filePattern", "target/EnhancedRollingFileAppender/size.%i.log", size.getFilePattern()); + policy = size.getTriggeringPolicy(); + assertTrue("is SizeBasedTriggeringPolicy", policy instanceof SizeBasedTriggeringPolicy); + assertEquals(10_000_000L, ((SizeBasedTriggeringPolicy) policy).getMaxFileSize()); + strategy = size.getManager().getRolloverStrategy(); + assertTrue("is DefaultRolloverStrategy", strategy instanceof DefaultRolloverStrategy); + defaultRolloverStrategy = (DefaultRolloverStrategy) strategy; + assertEquals(11, defaultRolloverStrategy.getMinIndex()); + assertEquals(20, defaultRolloverStrategy.getMaxIndex()); + } + + protected void testLevelRangeFilter() throws Exception { + try (final LoggerContext ctx = configure("config-1.2/log4j-LevelRangeFilter")) { + final Configuration config = ctx.getConfiguration(); + final Logger logger = LogManager.getLogger(PropertiesConfigurationTest.class); + // List appender + final Appender appender = config.getAppender("LIST"); + assertNotNull(appender); + final ListAppender legacyAppender = (ListAppender) ((Adapter) appender).getAppender(); + // deny + logger.trace("TRACE"); + assertEquals(0, legacyAppender.getEvents().size()); + // deny + logger.debug("DEBUG"); + assertEquals(0, legacyAppender.getEvents().size()); + // accept + logger.info("INFO"); + assertEquals(1, legacyAppender.getEvents().size()); + // accept + logger.warn("WARN"); + assertEquals(2, legacyAppender.getEvents().size()); + // accept + logger.error("ERROR"); + assertEquals(3, legacyAppender.getEvents().size()); + // deny + logger.fatal("FATAL"); + assertEquals(3, legacyAppender.getEvents().size()); + } + } } diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java index fa982579160..4ba9c2c8ae0 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/PropertiesConfigurationTest.java @@ -63,7 +63,7 @@ public class PropertiesConfigurationTest extends AbstractLog4j1ConfigurationTest @Override Configuration getConfiguration(final String configResourcePrefix) throws URISyntaxException, IOException { final String configResource = configResourcePrefix + SUFFIX; - final InputStream inputStream = ClassLoader.getSystemResourceAsStream(configResource); + final InputStream inputStream = getResourceAsStream(configResource); final ConfigurationSource source = new ConfigurationSource(inputStream); final LoggerContext context = LoggerContext.getContext(false); final Configuration configuration = new PropertiesConfigurationFactory().getConfiguration(context, source); @@ -127,10 +127,38 @@ public void testConsoleAppenderLevelRangeFilter() throws Exception { final Filterable filterable = (Filterable) appender; final CompositeFilter filter = (CompositeFilter) filterable.getFilter(); final org.apache.logging.log4j.core.Filter[] filters = filter.getFiltersArray(); - final LevelRangeFilter customFilterReal = (LevelRangeFilter) filters[0]; - assertEquals(Level.ALL, customFilterReal.getMinLevel()); - final LevelRangeFilter defaultFilter = (LevelRangeFilter) filters[1]; - assertEquals(Level.TRACE, defaultFilter.getMinLevel()); + final LevelRangeFilter filter1 = (LevelRangeFilter) filters[0]; + // XXX: LOG4J2-2315 + assertEquals(Level.OFF, filter1.getMinLevel()); + assertEquals(Level.ALL, filter1.getMaxLevel()); + final LevelRangeFilter filter2 = (LevelRangeFilter) filters[1]; + assertEquals(Level.ERROR, filter2.getMinLevel()); + assertEquals(Level.INFO, filter2.getMaxLevel()); + final LevelRangeFilter filter3 = (LevelRangeFilter) filters[2]; + assertEquals(Level.OFF, filter3.getMinLevel()); + assertEquals(Level.ALL, filter3.getMaxLevel()); + + final ListAppender legacyAppender = (ListAppender) ((AppenderAdapter.Adapter) appender).getAppender(); + final Logger logger = LogManager.getLogger(PropertiesConfigurationTest.class); + + // deny + logger.trace("TRACE"); + assertEquals(0, legacyAppender.getEvents().size()); + // deny + logger.debug("DEBUG"); + assertEquals(0, legacyAppender.getEvents().size()); + // accept + logger.info("INFO"); + assertEquals(1, legacyAppender.getEvents().size()); + // accept + logger.warn("WARN"); + assertEquals(2, legacyAppender.getEvents().size()); + // accept + logger.error("ERROR"); + assertEquals(3, legacyAppender.getEvents().size()); + // deny + logger.fatal("FATAL"); + assertEquals(3, legacyAppender.getEvents().size()); } } @@ -321,4 +349,19 @@ public void testUntrimmedValues() throws Exception { public void testGlobalThreshold() throws Exception { super.testGlobalThreshold(); } + + @Test + public void testEnhancedRollingFileAppender() throws Exception { + try (final LoggerContext ctx = configure("config-1.2/log4j-EnhancedRollingFileAppender")) { + final Configuration configuration = ctx.getConfiguration(); + assertNotNull(configuration); + testEnhancedRollingFileAppender(configuration); + } + } + + @Override + @Test + public void testLevelRangeFilter() throws Exception { + super.testLevelRangeFilter(); + } } diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java index 500d0caad5d..eb934c085e6 100644 --- a/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/config/XmlConfigurationTest.java @@ -16,6 +16,7 @@ */ package org.apache.log4j.config; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -34,6 +35,11 @@ import org.apache.log4j.xml.XmlConfigurationFactory; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.RollingFileAppender; +import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy; +import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy; +import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy; +import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.test.junit.ConfigurationFactoryType; @@ -51,8 +57,7 @@ public class XmlConfigurationTest extends AbstractLog4j1ConfigurationTest { @Override Configuration getConfiguration(final String configResourcePrefix) throws URISyntaxException, IOException { final String configResource = configResourcePrefix + SUFFIX; - final InputStream inputStream = ClassLoader.getSystemResourceAsStream(configResource); - assertNotNull(inputStream); + final InputStream inputStream = getResourceAsStream(configResource); final ConfigurationSource source = new ConfigurationSource(inputStream); final LoggerContext context = LoggerContext.getContext(false); final Configuration configuration = context.getConfiguration(source); @@ -181,4 +186,28 @@ public void testMultipleFilters(final @TempDir Path tmpFolder) throws Exception public void testGlobalThreshold() throws Exception { super.testGlobalThreshold(); } + + @Test + public void testEnhancedRollingFileAppender() throws Exception { + try (final LoggerContext ctx = configure("config-1.2/log4j-EnhancedRollingFileAppender")) { + final Configuration configuration = ctx.getConfiguration(); + assertNotNull(configuration); + testEnhancedRollingFileAppender(configuration); + // Only supported through XML configuration + final Appender appender = configuration.getAppender("MIXED"); + assertTrue(appender instanceof RollingFileAppender, "is RollingFileAppender"); + final TriggeringPolicy policy = ((RollingFileAppender) appender).getTriggeringPolicy(); + assertTrue(policy instanceof CompositeTriggeringPolicy, "is CompositeTriggeringPolicy"); + final TriggeringPolicy[] policies = ((CompositeTriggeringPolicy) policy).getTriggeringPolicies(); + assertEquals(2, policies.length); + assertTrue(policies[0] instanceof TimeBasedTriggeringPolicy, "is TimeBasedTriggeringPolicy"); + assertTrue(policies[1] instanceof SizeBasedTriggeringPolicy, "is SizeBasedTriggeringPolicy"); + } + } + + @Override + @Test + public void testLevelRangeFilter() throws Exception { + super.testLevelRangeFilter(); + } } diff --git a/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties b/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties index d417fb85c71..9fc31300b5f 100644 --- a/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties +++ b/log4j-1.2-api/src/test/resources/LOG4J2-3326.properties @@ -15,9 +15,12 @@ # limitations under the License. # -log4j.appender.CUSTOM=org.apache.log4j.CustomNoopAppender +log4j.appender.CUSTOM=org.apache.log4j.ListAppender log4j.appender.CUSTOM.filter.1=org.apache.log4j.varia.LevelRangeFilter log4j.appender.CUSTOM.filter.1.levelMin=ALL log4j.appender.CUSTOM.filter.2=org.apache.log4j.varia.LevelRangeFilter +log4j.appender.CUSTOM.filter.2.levelMin=INFO +log4j.appender.CUSTOM.filter.2.levelMax=ERROR +log4j.appender.CUSTOM.filter.3=org.apache.log4j.varia.LevelRangeFilter log4j.rootLogger=trace, CUSTOM diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-EnhancedRollingFileAppender.properties b/log4j-1.2-api/src/test/resources/config-1.2/log4j-EnhancedRollingFileAppender.properties new file mode 100644 index 00000000000..a0ef860d21c --- /dev/null +++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-EnhancedRollingFileAppender.properties @@ -0,0 +1,65 @@ +# +# 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. +# + +############################################################################### +# +# Log4J 1.2 Configuration. +# + +log4j.rootLogger=TRACE, DEFAULT_TIME, DEFAULT_SIZE, TIME, SIZE + +log4j.appender.DEFAULT_TIME = org.apache.log4j.rolling.RollingFileAppender +log4j.appender.DEFAULT_TIME.layout = org.apache.log4j.SimpleLayout +log4j.appender.DEFAULT_TIME.File = target/EnhancedRollingFileAppender/defaultTime.log +log4j.appender.DEFAULT_TIME.rollingPolicy = org.apache.log4j.rolling.TimeBasedRollingPolicy +log4j.appender.DEFAULT_TIME.rollingPolicy.FileNamePattern = target/EnhancedRollingFileAppender/defaultTime.%d{yyyy-MM-dd}.log + +log4j.appender.DEFAULT_SIZE = org.apache.log4j.rolling.RollingFileAppender +log4j.appender.DEFAULT_SIZE.File = target/EnhancedRollingFileAppender/defaultSize.log +log4j.appender.DEFAULT_SIZE.layout = org.apache.log4j.SimpleLayout +log4j.appender.DEFAULT_SIZE.triggeringPolicy = org.apache.log4j.rolling.SizeBasedTriggeringPolicy +log4j.appender.DEFAULT_SIZE.rollingPolicy = org.apache.log4j.rolling.FixedWindowRollingPolicy +log4j.appender.DEFAULT_SIZE.rollingPolicy.FileNamePattern = target/EnhancedRollingFileAppender/defaultSize.%i.log + +log4j.appender.TIME = org.apache.log4j.rolling.RollingFileAppender +log4j.appender.TIME.Append = false +log4j.appender.TIME.BufferedIO = true +log4j.appender.TIME.BufferSize = 1000 +log4j.appender.TIME.File = target/EnhancedRollingFileAppender/ignoredTime.log +log4j.appender.TIME.ImmediateFlush = false +log4j.appender.TIME.layout = org.apache.log4j.SimpleLayout +log4j.appender.TIME.triggeringPolicy = org.apache.log4j.rolling.TimeBasedRollingPolicy +# It is explicitly not a TimeBasedRolling +log4j.appender.TIME.rollingPolicy = org.apache.log4j.rolling.FixedWindowRollingPolicy +log4j.appender.TIME.rollingPolicy.ActiveFileName = target/EnhancedRollingFileAppender/time.log +log4j.appender.TIME.rollingPolicy.FileNamePattern = target/EnhancedRollingFileAppender/time.%d{yyyy-MM-dd}.log + +log4j.appender.SIZE = org.apache.log4j.rolling.RollingFileAppender +log4j.appender.SIZE.Append = false +log4j.appender.SIZE.BufferedIO = true +log4j.appender.SIZE.BufferSize = 1000 +log4j.appender.SIZE.File = target/EnhancedRollingFileAppender/ignoredSize.log +log4j.appender.SIZE.ImmediateFlush = false +log4j.appender.SIZE.layout = org.apache.log4j.SimpleLayout +log4j.appender.SIZE.FileName = target/EnhancedRollingFileAppender/size.log +log4j.appender.SIZE.triggeringPolicy = org.apache.log4j.rolling.SizeBasedTriggeringPolicy +log4j.appender.SIZE.triggeringPolicy.MaxFileSize = 10000000 +log4j.appender.SIZE.rollingPolicy = org.apache.log4j.rolling.FixedWindowRollingPolicy +log4j.appender.SIZE.rollingPolicy.ActiveFileName = target/EnhancedRollingFileAppender/size.log +log4j.appender.SIZE.rollingPolicy.FileNamePattern = target/EnhancedRollingFileAppender/size.%i.log +log4j.appender.SIZE.rollingPolicy.MinIndex = 11 +log4j.appender.SIZE.rollingPolicy.MaxIndex = 20 diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-EnhancedRollingFileAppender.xml b/log4j-1.2-api/src/test/resources/config-1.2/log4j-EnhancedRollingFileAppender.xml new file mode 100644 index 00000000000..a568dc21ca2 --- /dev/null +++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-EnhancedRollingFileAppender.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.properties b/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.properties new file mode 100644 index 00000000000..b84788b417d --- /dev/null +++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.properties @@ -0,0 +1,23 @@ +# +# 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. +# + +log4j.appender.LIST = org.apache.log4j.ListAppender +log4j.appender.LIST.filter.1 = org.apache.log4j.varia.LevelRangeFilter +log4j.appender.LIST.filter.1.LevelMin = INFO +log4j.appender.LIST.filter.1.LevelMax = ERROR +log4j.appender.LIST.filter.1.AcceptOnMatch = false +log4j.rootLogger = debug, LIST diff --git a/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.xml b/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.xml new file mode 100644 index 00000000000..ab4cdd7e5a4 --- /dev/null +++ b/log4j-1.2-api/src/test/resources/config-1.2/log4j-LevelRangeFilter.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelRangeFilter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelRangeFilter.java index 7d4adbc4f9e..e0402cd5688 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelRangeFilter.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/LevelRangeFilter.java @@ -265,16 +265,10 @@ public Result filter( return filter(level); } - /** - * @return the minimum level threshold - */ public Level getMinLevel() { return minLevel; } - /** - * @return the maximum level threshold - */ public Level getMaxLevel() { return maxLevel; } diff --git a/pom.xml b/pom.xml index 33111db267d..f1d578c2d3f 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.apache.logging logging-parent - 10.5.0 + 10.6.0 diff --git a/src/changelog/.3.x.x/update_org_apache_logging_logging_parent.xml b/src/changelog/.3.x.x/update_org_apache_logging_logging_parent.xml index 4eaf7d0ed4b..cb1345c9140 100644 --- a/src/changelog/.3.x.x/update_org_apache_logging_logging_parent.xml +++ b/src/changelog/.3.x.x/update_org_apache_logging_logging_parent.xml @@ -3,6 +3,6 @@ xmlns="http://logging.apache.org/log4j/changelog" xsi:schemaLocation="http://logging.apache.org/log4j/changelog https://logging.apache.org/log4j/changelog-0.1.3.xsd" type="updated"> - - Update `org.apache.logging:logging-parent` to version `10.5.0` + + Update `org.apache.logging:logging-parent` to version `10.6.0` diff --git a/src/site/_release-notes/_3.x.x.adoc b/src/site/_release-notes/_3.x.x.adoc index bc2b6fcdf19..0b495a76f1f 100644 --- a/src/site/_release-notes/_3.x.x.adoc +++ b/src/site/_release-notes/_3.x.x.adoc @@ -59,7 +59,7 @@ This release contains... * Update `com.fasterxml.jackson:jackson-bom` to version `2.16.1` (https://github.com/apache/logging-log4j2/pull/2127[2127]) * Update `com.github.h-thurow:simple-jndi` to version `0.24.0` (https://github.com/apache/logging-log4j2/pull/2195[2195]) * Update `org.apache.groovy:groovy-bom` to version `4.0.17` (https://github.com/apache/logging-log4j2/pull/2124[2124]) -* Update `org.apache.logging:logging-parent` to version `10.5.0` (https://github.com/apache/logging-log4j2/pull/2118[2118]) +* Update `org.apache.logging:logging-parent` to version `10.6.0` (https://github.com/apache/logging-log4j2/pull/2193[2193]) * Update `org.apache.maven.surefire:surefire-junit47` to version `3.2.5` (https://github.com/apache/logging-log4j2/pull/2177[2177]) * Update `org.apache.tomcat:tomcat-juli` to version `10.1.18` (https://github.com/apache/logging-log4j2/pull/2176[2176]) * Update `org.assertj:assertj-core` to version `3.25.1` (https://github.com/apache/logging-log4j2/pull/2152[2152])