You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2016/07/23 04:12:59 UTC
[08/17] logging-log4j2 git commit: Add tests, fix a bug.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/aed68ee9/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
index 9b48b27..6c26e29 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/JAnsiTextRenderer.java
@@ -1,312 +1,320 @@
-/*
- * 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 java.util.Collections;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.logging.log4j.status.StatusLogger;
-import org.fusesource.jansi.Ansi;
-import org.fusesource.jansi.AnsiRenderer;
-import org.fusesource.jansi.AnsiRenderer.Code;
-
-/**
- * Renders an input as ANSI escaped output.
- *
- * Uses the JAnsi rendering syntax as the default to render a message into an ANSI escaped string.
- *
- * The default syntax for embedded ANSI codes is:
- *
- * <pre>
- * @|<em>code</em>(,<em>code</em>)* <em>text</em>|@
- * </pre>
- *
- * For example, to render the message {@code "Hello"} in green, use:
- *
- * <pre>
- * @|green Hello|@
- * </pre>
- *
- * To render the message {@code "Hello"} in bold and red, use:
- *
- * <pre>
- * @|bold,red Warning!|@
- * </pre>
- *
- * You can also define custom style names in the configuration with the syntax:
- *
- * <pre>
- * %message{ansi}{StyleName=value(,value)*( StyleName=value(,value)*)*}%n
- * </pre>
- *
- * For example:
- *
- * <pre>
- * %message{ansi}{WarningStyle=red,bold KeyStyle=white ValueStyle=blue}%n
- * </pre>
- *
- * The call site can look like this:
- *
- * <pre>
- * logger.info("@|KeyStyle {}|@ = @|ValueStyle {}|@", entry.getKey(), entry.getValue());
- * </pre>
- *
- * Note: This class originally copied and then heavily modified code from JAnsi's AnsiRenderer (which is licensed as
- * Apache 2.0.)
- *
- * @see AnsiRenderer
- */
-public final class JAnsiTextRenderer implements TextRenderer {
-
- public static final Map<String, Code[]> DefaultExceptionStyleMap;
- static final Map<String, Code[]> DefaultMessageStyleMap;
- private static final Map<String,Map<String, Code[]>> PrefedinedStyleMaps;
-
- static {
- Map<String,Map<String, Code[]>> tempPreDefs = new HashMap<>();
- // Default: Spock
- {
- // TODO Should the keys be in an enum?
- Map<String, Code[]> temp = new HashMap<>();
- temp.put("Prefix", new Code[] { Code.WHITE });
- temp.put("Name", new Code[] { Code.BG_RED, Code.WHITE });
- temp.put("Message", new Code[] { Code.BG_RED, Code.WHITE, Code.BOLD });
- temp.put("At", new Code[] { Code.WHITE });
- temp.put("CauseLabel", new Code[] { Code.WHITE });
- temp.put("Text", new Code[] { Code.WHITE });
- // StackTraceElement
- temp.put("StackTraceElement.ClassName", new Code[] { Code.YELLOW });
- temp.put("StackTraceElement.ClassMethodSeparator", new Code[] { Code.YELLOW });
- temp.put("StackTraceElement.MethodName", new Code[] { Code.YELLOW });
- temp.put("StackTraceElement.NativeMethod", new Code[] { Code.YELLOW });
- temp.put("StackTraceElement.FileName", new Code[] { Code.CYAN });
- temp.put("StackTraceElement.LineNumber", new Code[] { Code.CYAN });
- temp.put("StackTraceElement.Container", new Code[] { Code.CYAN });
- temp.put("StackTraceElement.ContainerSeparator", new Code[] { Code.WHITE});
- temp.put("StackTraceElement.UnknownSource", new Code[] { Code.CYAN });
- // ExtraClassInfo
- temp.put("ExtraClassInfo.Inexact", new Code[] { Code.CYAN });
- temp.put("ExtraClassInfo.Container", new Code[] { Code.GREEN });
- temp.put("ExtraClassInfo.ContainerSeparator", new Code[] { Code.WHITE });
- temp.put("ExtraClassInfo.Location", new Code[] { Code.GREEN });
- temp.put("ExtraClassInfo.Version", new Code[] { Code.GREEN });
- // Save
- DefaultExceptionStyleMap = Collections.unmodifiableMap(temp);
- tempPreDefs.put("Spock", DefaultExceptionStyleMap);
- }
- // Kirk
- {
- // TODO Should the keys be in an enum?
- Map<String, Code[]> temp = new HashMap<>();
- temp.put("Prefix", new Code[] { Code.WHITE });
- temp.put("Name", new Code[] { Code.RED });
- temp.put("Message", new Code[] { Code.RED, Code.BOLD });
- temp.put("At", new Code[] { Code.WHITE });
- temp.put("CauseLabel", new Code[] { Code.WHITE });
- temp.put("Text", new Code[] { Code.WHITE });
- // StackTraceElement
- temp.put("StackTraceElement.ClassName", new Code[] { Code.MAGENTA });
- temp.put("StackTraceElement.ClassMethodSeparator", new Code[] { Code.MAGENTA });
- temp.put("StackTraceElement.MethodName", new Code[] { Code.YELLOW });
- temp.put("StackTraceElement.NativeMethod", new Code[] { Code.MAGENTA });
- temp.put("StackTraceElement.FileName", new Code[] { Code.CYAN });
- temp.put("StackTraceElement.LineNumber", new Code[] { Code.CYAN });
- temp.put("StackTraceElement.Container", new Code[] { Code.MAGENTA });
- temp.put("StackTraceElement.ContainerSeparator", new Code[] { Code.MAGENTA});
- temp.put("StackTraceElement.UnknownSource", new Code[] { Code.MAGENTA });
- // ExtraClassInfo
- temp.put("ExtraClassInfo.Inexact", new Code[] { Code.BG_CYAN });
- temp.put("ExtraClassInfo.Container", new Code[] { Code.BG_CYAN });
- temp.put("ExtraClassInfo.ContainerSeparator", new Code[] { Code.BG_CYAN });
- temp.put("ExtraClassInfo.Location", new Code[] { Code.BG_CYAN });
- temp.put("ExtraClassInfo.Version", new Code[] { Code.BG_CYAN });
- // Save
- tempPreDefs.put("Kirk", Collections.unmodifiableMap(temp));
- }
- {
- Map<String, Code[]> temp = new HashMap<>();
- // TODO
- DefaultMessageStyleMap = Collections.unmodifiableMap(temp);
- }
- PrefedinedStyleMaps = Collections.unmodifiableMap(tempPreDefs);
- }
-
- private final String beginToken;
- private final int beginTokenLen;
- private final String endToken;
- private final int endTokenLen;
- private final Map<String, Code[]> styleMap;
-
- public JAnsiTextRenderer(final String[] formats, Map<String, Code[]> defaultStyleMap) {
- String tempBeginToken = AnsiRenderer.BEGIN_TOKEN;
- String tempEndToken = AnsiRenderer.END_TOKEN;
- Map<String, Code[]> map;
- if (formats.length > 1) {
- final String allStylesStr = formats[1];
- // Style def split
- final String[] allStyleAssignmentsArr = allStylesStr.split(" ");
- map = new HashMap<>(allStyleAssignmentsArr.length + defaultStyleMap.size());
- map.putAll(defaultStyleMap);
- for (final String styleAssignmentStr : allStyleAssignmentsArr) {
- final String[] styleAssignmentArr = styleAssignmentStr.split("=");
- if (styleAssignmentArr.length != 2) {
- StatusLogger.getLogger().warn("{} parsing style \"{}\", expected format: StyleName=Code(,Code)*",
- getClass().getSimpleName(), styleAssignmentStr);
- } else {
- final String styleName = styleAssignmentArr[0];
- final String codeListStr = styleAssignmentArr[1];
- final String[] codeNames = codeListStr.split(",");
- if (codeNames.length == 0) {
- StatusLogger.getLogger().warn(
- "{} parsing style \"{}\", expected format: StyleName=Code(,Code)*",
- getClass().getSimpleName(), styleAssignmentStr);
- } else {
- switch (styleName) {
- case "BeginToken":
- tempBeginToken = codeNames[0];
- break;
- case "EndToken":
- tempEndToken = codeNames[0];
- break;
- case "StyleMapName":
- final String predefinedMapName = codeNames[0];
- Map<String, Code[]> predefinedMap = PrefedinedStyleMaps.get(predefinedMapName);
- if (predefinedMap != null) {
- map.putAll(predefinedMap);
- } else {
- StatusLogger.getLogger().warn("Unknown predefined map name {}, pick one of {}",
- predefinedMapName, null);
- }
- break;
- default:
- final Code[] codes = new Code[codeNames.length];
- for (int i = 0; i < codes.length; i++) {
- codes[i] = toCode(codeNames[i]);
- }
- map.put(styleName, codes);
- }
- }
- }
- }
- } else {
- map = defaultStyleMap;
- }
- styleMap = map;
- beginToken = tempBeginToken;
- endToken = tempEndToken;
- beginTokenLen = tempBeginToken.length();
- endTokenLen = tempEndToken.length();
- }
-
- private void render(final Ansi ansi, final Code code) {
- if (code.isColor()) {
- if (code.isBackground()) {
- ansi.bg(code.getColor());
- } else {
- ansi.fg(code.getColor());
- }
- } else if (code.isAttribute()) {
- ansi.a(code.getAttribute());
- }
- }
-
- private void render(final Ansi ansi, final Code... codes) {
- for (final Code code : codes) {
- render(ansi, code);
- }
- }
-
- /**
- * Renders the given text with the given names which can be ANSI code names or Log4j style names.
- *
- * @param text
- * The text to render
- * @param names
- * ANSI code names or Log4j style names.
- * @return A rendered string containing ANSI codes.
- */
- private String render(final String text, final String... names) {
- final Ansi ansi = Ansi.ansi();
- for (final String name : names) {
- final Code[] codes = styleMap.get(name);
- if (codes != null) {
- render(ansi, codes);
- } else {
- render(ansi, toCode(name));
- }
- }
- return ansi.a(text).reset().toString();
- }
-
- @Override
- public void render(final StringBuilder input, final StringBuilder output) throws IllegalArgumentException {
- int i = 0;
- int j, k;
-
- while (true) {
- j = input.indexOf(beginToken, i);
- if (j == -1) {
- if (i == 0) {
- output.append(input);
- return;
- }
- output.append(input.substring(i, input.length()));
- return;
- }
- output.append(input.substring(i, j));
- k = input.indexOf(endToken, j);
-
- if (k == -1) {
- output.append(input);
- return;
- }
- j += beginTokenLen;
- final String spec = input.substring(j, k);
-
- final String[] items = spec.split(AnsiRenderer.CODE_TEXT_SEPARATOR, 2);
- if (items.length == 1) {
- output.append(input);
- return;
- }
- final String replacement = render(items[1], items[0].split(","));
-
- output.append(replacement);
-
- i = k + endTokenLen;
- }
- }
-
- // EXACT COPY OF StringBuilder version of the method but typed as String for input
- @Override
- public void render(final String input, final StringBuilder output, final String styleName)
- throws IllegalArgumentException {
- output.append(render(input, styleName));
- }
-
- private Code toCode(final String name) {
- return Code.valueOf(name.toUpperCase(Locale.ENGLISH));
- }
-
- @Override
- public String toString() {
- return "JAnsiMessageRenderer [beginToken=" + beginToken + ", beginTokenLen=" + beginTokenLen + ", endToken="
- + endToken + ", endTokenLen=" + endTokenLen + ", styleMap=" + styleMap + "]";
- }
-
-}
+/*
+ * 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 java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.logging.log4j.status.StatusLogger;
+import org.fusesource.jansi.Ansi;
+import org.fusesource.jansi.AnsiRenderer;
+import org.fusesource.jansi.AnsiRenderer.Code;
+
+/**
+ * Renders an input as ANSI escaped output.
+ *
+ * Uses the JAnsi rendering syntax as the default to render a message into an ANSI escaped string.
+ *
+ * The default syntax for embedded ANSI codes is:
+ *
+ * <pre>
+ * @|<em>code</em>(,<em>code</em>)* <em>text</em>|@
+ * </pre>
+ *
+ * For example, to render the message {@code "Hello"} in green, use:
+ *
+ * <pre>
+ * @|green Hello|@
+ * </pre>
+ *
+ * To render the message {@code "Hello"} in bold and red, use:
+ *
+ * <pre>
+ * @|bold,red Warning!|@
+ * </pre>
+ *
+ * You can also define custom style names in the configuration with the syntax:
+ *
+ * <pre>
+ * %message{ansi}{StyleName=value(,value)*( StyleName=value(,value)*)*}%n
+ * </pre>
+ *
+ * For example:
+ *
+ * <pre>
+ * %message{ansi}{WarningStyle=red,bold KeyStyle=white ValueStyle=blue}%n
+ * </pre>
+ *
+ * The call site can look like this:
+ *
+ * <pre>
+ * logger.info("@|KeyStyle {}|@ = @|ValueStyle {}|@", entry.getKey(), entry.getValue());
+ * </pre>
+ *
+ * Note: This class originally copied and then heavily modified code from JAnsi's AnsiRenderer (which is licensed as
+ * Apache 2.0.)
+ *
+ * @see AnsiRenderer
+ */
+public final class JAnsiTextRenderer implements TextRenderer {
+
+ public static final Map<String, Code[]> DefaultExceptionStyleMap;
+ static final Map<String, Code[]> DefaultMessageStyleMap;
+ private static final Map<String,Map<String, Code[]>> PrefedinedStyleMaps;
+
+ static {
+ Map<String,Map<String, Code[]>> tempPreDefs = new HashMap<>();
+ // Default style: Spock
+ {
+ // TODO Should the keys be in an enum?
+ Map<String, Code[]> temp = new HashMap<>();
+ temp.put("Prefix", new Code[] { Code.WHITE });
+ temp.put("Name", new Code[] { Code.BG_RED, Code.WHITE });
+ temp.put("Message", new Code[] { Code.BG_RED, Code.WHITE, Code.BOLD });
+ temp.put("At", new Code[] { Code.WHITE });
+ temp.put("CauseLabel", new Code[] { Code.WHITE });
+ temp.put("Text", new Code[] { Code.WHITE });
+ temp.put("More", new Code[] { Code.WHITE });
+ temp.put("Suppressed", new Code[] { Code.WHITE });
+ // StackTraceElement
+ temp.put("StackTraceElement.ClassName", new Code[] { Code.YELLOW });
+ temp.put("StackTraceElement.ClassMethodSeparator", new Code[] { Code.YELLOW });
+ temp.put("StackTraceElement.MethodName", new Code[] { Code.YELLOW });
+ temp.put("StackTraceElement.NativeMethod", new Code[] { Code.YELLOW });
+ temp.put("StackTraceElement.FileName", new Code[] { Code.CYAN });
+ temp.put("StackTraceElement.LineNumber", new Code[] { Code.CYAN });
+ temp.put("StackTraceElement.Container", new Code[] { Code.CYAN });
+ temp.put("StackTraceElement.ContainerSeparator", new Code[] { Code.WHITE});
+ temp.put("StackTraceElement.UnknownSource", new Code[] { Code.CYAN });
+ // ExtraClassInfo
+ temp.put("ExtraClassInfo.Inexact", new Code[] { Code.CYAN });
+ temp.put("ExtraClassInfo.Container", new Code[] { Code.GREEN });
+ temp.put("ExtraClassInfo.ContainerSeparator", new Code[] { Code.WHITE });
+ temp.put("ExtraClassInfo.Location", new Code[] { Code.GREEN });
+ temp.put("ExtraClassInfo.Version", new Code[] { Code.GREEN });
+ // Save
+ DefaultExceptionStyleMap = Collections.unmodifiableMap(temp);
+ tempPreDefs.put("Spock", DefaultExceptionStyleMap);
+ }
+ // Style: Kirk
+ {
+ // TODO Should the keys be in an enum?
+ Map<String, Code[]> temp = new HashMap<>();
+ temp.put("Prefix", new Code[] { Code.WHITE });
+ temp.put("Name", new Code[] { Code.BG_RED, Code.YELLOW });
+ temp.put("Message", new Code[] { Code.BG_RED, Code.WHITE, Code.BOLD });
+ temp.put("At", new Code[] { Code.WHITE });
+ temp.put("CauseLabel", new Code[] { Code.WHITE });
+ temp.put("Text", new Code[] { Code.WHITE });
+ temp.put("More", new Code[] { Code.WHITE });
+ temp.put("Suppressed", new Code[] { Code.WHITE });
+ // StackTraceElement
+ temp.put("StackTraceElement.ClassName", new Code[] { Code.BG_RED, Code.WHITE });
+ temp.put("StackTraceElement.ClassMethodSeparator", new Code[] { Code.BG_RED, Code.YELLOW });
+ temp.put("StackTraceElement.MethodName", new Code[] { Code.BG_RED, Code.YELLOW });
+ temp.put("StackTraceElement.NativeMethod", new Code[] { Code.BG_RED, Code.YELLOW });
+ temp.put("StackTraceElement.FileName", new Code[] { Code.CYAN });
+ temp.put("StackTraceElement.LineNumber", new Code[] { Code.CYAN });
+ temp.put("StackTraceElement.Container", new Code[] { Code.CYAN });
+ temp.put("StackTraceElement.ContainerSeparator", new Code[] { Code.WHITE});
+ temp.put("StackTraceElement.UnknownSource", new Code[] { Code.CYAN });
+ // ExtraClassInfo
+ temp.put("ExtraClassInfo.Inexact", new Code[] { Code.CYAN });
+ temp.put("ExtraClassInfo.Container", new Code[] { Code.GREEN });
+ temp.put("ExtraClassInfo.ContainerSeparator", new Code[] { Code.WHITE });
+ temp.put("ExtraClassInfo.Location", new Code[] { Code.GREEN });
+ temp.put("ExtraClassInfo.Version", new Code[] { Code.GREEN });
+ // Save
+ tempPreDefs.put("Kirk", Collections.unmodifiableMap(temp));
+ }
+ {
+ Map<String, Code[]> temp = new HashMap<>();
+ // TODO
+ DefaultMessageStyleMap = Collections.unmodifiableMap(temp);
+ }
+ PrefedinedStyleMaps = Collections.unmodifiableMap(tempPreDefs);
+ }
+
+ private final String beginToken;
+ private final int beginTokenLen;
+ private final String endToken;
+ private final int endTokenLen;
+ private final Map<String, Code[]> styleMap;
+
+ public JAnsiTextRenderer(final String[] formats, Map<String, Code[]> defaultStyleMap) {
+ String tempBeginToken = AnsiRenderer.BEGIN_TOKEN;
+ String tempEndToken = AnsiRenderer.END_TOKEN;
+ Map<String, Code[]> map;
+ if (formats.length > 1) {
+ final String allStylesStr = formats[1];
+ // Style def split
+ final String[] allStyleAssignmentsArr = allStylesStr.split(" ");
+ map = new HashMap<>(allStyleAssignmentsArr.length + defaultStyleMap.size());
+ map.putAll(defaultStyleMap);
+ for (final String styleAssignmentStr : allStyleAssignmentsArr) {
+ final String[] styleAssignmentArr = styleAssignmentStr.split("=");
+ if (styleAssignmentArr.length != 2) {
+ StatusLogger.getLogger().warn("{} parsing style \"{}\", expected format: StyleName=Code(,Code)*",
+ getClass().getSimpleName(), styleAssignmentStr);
+ } else {
+ final String styleName = styleAssignmentArr[0];
+ final String codeListStr = styleAssignmentArr[1];
+ final String[] codeNames = codeListStr.split(",");
+ if (codeNames.length == 0) {
+ StatusLogger.getLogger().warn(
+ "{} parsing style \"{}\", expected format: StyleName=Code(,Code)*",
+ getClass().getSimpleName(), styleAssignmentStr);
+ } else {
+ switch (styleName) {
+ case "BeginToken":
+ tempBeginToken = codeNames[0];
+ break;
+ case "EndToken":
+ tempEndToken = codeNames[0];
+ break;
+ case "StyleMapName":
+ final String predefinedMapName = codeNames[0];
+ Map<String, Code[]> predefinedMap = PrefedinedStyleMaps.get(predefinedMapName);
+ if (predefinedMap != null) {
+ map.putAll(predefinedMap);
+ } else {
+ StatusLogger.getLogger().warn("Unknown predefined map name {}, pick one of {}",
+ predefinedMapName, null);
+ }
+ break;
+ default:
+ final Code[] codes = new Code[codeNames.length];
+ for (int i = 0; i < codes.length; i++) {
+ codes[i] = toCode(codeNames[i]);
+ }
+ map.put(styleName, codes);
+ }
+ }
+ }
+ }
+ } else {
+ map = defaultStyleMap;
+ }
+ styleMap = map;
+ beginToken = tempBeginToken;
+ endToken = tempEndToken;
+ beginTokenLen = tempBeginToken.length();
+ endTokenLen = tempEndToken.length();
+ }
+
+ public Map<String, Code[]> getStyleMap() {
+ return styleMap;
+ }
+
+ private void render(final Ansi ansi, final Code code) {
+ if (code.isColor()) {
+ if (code.isBackground()) {
+ ansi.bg(code.getColor());
+ } else {
+ ansi.fg(code.getColor());
+ }
+ } else if (code.isAttribute()) {
+ ansi.a(code.getAttribute());
+ }
+ }
+
+ private void render(final Ansi ansi, final Code... codes) {
+ for (final Code code : codes) {
+ render(ansi, code);
+ }
+ }
+
+ /**
+ * Renders the given text with the given names which can be ANSI code names or Log4j style names.
+ *
+ * @param text
+ * The text to render
+ * @param names
+ * ANSI code names or Log4j style names.
+ * @return A rendered string containing ANSI codes.
+ */
+ private String render(final String text, final String... names) {
+ final Ansi ansi = Ansi.ansi();
+ for (final String name : names) {
+ final Code[] codes = styleMap.get(name);
+ if (codes != null) {
+ render(ansi, codes);
+ } else {
+ render(ansi, toCode(name));
+ }
+ }
+ return ansi.a(text).reset().toString();
+ }
+
+ // EXACT COPY OF StringBuilder version of the method but typed as String for input
+ @Override
+ public void render(final String input, final StringBuilder output, final String styleName)
+ throws IllegalArgumentException {
+ output.append(render(input, styleName));
+ }
+
+ @Override
+ public void render(final StringBuilder input, final StringBuilder output) throws IllegalArgumentException {
+ int i = 0;
+ int j, k;
+
+ while (true) {
+ j = input.indexOf(beginToken, i);
+ if (j == -1) {
+ if (i == 0) {
+ output.append(input);
+ return;
+ }
+ output.append(input.substring(i, input.length()));
+ return;
+ }
+ output.append(input.substring(i, j));
+ k = input.indexOf(endToken, j);
+
+ if (k == -1) {
+ output.append(input);
+ return;
+ }
+ j += beginTokenLen;
+ final String spec = input.substring(j, k);
+
+ final String[] items = spec.split(AnsiRenderer.CODE_TEXT_SEPARATOR, 2);
+ if (items.length == 1) {
+ output.append(input);
+ return;
+ }
+ final String replacement = render(items[1], items[0].split(","));
+
+ output.append(replacement);
+
+ i = k + endTokenLen;
+ }
+ }
+
+ private Code toCode(final String name) {
+ return Code.valueOf(name.toUpperCase(Locale.ENGLISH));
+ }
+
+ @Override
+ public String toString() {
+ return "JAnsiMessageRenderer [beginToken=" + beginToken + ", beginTokenLen=" + beginTokenLen + ", endToken="
+ + endToken + ", endTokenLen=" + endTokenLen + ", styleMap=" + styleMap + "]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/aed68ee9/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
index 80373a3..c3de0d3 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableFormatOptionsTest.java
@@ -16,15 +16,21 @@
*/
package org.apache.logging.log4j.core.impl;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
+import org.apache.logging.log4j.core.pattern.JAnsiTextRenderer;
+import org.apache.logging.log4j.core.pattern.TextRenderer;
import org.apache.logging.log4j.core.util.Constants;
import org.apache.logging.log4j.util.Strings;
+import org.fusesource.jansi.AnsiRenderer.Code;
+import org.junit.Assert;
import org.junit.Test;
-import static org.junit.Assert.*;
-
/**
* Unit tests for {@code ThrowableFormatOptions}.
*/
@@ -32,22 +38,29 @@ public final class ThrowableFormatOptionsTest {
/**
* Runs a given test comparing against the expected values.
- * @param options The list of options to parse.
- * @param expectedLines The expected lines.
- * @param expectedPackages The expected package filters.
- * @param expectedSeparator The expected seperator.
- */
- private static void test(final String[] options, final int expectedLines, final String expectedSeparator, final List<String> expectedPackages) {
- final ThrowableFormatOptions o = ThrowableFormatOptions.newInstance(options);
- assertEquals("getLines", expectedLines, o.getLines());
- assertEquals("getSeparator", expectedSeparator, o.getSeparator());
- assertEquals("getPackages", expectedPackages, o.getIgnorePackages());
- assertEquals("allLines", expectedLines == Integer.MAX_VALUE, o.allLines());
- assertEquals("anyLines", expectedLines != 0, o.anyLines());
- assertEquals("minLines", 0, o.minLines(0));
- assertEquals("minLines", expectedLines, o.minLines(Integer.MAX_VALUE));
- assertEquals("hasPackages", expectedPackages != null && !expectedPackages.isEmpty(), o.hasPackages());
- assertNotNull("toString", o.toString());
+ *
+ * @param options
+ * The list of options to parse.
+ * @param expectedLines
+ * The expected lines.
+ * @param expectedPackages
+ * The expected package filters.
+ * @param expectedSeparator
+ * The expected separator.
+ */
+ private static ThrowableFormatOptions test(final String[] options, final int expectedLines,
+ final String expectedSeparator, final List<String> expectedPackages) {
+ final ThrowableFormatOptions tfo = ThrowableFormatOptions.newInstance(options);
+ assertEquals("getLines", expectedLines, tfo.getLines());
+ assertEquals("getSeparator", expectedSeparator, tfo.getSeparator());
+ assertEquals("getPackages", expectedPackages, tfo.getIgnorePackages());
+ assertEquals("allLines", expectedLines == Integer.MAX_VALUE, tfo.allLines());
+ assertEquals("anyLines", expectedLines != 0, tfo.anyLines());
+ assertEquals("minLines", 0, tfo.minLines(0));
+ assertEquals("minLines", expectedLines, tfo.minLines(Integer.MAX_VALUE));
+ assertEquals("hasPackages", expectedPackages != null && !expectedPackages.isEmpty(), tfo.hasPackages());
+ assertNotNull("toString", tfo.toString());
+ return tfo;
}
/**
@@ -63,7 +76,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testEmpty() {
- test(new String[]{}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ test(new String[] {}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
}
/**
@@ -71,7 +84,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testOneNullElement() {
- test(new String[]{null}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ test(new String[] { null }, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
}
/**
@@ -79,7 +92,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testOneEmptyElement() {
- test(new String[]{""}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ test(new String[] { "" }, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
}
/**
@@ -87,7 +100,88 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testFull() {
- test(new String[]{"full"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ test(new String[] { "full" }, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ }
+
+ /**
+ * Test {@code %throwable{full}{ansi} }
+ */
+ @Test
+ public void testFullAnsi() {
+ ThrowableFormatOptions tfo = test(new String[] { "full", "ansi" },
+ Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ testFullAnsiEmptyConfig(tfo);
+ }
+
+ /**
+ * Test {@code %throwable{full}{ansi} }
+ */
+ @Test
+ public void testFullAnsiEmptyConfig() {
+ ThrowableFormatOptions tfo = test(new String[] { "full", "ansi()" },
+ Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ testFullAnsiEmptyConfig(tfo);
+ }
+
+ private void testFullAnsiEmptyConfig(ThrowableFormatOptions tfo) {
+ TextRenderer textRenderer = tfo.getTextRenderer();
+ Assert.assertNotNull(textRenderer);
+ Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
+ JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
+ Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
+ // We have defaults
+ Assert.assertFalse(styleMap.isEmpty());
+ Assert.assertNotNull(styleMap.get("Name"));
+ }
+
+ /**
+ * Test {@code %throwable{full}{ansi(ansi(Warning=red))} }
+ */
+ @Test
+ public void testFullAnsiWithCustomStyle() {
+ ThrowableFormatOptions tfo = test(new String[] { "full", "ansi(Warning=red)" },
+ Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ TextRenderer textRenderer = tfo.getTextRenderer();
+ Assert.assertNotNull(textRenderer);
+ Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
+ JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
+ Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
+ Assert.assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
+ }
+
+ /**
+ * Test {@code %throwable{full}{ansi(ansi(Warning=red Key=blue Value=cyan))} }
+ */
+ @Test
+ public void testFullAnsiWithCustomStyles() {
+ ThrowableFormatOptions tfo = test(new String[] { "full", "ansi(Warning=red Key=blue Value=cyan)" },
+ Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ TextRenderer textRenderer = tfo.getTextRenderer();
+ Assert.assertNotNull(textRenderer);
+ Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
+ JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
+ Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
+ Assert.assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
+ Assert.assertArrayEquals(new Code[] { Code.BLUE }, styleMap.get("Key"));
+ Assert.assertArrayEquals(new Code[] { Code.CYAN }, styleMap.get("Value"));
+ }
+
+ /**
+ * Test {@code %throwable{full}{ansi(Warning=red Key=blue,bg_red Value=cyan,bg_black,underline)} }
+ */
+ @Test
+ public void testFullAnsiWithCustomComplexStyles() {
+ ThrowableFormatOptions tfo = test(
+ new String[] { "full", "ansi(Warning=red Key=blue,bg_red Value=cyan,bg_black,underline)" }, Integer.MAX_VALUE,
+ Constants.LINE_SEPARATOR, null);
+ TextRenderer textRenderer = tfo.getTextRenderer();
+ Assert.assertNotNull(textRenderer);
+ Assert.assertTrue(textRenderer instanceof JAnsiTextRenderer);
+ JAnsiTextRenderer jansiRenderer = (JAnsiTextRenderer) textRenderer;
+ Map<String, Code[]> styleMap = jansiRenderer.getStyleMap();
+ Assert.assertArrayEquals(new Code[] { Code.RED }, styleMap.get("Warning"));
+ Assert.assertArrayEquals(new Code[] { Code.BLUE, Code.BG_RED }, styleMap.get("Key"));
+ Assert.assertArrayEquals(new Code[] { Code.CYAN, Code.BG_BLACK, Code.UNDERLINE }, styleMap.get("Value"));
}
/**
@@ -95,7 +189,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testNone() {
- test(new String[]{"none"}, 0, Constants.LINE_SEPARATOR, null);
+ test(new String[] { "none" }, 0, Constants.LINE_SEPARATOR, null);
}
/**
@@ -103,7 +197,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testShort() {
- test(new String[]{"short"}, 2, Constants.LINE_SEPARATOR, null);
+ test(new String[] { "short" }, 2, Constants.LINE_SEPARATOR, null);
}
/**
@@ -111,7 +205,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testDepth() {
- test(new String[]{"10"}, 10, Constants.LINE_SEPARATOR, null);
+ test(new String[] { "10" }, 10, Constants.LINE_SEPARATOR, null);
}
/**
@@ -119,7 +213,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSeparator() {
- test(new String[]{"separator(|)"}, Integer.MAX_VALUE, "|", null);
+ test(new String[] { "separator(|)" }, Integer.MAX_VALUE, "|", null);
}
/**
@@ -127,7 +221,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSeparatorAsEmpty() {
- test(new String[]{"separator()"}, Integer.MAX_VALUE, Strings.EMPTY, null);
+ test(new String[] { "separator()" }, Integer.MAX_VALUE, Strings.EMPTY, null);
}
/**
@@ -135,7 +229,8 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSeparatorAsDefaultLineSeparator() {
- test(new String[]{"separator(" + Constants.LINE_SEPARATOR + ')'}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ test(new String[] { "separator(" + Constants.LINE_SEPARATOR + ')' }, Integer.MAX_VALUE,
+ Constants.LINE_SEPARATOR, null);
}
/**
@@ -143,7 +238,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSeparatorAsMultipleCharacters() {
- test(new String[]{"separator( | )"}, Integer.MAX_VALUE, " | ", null);
+ test(new String[] { "separator( | )" }, Integer.MAX_VALUE, " | ", null);
}
/**
@@ -151,7 +246,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testFullAndSeparator() {
- test(new String[]{"full","separator(|)"}, Integer.MAX_VALUE, "|", null);
+ test(new String[] { "full", "separator(|)" }, Integer.MAX_VALUE, "|", null);
}
/**
@@ -159,7 +254,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testNoneAndSeparator() {
- test(new String[]{"none","separator(|)"}, 0, "|", null);
+ test(new String[] { "none", "separator(|)" }, 0, "|", null);
}
/**
@@ -167,7 +262,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testShortAndSeparator() {
- test(new String[]{"short","separator(|)"}, 2, "|", null);
+ test(new String[] { "short", "separator(|)" }, 2, "|", null);
}
/**
@@ -175,7 +270,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testDepthAndSeparator() {
- test(new String[]{"10","separator(|)"}, 10, "|", null);
+ test(new String[] { "10", "separator(|)" }, 10, "|", null);
}
/**
@@ -183,7 +278,8 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testFilters() {
- test(new String[]{"filters(packages)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
+ test(new String[] { "filters(packages)" }, Integer.MAX_VALUE, Constants.LINE_SEPARATOR,
+ Arrays.asList("packages"));
}
/**
@@ -191,7 +287,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testFiltersAsEmpty() {
- test(new String[]{"filters()"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
+ test(new String[] { "filters()" }, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, null);
}
/**
@@ -199,7 +295,8 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testFiltersAsMultiplePackages() {
- test(new String[]{"filters(package1,package2)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
+ test(new String[] { "filters(package1,package2)" }, Integer.MAX_VALUE, Constants.LINE_SEPARATOR,
+ Arrays.asList("package1", "package2"));
}
/**
@@ -207,7 +304,8 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testFullAndFilters() {
- test(new String[]{"full","filters(packages)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
+ test(new String[] { "full", "filters(packages)" }, Integer.MAX_VALUE, Constants.LINE_SEPARATOR,
+ Arrays.asList("packages"));
}
/**
@@ -215,7 +313,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testNoneAndFilters() {
- test(new String[]{"none","filters(packages)"}, 0, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
+ test(new String[] { "none", "filters(packages)" }, 0, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
}
/**
@@ -223,7 +321,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testShortAndFilters() {
- test(new String[]{"short","filters(packages)"}, 2, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
+ test(new String[] { "short", "filters(packages)" }, 2, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
}
/**
@@ -231,7 +329,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testDepthAndFilters() {
- test(new String[]{"10","filters(packages)"}, 10, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
+ test(new String[] { "10", "filters(packages)" }, 10, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
}
/**
@@ -239,7 +337,8 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testFullAndSeparatorAndFilters() {
- test(new String[]{"full","separator(|)","filters(packages)"}, Integer.MAX_VALUE, "|", Arrays.asList("packages"));
+ test(new String[] { "full", "separator(|)", "filters(packages)" }, Integer.MAX_VALUE, "|",
+ Arrays.asList("packages"));
}
/**
@@ -247,7 +346,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testNoneAndSeparatorAndFilters() {
- test(new String[]{"none","separator(|)","filters(packages)"}, 0, "|", Arrays.asList("packages"));
+ test(new String[] { "none", "separator(|)", "filters(packages)" }, 0, "|", Arrays.asList("packages"));
}
/**
@@ -255,7 +354,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testShortAndSeparatorAndFilters() {
- test(new String[]{"short","separator(|)","filters(packages)"}, 2, "|", Arrays.asList("packages"));
+ test(new String[] { "short", "separator(|)", "filters(packages)" }, 2, "|", Arrays.asList("packages"));
}
/**
@@ -263,7 +362,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testDepthAndSeparatorAndFilters() {
- test(new String[]{"10","separator(|)","filters(packages)"}, 10, "|", Arrays.asList("packages"));
+ test(new String[] { "10", "separator(|)", "filters(packages)" }, 10, "|", Arrays.asList("packages"));
}
/**
@@ -271,7 +370,8 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSingleOptionFullAndFilters() {
- test(new String[]{"full,filters(packages)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
+ test(new String[] { "full,filters(packages)" }, Integer.MAX_VALUE, Constants.LINE_SEPARATOR,
+ Arrays.asList("packages"));
}
/**
@@ -279,7 +379,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSingleOptionNoneAndFilters() {
- test(new String[]{"none,filters(packages)"}, 0, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
+ test(new String[] { "none,filters(packages)" }, 0, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
}
/**
@@ -287,7 +387,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSingleOptionShortAndFilters() {
- test(new String[]{"short,filters(packages)"}, 2, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
+ test(new String[] { "short,filters(packages)" }, 2, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
}
/**
@@ -295,7 +395,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSingleOptionDepthAndFilters() {
- test(new String[]{"10,filters(packages)"}, 10, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
+ test(new String[] { "10,filters(packages)" }, 10, Constants.LINE_SEPARATOR, Arrays.asList("packages"));
}
/**
@@ -303,7 +403,8 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSingleOptionFullAndMultipleFilters() {
- test(new String[]{"full,filters(package1,package2)"}, Integer.MAX_VALUE, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
+ test(new String[] { "full,filters(package1,package2)" }, Integer.MAX_VALUE, Constants.LINE_SEPARATOR,
+ Arrays.asList("package1", "package2"));
}
/**
@@ -311,7 +412,8 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSingleOptionNoneAndMultipleFilters() {
- test(new String[]{"none,filters(package1,package2)"}, 0, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
+ test(new String[] { "none,filters(package1,package2)" }, 0, Constants.LINE_SEPARATOR,
+ Arrays.asList("package1", "package2"));
}
/**
@@ -319,7 +421,8 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSingleOptionShortAndMultipleFilters() {
- test(new String[]{"short,filters(package1,package2)"}, 2, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
+ test(new String[] { "short,filters(package1,package2)" }, 2, Constants.LINE_SEPARATOR,
+ Arrays.asList("package1", "package2"));
}
/**
@@ -327,6 +430,7 @@ public final class ThrowableFormatOptionsTest {
*/
@Test
public void testSingleOptionDepthAndMultipleFilters() {
- test(new String[]{"10,filters(package1,package2)"}, 10, Constants.LINE_SEPARATOR, Arrays.asList("package1","package2"));
+ test(new String[] { "10,filters(package1,package2)" }, 10, Constants.LINE_SEPARATOR,
+ Arrays.asList("package1", "package2"));
}
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/aed68ee9/log4j-core/src/test/resources/log4j2-console-xex-ansi-custom.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j2-console-xex-ansi-custom.xml b/log4j-core/src/test/resources/log4j2-console-xex-ansi-custom.xml
new file mode 100644
index 0000000..5d54f15
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j2-console-xex-ansi-custom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<Configuration status="OFF">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d [%t] %-5level: %msg{ansi}{CaughtMsg=red}%n%xThrowable{full}{ansi(CaughtMsg=red)}" />
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Logger name="org.foo" level="DEBUG" />
+ <Root level="TRACE">
+ <AppenderRef ref="Console" />
+ </Root>
+ </Loggers>
+</Configuration>
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/aed68ee9/log4j-core/src/test/resources/log4j2-console-xex-ansi.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j2-console-xex-ansi.xml b/log4j-core/src/test/resources/log4j2-console-xex-ansi.xml
index d28b169..b4143f9 100644
--- a/log4j-core/src/test/resources/log4j2-console-xex-ansi.xml
+++ b/log4j-core/src/test/resources/log4j2-console-xex-ansi.xml
@@ -1,31 +1,31 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
--->
-<Configuration status="OFF">
- <Appenders>
- <Console name="Console" target="SYSTEM_OUT">
- <PatternLayout pattern="%d [%t] %-5level: %msg{ansi}{CaughtMsg=red}%n%xThrowable{full}{ansi(CaughtMsg=red)}" />
- </Console>
- </Appenders>
- <Loggers>
- <Logger name="org.foo" level="DEBUG" />
- <Root level="TRACE">
- <AppenderRef ref="Console" />
- </Root>
- </Loggers>
-</Configuration>
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<Configuration status="OFF">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d [%t] %-5level: %msg%n%xThrowable{full}{ansi}" />
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Logger name="org.foo" level="DEBUG" />
+ <Root level="TRACE">
+ <AppenderRef ref="Console" />
+ </Root>
+ </Loggers>
+</Configuration>