SOAPParser.java revision 71a988c8e9859244b83cd55bb6b6ee913fcaf95c
1package com.android.server.wifi.hotspot2.omadm;
2
3import org.xml.sax.Attributes;
4import org.xml.sax.SAXException;
5import org.xml.sax.helpers.DefaultHandler;
6
7import javax.xml.parsers.ParserConfigurationException;
8import javax.xml.parsers.SAXParser;
9import javax.xml.parsers.SAXParserFactory;
10
11import java.io.*;
12import java.util.*;
13
14import static com.android.server.wifi.hotspot2.omadm.RequestDetail.RequestFields.*;
15
16public class SOAPParser extends DefaultHandler {
17    private XMLNode mRoot;
18    private XMLNode mCurrent;
19
20    private static String[] TagOnly = new String[0];
21    private static final Map<RequestDetail.RequestFields, String> sSoapMappings =
22            new EnumMap<RequestDetail.RequestFields, String>(RequestDetail.RequestFields.class);
23    private static final Map<String, RequestDetail.RequestFields> sRevMappings =
24            new HashMap<String, RequestDetail.RequestFields>();
25    private static final Map<String, String[]> sSoapAttributes =
26            new HashMap<String, String[]>();
27
28    static {
29        sSoapMappings.put(SPPVersion, "spp:sppVersion");
30        sSoapMappings.put(RedirectURI, "redirectURI");
31        sSoapMappings.put(RequestReason, "requestReason");
32        sSoapMappings.put(SessionID, "spp:sessionID");
33        sSoapMappings.put(SupportedVersions, "spp:supportedSPPVersions");
34        sSoapMappings.put(SupportedMOs, "spp:supportedMOList");
35
36        for (Map.Entry<RequestDetail.RequestFields, String> entry : sSoapMappings.entrySet()) {
37            sRevMappings.put(entry.getValue(), entry.getKey());
38        }
39
40        // Really: The first element inside the body
41        sSoapAttributes.put("spp:sppPostDevDataResponse", new String[]{
42                sSoapMappings.get(SPPVersion),
43                sSoapMappings.get(RedirectURI),
44                sSoapMappings.get(RequestReason),
45                sSoapMappings.get(SessionID)});
46
47        sSoapAttributes.put(sSoapMappings.get(SupportedVersions), TagOnly);
48        sSoapAttributes.put(sSoapMappings.get(SupportedMOs), TagOnly);
49    }
50
51    public XMLNode parse(File file) throws IOException, ParserConfigurationException, SAXException {
52        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
53
54        BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
55        try {
56            parser.parse(in, this);
57        } finally {
58            in.close();
59        }
60        return mRoot;
61    }
62
63    @Override
64    public void startElement(String uri, String localName, String qName, Attributes attributes)
65            throws SAXException {
66        XMLNode parent = mCurrent;
67
68        mCurrent = new XMLNode(mCurrent, qName, attributes);
69        System.out.println("Added " + mCurrent.getTag() + ", atts " + mCurrent.getAttributes());
70
71        if (mRoot == null)
72            mRoot = mCurrent;
73        else
74            parent.addChild(mCurrent);
75    }
76
77    @Override
78    public void endElement(String uri, String localName, String qName) throws SAXException {
79        if (!qName.equals(mCurrent.getTag()))
80            throw new SAXException("End tag '" + qName + "' doesn't match current node: " +
81                    mCurrent);
82
83        try {
84            mCurrent.close();
85        } catch (IOException ioe) {
86            throw new SAXException("Failed to close element", ioe);
87        }
88
89        mCurrent = mCurrent.getParent();
90    }
91
92    @Override
93    public void characters(char[] ch, int start, int length) throws SAXException {
94        mCurrent.addText(ch, start, length);
95    }
96
97    public RequestDetail getRequestDetail() {
98        Map<RequestDetail.RequestFields, String> values =
99                new EnumMap<RequestDetail.RequestFields, String>(RequestDetail.RequestFields.class);
100        List<MOTree> mos = new ArrayList<MOTree>();
101        extractFields(mRoot, values, mos);
102        return new RequestDetail(values, mos);
103    }
104
105    private static void extractFields(XMLNode node, Map<RequestDetail.RequestFields,
106            String> values, Collection<MOTree> mos) {
107        String[] attributes = sSoapAttributes.get(node.getTag());
108
109        if (attributes != null) {
110            if (attributes.length == 0) {
111                RequestDetail.RequestFields field = sRevMappings.get(node.getTag());
112                values.put(field, node.getText());
113            } else {
114                for (String attribute : attributes) {
115                    RequestDetail.RequestFields field = sRevMappings.get(attribute);
116                    if (field != null) {
117                        String value = node.getAttributeValue(attribute);
118
119                        if (value != null)
120                            values.put(field, value);
121                    }
122                }
123            }
124        }
125
126        if (node.getMOTree() != null)
127            mos.add(node.getMOTree());
128
129        for (XMLNode child : node.getChildren()) {
130            extractFields(child, values, mos);
131        }
132    }
133
134    public static void main(String[] args) throws Exception {
135        SOAPParser soapParser = new SOAPParser();
136        XMLNode root = soapParser.parse(new File(args[0]));
137        //System.out.println( root );
138        System.out.println(soapParser.getRequestDetail());
139        System.out.println("Marshalled: ");
140        for (MOTree mo : soapParser.getRequestDetail().getMOs()) {
141            ByteArrayOutputStream out = new ByteArrayOutputStream();
142            mo.marshal(out);
143            System.out.println(out.toString());
144            MOTree back = MOTree.unmarshal(new ByteArrayInputStream(out.toByteArray()));
145            System.out.println(back);
146        }
147        System.out.println("---");
148    }
149}
150