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("---");
}
}