View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.joran.event.stax;
15  
16  import ch.qos.logback.core.Context;
17  import ch.qos.logback.core.joran.spi.ElementPath;
18  import ch.qos.logback.core.joran.spi.JoranException;
19  import ch.qos.logback.core.spi.ContextAwareBase;
20  
21  import javax.xml.stream.XMLEventReader;
22  import javax.xml.stream.XMLInputFactory;
23  import javax.xml.stream.XMLStreamException;
24  import javax.xml.stream.events.Characters;
25  import javax.xml.stream.events.EndElement;
26  import javax.xml.stream.events.StartElement;
27  import javax.xml.stream.events.XMLEvent;
28  import java.io.InputStream;
29  import java.util.ArrayList;
30  import java.util.List;
31  
32  public class StaxEventRecorder extends ContextAwareBase {
33  
34      List<StaxEvent> eventList = new ArrayList<StaxEvent>();
35      ElementPath globalElementPath = new ElementPath();
36  
37      public StaxEventRecorder(Context context) {
38          setContext(context);
39      }
40  
41      public void recordEvents(InputStream inputStream) throws JoranException {
42          try {
43              XMLEventReader xmlEventReader = XMLInputFactory.newInstance().createXMLEventReader(inputStream);
44              read(xmlEventReader);
45          } catch (XMLStreamException e) {
46              throw new JoranException("Problem parsing XML document. See previously reported errors.", e);
47          }
48      }
49  
50      public List<StaxEvent> getEventList() {
51          return eventList;
52      }
53  
54      private void read(XMLEventReader xmlEventReader) throws XMLStreamException {
55          while (xmlEventReader.hasNext()) {
56              XMLEvent xmlEvent = xmlEventReader.nextEvent();
57              switch (xmlEvent.getEventType()) {
58              case XMLEvent.START_ELEMENT:
59                  addStartElement(xmlEvent);
60                  break;
61              case XMLEvent.CHARACTERS:
62                  addCharacters(xmlEvent);
63                  break;
64              case XMLEvent.END_ELEMENT:
65                  addEndEvent(xmlEvent);
66                  break;
67              default:
68                  break;
69              }
70          }
71      }
72  
73      private void addStartElement(XMLEvent xmlEvent) {
74          StartElement se = xmlEvent.asStartElement();
75          String tagName = se.getName().getLocalPart();
76          globalElementPath.push(tagName);
77          ElementPath current = globalElementPath.duplicate();
78          StartEvent startEvent = new StartEvent(current, tagName, se.getAttributes(), se.getLocation());
79          eventList.add(startEvent);
80      }
81  
82      private void addCharacters(XMLEvent xmlEvent) {
83          Characters characters = xmlEvent.asCharacters();
84          StaxEvent lastEvent = getLastEvent();
85  
86          if (lastEvent instanceof BodyEvent) {
87              BodyEvent be = (BodyEvent) lastEvent;
88              be.append(characters.getData());
89          } else {
90              // ignore space only text if the previous event is not a BodyEvent
91              if (!characters.isWhiteSpace()) {
92                  BodyEvent bodyEvent = new BodyEvent(characters.getData(), xmlEvent.getLocation());
93                  eventList.add(bodyEvent);
94              }
95          }
96      }
97  
98      private void addEndEvent(XMLEvent xmlEvent) {
99          EndElement ee = xmlEvent.asEndElement();
100         String tagName = ee.getName().getLocalPart();
101         EndEvent endEvent = new EndEvent(tagName, ee.getLocation());
102         eventList.add(endEvent);
103         globalElementPath.pop();
104     }
105 
106     StaxEvent getLastEvent() {
107         if (eventList.isEmpty()) {
108             return null;
109         }
110         int size = eventList.size();
111         if (size == 0)
112             return null;
113         return eventList.get(size - 1);
114     }
115 
116 }