This is an automated email from the ASF dual-hosted git repository.

rgoers pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/release-2.x by this push:
     new bd1ad8ae21 LOG4J2-3432 - SizeBasedTriggeringPolicy would fail to 
rename files properly when integer pattern contained a leading zero.
bd1ad8ae21 is described below

commit bd1ad8ae21d63df93184a7b2de89d2612474b23b
Author: Ralph Goers <[email protected]>
AuthorDate: Tue May 24 09:22:01 2022 -0600

    LOG4J2-3432 - SizeBasedTriggeringPolicy would fail to rename files properly 
when integer pattern contained a leading zero.
---
 .../appender/rolling/AbstractRolloverStrategy.java |   2 +-
 .../appender/rolling/DefaultRolloverStrategy.java  |   3 +-
 .../core/appender/rolling/PatternProcessor.java    |   8 ++
 .../rolling/RollingAppenderSizeMaxWidthTest.java   | 159 +++++++++++++++++++++
 .../resources/log4j-rolling-size-max-width-1.xml   |  49 +++++++
 .../resources/log4j-rolling-size-max-width-2.xml   |  49 +++++++
 .../resources/log4j-rolling-size-max-width-3.xml   |  49 +++++++
 .../resources/log4j-rolling-size-max-width-4.xml   |  53 +++++++
 src/changes/changes.xml                            |   3 +
 9 files changed, 373 insertions(+), 2 deletions(-)

diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/AbstractRolloverStrategy.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/AbstractRolloverStrategy.java
index d16f778f86..da720c08a1 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/AbstractRolloverStrategy.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/AbstractRolloverStrategy.java
@@ -131,7 +131,7 @@ public abstract class AbstractRolloverStrategy implements 
RolloverStrategy {
         }
         // since we insert a pattern inside a regex escaped string,
         // surround it with quote characters so that (\d) is treated as a 
pattern and not a literal
-        final String filePattern = fileName.replaceFirst("0?\\u0000", 
"\\\\E(0?\\\\d+)\\\\Q");
+        final String filePattern = fileName.replaceFirst("0*\\u0000", 
"\\\\E(0?\\\\d+)\\\\Q");
         final Pattern pattern = Pattern.compile(filePattern);
         final Path current = currentFile.length() > 0 ? new 
File(currentFile).toPath() : null;
         LOGGER.debug("Current file: {}", currentFile);
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
index d12af4a4d7..e38f1de51d 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
@@ -414,7 +414,7 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
     private int purgeAscending(final int lowIndex, final int highIndex, final 
RollingFileManager manager) {
         final SortedMap<Integer, Path> eligibleFiles = 
getEligibleFiles(manager);
         final int maxFiles = highIndex - lowIndex + 1;
-
+        LOGGER.debug("Eligible files: {}", eligibleFiles);
         boolean renameFiles = !eligibleFiles.isEmpty() && 
eligibleFiles.lastKey() >= maxIndex;
         while (eligibleFiles.size() >= maxFiles) {
             try {
@@ -475,6 +475,7 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
         while (eligibleFiles.size() >= maxFiles) {
             try {
                 final Integer key = eligibleFiles.firstKey();
+                LOGGER.debug("Deleting {}", 
eligibleFiles.get(key).toFile().getAbsolutePath());
                 Files.delete(eligibleFiles.get(key));
                 eligibleFiles.remove(key);
             } catch (final IOException ioe) {
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java
index 89d52668a2..352f36c1c8 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java
@@ -109,6 +109,14 @@ public class PatternProcessor {
         this.currentFileTime = copy.currentFileTime;
     }
 
+    public FormattingInfo[] getPatternFields() {
+        return patternFields;
+    }
+
+    public ArrayPatternConverter[] getPatternConverters() {
+        return patternConverters;
+    }
+
     public void setTimeBased(boolean isTimeBased) {
         this.isTimeBased = isTimeBased;
     }
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeMaxWidthTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeMaxWidthTest.java
new file mode 100644
index 0000000000..0f9abed6fa
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeMaxWidthTest.java
@@ -0,0 +1,159 @@
+/*
+ * 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.appender.rolling;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.appender.RollingFileAppender;
+import org.apache.logging.log4j.core.pattern.ArrayPatternConverter;
+import org.apache.logging.log4j.core.pattern.FormattingInfo;
+import org.apache.logging.log4j.core.pattern.IntegerPatternConverter;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ *
+ */
+@RunWith(Parameterized.class)
+public class RollingAppenderSizeMaxWidthTest implements RolloverListener {
+    @Parameterized.Parameters(name = "{0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {
+                { new LoggerContextRule("log4j-rolling-size-max-width-1.xml"), 
},
+                { new LoggerContextRule("log4j-rolling-size-max-width-2.xml"), 
},
+                { new LoggerContextRule("log4j-rolling-size-max-width-3.xml"), 
},
+                { new LoggerContextRule("log4j-rolling-size-max-width-4.xml"), 
},
+        });
+    }
+    private static final String DIR = "target/rolling-max-width/archive";
+    private static final String MESSAGE = "This is test message number ";
+    private static final int COUNT = 10000;
+    private static final int[] POWERS_OF_10 = {1, 10, 100, 1000, 10000, 
100000, 1000000, 10000000, 100000000,
+            1000000000};
+    public LoggerContextRule loggerContextRule;
+    @Rule
+    public RuleChain chain;
+    List<String> rolledFileNames = new ArrayList<>();
+    int min;
+    int max;
+    boolean isZeroPad;
+    int minWidth;
+    int maxWidth;
+    long rolloverSize;
+    private Logger logger;
+    private int rolloverCount = 0;
+
+    private static int powerOfTen(int pow) {
+        if (pow > POWERS_OF_10.length) {
+            throw new IllegalArgumentException("Max width is too large");
+        }
+        return POWERS_OF_10[pow];
+    }
+
+    public RollingAppenderSizeMaxWidthTest(final LoggerContextRule 
loggerContextRule) {
+        this.loggerContextRule = loggerContextRule;
+        this.chain = loggerContextRule.withCleanFoldersRule(DIR);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        this.logger = 
loggerContextRule.getLogger(RollingAppenderSizeMaxWidthTest.class.getName());
+        RollingFileAppender app = (RollingFileAppender) 
loggerContextRule.getRequiredAppender("RollingFile");
+        app.getManager().addRolloverListener(this);
+        ArrayPatternConverter[] patternConverters = 
app.getManager().getPatternProcessor().getPatternConverters();
+        int index = IntStream.range(0, patternConverters.length)
+                .filter(i -> patternConverters[i] instanceof 
IntegerPatternConverter).findFirst().orElse(-1);
+        if (index < 0) {
+            fail("Could not find integer pattern converter in " + 
app.getFilePattern());
+        }
+        FormattingInfo formattingInfo = 
app.getManager().getPatternProcessor().getPatternFields()[index];
+        minWidth = formattingInfo.getMinLength();
+        maxWidth = formattingInfo.getMaxLength();
+        isZeroPad = formattingInfo.isZeroPad();
+        DefaultRolloverStrategy strategy = (DefaultRolloverStrategy) 
app.getManager().getRolloverStrategy();
+        min = strategy.getMinIndex();
+        max = strategy.getMaxIndex();
+        SizeBasedTriggeringPolicy policy;
+        if (app.getTriggeringPolicy() instanceof CompositeTriggeringPolicy) {
+            policy = (SizeBasedTriggeringPolicy) 
Arrays.stream(((CompositeTriggeringPolicy) app.getTriggeringPolicy())
+                    .getTriggeringPolicies()).filter((p) -> p instanceof 
SizeBasedTriggeringPolicy).findFirst()
+                    .orElse(null);
+        } else {
+            policy = app.getTriggeringPolicy();
+        }
+        assertNotNull("No SizeBasedTriggeringPolicy", policy);
+        rolloverSize = policy.getMaxFileSize();
+    }
+
+    @Test
+    public void testAppender() throws Exception {
+        if (minWidth > 0) {
+            assertTrue("min must be greater than or equal to the minimum 
width",
+                    min > -powerOfTen(minWidth));
+        }
+        if (maxWidth < Integer.MAX_VALUE) {
+            assertTrue("max must be less than or equal to the maximum width",
+                    max <= powerOfTen(maxWidth));
+        }
+        long bytes = 0;
+        for (int i = 0; i < 10000; ++i) {
+            String message = MESSAGE + i;
+            logger.debug(message);
+            bytes += message.length() + 1;
+        }
+        final long minExpected = ((bytes / rolloverSize) * 95) / 100;
+        final long maxExpected = ((bytes / rolloverSize) * 105) / 100;
+        final File dir = new File(DIR);
+        assertTrue("Directory not created", dir.exists());
+        final File[] files = dir.listFiles();
+        assertNotNull(files);
+        assertTrue("Not enough rollovers: expected: " + minExpected + ", 
actual: " + rolloverCount,
+                rolloverCount + 1 >= minExpected);
+        assertTrue("Too many rollovers: expected: " + maxExpected + ", actual: 
" + rolloverCount,
+                rolloverCount <= maxExpected);
+        int maxFiles = max - min + 1;
+        int maxExpectedFiles = Math.min(maxFiles, rolloverCount);
+        assertEquals("More files than expected. expected: " + maxExpectedFiles 
+ ", actual: " + files.length,
+                maxExpectedFiles, files.length);
+    }
+
+    @Override
+    public void rolloverTriggered(String fileName) {
+        ++rolloverCount;
+    }
+
+    @Override
+    public void rolloverComplete(String fileName) {
+        rolledFileNames.add(fileName);
+    }
+}
diff --git a/log4j-core/src/test/resources/log4j-rolling-size-max-width-1.xml 
b/log4j-core/src/test/resources/log4j-rolling-size-max-width-1.xml
new file mode 100644
index 0000000000..95525ea370
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-rolling-size-max-width-1.xml
@@ -0,0 +1,49 @@
+<?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="WARN" name="XMLConfigTest">
+  <Properties>
+    <Property 
name="filename">target/rolling-max-width/rollingtest.log</Property>
+  </Properties>
+  <ThresholdFilter level="debug"/>
+
+  <Appenders>
+    <Console name="STDOUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+    <RollingFile name="RollingFile" fileName="${filename}"
+                 
filePattern="target/rolling-max-width/archive/rollingtest.log.%02i">
+      <PatternLayout>
+        <Pattern>%m%n</Pattern>
+      </PatternLayout>
+      <SizeBasedTriggeringPolicy size="1000" />
+      <DefaultRolloverStrategy min = "1" max="100"/>
+    </RollingFile>
+  </Appenders>
+
+  <Loggers>
+    <Logger name="org.apache.logging.log4j.core.appender.rolling" 
level="debug" additivity="false">
+      <AppenderRef ref="RollingFile"/>
+    </Logger>
+
+    <Root level="error">
+      <AppenderRef ref="STDOUT"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
\ No newline at end of file
diff --git a/log4j-core/src/test/resources/log4j-rolling-size-max-width-2.xml 
b/log4j-core/src/test/resources/log4j-rolling-size-max-width-2.xml
new file mode 100644
index 0000000000..1382dd4380
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-rolling-size-max-width-2.xml
@@ -0,0 +1,49 @@
+<?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="WARN" name="XMLConfigTest">
+  <Properties>
+    <Property 
name="filename">target/rolling-max-width/rollingtest.log</Property>
+  </Properties>
+  <ThresholdFilter level="debug"/>
+
+  <Appenders>
+    <Console name="STDOUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+    <RollingFile name="RollingFile" fileName="${filename}"
+                 
filePattern="target/rolling-max-width/archive/rollingtest.log.%02i">
+      <PatternLayout>
+        <Pattern>%m%n</Pattern>
+      </PatternLayout>
+      <SizeBasedTriggeringPolicy size="1000" />
+      <DefaultRolloverStrategy min = "120" max="500"/>
+    </RollingFile>
+  </Appenders>
+
+  <Loggers>
+    <Logger name="org.apache.logging.log4j.core.appender.rolling" 
level="debug" additivity="false">
+      <AppenderRef ref="RollingFile"/>
+    </Logger>
+
+    <Root level="error">
+      <AppenderRef ref="STDOUT"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
\ No newline at end of file
diff --git a/log4j-core/src/test/resources/log4j-rolling-size-max-width-3.xml 
b/log4j-core/src/test/resources/log4j-rolling-size-max-width-3.xml
new file mode 100644
index 0000000000..5a77612e2d
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-rolling-size-max-width-3.xml
@@ -0,0 +1,49 @@
+<?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="WARN" name="XMLConfigTest">
+  <Properties>
+    <Property 
name="filename">target/rolling-max-width/rollingtest.log</Property>
+  </Properties>
+  <ThresholdFilter level="debug"/>
+
+  <Appenders>
+    <Console name="STDOUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+    <RollingFile name="RollingFile" fileName="${filename}"
+                 
filePattern="target/rolling-max-width/archive/rollingtest.log.%06i">
+      <PatternLayout>
+        <Pattern>%m%n</Pattern>
+      </PatternLayout>
+      <SizeBasedTriggeringPolicy size="1000" />
+      <DefaultRolloverStrategy min = "10000" max="99999"/>
+    </RollingFile>
+  </Appenders>
+
+  <Loggers>
+    <Logger name="org.apache.logging.log4j.core.appender.rolling" 
level="debug" additivity="false">
+      <AppenderRef ref="RollingFile"/>
+    </Logger>
+
+    <Root level="error">
+      <AppenderRef ref="STDOUT"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
\ No newline at end of file
diff --git a/log4j-core/src/test/resources/log4j-rolling-size-max-width-4.xml 
b/log4j-core/src/test/resources/log4j-rolling-size-max-width-4.xml
new file mode 100644
index 0000000000..e37698c58e
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-rolling-size-max-width-4.xml
@@ -0,0 +1,53 @@
+<?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="WARN" name="XMLConfigTest">
+  <Properties>
+    <Property 
name="filename">target/rolling-max-width/rollingtest.log</Property>
+  </Properties>
+  <ThresholdFilter level="debug"/>
+
+  <Appenders>
+    <Console name="STDOUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+    <RollingFile name="RollingFile" fileName="${filename}"
+                 
filePattern="target/rolling-max-width/archive/rollingtest-%d{YYYY-MM-dd-HH}-%06i.log">
+      <PatternLayout>
+        <Pattern>%m%n</Pattern>
+      </PatternLayout>
+      <Policies>
+        <OnStartupTriggeringPolicy />
+        <SizeBasedTriggeringPolicy size="1000" />
+        <TimeBasedTriggeringPolicy />
+      </Policies>
+      <DefaultRolloverStrategy min = "10000" max="99999"/>
+    </RollingFile>
+  </Appenders>
+
+  <Loggers>
+    <Logger name="org.apache.logging.log4j.core.appender.rolling" 
level="debug" additivity="false">
+      <AppenderRef ref="RollingFile"/>
+    </Logger>
+
+    <Root level="error">
+      <AppenderRef ref="STDOUT"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
\ No newline at end of file
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 8c9dea221f..cbead83ee8 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -30,6 +30,9 @@
          - "remove" - Removed
     -->
     <release version="2.18.0" date="2022-TBD" description="GA Release 2.18.0">
+      <action issue="LOG4J2-3432" dev="rgoers" type="fix">
+        SizeBasedTriggeringPolicy would fail to rename files properly when 
integer pattern contained a leading zero.
+      </action>
       <action issue="LOG4J2-3491" dev="rgoers" type="fix" due-to="Avihai 
Marchiano">
         Async Loggers were including the location information by default.
       </action>

Reply via email to