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