Repository: logging-log4j2
Updated Branches:
  refs/heads/master 2ed5d3789 -> e94c9a46e


[LOG4J2-926] Truncate from the end of text format modifier. Also change
next version to 2.2 in changes.xml since this is a new minor feature.

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/e94c9a46
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/e94c9a46
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/e94c9a46

Branch: refs/heads/master
Commit: e94c9a46ed60527422442d0e5d7230dacab25e98
Parents: 2ed5d37
Author: Gary Gregory <[email protected]>
Authored: Mon Mar 9 14:49:50 2015 -0700
Committer: Gary Gregory <[email protected]>
Committed: Mon Mar 9 14:49:50 2015 -0700

----------------------------------------------------------------------
 .../log4j/core/pattern/FormattingInfo.java      | 27 ++++++++--
 .../log4j/core/pattern/PatternParser.java       | 32 ++++++-----
 .../log4j/core/pattern/FormattingInfoTest.java  | 57 ++++++++++++++++++++
 .../log4j/core/pattern/PatternParserTest.java   | 37 ++++++++++++-
 src/changes/changes.xml                         |  5 +-
 src/site/xdoc/manual/layouts.xml.vm             | 15 ++++++
 6 files changed, 156 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
index 950a7d5..d252bd6 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
@@ -29,7 +29,7 @@ public final class FormattingInfo {
     /**
      * Default instance.
      */
-    private static final FormattingInfo DEFAULT = new FormattingInfo(false, 0, 
Integer.MAX_VALUE);
+    private static final FormattingInfo DEFAULT = new FormattingInfo(false, 0, 
Integer.MAX_VALUE, true);
 
     /**
      * Minimum length.
@@ -47,6 +47,11 @@ public final class FormattingInfo {
     private final boolean leftAlign;
 
     /**
+     * Left vs. right-hand side truncation.
+     */
+    private final boolean leftTruncate;
+
+    /**
      * Creates new instance.
      *
      * @param leftAlign
@@ -56,10 +61,11 @@ public final class FormattingInfo {
      * @param maxLength
      *            maximum length.
      */
-    public FormattingInfo(final boolean leftAlign, final int minLength, final 
int maxLength) {
+    public FormattingInfo(final boolean leftAlign, final int minLength, final 
int maxLength, final boolean leftTruncate) {
         this.leftAlign = leftAlign;
         this.minLength = minLength;
         this.maxLength = maxLength;
+        this.leftTruncate = leftTruncate;
     }
 
     /**
@@ -81,6 +87,15 @@ public final class FormattingInfo {
     }
 
     /**
+     * Determine if left truncated.
+     *
+     * @return true if left truncated.
+     */
+    public boolean isLeftTruncate() {
+               return leftTruncate;
+       }
+
+    /**
      * Get minimum length.
      *
      * @return minimum length.
@@ -110,7 +125,11 @@ public final class FormattingInfo {
         final int rawLength = buffer.length() - fieldStart;
 
         if (rawLength > maxLength) {
-            buffer.delete(fieldStart, buffer.length() - maxLength);
+                       if (leftTruncate) {
+                               buffer.delete(fieldStart, buffer.length() - 
maxLength);
+                       } else {
+                               buffer.delete(fieldStart + maxLength, 
fieldStart + buffer.length());
+                       }
         } else if (rawLength < minLength) {
             if (leftAlign) {
                 final int fieldEnd = buffer.length();
@@ -146,6 +165,8 @@ public final class FormattingInfo {
         sb.append(maxLength);
         sb.append(", minLength=");
         sb.append(minLength);
+        sb.append(", leftTruncate=");
+        sb.append(leftTruncate);
         sb.append(']');
         return sb.toString();
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
index c0a7b9e..b8b4db3 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
@@ -362,7 +362,7 @@ public final class PatternParser {
                 switch (c) {
                 case '-':
                     formattingInfo = new FormattingInfo(true, 
formattingInfo.getMinLength(),
-                            formattingInfo.getMaxLength());
+                            formattingInfo.getMaxLength(), 
formattingInfo.isLeftTruncate());
                     break;
 
                 case '.':
@@ -373,7 +373,7 @@ public final class PatternParser {
 
                     if (c >= '0' && c <= '9') {
                         formattingInfo = new 
FormattingInfo(formattingInfo.isLeftAligned(), c - '0',
-                                formattingInfo.getMaxLength());
+                                formattingInfo.getMaxLength(), 
formattingInfo.isLeftTruncate());
                         state = ParserState.MIN_STATE;
                     } else {
                         i = finalizeConverter(c, pattern, i, currentLiteral, 
formattingInfo, converterRules,
@@ -394,7 +394,7 @@ public final class PatternParser {
                 if (c >= '0' && c <= '9') {
                     // Multiply the existing value and add the value of the 
number just encountered.
                     formattingInfo = new 
FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength()
-                            * DECIMAL + c - '0', 
formattingInfo.getMaxLength());
+                            * DECIMAL + c - '0', 
formattingInfo.getMaxLength(), formattingInfo.isLeftTruncate());
                 } else if (c == '.') {
                     state = ParserState.DOT_STATE;
                 } else {
@@ -409,16 +409,24 @@ public final class PatternParser {
 
             case DOT_STATE:
                 currentLiteral.append(c);
-
-                if (c >= '0' && c <= '9') {
+                switch (c) {
+                case '-':
                     formattingInfo = new 
FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(),
-                            c - '0');
-                    state = ParserState.MAX_STATE;
-                } else {
-                    LOGGER.error("Error occurred in position " + i + ".\n Was 
expecting digit, instead got char \"" + c
-                            + "\".");
+                            formattingInfo.getMaxLength(),false);
+                    break;
 
-                    state = ParserState.LITERAL_STATE;
+                default:
+
+                       if (c >= '0' && c <= '9') {
+                           formattingInfo = new 
FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(),
+                                   c - '0', formattingInfo.isLeftTruncate());
+                           state = ParserState.MAX_STATE;
+                       } else {
+                           LOGGER.error("Error occurred in position " + i + 
".\n Was expecting digit, instead got char \"" + c
+                                   + "\".");
+
+                           state = ParserState.LITERAL_STATE;
+                       }
                 }
 
                 break;
@@ -429,7 +437,7 @@ public final class PatternParser {
                 if (c >= '0' && c <= '9') {
                     // Multiply the existing value and add the value of the 
number just encountered.
                     formattingInfo = new 
FormattingInfo(formattingInfo.isLeftAligned(), formattingInfo.getMinLength(),
-                            formattingInfo.getMaxLength() * DECIMAL + c - '0');
+                            formattingInfo.getMaxLength() * DECIMAL + c - '0', 
formattingInfo.isLeftTruncate());
                 } else {
                     i = finalizeConverter(c, pattern, i, currentLiteral, 
formattingInfo, converterRules,
                             patternConverters, formattingInfos, 
noConsoleNoAnsi, convertBackslashes);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/FormattingInfoTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/FormattingInfoTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/FormattingInfoTest.java
new file mode 100644
index 0000000..e2f9621
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/FormattingInfoTest.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.logging.log4j.core.pattern;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+/**
+ * Testing FormattingInfo.
+ */
+public class FormattingInfoTest {
+
+       @Test
+       public void testFormatTruncateFromBeginning() {
+               StringBuilder message = new StringBuilder("Hello, world");
+
+               FormattingInfo formattingInfo = new FormattingInfo(false, 0, 5, 
true);
+               formattingInfo.format(0, message);
+
+               assertEquals("world", message.toString());
+       }
+
+       @Test
+       public void testFormatTruncateFromEnd() {
+               StringBuilder message = new StringBuilder("Hello, world");
+
+               FormattingInfo formattingInfo = new FormattingInfo(false, 0, 5, 
false);
+               formattingInfo.format(0, message);
+
+               assertEquals("Hello", message.toString());
+       }
+
+       @Test
+       public void testFormatTruncateFromEndGivenFieldStart() {
+               StringBuilder message = new StringBuilder("2015-03-09 
11:49:28,295; INFO  org.apache.logging.log4j.PatternParserTest");
+
+               FormattingInfo formattingInfo = new FormattingInfo(false, 0, 5, 
false);
+               formattingInfo.format(31, message);
+
+               assertEquals("2015-03-09 11:49:28,295; INFO  org.a", 
message.toString());
+       }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
index 075bb19..9bd118b 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/PatternParserTest.java
@@ -54,6 +54,8 @@ public class PatternParserTest {
 
     private static String badPattern = "[%d{yyyyMMdd HH:mm:ss,SSS] %-5p 
[%c{10}] - %m%n";
     private static String customPattern = "[%d{yyyyMMdd HH:mm:ss,SSS}] %-5p 
[%-25.25c{1}:%-4L] - %m%n";
+    private static String patternTruncateFromEnd = "%d; %-5p %5.-5c %m%n";
+    private static String patternTruncateFromBeginning = "%d; %-5p %5.5c %m%n";
     private static String nestedPatternHighlight =
             "%highlight{%d{dd MMM yyyy HH:mm:ss,SSS}{GMT+0} [%t] %-5level: 
%msg%n%throwable}";
 
@@ -102,9 +104,42 @@ public class PatternParserTest {
             formatter.format(event, buf);
         }
         final String str = buf.toString();
-        final String expected = "INFO  [PatternParserTest        :95  ] - 
Hello, world" + Constants.LINE_SEPARATOR;
+        final String expected = "INFO  [PatternParserTest        :97  ] - 
Hello, world" + Constants.LINE_SEPARATOR;
         assertTrue("Expected to end with: " + expected + ". Actual: " + str, 
str.endsWith(expected));
     }
+
+    @Test
+    public void testPatternTruncateFromBeginning() {
+        final List<PatternFormatter> formatters = 
parser.parse(patternTruncateFromBeginning);
+        assertNotNull(formatters);
+        final LogEvent event = new 
Log4jLogEvent("org.apache.logging.log4j.PatternParserTest", null,
+            Logger.class.getName(), Level.INFO, new SimpleMessage("Hello, 
world"), null,
+            null, null, "Thread1", null, System.currentTimeMillis());
+        final StringBuilder buf = new StringBuilder();
+        for (final PatternFormatter formatter : formatters) {
+            formatter.format(event, buf);
+        }
+        final String str = buf.toString();
+        final String expected = "INFO  rTest Hello, world" + 
Constants.LINE_SEPARATOR;
+        assertTrue("Expected to end with: " + expected + ". Actual: " + str, 
str.endsWith(expected));
+    }
+
+    @Test
+    public void testPatternTruncateFromEnd() {
+        final List<PatternFormatter> formatters = 
parser.parse(patternTruncateFromEnd);
+        assertNotNull(formatters);
+        final LogEvent event = new 
Log4jLogEvent("org.apache.logging.log4j.PatternParserTest", null,
+            Logger.class.getName(), Level.INFO, new SimpleMessage("Hello, 
world"), null,
+            null, null, "Thread1", null, System.currentTimeMillis());
+        final StringBuilder buf = new StringBuilder();
+        for (final PatternFormatter formatter : formatters) {
+            formatter.format(event, buf);
+        }
+        final String str = buf.toString();
+        final String expected = "INFO  org.a Hello, world" + 
Constants.LINE_SEPARATOR;
+        assertTrue("Expected to end with: " + expected + ". Actual: " + str, 
str.endsWith(expected));
+    }
+
     
     @Test
     public void testBadPattern() {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 25b9d1d..ff407ba 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -23,7 +23,10 @@
     <title>Changes</title>
   </properties>
   <body>
-    <release version="2.2.1" date="2015-0?-??" description="GA Release 2.2.1">
+    <release version="2.2" date="2015-0?-??" description="GA Release 2.2">
+      <action issue="LOG4J2-926" dev="ggregory" type="add" due-to="David 
Ohana">
+        Truncate from the end of text format modifier.
+      </action>
       <action issue="LOG4J2-966" dev="ggregory" type="fix" due-to="Gary 
Gregory">
         KeyStoreConfiguration.createKeyStoreConfiguration() ignores 
keyManagerFactoryAlgorithm.
       </action>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e94c9a46/src/site/xdoc/manual/layouts.xml.vm
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/layouts.xml.vm 
b/src/site/xdoc/manual/layouts.xml.vm
index dd4683a..cedf18e 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -1147,6 +1147,11 @@ WARN  [main]: Message 2</pre>
             are dropped. This behavior deviates from the printf function in C
             where truncation is done from the end.
           </p>
+          <p>Truncation from the end is possible by appending a minus character
+            right after the period. In that case, if the maximum field width
+            is eight and the data item is ten characters long, then the last
+            two characters of the data item are dropped.
+          </p>
           <p>Below are various format modifier examples for the category
             conversion specifier.
           </p>
@@ -1205,6 +1210,16 @@ WARN  [main]: Message 2</pre>
                 then truncate from the beginning.
               </td>
             </tr>
+            <tr>
+              <td align="center">%-20.-30c</td>
+              <td align="center">true</td>
+              <td align="center">20</td>
+              <td align="center">30</td>
+              <td>Right pad with spaces if the category name is shorter than 20
+                characters. However, if category name is longer than 30 
characters,
+                then truncate from the end.
+              </td>
+            </tr>
             <caption align="top">Pattern Converters</caption>
           </table>
           <h4>ANSI Styling on Windows</h4>

Reply via email to