1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.message;
18
19 import java.util.Arrays;
20 import java.util.Objects;
21
22 import org.apache.logging.log4j.util.PerformanceSensitive;
23
24
25
26
27
28
29
30
31 @PerformanceSensitive("allocation")
32 public class ReusableParameterizedMessage implements ReusableMessage {
33
34 private static final long serialVersionUID = 7800075879295123856L;
35 private static ThreadLocal<StringBuilder> buffer = new ThreadLocal<>();
36
37 private String messagePattern;
38 private int argCount;
39 private int usedCount;
40 private final int[] indices = new int[256];
41 private transient Object[] varargs;
42 private transient Object[] params = new Object[10];
43 private transient Throwable throwable;
44
45
46
47
48 public ReusableParameterizedMessage() {
49 }
50
51 private Object[] getTrimmedParams() {
52 return varargs == null ? Arrays.copyOf(params, argCount) : varargs;
53 }
54
55 private Object[] getParams() {
56 return varargs == null ? params : varargs;
57 }
58
59
60 @Override
61 public Object[] swapParameters(final Object[] emptyReplacement) {
62 Object[] result;
63 if (varargs == null) {
64 result = params;
65 params = Objects.requireNonNull(emptyReplacement);
66 } else {
67 result = varargs;
68 varargs = Objects.requireNonNull(emptyReplacement);
69 }
70 return result;
71 }
72
73
74 @Override
75 public short getParameterCount() {
76 return (short) argCount;
77 }
78
79 @Override
80 public Message memento() {
81 return new ParameterizedMessage(messagePattern, getTrimmedParams());
82 }
83
84 private void init(final String messagePattern, final int argCount, final Object[] paramArray) {
85 this.varargs = null;
86 this.messagePattern = messagePattern;
87 this.argCount = argCount;
88 int placeholderCount = count(messagePattern, indices);
89 initThrowable(paramArray, argCount, placeholderCount);
90 this.usedCount = Math.min(placeholderCount, argCount);
91 }
92
93 private static int count(final String messagePattern, final int[] indices) {
94 try {
95
96 return ParameterFormatter.countArgumentPlaceholders2(messagePattern, indices);
97 } catch (final Exception ex) {
98 return ParameterFormatter.countArgumentPlaceholders(messagePattern);
99 }
100 }
101
102 private void initThrowable(final Object[] params, final int argCount, final int usedParams) {
103 if (usedParams < argCount && this.throwable == null && params[argCount - 1] instanceof Throwable) {
104 this.throwable = (Throwable) params[argCount - 1];
105 }
106 }
107
108 ReusableParameterizedMessage set(String messagePattern, Object... arguments) {
109 init(messagePattern, arguments == null ? 0 : arguments.length, arguments);
110 varargs = arguments;
111 return this;
112 }
113
114 ReusableParameterizedMessage set(String messagePattern, Object p0) {
115 params[0] = p0;
116 init(messagePattern, 1, params);
117 return this;
118 }
119
120 ReusableParameterizedMessage set(String messagePattern, Object p0, Object p1) {
121 params[0] = p0;
122 params[1] = p1;
123 init(messagePattern, 2, params);
124 return this;
125 }
126
127 ReusableParameterizedMessage set(String messagePattern, Object p0, Object p1, Object p2) {
128 params[0] = p0;
129 params[1] = p1;
130 params[2] = p2;
131 init(messagePattern, 3, params);
132 return this;
133 }
134
135 ReusableParameterizedMessage set(String messagePattern, Object p0, Object p1, Object p2, Object p3) {
136 params[0] = p0;
137 params[1] = p1;
138 params[2] = p2;
139 params[3] = p3;
140 init(messagePattern, 4, params);
141 return this;
142 }
143
144 ReusableParameterizedMessage set(String messagePattern, Object p0, Object p1, Object p2, Object p3, Object p4) {
145 params[0] = p0;
146 params[1] = p1;
147 params[2] = p2;
148 params[3] = p3;
149 params[4] = p4;
150 init(messagePattern, 5, params);
151 return this;
152 }
153
154 ReusableParameterizedMessage set(String messagePattern, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {
155 params[0] = p0;
156 params[1] = p1;
157 params[2] = p2;
158 params[3] = p3;
159 params[4] = p4;
160 params[5] = p5;
161 init(messagePattern, 6, params);
162 return this;
163 }
164
165 ReusableParameterizedMessage set(String messagePattern, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5,
166 Object p6) {
167 params[0] = p0;
168 params[1] = p1;
169 params[2] = p2;
170 params[3] = p3;
171 params[4] = p4;
172 params[5] = p5;
173 params[6] = p6;
174 init(messagePattern, 7, params);
175 return this;
176 }
177
178 ReusableParameterizedMessage set(String messagePattern, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5,
179 Object p6, Object p7) {
180 params[0] = p0;
181 params[1] = p1;
182 params[2] = p2;
183 params[3] = p3;
184 params[4] = p4;
185 params[5] = p5;
186 params[6] = p6;
187 params[7] = p7;
188 init(messagePattern, 8, params);
189 return this;
190 }
191
192 ReusableParameterizedMessage set(String messagePattern, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5,
193 Object p6, Object p7, Object p8) {
194 params[0] = p0;
195 params[1] = p1;
196 params[2] = p2;
197 params[3] = p3;
198 params[4] = p4;
199 params[5] = p5;
200 params[6] = p6;
201 params[7] = p7;
202 params[8] = p8;
203 init(messagePattern, 9, params);
204 return this;
205 }
206
207 ReusableParameterizedMessage set(String messagePattern, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5,
208 Object p6, Object p7, Object p8, Object p9) {
209 params[0] = p0;
210 params[1] = p1;
211 params[2] = p2;
212 params[3] = p3;
213 params[4] = p4;
214 params[5] = p5;
215 params[6] = p6;
216 params[7] = p7;
217 params[8] = p8;
218 params[9] = p9;
219 init(messagePattern, 10, params);
220 return this;
221 }
222
223
224
225
226
227 @Override
228 public String getFormat() {
229 return messagePattern;
230 }
231
232
233
234
235
236 @Override
237 public Object[] getParameters() {
238 return getTrimmedParams();
239 }
240
241
242
243
244
245
246
247
248
249
250 @Override
251 public Throwable getThrowable() {
252 return throwable;
253 }
254
255
256
257
258
259 @Override
260 public String getFormattedMessage() {
261 final StringBuilder sb = getBuffer();
262 formatTo(sb);
263 return sb.toString();
264 }
265
266 private StringBuilder getBuffer() {
267 StringBuilder result = buffer.get();
268 if (result == null) {
269 final int currentPatternLength = messagePattern == null ? 0 : messagePattern.length();
270 result = new StringBuilder(Math.min(512, currentPatternLength * 2));
271 buffer.set(result);
272 }
273 result.setLength(0);
274 return result;
275 }
276
277 @Override
278 public void formatTo(final StringBuilder buffer) {
279 if (indices[0] < 0) {
280 ParameterFormatter.formatMessage(buffer, messagePattern, getParams(), argCount);
281 } else {
282 ParameterFormatter.formatMessage2(buffer, messagePattern, getParams(), usedCount, indices);
283 }
284 }
285
286
287 @Override
288 public String toString() {
289 return "ReusableParameterizedMessage[messagePattern=" + getFormat() + ", stringArgs=" +
290 Arrays.toString(getParameters()) + ", throwable=" + getThrowable() + ']';
291 }
292 }