001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.joran.event.stax; 015 016import java.io.InputStream; 017import java.util.ArrayList; 018import java.util.List; 019 020import javax.xml.stream.XMLEventReader; 021import javax.xml.stream.XMLInputFactory; 022import javax.xml.stream.XMLStreamException; 023import javax.xml.stream.events.Characters; 024import javax.xml.stream.events.EndElement; 025import javax.xml.stream.events.StartElement; 026import javax.xml.stream.events.XMLEvent; 027 028import ch.qos.logback.core.Context; 029import ch.qos.logback.core.joran.spi.ElementPath; 030import ch.qos.logback.core.joran.spi.JoranException; 031import ch.qos.logback.core.spi.ContextAwareBase; 032 033public class StaxEventRecorder extends ContextAwareBase { 034 035 List<StaxEvent> eventList = new ArrayList<StaxEvent>(); 036 ElementPath globalElementPath = new ElementPath(); 037 038 public StaxEventRecorder(Context context) { 039 setContext(context); 040 } 041 042 public void recordEvents(InputStream inputStream) throws JoranException { 043 try { 044 XMLEventReader xmlEventReader = XMLInputFactory.newInstance().createXMLEventReader(inputStream); 045 read(xmlEventReader); 046 } catch (XMLStreamException e) { 047 throw new JoranException("Problem parsing XML document. See previously reported errors.", e); 048 } 049 } 050 051 public List<StaxEvent> getEventList() { 052 return eventList; 053 } 054 055 private void read(XMLEventReader xmlEventReader) throws XMLStreamException { 056 while (xmlEventReader.hasNext()) { 057 XMLEvent xmlEvent = xmlEventReader.nextEvent(); 058 switch (xmlEvent.getEventType()) { 059 case XMLEvent.START_ELEMENT: 060 addStartElement(xmlEvent); 061 break; 062 case XMLEvent.CHARACTERS: 063 addCharacters(xmlEvent); 064 break; 065 case XMLEvent.END_ELEMENT: 066 addEndEvent(xmlEvent); 067 break; 068 default: 069 break; 070 } 071 } 072 } 073 074 private void addStartElement(XMLEvent xmlEvent) { 075 StartElement se = xmlEvent.asStartElement(); 076 String tagName = se.getName().getLocalPart(); 077 this.globalElementPath.push(tagName); 078 ElementPath current = globalElementPath.duplicate(); 079 StartEvent startEvent = new StartEvent(current, tagName, se.getAttributes(), se.getLocation()); 080 eventList.add(startEvent); 081 } 082 083 private void addCharacters(XMLEvent xmlEvent) { 084 Characters characters = xmlEvent.asCharacters(); 085 StaxEvent lastEvent = getLastEvent(); 086 087 if (lastEvent instanceof BodyEvent) { 088 BodyEvent be = (BodyEvent) lastEvent; 089 be.append(characters.getData()); 090 } else { 091 // ignore space only text if the previous event is not a BodyEvent 092 if (!characters.isWhiteSpace()) { 093 BodyEvent bodyEvent = new BodyEvent(characters.getData(), xmlEvent.getLocation()); 094 eventList.add(bodyEvent); 095 } 096 } 097 } 098 099 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}