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