Skip to content

Commit

Permalink
cache xml parsing/transformation by threadlocal
Browse files Browse the repository at this point in the history
  • Loading branch information
SavvasMisaghMoayyed committed Mar 5, 2018
1 parent d7aafcc commit 91ee02e
Showing 1 changed file with 45 additions and 45 deletions.
90 changes: 45 additions & 45 deletions infra/util/src/main/java/com/evolveum/midpoint/util/DOMUtil.java
Expand Up @@ -163,28 +163,55 @@ public class DOMUtil {
// To generate random namespace prefixes
private static Random rnd = new Random();

private static final DocumentBuilder loader;
private static final DocumentBuilderFactory documentBuilderFactory;
private static final ThreadLocal<DocumentBuilder> documentBuilderThreadLocal;

private static final TransformerFactory transformerFactory;
private static final ThreadLocal<Transformer> transformerThreadLocal;

static {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
loader = factory.newDocumentBuilder();
documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setFeature("http://xml.org/sax/features/namespaces", true);
// voodoo to turn off reading of DTDs during parsing. This is needed e.g. to pre-parse schemas
documentBuilderFactory.setValidating(false);
documentBuilderFactory.setFeature("http://xml.org/sax/features/validation", false);
documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

documentBuilderThreadLocal = ThreadLocal.withInitial(() -> {
try {
return documentBuilderFactory.newDocumentBuilder();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
} catch (ParserConfigurationException ex) {
throw new IllegalStateException("Error creating XML document " + ex.getMessage());
}

transformerFactory = TransformerFactory.newInstance();
transformerThreadLocal = ThreadLocal.withInitial(() -> {
try {
Transformer trans = transformerFactory.newTransformer();
trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); // XALAN-specific
trans.setParameter(OutputKeys.ENCODING, "utf-8");
return trans;
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}

public static String serializeDOMToString(org.w3c.dom.Node node) {
return printDom(node).toString();
}

public static void serializeDOMToFile(org.w3c.dom.Node node, File file) throws TransformerFactoryConfigurationError, TransformerException {

Transformer transformer = TransformerFactory.newInstance().newTransformer();
Transformer transformer = transformerThreadLocal.get();
Result output = new StreamResult(file);
Source input = new DOMSource(node);

transformer.transform(input, output);
}

Expand All @@ -196,23 +223,17 @@ public static Document getDocument(Node node) {
}

public static Document getDocument() {
return loader.newDocument();
return documentBuilderThreadLocal.get().newDocument();
}

public static Document getDocument(QName rootElementName) {
Document document = loader.newDocument();
Document document = documentBuilderThreadLocal.get().newDocument();
document.appendChild(createElement(document, rootElementName));
return document;
}

public static DocumentBuilder createDocumentBuilder() {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
return factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new IllegalStateException("Error creating document builder " + e.getMessage(), e);
}
return documentBuilderThreadLocal.get();
}

public static Document parseDocument(String doc) {
Expand All @@ -230,28 +251,16 @@ public static Document parseFile(String filePath) {

public static Document parseFile(File file) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder loader = factory.newDocumentBuilder();
return loader.parse(file);
} catch (SAXException | IOException | ParserConfigurationException ex) {
return documentBuilderThreadLocal.get().parse(file);
} catch (SAXException | IOException ex) {
throw new IllegalStateException("Error parsing XML document " + ex.getMessage(),ex);
}
}

public static Document parse(InputStream inputStream) throws IOException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setFeature("http://xml.org/sax/features/namespaces", true);
// voodoo to turn off reading of DTDs during parsing. This is needed e.g. to pre-parse schemas
factory.setValidating(false);
factory.setFeature("http://xml.org/sax/features/validation", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder loader = factory.newDocumentBuilder();
return loader.parse(inputStream);
} catch (SAXException | ParserConfigurationException ex) {
return documentBuilderThreadLocal.get().parse(inputStream);
} catch (SAXException ex) {
throw new IllegalStateException("Error parsing XML document " + ex.getMessage(),ex);
}
}
Expand All @@ -271,21 +280,12 @@ public static StringBuffer printDom(Node node) {

public static StringBuffer printDom(Node node, boolean indent, boolean omitXmlDeclaration) {
StringWriter writer = new StringWriter();
TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans;
try {
trans = transfac.newTransformer();
} catch (TransformerConfigurationException e) {
throw new SystemException("Error in XML configuration: "+e.getMessage(),e);
}
trans.setOutputProperty(OutputKeys.INDENT, (indent ? "yes" : "no"));
trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); // XALAN-specific
trans.setParameter(OutputKeys.ENCODING, "utf-8");
// Note: serialized XML does not contain xml declaration
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, (omitXmlDeclaration ? "yes" : "no"));

DOMSource source = new DOMSource(node);
try {
Transformer trans = transformerThreadLocal.get();
trans.setOutputProperty(OutputKeys.INDENT, (indent ? "yes" : "no"));
// Note: serialized XML does not contain xml declaration
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, (omitXmlDeclaration ? "yes" : "no"));
trans.transform(source, new StreamResult(writer));
} catch (TransformerException e) {
throw new SystemException("Error in XML transformation: "+e.getMessage(),e);
Expand Down

0 comments on commit 91ee02e

Please sign in to comment.