package com.feisystems.polrep.util; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.Optional; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.springframework.util.Assert; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.feisystems.polrep.service.exception.DOMUtilsException; import com.feisystems.polrep.service.xacml.XACMLNamespaceContext; public class DOMUtils { private static final String DEFAULT_TRANSFORMER_PROPERTY_INDENT_AMOUNT = "4"; private static final String DEFAULT_TRANSFORMER_PROPERTY_INDENT = "yes"; private static final String DEFAULT_TRANSFORMER_PROPERTY_METHOD = "xml"; private static final String DEFAULT_TRANSFORMER_PROPERTY_OMIT_XML_DECLARATION = "no"; public static final String DEFAULT_ENCODING = "UTF-8"; public static Document bytesToDocument(byte[] bytes) { String xacmlString; try { xacmlString = new String(bytes, DEFAULT_ENCODING); } catch (final UnsupportedEncodingException e) { throw new DOMUtilsException(e); } return xmlToDocument(xacmlString); } public static byte[] documentToBytes(Document xmlDocument) { try { return documentToXml(xmlDocument).getBytes(DEFAULT_ENCODING); } catch (final UnsupportedEncodingException e) { throw new DOMUtilsException(e); } } public static String documentToXml(Document xmlDocument) { try { String xmlString = ""; final TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer; transformer = tf.newTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, DEFAULT_TRANSFORMER_PROPERTY_OMIT_XML_DECLARATION); transformer.setOutputProperty(OutputKeys.METHOD, DEFAULT_TRANSFORMER_PROPERTY_METHOD); transformer.setOutputProperty(OutputKeys.INDENT, DEFAULT_TRANSFORMER_PROPERTY_INDENT); transformer .setOutputProperty(OutputKeys.ENCODING, DEFAULT_ENCODING); transformer.setOutputProperty( "{http://xml.apache.org/xslt}indent-amount", DEFAULT_TRANSFORMER_PROPERTY_INDENT_AMOUNT); final StringWriter writer = new StringWriter(); transformer.transform(new DOMSource(xmlDocument), new StreamResult( writer)); xmlString = writer.getBuffer().toString().replaceAll("\n|\r", ""); Assert.hasText(xmlString, "Document object cannot be converted to XML string!"); return xmlString; } catch (TransformerException | IllegalArgumentException e) { throw new DOMUtilsException(e); } } public static Optional<Node> getNode(Document xmlDocument, String xPathExpr, String... arguments) { xPathExpr = setXpathArguments(xPathExpr, arguments); // Create XPath instance final XPath xpath = xpath(); // Evaluate XPath expression against parsed document Node node = null; try { node = (Node) xpath.evaluate(xPathExpr, xmlDocument, XPathConstants.NODE); return Optional.ofNullable(node); } catch (final XPathExpressionException e) { throw new DOMUtilsException(e); } } public static Optional<NodeList> getNodeList(Document xmlDocument, String xPathExpr, String... arguments) { xPathExpr = setXpathArguments(xPathExpr, arguments); // Create XPath instance final XPath xpath = xpath(); // Evaluate XPath expression against parsed document NodeList nodeList = null; try { nodeList = (NodeList) xpath.evaluate(xPathExpr, xmlDocument, XPathConstants.NODESET); if (nodeList != null && nodeList.getLength() == 0) { nodeList = null; } return Optional.ofNullable(nodeList); } catch (final XPathExpressionException e) { throw new DOMUtilsException(e); } } public static Document xmlToDocument(String xmlString) { try { final DocumentBuilderFactory dbf = DocumentBuilderFactory .newInstance(); dbf.setValidating(false); dbf.setNamespaceAware(true); final DocumentBuilder db = dbf.newDocumentBuilder(); final InputSource source = new InputSource(new StringReader( xmlString)); final Document doc = db.parse(source); Assert.notNull(doc, "XML string cannot be converted to Document object!"); return doc; } catch (ParserConfigurationException | SAXException | IOException | IllegalArgumentException e) { throw new DOMUtilsException(e); } } private static String setXpathArguments(String xPath, String... arguments) { for (int i = 0; i < arguments.length; i++) { xPath = xPath.replace("%" + Integer.toString(i + 1), arguments[i]); } return xPath; } private static XPath xpath() { // Create XPath instance final XPath xpath = XPathFactory.newInstance().newXPath(); xpath.setNamespaceContext(XACMLNamespaceContext.CONTEXT); return xpath; } }