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