From f84a56efa22acfd35f4fb9f3c428c68830a797af Mon Sep 17 00:00:00 2001 From: Laurent SCHOELENS <61973605+laurentschoelens@users.noreply.github.com> Date: Thu, 6 Nov 2025 11:32:26 +0100 Subject: [PATCH] [#1824] createTransformerFactory useCache new param, optimize createTransformerHandler / createTransformer --- .../jaxb/core/v2/util/XmlFactory.java | 49 ++++++++++++++++++- .../runtime/v2/runtime/JAXBContextImpl.java | 4 +- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/jaxb-ri/core/src/main/java/org/glassfish/jaxb/core/v2/util/XmlFactory.java b/jaxb-ri/core/src/main/java/org/glassfish/jaxb/core/v2/util/XmlFactory.java index e13c8a392..4ad8d6ff2 100644 --- a/jaxb-ri/core/src/main/java/org/glassfish/jaxb/core/v2/util/XmlFactory.java +++ b/jaxb-ri/core/src/main/java/org/glassfish/jaxb/core/v2/util/XmlFactory.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025 Contributors to the Eclipse Foundation. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0, which is available at @@ -12,8 +13,12 @@ import org.glassfish.jaxb.core.v2.Messages; +import java.lang.ref.SoftReference; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.Map; +import java.util.WeakHashMap; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.XMLConstants; @@ -39,6 +44,7 @@ public class XmlFactory { private static final Logger LOGGER = Logger.getLogger(XmlFactory.class.getName()); + private static final Map> transformerFactoryCache = Collections.synchronizedMap(new WeakHashMap<>()); /** * If true XML security features when parsing XML documents will be disabled. @@ -131,10 +137,51 @@ public static XPathFactory createXPathFactory(boolean disableSecureProcessing) t } /** - * Returns properly configured (e.g. security features) factory + * Returns properly configured (e.g., security features) factory * - securityProcessing == is set based on security processing property, default is true + * + * @param disableSecureProcessing disable secure processing in TransformerFactory + * @return TransformerFactory new instance + * @throws IllegalStateException error on configuring TransformerFactory */ public static TransformerFactory createTransformerFactory(boolean disableSecureProcessing) throws IllegalStateException { + return createTransformerFactory(disableSecureProcessing, false); + } + + /** + * Returns properly configured (e.g., security features) factory + * - securityProcessing == is set based on security processing property, default is true + * + * @param disableSecureProcessing disable secure processing in TransformerFactory + * @param useCache use cached instances of TransformerFactory, false will always create new ones + * @return TransformerFactory new instance or cached one if useCache is true and found in cache + * @throws IllegalStateException error on configuring TransformerFactory + */ + public static TransformerFactory createTransformerFactory(boolean disableSecureProcessing, boolean useCache) throws IllegalStateException { + if (!useCache) { + return _createTransformerFactory(disableSecureProcessing); + } + TransformerFactory tf = null; + SoftReference tfRef = transformerFactoryCache.get(disableSecureProcessing); + if (tfRef != null) { + tf = tfRef.get(); + } + if (tf == null) { + tf = _createTransformerFactory(disableSecureProcessing); + transformerFactoryCache.put(disableSecureProcessing, new SoftReference<>(tf)); + } + return tf; + } + + /** + * Internal method: returns properly configured (e.g., security features) factory + * - securityProcessing == is set based on security processing property, default is true + * + * @param disableSecureProcessing disable secure processing in TransformerFactory + * @return TransformerFactory new instance + * @throws IllegalStateException error on configuring TransformerFactory + */ + private static TransformerFactory _createTransformerFactory(boolean disableSecureProcessing) throws IllegalStateException { try { TransformerFactory factory = TransformerFactory.newInstance(); if (LOGGER.isLoggable(Level.FINE)) { diff --git a/jaxb-ri/runtime/impl/src/main/java/org/glassfish/jaxb/runtime/v2/runtime/JAXBContextImpl.java b/jaxb-ri/runtime/impl/src/main/java/org/glassfish/jaxb/runtime/v2/runtime/JAXBContextImpl.java index 9374855e7..55686f652 100644 --- a/jaxb-ri/runtime/impl/src/main/java/org/glassfish/jaxb/runtime/v2/runtime/JAXBContextImpl.java +++ b/jaxb-ri/runtime/impl/src/main/java/org/glassfish/jaxb/runtime/v2/runtime/JAXBContextImpl.java @@ -673,7 +673,7 @@ public int getNumberOfAttributeNames() { */ static Transformer createTransformer(boolean disableSecureProcessing) { try { - SAXTransformerFactory tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing); + SAXTransformerFactory tf = (SAXTransformerFactory) XmlFactory.createTransformerFactory(disableSecureProcessing, true); return tf.newTransformer(); } catch (TransformerConfigurationException e) { throw new Error(e); // impossible @@ -685,7 +685,7 @@ static Transformer createTransformer(boolean disableSecureProcessing) { */ public static TransformerHandler createTransformerHandler(boolean disableSecureProcessing) { try { - SAXTransformerFactory tf = (SAXTransformerFactory)XmlFactory.createTransformerFactory(disableSecureProcessing); + SAXTransformerFactory tf = (SAXTransformerFactory) XmlFactory.createTransformerFactory(disableSecureProcessing, true); return tf.newTransformerHandler(); } catch (TransformerConfigurationException e) { throw new Error(e); // impossible