171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistpackage com.android.server.wifi.hotspot2.omadm;
271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport org.xml.sax.Attributes;
471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport org.xml.sax.SAXException;
571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport org.xml.sax.helpers.DefaultHandler;
671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport javax.xml.parsers.ParserConfigurationException;
871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport javax.xml.parsers.SAXParser;
971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport javax.xml.parsers.SAXParserFactory;
1071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
1171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport java.io.*;
1271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport java.util.*;
1371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
1471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistimport static com.android.server.wifi.hotspot2.omadm.RequestDetail.RequestFields.*;
1571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
16e0a4f90efb6b6e42c1ece5b4a0c9831770f2f7aaJan Nordqvist/**
17e0a4f90efb6b6e42c1ece5b4a0c9831770f2f7aaJan Nordqvist * This is an incomplete SOAP-XML parser for OSU data needing enhancements for r2.
18e0a4f90efb6b6e42c1ece5b4a0c9831770f2f7aaJan Nordqvist */
19e0a4f90efb6b6e42c1ece5b4a0c9831770f2f7aaJan Nordqvist
2071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvistpublic class SOAPParser extends DefaultHandler {
2171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    private XMLNode mRoot;
2271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    private XMLNode mCurrent;
2371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
2471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    private static String[] TagOnly = new String[0];
2571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    private static final Map<RequestDetail.RequestFields, String> sSoapMappings =
2671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            new EnumMap<RequestDetail.RequestFields, String>(RequestDetail.RequestFields.class);
2771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    private static final Map<String, RequestDetail.RequestFields> sRevMappings =
2871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            new HashMap<String, RequestDetail.RequestFields>();
2971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    private static final Map<String, String[]> sSoapAttributes =
3071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            new HashMap<String, String[]>();
3171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
3271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    static {
3371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        sSoapMappings.put(SPPVersion, "spp:sppVersion");
3471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        sSoapMappings.put(RedirectURI, "redirectURI");
3571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        sSoapMappings.put(RequestReason, "requestReason");
3671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        sSoapMappings.put(SessionID, "spp:sessionID");
3771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        sSoapMappings.put(SupportedVersions, "spp:supportedSPPVersions");
3871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        sSoapMappings.put(SupportedMOs, "spp:supportedMOList");
3971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
4071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        for (Map.Entry<RequestDetail.RequestFields, String> entry : sSoapMappings.entrySet()) {
4171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            sRevMappings.put(entry.getValue(), entry.getKey());
4271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
4371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
44e0a4f90efb6b6e42c1ece5b4a0c9831770f2f7aaJan Nordqvist        // !!! Really: The first element inside the body
4571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        sSoapAttributes.put("spp:sppPostDevDataResponse", new String[]{
4671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                sSoapMappings.get(SPPVersion),
4771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                sSoapMappings.get(RedirectURI),
4871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                sSoapMappings.get(RequestReason),
4971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                sSoapMappings.get(SessionID)});
5071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
5171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        sSoapAttributes.put(sSoapMappings.get(SupportedVersions), TagOnly);
5271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        sSoapAttributes.put(sSoapMappings.get(SupportedMOs), TagOnly);
5371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
5471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
5571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    public XMLNode parse(File file) throws IOException, ParserConfigurationException, SAXException {
5671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
5771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
5871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
5971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        try {
6071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            parser.parse(in, this);
6171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        } finally {
6271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            in.close();
6371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
6471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        return mRoot;
6571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
6671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
6771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    @Override
6871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    public void startElement(String uri, String localName, String qName, Attributes attributes)
6971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            throws SAXException {
7071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        XMLNode parent = mCurrent;
7171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
7271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        mCurrent = new XMLNode(mCurrent, qName, attributes);
7371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        System.out.println("Added " + mCurrent.getTag() + ", atts " + mCurrent.getAttributes());
7471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
7571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        if (mRoot == null)
7671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            mRoot = mCurrent;
7771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        else
7871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            parent.addChild(mCurrent);
7971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
8071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
8171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    @Override
8271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    public void endElement(String uri, String localName, String qName) throws SAXException {
8371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        if (!qName.equals(mCurrent.getTag()))
8471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            throw new SAXException("End tag '" + qName + "' doesn't match current node: " +
8571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                    mCurrent);
8671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
8771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        try {
8871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            mCurrent.close();
8971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        } catch (IOException ioe) {
9071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            throw new SAXException("Failed to close element", ioe);
9171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
9271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
9371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        mCurrent = mCurrent.getParent();
9471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
9571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
9671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    @Override
9771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    public void characters(char[] ch, int start, int length) throws SAXException {
9871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        mCurrent.addText(ch, start, length);
9971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
10071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
10171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    public RequestDetail getRequestDetail() {
10271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        Map<RequestDetail.RequestFields, String> values =
10371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                new EnumMap<RequestDetail.RequestFields, String>(RequestDetail.RequestFields.class);
10471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        List<MOTree> mos = new ArrayList<MOTree>();
10571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        extractFields(mRoot, values, mos);
10671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        return new RequestDetail(values, mos);
10771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
10871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
10971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    private static void extractFields(XMLNode node, Map<RequestDetail.RequestFields,
11071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            String> values, Collection<MOTree> mos) {
11171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        String[] attributes = sSoapAttributes.get(node.getTag());
11271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
11371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        if (attributes != null) {
11471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            if (attributes.length == 0) {
11571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                RequestDetail.RequestFields field = sRevMappings.get(node.getTag());
11671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                values.put(field, node.getText());
11771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            } else {
11871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                for (String attribute : attributes) {
11971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                    RequestDetail.RequestFields field = sRevMappings.get(attribute);
12071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                    if (field != null) {
12171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                        String value = node.getAttributeValue(attribute);
12271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
12371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                        if (value != null)
12471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                            values.put(field, value);
12571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                    }
12671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist                }
12771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            }
12871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
12971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
13071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        if (node.getMOTree() != null)
13171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            mos.add(node.getMOTree());
13271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
13371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        for (XMLNode child : node.getChildren()) {
13471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            extractFields(child, values, mos);
13571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
13671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
13771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist
13871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    public static void main(String[] args) throws Exception {
13971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        SOAPParser soapParser = new SOAPParser();
14071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        XMLNode root = soapParser.parse(new File(args[0]));
14171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        //System.out.println( root );
14271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        System.out.println(soapParser.getRequestDetail());
14371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        System.out.println("Marshalled: ");
14471a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        for (MOTree mo : soapParser.getRequestDetail().getMOs()) {
14571a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            ByteArrayOutputStream out = new ByteArrayOutputStream();
14671a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            mo.marshal(out);
14771a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            System.out.println(out.toString());
14871a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            MOTree back = MOTree.unmarshal(new ByteArrayInputStream(out.toByteArray()));
14971a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist            System.out.println(back);
15071a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        }
15171a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist        System.out.println("---");
15271a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist    }
15371a988c8e9859244b83cd55bb6b6ee913fcaf95cJan Nordqvist}
154