1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.xml;
19
20 import org.apache.log4j.Level;
21 import org.apache.log4j.Logger;
22 import org.apache.log4j.spi.Decoder;
23 import org.apache.log4j.spi.LocationInfo;
24 import org.apache.log4j.spi.LoggingEvent;
25 import org.apache.log4j.spi.ThrowableInformation;
26 import org.w3c.dom.Document;
27 import org.w3c.dom.Node;
28 import org.w3c.dom.NodeList;
29 import org.xml.sax.InputSource;
30
31 import javax.swing.*;
32 import javax.xml.parsers.DocumentBuilder;
33 import javax.xml.parsers.DocumentBuilderFactory;
34 import javax.xml.parsers.ParserConfigurationException;
35 import java.awt.*;
36 import java.io.*;
37 import java.net.URL;
38 import java.util.HashMap;
39 import java.util.Hashtable;
40 import java.util.Map;
41 import java.util.Vector;
42 import java.util.zip.ZipInputStream;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class XMLDecoder implements Decoder {
63
64 private static final String ENCODING = "UTF-8";
65
66
67
68
69 private static final String BEGINPART =
70 "<?xml version=\"1.0\" encoding=\"" + ENCODING + "\" ?>"
71 + "<!DOCTYPE log4j:eventSet SYSTEM \"http://localhost/log4j.dtd\">"
72 + "<log4j:eventSet version=\"1.2\" "
73 + "xmlns:log4j=\"http://jakarta.apache.org/log4j/\">";
74
75
76
77 private static final String ENDPART = "</log4j:eventSet>";
78
79
80
81 private static final String RECORD_END = "</log4j:event>";
82
83
84
85
86 private DocumentBuilder docBuilder;
87
88
89
90 private Map additionalProperties = new HashMap();
91
92
93
94 private String partialEvent;
95
96
97
98 private Component owner = null;
99
100
101
102
103
104
105 public XMLDecoder(final Component o) {
106 this();
107 this.owner = o;
108 }
109
110
111
112
113 public XMLDecoder() {
114 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
115 dbf.setValidating(false);
116
117 try {
118 docBuilder = dbf.newDocumentBuilder();
119 docBuilder.setErrorHandler(new SAXErrorHandler());
120 docBuilder.setEntityResolver(new Log4jEntityResolver());
121 } catch (ParserConfigurationException pce) {
122 System.err.println("Unable to get document builder");
123 }
124 }
125
126
127
128
129
130
131
132
133
134 public void setAdditionalProperties(final Map properties) {
135 this.additionalProperties = properties;
136 }
137
138
139
140
141
142
143
144
145 private Document parse(final String data) {
146 if (docBuilder == null || data == null) {
147 return null;
148 }
149 Document document = null;
150
151 try {
152
153
154
155
156
157
158
159
160
161 String buf = BEGINPART + data + ENDPART;
162 InputSource inputSource = new InputSource(new StringReader(buf));
163 document = docBuilder.parse(inputSource);
164 } catch (Exception e) {
165 e.printStackTrace();
166 }
167
168 return document;
169 }
170
171
172
173
174
175
176
177
178 public Vector<LoggingEvent> decode(final URL url) throws IOException {
179 LineNumberReader reader;
180 boolean isZipFile = url.getPath().toLowerCase().endsWith(".zip");
181 InputStream inputStream;
182 if (isZipFile) {
183 inputStream = new ZipInputStream(url.openStream());
184
185 ((ZipInputStream) inputStream).getNextEntry();
186 } else {
187 inputStream = url.openStream();
188 }
189 if (owner != null) {
190 reader = new LineNumberReader(
191 new InputStreamReader(
192 new ProgressMonitorInputStream(owner,
193 "Loading " + url, inputStream), ENCODING));
194 } else {
195 reader = new LineNumberReader(new InputStreamReader(inputStream, ENCODING));
196 }
197
198 Vector<LoggingEvent> v = new Vector<>();
199
200 String line;
201 Vector<LoggingEvent> events;
202 try {
203 while ((line = reader.readLine()) != null) {
204 StringBuilder buffer = new StringBuilder(line);
205 for (int i = 0; i < 1000; i++) {
206 buffer.append(reader.readLine()).append("\n");
207 }
208 events = decodeEvents(buffer.toString());
209 if (events != null) {
210 v.addAll(events);
211 }
212 }
213 } finally {
214 partialEvent = null;
215 try {
216 if (reader != null) {
217 reader.close();
218 }
219 } catch (Exception e) {
220 e.printStackTrace();
221 }
222 }
223 return v;
224 }
225
226
227
228
229
230
231
232
233 public Vector<LoggingEvent> decodeEvents(final String document) {
234 if (document != null) {
235 if (document.trim().equals("")) {
236 return null;
237 }
238 String newDoc;
239 String newPartialEvent = null;
240
241
242
243
244
245
246
247 if (document.lastIndexOf(RECORD_END) == -1) {
248 partialEvent = partialEvent + document;
249 return null;
250 }
251
252 if (document.lastIndexOf(RECORD_END)
253 + RECORD_END.length() < document.length()) {
254 newDoc = document.substring(0,
255 document.lastIndexOf(RECORD_END) + RECORD_END.length());
256 newPartialEvent = document.substring(
257 document.lastIndexOf(RECORD_END) + RECORD_END.length());
258 } else {
259 newDoc = document;
260 }
261 if (partialEvent != null) {
262 newDoc = partialEvent + newDoc;
263 }
264 partialEvent = newPartialEvent;
265 Document doc = parse(newDoc);
266 if (doc == null) {
267 return null;
268 }
269 return decodeEvents(doc);
270 }
271 return null;
272 }
273
274
275
276
277
278
279
280
281
282 public LoggingEvent decode(final String data) {
283 Document document = parse(data);
284
285 if (document == null) {
286 return null;
287 }
288
289 Vector<LoggingEvent> events = decodeEvents(document);
290
291 if (events.size() > 0) {
292 return events.firstElement();
293 }
294
295 return null;
296 }
297
298
299
300
301
302
303
304 private Vector<LoggingEvent> decodeEvents(final Document document) {
305 Vector<LoggingEvent> events = new Vector<>();
306
307 Logger logger;
308 long timeStamp;
309 Level level;
310 String threadName;
311 Object message = null;
312 String ndc = null;
313 String[] exception = null;
314 String className = null;
315 String methodName = null;
316 String fileName = null;
317 String lineNumber = null;
318 Hashtable properties = null;
319
320 NodeList nl = document.getElementsByTagName("log4j:eventSet");
321 Node eventSet = nl.item(0);
322
323 NodeList eventList = eventSet.getChildNodes();
324
325 for (int eventIndex = 0; eventIndex < eventList.getLength();
326 eventIndex++) {
327 Node eventNode = eventList.item(eventIndex);
328
329 if (eventNode.getNodeType() != Node.ELEMENT_NODE) {
330 continue;
331 }
332 logger = Logger.getLogger(eventNode.getAttributes().getNamedItem("logger").getNodeValue());
333 timeStamp = Long.parseLong(eventNode.getAttributes().getNamedItem("timestamp").getNodeValue());
334 level = Level.toLevel(eventNode.getAttributes().getNamedItem("level").getNodeValue());
335 threadName = eventNode.getAttributes().getNamedItem("thread").getNodeValue();
336
337 NodeList list = eventNode.getChildNodes();
338 int listLength = list.getLength();
339
340 if (listLength == 0) {
341 continue;
342 }
343
344 for (int y = 0; y < listLength; y++) {
345 String tagName = list.item(y).getNodeName();
346
347 if (tagName.equalsIgnoreCase("log4j:message")) {
348 message = getCData(list.item(y));
349 }
350
351 if (tagName.equalsIgnoreCase("log4j:NDC")) {
352 ndc = getCData(list.item(y));
353 }
354
355 if (tagName.equalsIgnoreCase("log4j:MDC")) {
356 properties = new Hashtable();
357 NodeList propertyList = list.item(y).getChildNodes();
358 int propertyLength = propertyList.getLength();
359
360 for (int i = 0; i < propertyLength; i++) {
361 String propertyTag = propertyList.item(i).getNodeName();
362
363 if (propertyTag.equalsIgnoreCase("log4j:data")) {
364 Node property = propertyList.item(i);
365 String name =
366 property.getAttributes().getNamedItem("name").getNodeValue();
367 String value =
368 property.getAttributes().getNamedItem("value").getNodeValue();
369 properties.put(name, value);
370 }
371 }
372 }
373
374 if (tagName.equalsIgnoreCase("log4j:throwable")) {
375 String exceptionString = getCData(list.item(y));
376 if (exceptionString != null && !exceptionString.trim().equals("")) {
377 exception = new String[]{exceptionString.trim()
378 };
379 }
380 }
381
382 if (tagName.equalsIgnoreCase("log4j:locationinfo")) {
383 className =
384 list.item(y).getAttributes().getNamedItem("class").getNodeValue();
385 methodName =
386 list.item(y).getAttributes().getNamedItem("method").getNodeValue();
387 fileName =
388 list.item(y).getAttributes().getNamedItem("file").getNodeValue();
389 lineNumber =
390 list.item(y).getAttributes().getNamedItem("line").getNodeValue();
391 }
392
393 if (tagName.equalsIgnoreCase("log4j:properties")) {
394 if (properties == null) {
395 properties = new Hashtable();
396 }
397 NodeList propertyList = list.item(y).getChildNodes();
398 int propertyLength = propertyList.getLength();
399
400 for (int i = 0; i < propertyLength; i++) {
401 String propertyTag = propertyList.item(i).getNodeName();
402
403 if (propertyTag.equalsIgnoreCase("log4j:data")) {
404 Node property = propertyList.item(i);
405 String name =
406 property.getAttributes().getNamedItem("name").getNodeValue();
407 String value =
408 property.getAttributes().getNamedItem("value").getNodeValue();
409 properties.put(name, value);
410 }
411 }
412 }
413
414
415
416
417
418 if (additionalProperties.size() > 0) {
419 if (properties == null) {
420 properties = new Hashtable(additionalProperties);
421 }
422 for (Object o : additionalProperties.entrySet()) {
423 Map.Entry e = (Map.Entry) o;
424 properties.put(e.getKey(), e.getValue());
425 }
426 }
427 }
428
429 LocationInfo info;
430 if ((fileName != null)
431 || (className != null)
432 || (methodName != null)
433 || (lineNumber != null)) {
434 info = new LocationInfo(fileName, className, methodName, lineNumber);
435 } else {
436 info = LocationInfo.NA_LOCATION_INFO;
437 }
438 ThrowableInformation throwableInfo = null;
439 if (exception != null) {
440 throwableInfo = new ThrowableInformation(exception);
441 }
442
443 LoggingEvent loggingEvent = new LoggingEvent(null,
444 logger, timeStamp, level, message,
445 threadName,
446 throwableInfo,
447 ndc,
448 info,
449 properties);
450
451
452 events.add(loggingEvent);
453
454 message = null;
455 ndc = null;
456 exception = null;
457 className = null;
458 methodName = null;
459 fileName = null;
460 lineNumber = null;
461 properties = null;
462 }
463
464 return events;
465 }
466
467
468
469
470
471
472
473 private String getCData(final Node n) {
474 StringBuilder buf = new StringBuilder();
475 NodeList nl = n.getChildNodes();
476
477 for (int x = 0; x < nl.getLength(); x++) {
478 Node innerNode = nl.item(x);
479
480 if (
481 (innerNode.getNodeType() == Node.TEXT_NODE)
482 || (innerNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
483 buf.append(innerNode.getNodeValue());
484 }
485 }
486
487 return buf.toString();
488 }
489 }