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