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