From a2ad717d04700c4945c36d28b0f665456f100dc4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 2 May 2026 07:45:59 +0000 Subject: [PATCH] perf: cache compiled XSLT Templates per XSL file in MessageCodeGenerator Agent-Logs-Url: https://github.com/quickfix-j/quickfixj/sessions/e6405c75-ee5e-4d1b-8f7a-7970f31601fb Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> --- .../codegenerator/MessageCodeGenerator.java | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/quickfixj-codegenerator/src/main/java/org/quickfixj/codegenerator/MessageCodeGenerator.java b/quickfixj-codegenerator/src/main/java/org/quickfixj/codegenerator/MessageCodeGenerator.java index 615e639661..b2f6ad102e 100644 --- a/quickfixj-codegenerator/src/main/java/org/quickfixj/codegenerator/MessageCodeGenerator.java +++ b/quickfixj-codegenerator/src/main/java/org/quickfixj/codegenerator/MessageCodeGenerator.java @@ -27,6 +27,7 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Templates; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; @@ -50,6 +51,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import javax.xml.XMLConstants; @@ -220,18 +222,39 @@ private void generateComponentClasses(Task task) throws ParserConfigurationExcep } } + private final TransformerFactory transformerFactory = new net.sf.saxon.TransformerFactoryImpl(); + + private final Map templatesCache = new ConcurrentHashMap<>(); + private Transformer createTransformer(Task task, String xsltFile) throws TransformerFactoryConfigurationError, TransformerConfigurationException { - StreamSource styleSource; + final String cacheKey; + final StreamSource styleSource; File xslt = new File(task.getTransformDirectory() + "/" + xsltFile); if (xslt.exists()) { + cacheKey = xslt.getAbsolutePath(); styleSource = new StreamSource(xslt); } else { logInfo("Loading predefined xslt file:" + xsltFile); + cacheKey = "classpath:" + xsltFile; styleSource = new StreamSource(this.getClass().getResourceAsStream(xsltFile)); } - TransformerFactory transformerFactory = new net.sf.saxon.TransformerFactoryImpl(); - return transformerFactory.newTransformer(styleSource); + + try { + Templates templates = templatesCache.computeIfAbsent(cacheKey, k -> { + try { + return transformerFactory.newTemplates(styleSource); + } catch (TransformerConfigurationException e) { + throw new CodeGenerationException(e); + } + }); + return templates.newTransformer(); + } catch (CodeGenerationException e) { + if (e.getCause() instanceof TransformerConfigurationException) { + throw (TransformerConfigurationException) e.getCause(); + } + throw e; + } } private final Map specificationCache = new HashMap<>();