1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 package io.netty5.util.internal.logging;
41
42 import java.text.MessageFormat;
43 import java.util.HashSet;
44 import java.util.Set;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 public final class MessageFormatter {
112 private static final String DELIM_STR = "{}";
113 private static final char ESCAPE_CHAR = '\\';
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 static FormattingTuple format(String messagePattern, Object arg) {
133 return arrayFormat(messagePattern, new Object[]{arg});
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 static FormattingTuple format(final String messagePattern,
156 Object argA, Object argB) {
157 return arrayFormat(messagePattern, new Object[]{argA, argB});
158 }
159
160
161
162
163
164
165
166
167
168
169
170 static FormattingTuple arrayFormat(final String messagePattern,
171 final Object[] argArray) {
172 if (argArray == null || argArray.length == 0) {
173 return new FormattingTuple(messagePattern, null);
174 }
175
176 int lastArrIdx = argArray.length - 1;
177 Object lastEntry = argArray[lastArrIdx];
178 Throwable throwable = lastEntry instanceof Throwable? (Throwable) lastEntry : null;
179
180 if (messagePattern == null) {
181 return new FormattingTuple(null, throwable);
182 }
183
184 int j = messagePattern.indexOf(DELIM_STR);
185 if (j == -1) {
186
187 return new FormattingTuple(messagePattern, throwable);
188 }
189
190 StringBuilder sbuf = new StringBuilder(messagePattern.length() + 50);
191 int i = 0;
192 int L = 0;
193 do {
194 boolean notEscaped = j == 0 || messagePattern.charAt(j - 1) != ESCAPE_CHAR;
195 if (notEscaped) {
196
197 sbuf.append(messagePattern, i, j);
198 } else {
199 sbuf.append(messagePattern, i, j - 1);
200
201 notEscaped = j >= 2 && messagePattern.charAt(j - 2) == ESCAPE_CHAR;
202 }
203
204 i = j + 2;
205 if (notEscaped) {
206 deeplyAppendParameter(sbuf, argArray[L], null);
207 L++;
208 if (L > lastArrIdx) {
209 break;
210 }
211 } else {
212 sbuf.append(DELIM_STR);
213 }
214 j = messagePattern.indexOf(DELIM_STR, i);
215 } while (j != -1);
216
217
218 sbuf.append(messagePattern, i, messagePattern.length());
219 return new FormattingTuple(sbuf.toString(), L <= lastArrIdx? throwable : null);
220 }
221
222
223 private static void deeplyAppendParameter(StringBuilder sbuf, Object o,
224 Set<Object[]> seenSet) {
225 if (o == null) {
226 sbuf.append("null");
227 return;
228 }
229 Class<?> objClass = o.getClass();
230 if (!objClass.isArray()) {
231 if (Number.class.isAssignableFrom(objClass)) {
232
233 if (objClass == Long.class) {
234 sbuf.append(((Long) o).longValue());
235 } else if (objClass == Integer.class || objClass == Short.class || objClass == Byte.class) {
236 sbuf.append(((Number) o).intValue());
237 } else if (objClass == Double.class) {
238 sbuf.append(((Double) o).doubleValue());
239 } else if (objClass == Float.class) {
240 sbuf.append(((Float) o).floatValue());
241 } else {
242 safeObjectAppend(sbuf, o);
243 }
244 } else {
245 safeObjectAppend(sbuf, o);
246 }
247 } else {
248
249
250 sbuf.append('[');
251 if (objClass == boolean[].class) {
252 booleanArrayAppend(sbuf, (boolean[]) o);
253 } else if (objClass == byte[].class) {
254 byteArrayAppend(sbuf, (byte[]) o);
255 } else if (objClass == char[].class) {
256 charArrayAppend(sbuf, (char[]) o);
257 } else if (objClass == short[].class) {
258 shortArrayAppend(sbuf, (short[]) o);
259 } else if (objClass == int[].class) {
260 intArrayAppend(sbuf, (int[]) o);
261 } else if (objClass == long[].class) {
262 longArrayAppend(sbuf, (long[]) o);
263 } else if (objClass == float[].class) {
264 floatArrayAppend(sbuf, (float[]) o);
265 } else if (objClass == double[].class) {
266 doubleArrayAppend(sbuf, (double[]) o);
267 } else {
268 objectArrayAppend(sbuf, (Object[]) o, seenSet);
269 }
270 sbuf.append(']');
271 }
272 }
273
274 private static void safeObjectAppend(StringBuilder sbuf, Object o) {
275 try {
276 String oAsString = o.toString();
277 sbuf.append(oAsString);
278 } catch (Throwable t) {
279 System.err
280 .println("SLF4J: Failed toString() invocation on an object of type ["
281 + o.getClass().getName() + ']');
282 t.printStackTrace();
283 sbuf.append("[FAILED toString()]");
284 }
285 }
286
287 private static void objectArrayAppend(StringBuilder sbuf, Object[] a, Set<Object[]> seenSet) {
288 if (a.length == 0) {
289 return;
290 }
291 if (seenSet == null) {
292 seenSet = new HashSet<>(a.length);
293 }
294 if (seenSet.add(a)) {
295 deeplyAppendParameter(sbuf, a[0], seenSet);
296 for (int i = 1; i < a.length; i++) {
297 sbuf.append(", ");
298 deeplyAppendParameter(sbuf, a[i], seenSet);
299 }
300
301 seenSet.remove(a);
302 } else {
303 sbuf.append("...");
304 }
305 }
306
307 private static void booleanArrayAppend(StringBuilder sbuf, boolean[] a) {
308 if (a.length == 0) {
309 return;
310 }
311 sbuf.append(a[0]);
312 for (int i = 1; i < a.length; i++) {
313 sbuf.append(", ");
314 sbuf.append(a[i]);
315 }
316 }
317
318 private static void byteArrayAppend(StringBuilder sbuf, byte[] a) {
319 if (a.length == 0) {
320 return;
321 }
322 sbuf.append(a[0]);
323 for (int i = 1; i < a.length; i++) {
324 sbuf.append(", ");
325 sbuf.append(a[i]);
326 }
327 }
328
329 private static void charArrayAppend(StringBuilder sbuf, char[] a) {
330 if (a.length == 0) {
331 return;
332 }
333 sbuf.append(a[0]);
334 for (int i = 1; i < a.length; i++) {
335 sbuf.append(", ");
336 sbuf.append(a[i]);
337 }
338 }
339
340 private static void shortArrayAppend(StringBuilder sbuf, short[] a) {
341 if (a.length == 0) {
342 return;
343 }
344 sbuf.append(a[0]);
345 for (int i = 1; i < a.length; i++) {
346 sbuf.append(", ");
347 sbuf.append(a[i]);
348 }
349 }
350
351 private static void intArrayAppend(StringBuilder sbuf, int[] a) {
352 if (a.length == 0) {
353 return;
354 }
355 sbuf.append(a[0]);
356 for (int i = 1; i < a.length; i++) {
357 sbuf.append(", ");
358 sbuf.append(a[i]);
359 }
360 }
361
362 private static void longArrayAppend(StringBuilder sbuf, long[] a) {
363 if (a.length == 0) {
364 return;
365 }
366 sbuf.append(a[0]);
367 for (int i = 1; i < a.length; i++) {
368 sbuf.append(", ");
369 sbuf.append(a[i]);
370 }
371 }
372
373 private static void floatArrayAppend(StringBuilder sbuf, float[] a) {
374 if (a.length == 0) {
375 return;
376 }
377 sbuf.append(a[0]);
378 for (int i = 1; i < a.length; i++) {
379 sbuf.append(", ");
380 sbuf.append(a[i]);
381 }
382 }
383
384 private static void doubleArrayAppend(StringBuilder sbuf, double[] a) {
385 if (a.length == 0) {
386 return;
387 }
388 sbuf.append(a[0]);
389 for (int i = 1; i < a.length; i++) {
390 sbuf.append(", ");
391 sbuf.append(a[i]);
392 }
393 }
394
395 private MessageFormatter() {
396 }
397 }