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