You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2016/03/28 10:11:40 UTC
[1/4] logging-log4j2 git commit: LOG4J2-1271 added unit test
Repository: logging-log4j2
Updated Branches:
refs/heads/master 5c8acfb54 -> a21828565
LOG4J2-1271 added unit test
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/0ed5b50d
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/0ed5b50d
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/0ed5b50d
Branch: refs/heads/master
Commit: 0ed5b50d59b8095abae58837e61cc7f19da28920
Parents: 5c8acfb
Author: rpopma <rp...@apache.org>
Authored: Mon Mar 28 17:00:26 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Mon Mar 28 17:00:26 2016 +0900
----------------------------------------------------------------------
.../logging/log4j/message/ParameterizedMessageTest.java | 8 ++++++++
1 file changed, 8 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ed5b50d/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterizedMessageTest.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterizedMessageTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterizedMessageTest.java
index 6b550b3..ac9895e 100644
--- a/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterizedMessageTest.java
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterizedMessageTest.java
@@ -79,6 +79,14 @@ public class ParameterizedMessageTest {
}
@Test
+ public void testFormatStringArgsWithTrailingText() {
+ final String testMsg = "Test message {}{} {}Text";
+ final String[] args = { "a", "b", "c" };
+ final String result = ParameterizedMessage.format(testMsg, args);
+ assertEquals("Test message ab cText", result);
+ }
+
+ @Test
public void testFormatStringArgsWithTrailingEscapedEscape() {
final String testMsg = "Test message {}{} {}\\\\";
final String[] args = { "a", "b", "c" };
[3/4] logging-log4j2 git commit: LOG4J2-1271 added benchmark for
different ways to format parameterized messages
Posted by rp...@apache.org.
LOG4J2-1271 added benchmark for different ways to format parameterized messages
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/8242eb6b
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/8242eb6b
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/8242eb6b
Branch: refs/heads/master
Commit: 8242eb6b6234d0550a4285bc481ea9f3a0709ebb
Parents: b1e1db8
Author: rpopma <rp...@apache.org>
Authored: Mon Mar 28 17:10:35 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Mon Mar 28 17:10:35 2016 +0900
----------------------------------------------------------------------
.../message/ParameterFormatterBenchmark.java | 188 +++++++++++++++++++
1 file changed, 188 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8242eb6b/log4j-perf/src/main/java/org/apache/logging/log4j/message/ParameterFormatterBenchmark.java
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/message/ParameterFormatterBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/message/ParameterFormatterBenchmark.java
new file mode 100644
index 0000000..d7dbf5d
--- /dev/null
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/message/ParameterFormatterBenchmark.java
@@ -0,0 +1,188 @@
+/*
+ * 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.message;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.logging.log4j.message.ParameterizedMessage;
+import org.apache.logging.log4j.perf.jmh.ParameterizedMessageBenchmark;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+
+/**
+ * This benchmark is not in the perf.jmh package because it tests the package-protected ParameterFormatter class.
+ */
+// ============================== HOW TO RUN THIS TEST: ====================================
+//
+// single thread:
+// java -jar log4j-perf/target/benchmarks.jar ".*ParameterFormatterBench.*" -f 1 -wi 5 -i 10
+//
+// multiple threads (for example, 4 threads):
+// java -jar log4j-perf/target/benchmarks.jar ".*ParameterFormatterBench.*" -f 1 -wi 5 -i 10 -t 4 -si true
+//
+// Usage help:
+// java -jar log4j-perf/target/benchmarks.jar -help
+//
+@State(Scope.Benchmark)
+public class ParameterFormatterBenchmark {
+ private static final Object[] ARGS = { "arg1", "arg2", "arg3", "arg4", "arg5", "arg6", "arg7", "arg8",
+ "arg9", "arg10",};
+
+ @State(Scope.Thread)
+ public static class ThreadState {
+ StringBuilder buffer = new StringBuilder(2048);
+ int[] indices = new int[255];
+ char[] copy = new char[4096];
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency3ParamsV3(final ThreadState state) {
+ state.buffer.setLength(0);
+ String STR = "p1={}, p2={}, p3={}";
+ int length = STR.length();
+ STR.getChars(0, length, state.copy, 0);
+ int count = ParameterFormatter.countArgumentPlaceholders3(state.copy, length, state.indices);
+ ParameterFormatter.formatMessage3(state.buffer, state.copy, length, ARGS, count, state.indices);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency5ParamsV3(final ThreadState state) {
+ state.buffer.setLength(0);
+ String STR = "p1={}, p2={}, p3={}, p4={}, p5={}";
+ int length = STR.length();
+ STR.getChars(0, length, state.copy, 0);
+ int count = ParameterFormatter.countArgumentPlaceholders3(state.copy, length, state.indices);
+ ParameterFormatter.formatMessage3(state.buffer, state.copy, length, ARGS, count, state.indices);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency7ParamsV3(final ThreadState state) {
+ state.buffer.setLength(0);
+ String STR = "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}";
+ int length = STR.length();
+ STR.getChars(0, length, state.copy, 0);
+ int count = ParameterFormatter.countArgumentPlaceholders3(state.copy, length, state.indices);
+ ParameterFormatter.formatMessage3(state.buffer, state.copy, length, ARGS, count, state.indices);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency9ParamsV3(final ThreadState state) {
+ state.buffer.setLength(0);
+ String STR = "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}";
+ int length = STR.length();
+ STR.getChars(0, length, state.copy, 0);
+ int count = ParameterFormatter.countArgumentPlaceholders3(state.copy, length, state.indices);
+ ParameterFormatter.formatMessage3(state.buffer, state.copy, length, ARGS, count, state.indices);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency3ParamsV2(final ThreadState state) {
+ state.buffer.setLength(0);
+ int count = ParameterFormatter.countArgumentPlaceholders2("p1={}, p2={}, p3={}", state.indices);
+ ParameterFormatter.formatMessage2(state.buffer, "p1={}, p2={}, p3={}", ARGS, count, state.indices);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency5ParamsV2(final ThreadState state) {
+ state.buffer.setLength(0);
+ int count = ParameterFormatter.countArgumentPlaceholders2("p1={}, p2={}, p3={}, p4={}, p5={}", state.indices);
+ ParameterFormatter.formatMessage2(state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}", ARGS, count, state.indices);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency7ParamsV2(final ThreadState state) {
+ state.buffer.setLength(0);
+ int count = ParameterFormatter.countArgumentPlaceholders2("p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}", state.indices);
+ ParameterFormatter.formatMessage2(state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}", ARGS, count, state.indices);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency9ParamsV2(final ThreadState state) {
+ state.buffer.setLength(0);
+ int count = ParameterFormatter.countArgumentPlaceholders2("p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}", state.indices);
+ ParameterFormatter.formatMessage2(state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}", ARGS, count, state.indices);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency3Params(final ThreadState state) {
+ state.buffer.setLength(0);
+ int count = ParameterFormatter.countArgumentPlaceholders("p1={}, p2={}, p3={}");
+ ParameterFormatter.formatMessage(state.buffer, "p1={}, p2={}, p3={}", ARGS, count);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency5Params(final ThreadState state) {
+ state.buffer.setLength(0);
+ int count = ParameterFormatter.countArgumentPlaceholders("p1={}, p2={}, p3={}, p4={}, p5={}");
+ ParameterFormatter.formatMessage(state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}", ARGS, count);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency7Params(final ThreadState state) {
+ state.buffer.setLength(0);
+ int count = ParameterFormatter.countArgumentPlaceholders("p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}");
+ ParameterFormatter.formatMessage(state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}", ARGS, count);
+ return state.buffer.length();
+ }
+
+ @Benchmark
+ @BenchmarkMode(Mode.SampleTime)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public int latency9Params(final ThreadState state) {
+ state.buffer.setLength(0);
+ int count = ParameterFormatter.countArgumentPlaceholders("p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}");
+ ParameterFormatter.formatMessage(state.buffer, "p1={}, p2={}, p3={}, p4={}, p5={}, p6={}, p7={}, p8={}, p9={}", ARGS, count);
+ return state.buffer.length();
+ }
+}
[4/4] logging-log4j2 git commit: LOG4J2-1271 use the
System.arrayCopy-based fast copy where possible for formatting the message
Posted by rp...@apache.org.
LOG4J2-1271 use the System.arrayCopy-based fast copy where possible for formatting the message
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/a2182856
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/a2182856
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/a2182856
Branch: refs/heads/master
Commit: a21828565ba164aea8fe6356d656d0a345d99f4e
Parents: 8242eb6
Author: rpopma <rp...@apache.org>
Authored: Mon Mar 28 17:11:43 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Mon Mar 28 17:11:43 2016 +0900
----------------------------------------------------------------------
.../log4j/message/ParameterizedMessage.java | 13 ++++++++++---
.../message/ReusableParameterizedMessage.java | 20 +++++++++++++++++---
2 files changed, 27 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/a2182856/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedMessage.java
index fe22b02..e1ef2a5 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterizedMessage.java
@@ -67,6 +67,7 @@ public class ParameterizedMessage implements Message, StringBuilderFormattable {
private String formattedMessage;
private transient Throwable throwable;
+ private int[] indices;
/**
* Creates a parameterized message.
@@ -133,7 +134,8 @@ public class ParameterizedMessage implements Message, StringBuilderFormattable {
private void init(String messagePattern) {
this.messagePattern = messagePattern;
- final int usedCount = countArgumentPlaceholders(messagePattern);
+ this.indices = new int[messagePattern == null ? 0 : messagePattern.length() << 1];
+ final int usedCount = ParameterFormatter.countArgumentPlaceholders2(messagePattern, indices);
initThrowable(argArray, usedCount);
}
@@ -207,8 +209,13 @@ public class ParameterizedMessage implements Message, StringBuilderFormattable {
if (formattedMessage != null) {
buffer.append(formattedMessage);
} else {
- ParameterFormatter.formatMessage(buffer, messagePattern, argArray,
- argArray == null ? 0 : argArray.length);
+ if (indices[0] < 0) {
+ ParameterFormatter.formatMessage(buffer, messagePattern, argArray,
+ argArray == null ? 0 : argArray.length);
+ } else {
+ ParameterFormatter.formatMessage2(buffer, messagePattern, argArray,
+ argArray == null ? 0 : argArray.length, indices);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/a2182856/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
index bd6205f..bf7095c 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
@@ -35,6 +35,7 @@ public class ReusableParameterizedMessage implements ReusableMessage {
private String messagePattern;
private int argCount;
+ private int[] indices = new int[256];
private transient Object[] varargs;
private transient Object[] params = new Object[10];
private transient Throwable throwable;
@@ -53,14 +54,23 @@ public class ReusableParameterizedMessage implements ReusableMessage {
return varargs == null ? params : varargs;
}
- private void init(String messagePattern, int argCount, Object[] paramArray) {
+ private void init(final String messagePattern, final int argCount, final Object[] paramArray) {
this.varargs = null;
this.messagePattern = messagePattern;
this.argCount= argCount;
- int usedCount = ParameterFormatter.countArgumentPlaceholders(messagePattern);
+ int usedCount = count(messagePattern, indices);
initThrowable(paramArray, usedCount);
}
+ private static int count(final String messagePattern, final int[] indices) {
+ try {
+ // try the fast path first
+ return ParameterFormatter.countArgumentPlaceholders2(messagePattern, indices);
+ } catch (final Exception ex) { // fallback if more than int[] length (256) parameter placeholders
+ return ParameterFormatter.countArgumentPlaceholders(messagePattern);
+ }
+ }
+
private void initThrowable(final Object[] params, final int usedParams) {
if (usedParams < argCount && this.throwable == null && params[argCount - 1] instanceof Throwable) {
this.throwable = (Throwable) params[argCount - 1];
@@ -238,7 +248,11 @@ public class ReusableParameterizedMessage implements ReusableMessage {
@Override
public void formatTo(final StringBuilder buffer) {
- ParameterFormatter.formatMessage(buffer, messagePattern, getParams(), argCount);
+ if (indices[0] < 0) {
+ ParameterFormatter.formatMessage(buffer, messagePattern, getParams(), argCount);
+ } else {
+ ParameterFormatter.formatMessage2(buffer, messagePattern, getParams(), argCount, indices);
+ }
}
[2/4] logging-log4j2 git commit: LOG4J2-1271 added multiple optimized
implementations
Posted by rp...@apache.org.
LOG4J2-1271 added multiple optimized implementations
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/b1e1db8b
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/b1e1db8b
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/b1e1db8b
Branch: refs/heads/master
Commit: b1e1db8be5efdf8ae816e5c542419b353aaf79f3
Parents: 0ed5b50
Author: rpopma <rp...@apache.org>
Authored: Mon Mar 28 17:10:00 2016 +0900
Committer: rpopma <rp...@apache.org>
Committed: Mon Mar 28 17:10:00 2016 +0900
----------------------------------------------------------------------
.../log4j/message/ParameterFormatter.java | 103 +++++++++++++++++++
1 file changed, 103 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b1e1db8b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java
index 453cd52..4e1f825 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ParameterFormatter.java
@@ -96,6 +96,65 @@ final class ParameterFormatter {
}
/**
+ * Counts the number of unescaped placeholders in the given messagePattern.
+ *
+ * @param messagePattern the message pattern to be analyzed.
+ * @return the number of unescaped placeholders.
+ */
+ static int countArgumentPlaceholders2(final String messagePattern, final int[] indices) {
+ if (messagePattern == null) {
+ return 0;
+ }
+ int length = messagePattern.length();
+ int result = 0;
+ boolean isEscaped = false;
+ for (int i = 0; i < length - 1; i++) {
+ final char curChar = messagePattern.charAt(i);
+ if (curChar == ESCAPE_CHAR) {
+ isEscaped = !isEscaped;
+ indices[0] = -1; // escaping means fast path is not available...
+ } else if (curChar == DELIM_START) {
+ if (!isEscaped && messagePattern.charAt(i + 1) == DELIM_STOP) {
+ indices[result] = i;
+ result++;
+ i++;
+ }
+ isEscaped = false;
+ } else {
+ isEscaped = false;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Counts the number of unescaped placeholders in the given messagePattern.
+ *
+ * @param messagePattern the message pattern to be analyzed.
+ * @return the number of unescaped placeholders.
+ */
+ static int countArgumentPlaceholders3(final char[] messagePattern, int length, final int[] indices) {
+ int result = 0;
+ boolean isEscaped = false;
+ for (int i = 0; i < length - 1; i++) {
+ final char curChar = messagePattern[i];
+ if (curChar == ESCAPE_CHAR) {
+ isEscaped = !isEscaped;
+ } else if (curChar == DELIM_START) {
+ if (!isEscaped && messagePattern[i + 1] == DELIM_STOP) {
+ indices[result] = i;
+ result++;
+ i++;
+ }
+ isEscaped = false;
+ } else {
+ isEscaped = false;
+ }
+ }
+ return result;
+ }
+
+ /**
* Replace placeholders in the given messagePattern with arguments.
*
* @param messagePattern the message pattern containing placeholders.
@@ -116,6 +175,50 @@ final class ParameterFormatter {
* @param messagePattern the message pattern containing placeholders.
* @param arguments the arguments to be used to replace placeholders.
*/
+ static void formatMessage2(final StringBuilder buffer, final String messagePattern,
+ final Object[] arguments, final int argCount, final int[] indices) {
+ if (messagePattern == null || arguments == null || argCount == 0) {
+ buffer.append(messagePattern);
+ return;
+ }
+ int previous = 0;
+ for (int i = 0; i < argCount; i++) {
+ buffer.append(messagePattern, previous, indices[i]);
+ previous = indices[i] + 2;
+ recursiveDeepToString(arguments[i], buffer, null);
+ }
+ buffer.append(messagePattern, previous, messagePattern.length());
+ }
+
+ /**
+ * Replace placeholders in the given messagePattern with arguments.
+ *
+ * @param buffer the buffer to write the formatted message into
+ * @param messagePattern the message pattern containing placeholders.
+ * @param arguments the arguments to be used to replace placeholders.
+ */
+ static void formatMessage3(final StringBuilder buffer, final char[] messagePattern, final int patternLength,
+ final Object[] arguments, final int argCount, final int[] indices) {
+ if (messagePattern == null || arguments == null || argCount == 0) {
+ buffer.append(messagePattern);
+ return;
+ }
+ int previous = 0;
+ for (int i = 0; i < argCount; i++) {
+ buffer.append(messagePattern, previous, indices[i]);
+ previous = indices[i] + 2;
+ recursiveDeepToString(arguments[i], buffer, null);
+ }
+ buffer.append(messagePattern, previous, patternLength);
+ }
+
+ /**
+ * Replace placeholders in the given messagePattern with arguments.
+ *
+ * @param buffer the buffer to write the formatted message into
+ * @param messagePattern the message pattern containing placeholders.
+ * @param arguments the arguments to be used to replace placeholders.
+ */
static void formatMessage(final StringBuilder buffer, final String messagePattern,
final Object[] arguments, final int argCount) {
if (messagePattern == null || arguments == null || argCount == 0) {