package com.android.server.wifi.hotspot2.omadm; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.*; import java.util.*; import static com.android.server.wifi.hotspot2.omadm.RequestDetail.RequestFields.*; /** * This is an incomplete SOAP-XML parser for OSU data needing enhancements for r2. */ public class SOAPParser extends DefaultHandler { private XMLNode mRoot; private XMLNode mCurrent; private static String[] TagOnly = new String[0]; private static final Map<RequestDetail.RequestFields, String> sSoapMappings = new EnumMap<RequestDetail.RequestFields, String>(RequestDetail.RequestFields.class); private static final Map<String, RequestDetail.RequestFields> sRevMappings = new HashMap<String, RequestDetail.RequestFields>(); private static final Map<String, String[]> sSoapAttributes = new HashMap<String, String[]>(); static { sSoapMappings.put(SPPVersion, "spp:sppVersion"); sSoapMappings.put(RedirectURI, "redirectURI"); sSoapMappings.put(RequestReason, "requestReason"); sSoapMappings.put(SessionID, "spp:sessionID"); sSoapMappings.put(SupportedVersions, "spp:supportedSPPVersions"); sSoapMappings.put(SupportedMOs, "spp:supportedMOList"); for (Map.Entry<RequestDetail.RequestFields, String> entry : sSoapMappings.entrySet()) { sRevMappings.put(entry.getValue(), entry.getKey()); } // !!! Really: The first element inside the body sSoapAttributes.put("spp:sppPostDevDataResponse", new String[]{ sSoapMappings.get(SPPVersion), sSoapMappings.get(RedirectURI), sSoapMappings.get(RequestReason), sSoapMappings.get(SessionID)}); sSoapAttributes.put(sSoapMappings.get(SupportedVersions), TagOnly); sSoapAttributes.put(sSoapMappings.get(SupportedMOs), TagOnly); } public XMLNode parse(File file) throws IOException, ParserConfigurationException, SAXException { SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); try { parser.parse(in, this); } finally { in.close(); } return mRoot; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { XMLNode parent = mCurrent; mCurrent = new XMLNode(mCurrent, qName, attributes); System.out.println("Added " + mCurrent.getTag() + ", atts " + mCurrent.getAttributes()); if (mRoot == null) mRoot = mCurrent; else parent.addChild(mCurrent); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (!qName.equals(mCurrent.getTag())) throw new SAXException("End tag '" + qName + "' doesn't match current node: " + mCurrent); try { mCurrent.close(); } catch (IOException ioe) { throw new SAXException("Failed to close element", ioe); } mCurrent = mCurrent.getParent(); } @Override public void characters(char[] ch, int start, int length) throws SAXException { mCurrent.addText(ch, start, length); } public RequestDetail getRequestDetail() { Map<RequestDetail.RequestFields, String> values = new EnumMap<RequestDetail.RequestFields, String>(RequestDetail.RequestFields.class); List<MOTree> mos = new ArrayList<MOTree>(); extractFields(mRoot, values, mos); return new RequestDetail(values, mos); } private static void extractFields(XMLNode node, Map<RequestDetail.RequestFields, String> values, Collection<MOTree> mos) { String[] attributes = sSoapAttributes.get(node.getTag()); if (attributes != null) { if (attributes.length == 0) { RequestDetail.RequestFields field = sRevMappings.get(node.getTag()); values.put(field, node.getText()); } else { for (String attribute : attributes) { RequestDetail.RequestFields field = sRevMappings.get(attribute); if (field != null) { String value = node.getAttributeValue(attribute); if (value != null) values.put(field, value); } } } } if (node.getMOTree() != null) mos.add(node.getMOTree()); for (XMLNode child : node.getChildren()) { extractFields(child, values, mos); } } public static void main(String[] args) throws Exception { SOAPParser soapParser = new SOAPParser(); XMLNode root = soapParser.parse(new File(args[0])); //System.out.println( root ); System.out.println(soapParser.getRequestDetail()); System.out.println("Marshalled: "); for (MOTree mo : soapParser.getRequestDetail().getMOs()) { ByteArrayOutputStream out = new ByteArrayOutputStream(); mo.marshal(out); System.out.println(out.toString()); MOTree back = MOTree.unmarshal(new ByteArrayInputStream(out.toByteArray())); System.out.println(back); } System.out.println("---"); } }