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