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

vy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/main by this push:
     new f04667fda8 LOG4J2-3660 Fix `%notEmpty` for empty MDC/NDC inputs
f04667fda8 is described below

commit f04667fda86804c882dc3cfab4604f5526a0400b
Author: Volkan Yazıcı <vol...@yazi.ci>
AuthorDate: Sun Apr 23 21:28:04 2023 +0200

    LOG4J2-3660 Fix `%notEmpty` for empty MDC/NDC inputs
---
 .../VariablesNotEmptyReplacementConverterTest.java | 16 +++++++++++
 .../core/pattern/LogEventPatternConverter.java     |  8 ++++++
 .../log4j/core/pattern/MdcPatternConverter.java    |  9 ++++---
 .../log4j/core/pattern/NdcPatternConverter.java    |  6 +++++
 .../VariablesNotEmptyReplacementConverter.java     | 31 ++++++++++++++++++++--
 5 files changed, 65 insertions(+), 5 deletions(-)

diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverterTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverterTest.java
index 34a8a137f2..580e994167 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverterTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverterTest.java
@@ -58,6 +58,21 @@ public class VariablesNotEmptyReplacementConverterTest {
         testReplacement("%logger", "[" + 
VariablesNotEmptyReplacementConverterTest.class.getName() + "]");
     }
 
+    @Test
+    void empty_NDC_should_be_replaced() {
+        testReplacement("%NDC", "");
+    }
+
+    @Test
+    void empty_MDC_should_be_replaced() {
+        testReplacement("%mdc", "");
+    }
+
+    @Test
+    void MDC_with_non_existent_keys_should_be_replaced() {
+        testReplacement("%mdc{noSuchKey1,noSuchKey2}", "");
+    }
+
     private void testReplacement(final String tag, final String expectedValue) 
{
         final LogEvent event = Log4jLogEvent.newBuilder() //
                 
.setLoggerName(VariablesNotEmptyReplacementConverterTest.class.getName()) //
@@ -73,4 +88,5 @@ public class VariablesNotEmptyReplacementConverterTest {
         converter.format(event, sb);
         assertEquals(expectedValue, sb.toString());
     }
+
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LogEventPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LogEventPatternConverter.java
index 2ff42974fe..2958e4bef2 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LogEventPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LogEventPatternConverter.java
@@ -77,4 +77,12 @@ public abstract class LogEventPatternConverter extends 
AbstractPatternConverter
     public boolean isVariable() {
         return true;
     }
+
+    /**
+     * @return the formatted output when the input variable (MDC, NDC, etc.) 
is empty
+     */
+    public String emptyVariableOutput() {
+        return "";
+    }
+
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MdcPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MdcPatternConverter.java
index 9649886607..7c1ff18031 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MdcPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/MdcPatternConverter.java
@@ -16,9 +16,6 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.plugins.Namespace;
-import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.util.PerformanceSensitive;
 import org.apache.logging.log4j.util.ReadOnlyStringMap;
 import org.apache.logging.log4j.util.StringBuilders;
@@ -147,4 +144,10 @@ public final class MdcPatternConverter extends 
LogEventPatternConverter {
         }
         sb.append('}');
     }
+
+    @Override
+    public String emptyVariableOutput() {
+        return "{}";
+    }
+
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/NdcPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/NdcPatternConverter.java
index 31deeb1252..9f351036c4 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/NdcPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/NdcPatternConverter.java
@@ -57,4 +57,10 @@ public final class NdcPatternConverter extends 
LogEventPatternConverter {
     public void format(final LogEvent event, final StringBuilder toAppendTo) {
         toAppendTo.append(event.getContextStack());
     }
+
+    @Override
+    public String emptyVariableOutput() {
+        return "[]";
+    }
+
 }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverter.java
index c513ff5cd0..0391ec67be 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/VariablesNotEmptyReplacementConverter.java
@@ -83,13 +83,40 @@ public final class VariablesNotEmptyReplacementConverter 
extends LogEventPattern
             final PatternFormatter formatter = formatters.get(i);
             final int formatterStart = toAppendTo.length();
             formatter.format(event, toAppendTo);
-            if (formatter.getConverter().isVariable()) {
+            LogEventPatternConverter converter = formatter.getConverter();
+            if (converter.isVariable()) {
                 hasVars = true;
-                allVarsEmpty = allVarsEmpty && (toAppendTo.length() == 
formatterStart);
+                allVarsEmpty = allVarsEmpty && 
sequenceRegionMatches(toAppendTo, formatterStart, 
converter.emptyVariableOutput());
             }
         }
         if (!hasVars || allVarsEmpty) {
             toAppendTo.setLength(start); // remove formatter results
         }
     }
+
+    /**
+     * @param sequence1 the 1st sequence
+     * @param sequence1Offset the start index of the 1st sequence region
+     * @param sequence2 the 2nd sequence
+     * @return {@code true}, if the pointed region of the 1st sequence matches 
to the 2nd sequence; {@code false}, otherwise
+     */
+    private static boolean sequenceRegionMatches(
+            final CharSequence sequence1,
+            final int sequence1Offset,
+            final CharSequence sequence2) {
+        final boolean lengthMatches = (sequence1.length() - sequence1Offset) 
== sequence2.length();
+        if (!lengthMatches) {
+            return false;
+        }
+        for (int i2 = 0; i2 < sequence2.length(); i2++) {
+            final char c2 = sequence2.charAt(i2);
+            final int i1 = i2 + sequence1Offset;
+            final char c1 = sequence1.charAt(i1);
+            if (c2 != c1) {
+                return false;
+            }
+        }
+        return true;
+    }
+
 }

Reply via email to