package org.objectstyle.woenvironment.plist; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.net.URL; import java.util.Collection; import java.util.Map; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; public class WOLXMLPropertyListSerialization { private static final DocumentBuilderFactory _builderFactory; static { _builderFactory = DocumentBuilderFactory.newInstance(); _builderFactory.setValidating(false); _builderFactory.setNamespaceAware(false); _builderFactory.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); } public static Object propertyListFromString(String string) throws IOException, PropertyListParserException, SAXException, ParserConfigurationException { return WOLXMLPropertyListSerialization.propertyListFromString(string, new SimpleParserDataStructureFactory()); } public static Object propertyListFromString(String string, ParserDataStructureFactory factory) throws PropertyListParserException, SAXException, IOException, ParserConfigurationException { return parse(_builderFactory.newDocumentBuilder().parse(new InputSource(new StringReader(string))), factory); } public static Object propertyListWithPathURL(URL url, ParserDataStructureFactory factory) throws IOException, PropertyListParserException, SAXException, ParserConfigurationException { InputStream is = url.openStream(); try { return parse(_builderFactory.newDocumentBuilder().parse(is), factory); } finally { is.close(); } } public static Object propertyListWithContentsOfInputStream(InputStream inputStream, ParserDataStructureFactory factory) throws IOException, PropertyListParserException, SAXException, ParserConfigurationException { return parse(_builderFactory.newDocumentBuilder().parse(inputStream), factory); } public static Object propertyListWithContentsOfFile(String path, ParserDataStructureFactory factory) throws IOException, PropertyListParserException, SAXException, ParserConfigurationException { return parse(_builderFactory.newDocumentBuilder().parse(new File(path)), factory); } public static Object propertyListWithContentsOfFile(File file, ParserDataStructureFactory factory) throws IOException, PropertyListParserException, SAXException, ParserConfigurationException { return parse(_builderFactory.newDocumentBuilder().parse(file), factory); } protected static Object parse(Document document, ParserDataStructureFactory factory) { document.normalize(); Element plistElement = document.getDocumentElement(); if ("plist".equalsIgnoreCase(plistElement.getNodeName())) { NodeList plistChildren = plistElement.getChildNodes(); for (int i = 0; i < plistChildren.getLength(); i++) { Node plistChild = plistChildren.item(i); if (plistChild instanceof Element) { return parseValue((Element) plistChild, "", factory); } } } return null; } protected static Map<Object, Object> parseDict(Element dictElement, String keyPath, ParserDataStructureFactory factory) { Map<Object, Object> result = factory.createMap(keyPath); NodeList dictNodes = dictElement.getChildNodes(); String key = null; for (int i = 0; i < dictNodes.getLength(); i++) { Node node = dictNodes.item(i); if (node instanceof Element) { String nodeName = node.getNodeName(); if ("key".equalsIgnoreCase(nodeName)) { key = node.getTextContent(); } else { String newKeyPath = keyPath.length() == 0 ? key : (keyPath + "." + key); Object value = parseValue((Element) node, newKeyPath, factory); result.put(key, value); } } } return result; } protected static Collection<Object> parseArray(Element arrayElement, String keyPath, ParserDataStructureFactory factory) { Collection<Object> result = factory.createCollection(keyPath); NodeList arrayNodes = arrayElement.getChildNodes(); for (int i = 0; i < arrayNodes.getLength(); i++) { Node node = arrayNodes.item(i); if (node instanceof Element) { Object value = parseValue((Element) node, keyPath, factory); result.add(value); } } return result; } protected static Object parseValue(Element element, String keyPath, ParserDataStructureFactory factory) { Object value; String nodeName = element.getNodeName(); if ("string".equalsIgnoreCase(nodeName)) { value = element.getTextContent(); } else if ("true".equalsIgnoreCase(nodeName)) { value = Boolean.TRUE; } else if ("false".equalsIgnoreCase(nodeName)) { value = Boolean.FALSE; } else if ("array".equalsIgnoreCase(nodeName)) { value = parseArray(element, keyPath, factory); } else if ("dict".equalsIgnoreCase(nodeName)) { value = parseDict(element, keyPath, factory); } else { value = null; } return value; } }