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