package org.apache.haox.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.InputStream; import java.util.ArrayList; import java.util.List; public class XmlConfigLoader extends ConfigLoader { private static final Logger logger = LoggerFactory.getLogger(Config.class); @Override protected void loadConfig(ConfigImpl config, Resource resource) throws Exception { Element doc = loadResourceDocument(resource); loadConfig((ConfigImpl) config, doc); } private Element loadResourceDocument(Resource resource) throws Exception { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); docBuilderFactory.setIgnoringComments(true); docBuilderFactory.setNamespaceAware(true); try { docBuilderFactory.setXIncludeAware(true); } catch (UnsupportedOperationException e) { logger.error("Failed to set setXIncludeAware(true) for parser", e); } DocumentBuilder builder = docBuilderFactory.newDocumentBuilder(); InputStream is = (InputStream) resource.getResource(); Document doc = null; try { doc = builder.parse(is); } finally { is.close(); } Element root = doc.getDocumentElement(); validateConfig(root); return root; } private boolean validateConfig(Element root) { boolean valid = false; if ("config".equals(root.getTagName())) { valid = true; } else { logger.error("bad conf element: top-level element not <configuration>"); } return valid; } private void loadConfig(ConfigImpl conifg, Element element) { String name; ConfigObject value; NodeList props = element.getChildNodes(); for (int i = 0; i < props.getLength(); i++) { Node subNode = props.item(i); if (!(subNode instanceof Element)) { continue; } Element prop = (Element)subNode; name = getElementName(prop); if (name == null) { continue; } value = null; String tagName = prop.getTagName(); if ("property".equals(tagName) && prop.hasChildNodes()) { value = loadProperty(prop); } else if ("config".equals(tagName) && prop.hasChildNodes()) { ConfigImpl cfg = new ConfigImpl(name); loadConfig(cfg, prop); value = new ConfigObject(cfg); } if (name != null) { conifg.set(name, value); } } } private static ConfigObject loadProperty(Element ele) { String value = null; if (ele.getFirstChild() instanceof Text) { value = ((Text)ele.getFirstChild()).getData(); return new ConfigObject(value); } ConfigObject result = null; NodeList nodes = ele.getChildNodes(); List<String> values = new ArrayList<String>(nodes.getLength()); for (int i = 0; i < nodes.getLength(); i++) { value = null; Node valueNode = nodes.item(i); if (!(valueNode instanceof Element)) continue; Element valueEle = (Element)valueNode; if ("value".equals(valueEle.getTagName()) && valueEle.hasChildNodes()) { value = ((Text)valueEle.getFirstChild()).getData(); } if (value != null) { values.add(value); } } return new ConfigObject(values); } private static String getElementName(Element ele) { String name, value; Node node; Attr attr; NamedNodeMap nnm = ele.getAttributes(); for (int i = 0; i < nnm.getLength(); ++i) { node = nnm.item(i); if (!(node instanceof Attr)) continue; attr = (Attr) node; name = attr.getName(); value = attr.getValue(); if ("name".equals(name)) { return value; } } return null; } }