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