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 java.io.InputStream;
17  import java.util.ArrayList;
18  import java.util.List;
19  
20  import javax.xml.stream.XMLEventReader;
21  import javax.xml.stream.XMLInputFactory;
22  import javax.xml.stream.XMLStreamException;
23  import javax.xml.stream.events.Characters;
24  import javax.xml.stream.events.EndElement;
25  import javax.xml.stream.events.StartElement;
26  import javax.xml.stream.events.XMLEvent;
27  
28  import ch.qos.logback.core.Context;
29  import ch.qos.logback.core.joran.spi.ElementPath;
30  import ch.qos.logback.core.joran.spi.JoranException;
31  import ch.qos.logback.core.spi.ContextAwareBase;
32  
33  public class StaxEventRecorder extends ContextAwareBase {
34  
35      List<StaxEvent> eventList = new ArrayList<StaxEvent>();
36      ElementPath globalElementPath = new ElementPath();
37  
38      public StaxEventRecorder(Context context) {
39          setContext(context);
40      }
41  
42      public void recordEvents(InputStream inputStream) throws JoranException {
43          try {
44              XMLEventReader xmlEventReader = XMLInputFactory.newInstance().createXMLEventReader(inputStream);
45              read(xmlEventReader);
46          } catch (XMLStreamException e) {
47              throw new JoranException("Problem parsing XML document. See previously reported errors.", e);
48          }
49      }
50  
51      public List<StaxEvent> getEventList() {
52          return eventList;
53      }
54  
55      private void read(XMLEventReader xmlEventReader) throws XMLStreamException {
56          while (xmlEventReader.hasNext()) {
57              XMLEvent xmlEvent = xmlEventReader.nextEvent();
58              switch (xmlEvent.getEventType()) {
59              case XMLEvent.START_ELEMENT:
60                  addStartElement(xmlEvent);
61                  break;
62              case XMLEvent.CHARACTERS:
63                  addCharacters(xmlEvent);
64                  break;
65              case XMLEvent.END_ELEMENT:
66                  addEndEvent(xmlEvent);
67                  break;
68              default:
69                  break;
70              }
71          }
72      }
73  
74      private void addStartElement(XMLEvent xmlEvent) {
75          StartElement se = xmlEvent.asStartElement();
76          String tagName = se.getName().getLocalPart();
77          this.globalElementPath.push(tagName);
78          ElementPath current = globalElementPath.duplicate();
79          StartEvent startEvent = new StartEvent(current, tagName, se.getAttributes(), se.getLocation());
80          eventList.add(startEvent);
81      }
82  
83      private void addCharacters(XMLEvent xmlEvent) {
84          Characters characters = xmlEvent.asCharacters();
85          StaxEvent lastEvent = getLastEvent();
86  
87          if (lastEvent instanceof BodyEvent) {
88              BodyEvent be = (BodyEvent) lastEvent;
89              be.append(characters.getData());
90          } else {
91              // ignore space only text if the previous event is not a BodyEvent
92              if (!characters.isWhiteSpace()) {
93                  BodyEvent bodyEvent = new BodyEvent(characters.getData(), xmlEvent.getLocation());
94                  eventList.add(bodyEvent);
95              }
96          }
97      }
98  
99      private void addEndEvent(XMLEvent xmlEvent) {
100         EndElement ee = xmlEvent.asEndElement();
101         String tagName = ee.getName().getLocalPart();
102         EndEvent endEvent = new EndEvent(tagName, ee.getLocation());
103         eventList.add(endEvent);
104         this.globalElementPath.pop();
105     }
106 
107     StaxEvent getLastEvent() {
108         if (eventList.isEmpty()) {
109             return null;
110         }
111         int size = eventList.size();
112         if (size == 0)
113             return null;
114         return eventList.get(size - 1);
115     }
116 
117 }