Repository: logging-log4j2
Updated Branches:
  refs/heads/master e9d3c616a -> 9ff63b2e5


[LOG4J2-2195] Cannot define both `filters` and `separator` for
PatternLayout %xEx.

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

Branch: refs/heads/master
Commit: 9ff63b2e50be754ae394feda2c33d9e64fd0ab3a
Parents: e9d3c61
Author: Gary Gregory <[email protected]>
Authored: Thu Jan 25 15:14:52 2018 -0700
Committer: Gary Gregory <[email protected]>
Committed: Thu Jan 25 15:14:52 2018 -0700

----------------------------------------------------------------------
 .../logging/log4j/core/impl/ThrowableProxy.java | 146 ++++++++++++-------
 .../log4j/core/layout/PatternLayout.java        |   4 +
 .../ExtendedThrowablePatternConverter.java      |  19 +--
 .../core/pattern/ThrowablePatternConverter.java |  34 +++--
 .../log4j/core/appender/HttpAppenderTest.java   |   3 +-
 .../core/impl/ThrowableFormatOptionsTest.java   |  27 +++-
 .../log4j/core/impl/ThrowableProxyTest.java     |  21 ++-
 .../log4j/core/layout/Log4j2_2195_Test.java     |  62 ++++++++
 .../ExtendedThrowablePatternConverterTest.java  |  19 ++-
 .../log4j/core/pattern/PatternParserTest.java   |  39 ++++-
 .../src/test/resources/LOG4J-2195/log4j2.xml    |  17 +++
 src/changes/changes.xml                         |   3 +
 src/site/xdoc/manual/layouts.xml.vm             |  21 ++-
 13 files changed, 311 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
index 4cbac54..fe557ad 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java
@@ -207,13 +207,13 @@ public class ThrowableProxy implements Serializable {
     }
 
     private void formatCause(final StringBuilder sb, final String prefix, 
final ThrowableProxy cause,
-                             final List<String> ignorePackages, final 
TextRenderer textRenderer, final String suffix) {
-        formatThrowableProxy(sb, prefix, CAUSED_BY_LABEL, cause, 
ignorePackages, textRenderer, suffix);
+                             final List<String> ignorePackages, final 
TextRenderer textRenderer, final String suffix, String lineSeparator) {
+        formatThrowableProxy(sb, prefix, CAUSED_BY_LABEL, cause, 
ignorePackages, textRenderer, suffix, lineSeparator);
     }
 
     private void formatThrowableProxy(final StringBuilder sb, final String 
prefix, final String causeLabel,
                                       final ThrowableProxy throwableProxy, 
final List<String> ignorePackages,
-                                      final TextRenderer textRenderer, final 
String suffix) {
+                                      final TextRenderer textRenderer, final 
String suffix, String lineSeparator) {
         if (throwableProxy == null) {
             return;
         }
@@ -221,11 +221,11 @@ public class ThrowableProxy implements Serializable {
         textRenderer.render(causeLabel, sb, "CauseLabel");
         throwableProxy.renderOn(sb, textRenderer);
         renderSuffix(suffix, sb, textRenderer);
-        textRenderer.render(EOL_STR, sb, "Text");
+        textRenderer.render(lineSeparator, sb, "Text");
         this.formatElements(sb, prefix, throwableProxy.commonElementCount,
-            throwableProxy.getStackTrace(), throwableProxy.extendedStackTrace, 
ignorePackages, textRenderer, suffix);
-        this.formatSuppressed(sb, prefix + TAB, 
throwableProxy.suppressedProxies, ignorePackages, textRenderer, suffix);
-        this.formatCause(sb, prefix, throwableProxy.causeProxy, 
ignorePackages, textRenderer, suffix);
+            throwableProxy.getStackTrace(), throwableProxy.extendedStackTrace, 
ignorePackages, textRenderer, suffix, lineSeparator);
+        this.formatSuppressed(sb, prefix + TAB, 
throwableProxy.suppressedProxies, ignorePackages, textRenderer, suffix, 
lineSeparator);
+        this.formatCause(sb, prefix, throwableProxy.causeProxy, 
ignorePackages, textRenderer, suffix, lineSeparator);
     }
 
     void renderOn(final StringBuilder output, final TextRenderer textRenderer) 
{
@@ -238,37 +238,37 @@ public class ThrowableProxy implements Serializable {
     }
 
     private void formatSuppressed(final StringBuilder sb, final String prefix, 
final ThrowableProxy[] suppressedProxies,
-                                  final List<String> ignorePackages, final 
TextRenderer textRenderer, final String suffix) {
+                                  final List<String> ignorePackages, final 
TextRenderer textRenderer, final String suffix, String lineSeparator) {
         if (suppressedProxies == null) {
             return;
         }
         for (final ThrowableProxy suppressedProxy : suppressedProxies) {
-            formatThrowableProxy(sb, prefix, SUPPRESSED_LABEL, 
suppressedProxy, ignorePackages, textRenderer, suffix);
+            formatThrowableProxy(sb, prefix, SUPPRESSED_LABEL, 
suppressedProxy, ignorePackages, textRenderer, suffix, lineSeparator);
         }
     }
 
     private void formatElements(final StringBuilder sb, final String prefix, 
final int commonCount,
                                 final StackTraceElement[] causedTrace, final 
ExtendedStackTraceElement[] extStackTrace,
-                                final List<String> ignorePackages, final 
TextRenderer textRenderer, final String suffix) {
+                                final List<String> ignorePackages, final 
TextRenderer textRenderer, final String suffix, String lineSeparator) {
         if (ignorePackages == null || ignorePackages.isEmpty()) {
             for (final ExtendedStackTraceElement element : extStackTrace) {
-                this.formatEntry(element, sb, prefix, textRenderer, suffix);
+                this.formatEntry(element, sb, prefix, textRenderer, suffix, 
lineSeparator);
             }
         } else {
             int count = 0;
             for (int i = 0; i < extStackTrace.length; ++i) {
                 if (!this.ignoreElement(causedTrace[i], ignorePackages)) {
                     if (count > 0) {
-                        appendSuppressedCount(sb, prefix, count, textRenderer, 
suffix);
+                        appendSuppressedCount(sb, prefix, count, textRenderer, 
suffix, lineSeparator);
                         count = 0;
                     }
-                    this.formatEntry(extStackTrace[i], sb, prefix, 
textRenderer, suffix);
+                    this.formatEntry(extStackTrace[i], sb, prefix, 
textRenderer, suffix, lineSeparator);
                 } else {
                     ++count;
                 }
             }
             if (count > 0) {
-                appendSuppressedCount(sb, prefix, count, textRenderer, suffix);
+                appendSuppressedCount(sb, prefix, count, textRenderer, suffix, 
lineSeparator);
             }
         }
         if (commonCount != 0) {
@@ -277,7 +277,7 @@ public class ThrowableProxy implements Serializable {
             textRenderer.render(Integer.toString(commonCount), sb, "More");
             textRenderer.render(" more", sb, "More");
             renderSuffix(suffix, sb, textRenderer);
-            textRenderer.render(EOL_STR, sb, "Text");
+            textRenderer.render(lineSeparator, sb, "Text");
         }
     }
 
@@ -289,7 +289,7 @@ public class ThrowableProxy implements Serializable {
     }
 
     private void appendSuppressedCount(final StringBuilder sb, final String 
prefix, final int count,
-                                       final TextRenderer textRenderer, final 
String suffix) {
+                                       final TextRenderer textRenderer, final 
String suffix, String lineSeparator) {
         textRenderer.render(prefix, sb, "Prefix");
         if (count == 1) {
             textRenderer.render("\t... ", sb, "Suppressed");
@@ -299,16 +299,16 @@ public class ThrowableProxy implements Serializable {
             textRenderer.render(" lines", sb, "Suppressed");
         }
         renderSuffix(suffix, sb, textRenderer);
-        textRenderer.render(EOL_STR, sb, "Text");
+        textRenderer.render(lineSeparator, sb, "Text");
     }
 
     private void formatEntry(final ExtendedStackTraceElement 
extStackTraceElement, final StringBuilder sb,
-                             final String prefix, final TextRenderer 
textRenderer, final String suffix) {
+                             final String prefix, final TextRenderer 
textRenderer, final String suffix, String lineSeparator) {
         textRenderer.render(prefix, sb, "Prefix");
         textRenderer.render("\tat ", sb, "At");
         extStackTraceElement.renderOn(sb, textRenderer);
         renderSuffix(suffix, sb, textRenderer);
-        textRenderer.render(EOL_STR, sb, "Text");
+        textRenderer.render(lineSeparator, sb, "Text");
     }
 
     /**
@@ -335,26 +335,41 @@ public class ThrowableProxy implements Serializable {
 
     /**
      * Formats the specified Throwable.
-     *  @param sb             StringBuilder to contain the formatted Throwable.
-     * @param cause          The Throwable to format.
-     * @param ignorePackages The List of packages to be suppressed from the 
trace.
-     * @param textRenderer   The text render
-     * @param suffix
+     * @param sb StringBuilder to contain the formatted Throwable.
+     * @param cause The Throwable to format.
+     * @param ignorePackages The List of packages to be suppressed from the 
stack trace.
+     * @param textRenderer The text renderer.
+     * @param suffix Append this to the end of each stack frame.
      */
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
     public void formatWrapper(final StringBuilder sb, final ThrowableProxy 
cause, final List<String> ignorePackages,
-                              final TextRenderer textRenderer, final String 
suffix) {
+            final TextRenderer textRenderer, final String suffix) {
+        formatWrapper(sb, cause, ignorePackages, textRenderer, suffix, 
EOL_STR);
+    }
+
+    /**
+     * Formats the specified Throwable.
+     * @param sb StringBuilder to contain the formatted Throwable.
+     * @param cause The Throwable to format.
+     * @param ignorePackages The List of packages to be suppressed from the 
stack trace.
+     * @param textRenderer The text renderer.
+     * @param suffix Append this to the end of each stack frame.
+     * @param lineSeparator The end-of-line separator.
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public void formatWrapper(final StringBuilder sb, final ThrowableProxy 
cause, final List<String> ignorePackages,
+                              final TextRenderer textRenderer, final String 
suffix, final String lineSeparator) {
         final Throwable caused = cause.getCauseProxy() != null ? 
cause.getCauseProxy().getThrowable() : null;
         if (caused != null) {
-            this.formatWrapper(sb, cause.causeProxy, ignorePackages, 
textRenderer, suffix);
+            this.formatWrapper(sb, cause.causeProxy, ignorePackages, 
textRenderer, suffix, lineSeparator);
             sb.append(WRAPPED_BY_LABEL);
             renderSuffix(suffix, sb, textRenderer);
         }
         cause.renderOn(sb, textRenderer);
         renderSuffix(suffix, sb, textRenderer);
-        textRenderer.render(EOL_STR, sb, "Text");
+        textRenderer.render(lineSeparator, sb, "Text");
         this.formatElements(sb, Strings.EMPTY, cause.commonElementCount,
-            cause.getThrowable().getStackTrace(), cause.extendedStackTrace, 
ignorePackages, textRenderer, suffix);
+            cause.getThrowable().getStackTrace(), cause.extendedStackTrace, 
ignorePackages, textRenderer, suffix, lineSeparator);
     }
 
     public ThrowableProxy getCauseProxy() {
@@ -368,40 +383,53 @@ public class ThrowableProxy implements Serializable {
      * @param suffix
      */
     public String getCauseStackTraceAsString(final String suffix) {
-        return this.getCauseStackTraceAsString(null, 
PlainTextRenderer.getInstance(), suffix);
+        return this.getCauseStackTraceAsString(null, 
PlainTextRenderer.getInstance(), suffix, EOL_STR);
     }
 
     /**
      * Formats the Throwable that is the cause of this Throwable.
      *
      * @param packages The List of packages to be suppressed from the trace.
-     * @param suffix
+     * @param suffix Append this to the end of each stack frame.
      * @return The formatted Throwable that caused this Throwable.
      */
     public String getCauseStackTraceAsString(final List<String> packages, 
final String suffix) {
-        return getCauseStackTraceAsString(packages, 
PlainTextRenderer.getInstance(), suffix);
+        return getCauseStackTraceAsString(packages, 
PlainTextRenderer.getInstance(), suffix, EOL_STR);
     }
 
     /**
      * Formats the Throwable that is the cause of this Throwable.
      *
      * @param ignorePackages The List of packages to be suppressed from the 
trace.
-     * @param textRenderer   the text renderer
-     * @param suffix
+     * @param textRenderer The text renderer.
+     * @param suffix Append this to the end of each stack frame.
      * @return The formatted Throwable that caused this Throwable.
      */
     public String getCauseStackTraceAsString(final List<String> 
ignorePackages, final TextRenderer textRenderer, final String suffix) {
+        return getCauseStackTraceAsString(ignorePackages, textRenderer, 
suffix, EOL_STR);
+    }
+
+    /**
+     * Formats the Throwable that is the cause of this Throwable.
+     *
+     * @param ignorePackages The List of packages to be suppressed from the 
stack trace.
+     * @param textRenderer The text renderer.
+     * @param suffix Append this to the end of each stack frame.
+     * @param lineSeparator The end-of-line separator.
+     * @return The formatted Throwable that caused this Throwable.
+     */
+    public String getCauseStackTraceAsString(final List<String> 
ignorePackages, final TextRenderer textRenderer, final String suffix, final 
String lineSeparator) {
         final StringBuilder sb = new StringBuilder();
         if (this.causeProxy != null) {
-            this.formatWrapper(sb, this.causeProxy, ignorePackages, 
textRenderer, suffix);
+            this.formatWrapper(sb, this.causeProxy, ignorePackages, 
textRenderer, suffix, lineSeparator);
             sb.append(WRAPPED_BY_LABEL);
             renderSuffix(suffix, sb, textRenderer);
         }
         this.renderOn(sb, textRenderer);
         renderSuffix(suffix, sb, textRenderer);
-        textRenderer.render(EOL_STR, sb, "Text");
+        textRenderer.render(lineSeparator, sb, "Text");
         this.formatElements(sb, Strings.EMPTY, 0, 
this.throwable.getStackTrace(), this.extendedStackTrace,
-            ignorePackages, textRenderer, suffix);
+            ignorePackages, textRenderer, suffix, lineSeparator);
         return sb.toString();
     }
 
@@ -425,55 +453,67 @@ public class ThrowableProxy implements Serializable {
     }
 
     /**
-     * Format the stack trace including packaging information.
+     * Formats the stack trace including packaging information.
      *
      * @return The formatted stack trace including packaging information.
-     * @param suffix
      */
     public String getExtendedStackTraceAsString() {
-        return this.getExtendedStackTraceAsString(null, 
PlainTextRenderer.getInstance(), "");
+        return this.getExtendedStackTraceAsString(null, 
PlainTextRenderer.getInstance(), Strings.EMPTY, EOL_STR);
     }
 
     /**
-     * Format the stack trace including packaging information.
+     * Formats the stack trace including packaging information.
      *
      * @return The formatted stack trace including packaging information.
-     * @param suffix
+     * @param suffix Append this to the end of each stack frame.
      */
     public String getExtendedStackTraceAsString(final String suffix) {
-        return this.getExtendedStackTraceAsString(null, 
PlainTextRenderer.getInstance(), suffix);
+        return this.getExtendedStackTraceAsString(null, 
PlainTextRenderer.getInstance(), suffix, EOL_STR);
     }
 
     /**
-     * Format the stack trace including packaging information.
+     * Formats the stack trace including packaging information.
      *
      * @param ignorePackages List of packages to be ignored in the trace.
-     * @param suffix
+     * @param suffix Append this to the end of each stack frame.
      * @return The formatted stack trace including packaging information.
      */
     public String getExtendedStackTraceAsString(final List<String> 
ignorePackages, final String suffix) {
-        return getExtendedStackTraceAsString(ignorePackages, 
PlainTextRenderer.getInstance(), suffix);
+        return getExtendedStackTraceAsString(ignorePackages, 
PlainTextRenderer.getInstance(), suffix, EOL_STR);
     }
 
     /**
-     * Format the stack trace including packaging information.
+     * Formats the stack trace including packaging information.
      *
      * @param ignorePackages List of packages to be ignored in the trace.
-     * @param textRenderer   The message renderer
-     * @param suffix
+     * @param textRenderer The message renderer.
+     * @param suffix Append this to the end of each stack frame.
      * @return The formatted stack trace including packaging information.
      */
     public String getExtendedStackTraceAsString(final List<String> 
ignorePackages, final TextRenderer textRenderer, final String suffix) {
+        return getExtendedStackTraceAsString(ignorePackages, textRenderer, 
suffix, EOL_STR);
+    }
+
+    /**
+     * Formats the stack trace including packaging information.
+     *
+     * @param ignorePackages List of packages to be ignored in the trace.
+     * @param textRenderer The message renderer.
+     * @param suffix Append this to the end of each stack frame.
+     * @param lineSeparator The end-of-line separator.
+     * @return The formatted stack trace including packaging information.
+     */
+    public String getExtendedStackTraceAsString(final List<String> 
ignorePackages, final TextRenderer textRenderer, final String suffix, final 
String lineSeparator) {
         final StringBuilder sb = new StringBuilder(1024);
         textRenderer.render(name, sb, "Name");
         textRenderer.render(": ", sb, "NameMessageSeparator");
         textRenderer.render(this.message, sb, "Message");
         renderSuffix(suffix, sb, textRenderer);
-        textRenderer.render(EOL_STR, sb, "Text");
+        textRenderer.render(lineSeparator, sb, "Text");
         final StackTraceElement[] causedTrace = this.throwable != null ? 
this.throwable.getStackTrace() : null;
-        this.formatElements(sb, Strings.EMPTY, 0, causedTrace, 
this.extendedStackTrace, ignorePackages, textRenderer, suffix);
-        this.formatSuppressed(sb, TAB, this.suppressedProxies, ignorePackages, 
textRenderer, suffix);
-        this.formatCause(sb, Strings.EMPTY, this.causeProxy, ignorePackages, 
textRenderer, suffix);
+        this.formatElements(sb, Strings.EMPTY, 0, causedTrace, 
this.extendedStackTrace, ignorePackages, textRenderer, suffix, lineSeparator);
+        this.formatSuppressed(sb, TAB, this.suppressedProxies, ignorePackages, 
textRenderer, suffix, lineSeparator);
+        this.formatCause(sb, Strings.EMPTY, this.causeProxy, ignorePackages, 
textRenderer, suffix, lineSeparator);
         return sb.toString();
     }
 
@@ -508,7 +548,7 @@ public class ThrowableProxy implements Serializable {
     }
 
     /**
-     * Format the suppressed Throwables.
+     * Formats the suppressed Throwables.
      *
      * @return The formatted suppressed Throwables.
      * @param suffix

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
index a6b3a88..57cbb9c 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
@@ -661,4 +661,8 @@ public final class PatternLayout extends 
AbstractStringLayout {
                 alwaysWriteExceptions, disableAnsi, noConsoleNoAnsi, header, 
footer);
         }
     }
+
+    public Serializer getEventSerializer() {
+        return eventSerializer;
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
index 0105f3c..3196758 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
@@ -68,26 +68,13 @@ public final class ExtendedThrowablePatternConverter 
extends ThrowablePatternCon
                 super.format(event, toAppendTo);
                 return;
             }
-            final String suffix = getSuffix(event);
-            final String extStackTrace = 
proxy.getExtendedStackTraceAsString(options.getIgnorePackages(), 
options.getTextRenderer(), suffix);
+            final String extStackTrace = 
proxy.getExtendedStackTraceAsString(options.getIgnorePackages(),
+                    options.getTextRenderer(), getSuffix(event), 
options.getSeparator());
             final int len = toAppendTo.length();
             if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 
1))) {
                 toAppendTo.append(' ');
             }
-            if (!options.allLines() || 
!Strings.LINE_SEPARATOR.equals(options.getSeparator())) {
-                final StringBuilder sb = new StringBuilder();
-                final String[] array = 
extStackTrace.split(Strings.LINE_SEPARATOR);
-                final int limit = options.minLines(array.length) - 1;
-                for (int i = 0; i <= limit; ++i) {
-                    sb.append(array[i]);
-                    if (i < limit) {
-                        sb.append(options.getSeparator());
-                    }
-                }
-                toAppendTo.append(sb.toString());
-            } else {
-                toAppendTo.append(extStackTrace);
-            }
+            toAppendTo.append(extStackTrace);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
index b14aad3..eadb3f3 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ThrowablePatternConverter.java
@@ -39,11 +39,14 @@ import org.apache.logging.log4j.util.Strings;
 @ConverterKeys({ "ex", "throwable", "exception" })
 public class ThrowablePatternConverter extends LogEventPatternConverter {
 
+    /**
+     * Lists {@link PatternFormatter}s for the suffix attribute.
+     */
     protected final List<PatternFormatter> formatters;
     private String rawOption;
 
     /**
-     * The number of lines to write.
+     * Options.
      */
     protected final ThrowableFormatOptions options;
 
@@ -62,24 +65,24 @@ public class ThrowablePatternConverter extends 
LogEventPatternConverter {
         }
         if (this.options.getSuffix() != null) {
             final PatternParser parser = 
PatternLayout.createPatternParser(config);
-            final List<PatternFormatter> parsedFormatters = 
parser.parse(this.options.getSuffix());
+            final List<PatternFormatter> parsedSuffixFormatters = 
parser.parse(this.options.getSuffix());
             // filter out nested formatters that will handle throwable
-            boolean hasThrowableFormatter = false;
-            for (final PatternFormatter formatter : parsedFormatters) {
-                if (formatter.handlesThrowable()) {
-                    hasThrowableFormatter = true;
+            boolean hasThrowableSuffixFormatter = false;
+            for (final PatternFormatter suffixFormatter : 
parsedSuffixFormatters) {
+                if (suffixFormatter.handlesThrowable()) {
+                    hasThrowableSuffixFormatter = true;
                 }
             }
-            if (!hasThrowableFormatter) {
-                this.formatters = parsedFormatters;
+            if (!hasThrowableSuffixFormatter) {
+                this.formatters = parsedSuffixFormatters;
             } else {
-                final List<PatternFormatter> formatters = new ArrayList<>();
-                for (final PatternFormatter formatter : parsedFormatters) {
-                    if (!formatter.handlesThrowable()) {
-                        formatters.add(formatter);
+                final List<PatternFormatter> suffixFormatters = new 
ArrayList<>();
+                for (final PatternFormatter suffixFormatter : 
parsedSuffixFormatters) {
+                    if (!suffixFormatter.handlesThrowable()) {
+                        suffixFormatters.add(suffixFormatter);
                     }
                 }
-                this.formatters = formatters;
+                this.formatters = suffixFormatters;
             }
         } else {
             this.formatters = Collections.emptyList();
@@ -90,7 +93,6 @@ public class ThrowablePatternConverter extends 
LogEventPatternConverter {
     /**
      * Gets an instance of the class.
      *
-     *
      * @param config
      * @param options pattern options, may be null.  If first element is 
"short",
      *                only the first line of the throwable will be formatted.
@@ -219,4 +221,8 @@ public class ThrowablePatternConverter extends 
LogEventPatternConverter {
         }
         return toAppendTo.toString();
     }
+
+    public ThrowableFormatOptions getOptions() {
+        return options;
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
index 1c6a2ec..25261f9 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/HttpAppenderTest.java
@@ -46,13 +46,14 @@ import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.status.StatusData;
 import org.apache.logging.log4j.status.StatusListener;
 import org.apache.logging.log4j.status.StatusLogger;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
 import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
 import com.github.tomakehurst.wiremock.junit.WireMockRule;
 
-//@Ignore("Fails often on Windows")
+@Ignore("Fails often on Windows")
 
 /* Fails often on Windows, for example:
 [ERROR] Failed to execute goal 
org.apache.maven.plugins:maven-surefire-plugin:2.20.1:test (default-test) on 
project log4j-core: There are test failures.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/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 091322b..d099da1 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
@@ -63,7 +63,7 @@ public final class ThrowableFormatOptionsTest {
     }
 
     /**
-     * Test {@code %throwable } with null options.
+     * Test {@code %throwable} with null options.
      */
     @Test
     public void testNull() {
@@ -71,7 +71,7 @@ public final class ThrowableFormatOptionsTest {
     }
 
     /**
-     * Test {@code %throwable }
+     * Test {@code %throwable}
      */
     @Test
     public void testEmpty() {
@@ -113,7 +113,7 @@ public final class ThrowableFormatOptionsTest {
     }
 
     /**
-     * Test {@code %throwable{full}{ansi} }
+     * Test {@code %throwable{full}{ansi()} }
      */
     @Test
     public void testFullAnsiEmptyConfig() {
@@ -233,7 +233,7 @@ public final class ThrowableFormatOptionsTest {
     }
 
     /**
-     * Test {@code %throwable{separator(|)} }
+     * Test {@code %throwable{separator( | )} }
      */
     @Test
     public void testSeparatorAsMultipleCharacters() {
@@ -249,6 +249,14 @@ public final class ThrowableFormatOptionsTest {
     }
 
     /**
+     * Test {@code %throwable{full}{filters(org.junit)}{separator(|)} }
+     */
+    @Test
+    public void testFullAndFiltersAndSeparator() {
+        test(new String[] { "full", "filters(org.junit)", "separator(|)" }, 
Integer.MAX_VALUE, "|", Arrays.asList("org.junit"));
+    }
+
+    /**
      * Test {@code %throwable{none}{separator(|)} }
      */
     @Test
@@ -335,12 +343,21 @@ public final class ThrowableFormatOptionsTest {
      * Test {@code %throwable{full}{separator(|)}{filters(packages)} }
      */
     @Test
-    public void testFullAndSeparatorAndFilters() {
+    public void testFullAndSeparatorAndFilter() {
         test(new String[] { "full", "separator(|)", "filters(packages)" }, 
Integer.MAX_VALUE, "|",
                 Arrays.asList("packages"));
     }
 
     /**
+     * Test {@code %throwable{full}{separator(|)}{filters(package1,package2)} }
+     */
+    @Test
+    public void testFullAndSeparatorAndFilters() {
+        test(new String[] { "full", "separator(|)", 
"filters(package1,package2)" }, Integer.MAX_VALUE, "|",
+                Arrays.asList("package1", "package2"));
+    }
+
+    /**
      * Test {@code %throwable{none}{separator(|)}{filters(packages)} }
      */
     @Test

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
index 2b5edd7..813a5b7 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThrowableProxyTest.java
@@ -47,6 +47,7 @@ import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.config.plugins.convert.Base64Converter;
 import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
 import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
+import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
 import org.apache.logging.log4j.util.Strings;
 import org.junit.Test;
 
@@ -94,6 +95,12 @@ public class ThrowableProxyTest {
         return true;
     }
 
+    private boolean lastLineContains(final String text, final String 
containedText) {
+        final String[] lines = text.split("\n");
+        final String lastLine = lines[lines.length-1];
+        return lastLine.contains(containedText);
+    }
+
     private void testIoContainer(final ObjectMapper objectMapper ) throws 
IOException {
         final Fixture expected = new Fixture();
         final String s = objectMapper.writeValueAsString(expected);
@@ -294,12 +301,24 @@ public class ThrowableProxyTest {
     }
 
     @Test
+    public void testSeparator_getExtendedStackTraceAsString() throws Exception 
{
+        final Throwable throwable = new IllegalArgumentException("This is a 
test");
+        final ThrowableProxy proxy = new ThrowableProxy(throwable);
+
+        final String separator = " | ";
+        final String extendedStackTraceAsString = 
proxy.getExtendedStackTraceAsString(null,
+                PlainTextRenderer.getInstance(), " | ", Strings.EMPTY);
+        assertTrue(extendedStackTraceAsString, 
allLinesContain(extendedStackTraceAsString, separator));
+    }
+
+    @Test
     public void testSuffix_getExtendedStackTraceAsString() throws Exception {
         final Throwable throwable = new IllegalArgumentException("This is a 
test");
         final ThrowableProxy proxy = new ThrowableProxy(throwable);
 
         final String suffix = "some suffix";
-        
assertTrue(allLinesContain(proxy.getExtendedStackTraceAsString(suffix), 
suffix));
+        final String extendedStackTraceAsString = 
proxy.getExtendedStackTraceAsString(suffix);
+        assertTrue(extendedStackTraceAsString, 
lastLineContains(extendedStackTraceAsString, suffix));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/Log4j2_2195_Test.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/Log4j2_2195_Test.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/Log4j2_2195_Test.java
new file mode 100644
index 0000000..958e38a
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/Log4j2_2195_Test.java
@@ -0,0 +1,62 @@
+/*
+ * 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.layout;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+public class Log4j2_2195_Test {
+
+    @ClassRule
+    public static final LoggerContextRule loggerContextRule = new 
LoggerContextRule(
+            "src/test/resources/LOG4J-2195/log4j2.xml");
+
+    private static final Logger logger = 
LogManager.getLogger(Log4j2_2195_Test.class);
+
+    @Test
+    public void test() {
+        logger.info("This is a test.", new Exception("Test exception!"));
+        ListAppender listAppender = 
loggerContextRule.getListAppender("ListAppender");
+        Assert.assertNotNull(listAppender);
+        List<String> events = listAppender.getMessages();
+        Assert.assertNotNull(events);
+        Assert.assertEquals(1, events.size());
+        String logEvent = events.get(0);
+        Assert.assertNotNull(logEvent);
+        Assert.assertFalse("\"org.junit\" should not be here", 
logEvent.contains("org.junit"));
+        Assert.assertFalse("\"org.eclipse\" should not be here", 
logEvent.contains("org.eclipse"));
+        //
+        Layout<? extends Serializable> layout = listAppender.getLayout();
+        PatternLayout pLayout = (PatternLayout) layout;
+        Assert.assertNotNull(pLayout);
+        Serializer eventSerializer = pLayout.getEventSerializer();
+        Assert.assertNotNull(eventSerializer);
+        //
+        Assert.assertTrue("Missing \"|\"", logEvent.contains("|"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
index 839a3a7..445b893 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverterTest.java
@@ -18,15 +18,18 @@ package org.apache.logging.log4j.core.pattern;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.util.List;
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.impl.ThrowableFormatOptions;
 import org.apache.logging.log4j.core.impl.ThrowableProxy;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.util.Strings;
@@ -153,7 +156,21 @@ public class ExtendedThrowablePatternConverterTest {
         parent.printStackTrace(pw);
         String result = sb.toString();
         result = result.replaceAll(" ~?\\[.*\\]", Strings.EMPTY);
-        final String expected = sw.toString().replaceAll("\r", Strings.EMPTY);
+        final String expected = sw.toString(); //.replaceAll("\r", 
Strings.EMPTY);
         assertEquals(expected, result);
     }
+    
+    @Test
+    public void testFiltersAndSeparator() {
+        final ExtendedThrowablePatternConverter exConverter = 
ExtendedThrowablePatternConverter.newInstance(null,
+                new String[] { "full", "filters(org.junit,org.eclipse)", 
"separator(|)" });
+        final ThrowableFormatOptions options = exConverter.getOptions();
+        final List<String> ignorePackages = options.getIgnorePackages();
+        assertNotNull(ignorePackages);
+        final String ignorePackagesString = ignorePackages.toString();
+        assertTrue(ignorePackagesString, ignorePackages.contains("org.junit"));
+        assertTrue(ignorePackagesString, 
ignorePackages.contains("org.eclipse"));
+        assertEquals("|", options.getSeparator());
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/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 00c1db9..1c15091 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
@@ -32,6 +32,7 @@ import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.NullConfiguration;
 import org.apache.logging.log4j.core.impl.ContextDataFactory;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.impl.ThrowableFormatOptions;
 import org.apache.logging.log4j.core.util.DummyNanoClock;
 import org.apache.logging.log4j.core.util.SystemNanoClock;
 import org.apache.logging.log4j.message.SimpleMessage;
@@ -117,7 +118,7 @@ public class PatternParserTest {
             formatter.format(event, buf);
         }
         final String str = buf.toString();
-        final String expected = "INFO  [PatternParserTest        :103 ] - 
Hello, world" + Strings.LINE_SEPARATOR;
+        final String expected = "INFO  [PatternParserTest        :104 ] - 
Hello, world" + Strings.LINE_SEPARATOR;
         assertTrue("Expected to end with: " + expected + ". Actual: " + str, 
str.endsWith(expected));
     }
 
@@ -369,4 +370,40 @@ public class PatternParserTest {
         validateConverter(formatters, 0, "Literal");
         validateConverter(formatters, 1, "Date");
     }
+
+    @Test
+    public void testExceptionWithFilters() {
+        final List<PatternFormatter> formatters = parser
+                .parse("%d{DEFAULT} - %msg - 
%xEx{full}{filters(org.junit,org.eclipse)}%n");
+        assertNotNull(formatters);
+        assertEquals(6, formatters.size());
+        final PatternFormatter patternFormatter = formatters.get(4);
+        final LogEventPatternConverter converter = 
patternFormatter.getConverter();
+        assertEquals(ExtendedThrowablePatternConverter.class, 
converter.getClass());
+        final ExtendedThrowablePatternConverter exConverter = 
(ExtendedThrowablePatternConverter) converter;
+        final ThrowableFormatOptions options = exConverter.getOptions();
+        assertTrue(options.getIgnorePackages().contains("org.junit"));
+        assertTrue(options.getIgnorePackages().contains("org.eclipse"));
+        assertEquals(System.lineSeparator(), options.getSeparator());
+    }
+
+    @Test
+    public void testExceptionWithFiltersAndSeparator() {
+        final List<PatternFormatter> formatters = parser
+                .parse("%d{DEFAULT} - %msg - 
%xEx{full}{filters(org.junit,org.eclipse)}{separator(|)}%n");
+        assertNotNull(formatters);
+        assertEquals(6, formatters.size());
+        final PatternFormatter patternFormatter = formatters.get(4);
+        final LogEventPatternConverter converter = 
patternFormatter.getConverter();
+        assertEquals(ExtendedThrowablePatternConverter.class, 
converter.getClass());
+        final ExtendedThrowablePatternConverter exConverter = 
(ExtendedThrowablePatternConverter) converter;
+        final ThrowableFormatOptions options = exConverter.getOptions();
+        final List<String> ignorePackages = options.getIgnorePackages();
+        assertNotNull(ignorePackages);
+        final String ignorePackagesString = ignorePackages.toString();
+        assertTrue(ignorePackagesString, ignorePackages.contains("org.junit"));
+        assertTrue(ignorePackagesString, 
ignorePackages.contains("org.eclipse"));
+        assertEquals("|", options.getSeparator());
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/log4j-core/src/test/resources/LOG4J-2195/log4j2.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/LOG4J-2195/log4j2.xml 
b/log4j-core/src/test/resources/LOG4J-2195/log4j2.xml
new file mode 100644
index 0000000..bf780d6
--- /dev/null
+++ b/log4j-core/src/test/resources/LOG4J-2195/log4j2.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="warn">
+  <Appenders>
+    <List name="ListAppender">
+      <PatternLayout pattern="%d{DEFAULT} - %msg - 
%xEx{full}{filters(org.junit,org.eclipse)}{separator(|)}%n" />
+    </List>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="%d{DEFAULT} - %msg - 
%xEx{full}{filters(org.junit,org.eclipse)}{separator(|)}%n" />
+    </Console>
+  </Appenders>
+  <Loggers>
+    <Root level="debug">
+      <AppenderRef ref="ListAppender" />
+      <AppenderRef ref="Console" />
+    </Root>
+  </Loggers>
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d216855..bba91ba 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -1038,6 +1038,9 @@
       <action issue="LOG4J2-1733" dev="ggregory" type="add" due-to="Vincent 
Tieleman">
         Add SyncSend attribute to KafkaAppender (as in KafkaLog4jAppender).
       </action>
+      <action issue="LOG4J2-2195" dev="ggregory" type="add" due-to="Raman 
Gupta, Gary Gregory">
+        Cannot define both `filters` and `separator` for PatternLayout %xEx.
+      </action>
     </release>
     <release version="2.7" date="2016-10-02" description="GA Release 2.7">
       <action issue="LOG4J2-1618" dev="rpopma" type="fix" due-to="Raman Gupta">

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9ff63b2e/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 c406aaa..d8d9ec3 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -906,12 +906,11 @@ WARN  [main]: Message 2</pre>
                 &nbsp;&nbsp;&nbsp;| "short.lineNumber"<br />
                 &nbsp;&nbsp;&nbsp;| "short.methodName"<br />
                 &nbsp;&nbsp;&nbsp;| "short.message"<br />
-                &nbsp;&nbsp;&nbsp;| "short.localizedMessage"]}<br />
-                &nbsp;&nbsp;[,filters(package,package,...)]<br/>
-                &nbsp;&nbsp;[,separator(<i>separator</i>)]<br/>
-                }<br/>
-                {suffix(<i>pattern</i>)<br/>
-                }<br/>
+                &nbsp;&nbsp;&nbsp;| "short.localizedMessage"]<br />
+                }<br />
+                &nbsp;&nbsp;{filters(package,package,...)}<br/>
+                &nbsp;&nbsp;{suffix(<i>pattern</i>)}<br/>
+                &nbsp;&nbsp;{separator(<i>separator</i>)}<br/>
               </td>
               <td>
                 <p>
@@ -949,17 +948,15 @@ WARN  [main]: Message 2</pre>
                   Specifying <code>%throwable{none}</code> or 
<code>%throwable{0}</code> suppresses output of the exception.
                 </p>
                 <p>
-                  Use <code>filters(<i>packages</i>)</code> where 
<i>packages</i> is a list of package names to
+                  Use <code>{filters(<i>packages</i>)}</code> where 
<i>packages</i> is a list of package names to
                   suppress matching stack frames from stack traces.
                 </p>
                 <p>
-                  Use a <code>separator</code> string to separate the lines of 
a stack trace. For example:
-                  <code>separator(|)</code>. The default value is the 
<code>line.separator</code> system property,
-                  which is operating system dependent.
+                  Use <code>{suffix(<i>pattern</i>)}</code> to add the output 
of <i>pattern</i> at the end of each stack frames.
                 </p>
                 <p>
-                  Use <code>ex{suffix(<i>pattern</i>)</code> to add the output 
of <i>pattern</i> to the output only
-                  when there is a throwable to print.
+                  Use a <code>{separator(...)}</code> as the end-of-line 
string. For example: <code>separator(|)</code>. 
+                  The default value is the <code>line.separator</code> system 
property, which is operating system dependent.
                 </p>
               </td>
             </tr>

Reply via email to