1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.logging.log4j.message;
19
20 import java.util.Map;
21
22 import org.apache.logging.log4j.util.EnglishEnums;
23
24
25
26
27
28
29
30
31
32
33
34
35 public class StructuredDataMessage extends MapMessage {
36
37 private static final long serialVersionUID = 1703221292892071920L;
38 private static final int MAX_LENGTH = 32;
39 private static final int HASHVAL = 31;
40
41 private StructuredDataId id;
42
43 private String message;
44
45 private String type;
46
47
48
49
50 public enum Format {
51
52 XML,
53
54 FULL
55 }
56
57
58
59
60
61
62
63 public StructuredDataMessage(final String id, final String msg, final String type) {
64 this.id = new StructuredDataId(id, null, null);
65 this.message = msg;
66 this.type = type;
67 }
68
69
70
71
72
73
74
75
76 public StructuredDataMessage(final String id, final String msg, final String type,
77 final Map<String, String> data) {
78 super(data);
79 this.id = new StructuredDataId(id, null, null);
80 this.message = msg;
81 this.type = type;
82 }
83
84
85
86
87
88
89
90 public StructuredDataMessage(final StructuredDataId id, final String msg, final String type) {
91 this.id = id;
92 this.message = msg;
93 this.type = type;
94 }
95
96
97
98
99
100
101
102
103
104 public StructuredDataMessage(final StructuredDataId id, final String msg, final String type,
105 final Map<String, String> data) {
106 super(data);
107 this.id = id;
108 this.message = msg;
109 this.type = type;
110 }
111
112
113
114
115
116
117
118 private StructuredDataMessage(final StructuredDataMessage msg, final Map<String, String> map) {
119 super(map);
120 this.id = msg.id;
121 this.message = msg.message;
122 this.type = msg.type;
123 }
124
125
126
127
128
129 protected StructuredDataMessage() {
130
131 }
132
133
134
135
136
137 @Override
138 public String[] getFormats() {
139 final String[] formats = new String[Format.values().length];
140 int i = 0;
141 for (final Format format : Format.values()) {
142 formats[i++] = format.name();
143 }
144 return formats;
145 }
146
147
148
149
150
151 public StructuredDataId getId() {
152 return id;
153 }
154
155
156
157
158
159 protected void setId(final String id) {
160 this.id = new StructuredDataId(id, null, null);
161 }
162
163
164
165
166
167 protected void setId(final StructuredDataId id) {
168 this.id = id;
169 }
170
171
172
173
174
175 public String getType() {
176 return type;
177 }
178
179 protected void setType(final String type) {
180 if (type.length() > MAX_LENGTH) {
181 throw new IllegalArgumentException("structured data type exceeds maximum length of 32 characters: " + type);
182 }
183 this.type = type;
184 }
185
186
187
188
189
190 @Override
191 public String getFormat() {
192 return message;
193 }
194
195 protected void setMessageFormat(final String msg) {
196 this.message = msg;
197 }
198
199
200 @Override
201 protected void validate(final String key, final String value) {
202 validateKey(key);
203 }
204
205 private void validateKey(final String key) {
206 if (key.length() > MAX_LENGTH) {
207 throw new IllegalArgumentException("Structured data keys are limited to 32 characters. key: " + key);
208 }
209 final char[] chars = key.toCharArray();
210 for (final char c : chars) {
211 if (c < '!' || c > '~' || c == '=' || c == ']' || c == '"') {
212 throw new IllegalArgumentException("Structured data keys must contain printable US ASCII characters" +
213 "and may not contain a space, =, ], or \"");
214 }
215 }
216 }
217
218
219
220
221
222
223 @Override
224 public String asString() {
225 return asString(Format.FULL, null);
226 }
227
228
229
230
231
232
233
234
235 @Override
236 public String asString(final String format) {
237 try {
238 return asString(EnglishEnums.valueOf(Format.class, format), null);
239 } catch (final IllegalArgumentException ex) {
240 return asString();
241 }
242 }
243
244
245
246
247
248
249
250
251
252
253 public final String asString(final Format format, final StructuredDataId structuredDataId) {
254 final StringBuilder sb = new StringBuilder();
255 final boolean full = Format.FULL.equals(format);
256 if (full) {
257 final String myType = getType();
258 if (myType == null) {
259 return sb.toString();
260 }
261 sb.append(getType()).append(' ');
262 }
263 StructuredDataId sdId = getId();
264 if (sdId != null) {
265 sdId = sdId.makeId(structuredDataId);
266 } else {
267 sdId = structuredDataId;
268 }
269 if (sdId == null || sdId.getName() == null) {
270 return sb.toString();
271 }
272 sb.append('[');
273 sb.append(sdId);
274 sb.append(' ');
275 appendMap(sb);
276 sb.append(']');
277 if (full) {
278 final String msg = getFormat();
279 if (msg != null) {
280 sb.append(' ').append(msg);
281 }
282 }
283 return sb.toString();
284 }
285
286
287
288
289
290 @Override
291 public String getFormattedMessage() {
292 return asString(Format.FULL, null);
293 }
294
295
296
297
298
299
300
301
302
303
304 @Override
305 public String getFormattedMessage(final String[] formats) {
306 if (formats != null && formats.length > 0) {
307 for (final String format : formats) {
308 if (Format.XML.name().equalsIgnoreCase(format)) {
309 return asXml();
310 } else if (Format.FULL.name().equalsIgnoreCase(format)) {
311 return asString(Format.FULL, null);
312 }
313 }
314 return asString(null, null);
315 }
316 return asString(Format.FULL, null);
317 }
318
319 private String asXml() {
320 final StringBuilder sb = new StringBuilder();
321 final StructuredDataId sdId = getId();
322 if (sdId == null || sdId.getName() == null || type == null) {
323 return sb.toString();
324 }
325 sb.append("<StructuredData>\n");
326 sb.append("<type>").append(type).append("</type>\n");
327 sb.append("<id>").append(sdId).append("</id>\n");
328 super.asXml(sb);
329 sb.append("</StructuredData>\n");
330 return sb.toString();
331 }
332
333 @Override
334 public String toString() {
335 return asString(null, null);
336 }
337
338
339 @Override
340 public MapMessage newInstance(final Map<String, String> map) {
341 return new StructuredDataMessage(this, map);
342 }
343
344 @Override
345 public boolean equals(final Object o) {
346 if (this == o) {
347 return true;
348 }
349 if (o == null || getClass() != o.getClass()) {
350 return false;
351 }
352
353 final StructuredDataMessage that = (StructuredDataMessage) o;
354
355 if (!super.equals(o)) {
356 return false;
357 }
358 if (type != null ? !type.equals(that.type) : that.type != null) {
359 return false;
360 }
361 if (id != null ? !id.equals(that.id) : that.id != null) {
362 return false;
363 }
364 if (message != null ? !message.equals(that.message) : that.message != null) {
365 return false;
366 }
367
368 return true;
369 }
370
371 @Override
372 public int hashCode() {
373 int result = super.hashCode();
374 result = HASHVAL * result + (type != null ? type.hashCode() : 0);
375 result = HASHVAL * result + (id != null ? id.hashCode() : 0);
376 result = HASHVAL * result + (message != null ? message.hashCode() : 0);
377 return result;
378 }
379 }