1 package org.robolectric.res; 2 3 import java.util.ArrayDeque; 4 import java.util.Deque; 5 import javax.xml.stream.XMLInputFactory; 6 import javax.xml.stream.XMLStreamConstants; 7 import javax.xml.stream.XMLStreamException; 8 import javax.xml.stream.XMLStreamReader; 9 10 public class StaxDocumentLoader extends DocumentLoader { 11 private static final NodeHandler NO_OP_HANDLER = new NodeHandler(); 12 13 private final NodeHandler topLevelNodeHandler; 14 private final XMLInputFactory factory; 15 StaxDocumentLoader(String packageName, FsFile resourceBase, NodeHandler topLevelNodeHandler)16 public StaxDocumentLoader(String packageName, FsFile resourceBase, NodeHandler topLevelNodeHandler) { 17 super(packageName, resourceBase); 18 19 this.topLevelNodeHandler = topLevelNodeHandler; 20 factory = XMLInputFactory.newFactory(); 21 } 22 23 @Override loadResourceXmlFile(XmlContext xmlContext)24 protected void loadResourceXmlFile(XmlContext xmlContext) { 25 FsFile xmlFile = xmlContext.getXmlFile(); 26 27 XMLStreamReader xmlStreamReader; 28 try { 29 xmlStreamReader = factory.createXMLStreamReader(xmlFile.getInputStream()); 30 doParse(xmlStreamReader, xmlContext); 31 } catch (Exception e) { 32 throw new RuntimeException("error parsing " + xmlFile, e); 33 } 34 if (xmlStreamReader != null) { 35 try { 36 xmlStreamReader.close(); 37 } catch (XMLStreamException e) { 38 throw new RuntimeException(e); 39 } 40 } 41 } 42 doParse(XMLStreamReader reader, XmlContext xmlContext)43 protected void doParse(XMLStreamReader reader, XmlContext xmlContext) throws XMLStreamException { 44 NodeHandler nodeHandler = this.topLevelNodeHandler; 45 Deque<NodeHandler> nodeHandlerStack = new ArrayDeque<>(); 46 47 while (reader.hasNext()) { 48 int event = reader.next(); 49 switch (event) { 50 case XMLStreamConstants.START_DOCUMENT: 51 break; 52 53 case XMLStreamConstants.START_ELEMENT: 54 nodeHandlerStack.push(nodeHandler); 55 NodeHandler elementHandler = nodeHandler.findMatchFor(reader); 56 nodeHandler = elementHandler == null ? NO_OP_HANDLER : elementHandler; 57 nodeHandler.onStart(reader, xmlContext); 58 break; 59 60 case XMLStreamConstants.CDATA: 61 case XMLStreamConstants.CHARACTERS: 62 nodeHandler.onCharacters(reader, xmlContext); 63 break; 64 65 case XMLStreamConstants.END_ELEMENT: 66 nodeHandler.onEnd(reader, xmlContext); 67 nodeHandler = nodeHandlerStack.pop(); 68 break; 69 70 case XMLStreamConstants.ATTRIBUTE: 71 } 72 } 73 } 74 } 75