From c236ab5fcc8e4e93b88238975d9649f77d3ebfcc Mon Sep 17 00:00:00 2001 From: Vincent Paturet Date: Fri, 27 Feb 2026 11:38:45 +0100 Subject: [PATCH] Cache Woodstox XMLInputFactory --- .../entur/siri/XmlInputFactoryProvider.java | 48 +++++++++++++++++++ .../java/org/entur/siri21/util/SiriXml.java | 7 +-- .../org/rutebanken/siri20/util/SiriXml.java | 7 +-- 3 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/entur/siri/XmlInputFactoryProvider.java diff --git a/src/main/java/org/entur/siri/XmlInputFactoryProvider.java b/src/main/java/org/entur/siri/XmlInputFactoryProvider.java new file mode 100644 index 0000000..f849c20 --- /dev/null +++ b/src/main/java/org/entur/siri/XmlInputFactoryProvider.java @@ -0,0 +1,48 @@ +/* + * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/software/page/eupl + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + */ + +package org.entur.siri; + +import javax.xml.stream.XMLInputFactory; + +/** + * Provides a shared {@link XMLInputFactory} when the StAX provider is Woodstox + * (thread-safe after initialization), otherwise creates a new factory per call. + */ +public class XmlInputFactoryProvider { + + private static final XMLInputFactory SHARED_XML_INPUT_FACTORY = createSharedFactory(); + + /** + * Returns a shared instance if the StAX provider is Woodstox (thread-safe after + * initialization), otherwise creates a new factory per call (spec-safe default). + */ + public static XMLInputFactory getXmlInputFactory() { + if (SHARED_XML_INPUT_FACTORY != null) { + return SHARED_XML_INPUT_FACTORY; + } + return XMLInputFactory.newInstance(); + } + + private static XMLInputFactory createSharedFactory() { + XMLInputFactory factory = XMLInputFactory.newInstance(); + // Woodstox factories are thread-safe after initialization. + // https://github.com/FasterXML/Woodstox4/blob/master/release-notes/USAGE + if (factory.getClass().getName().startsWith("com.ctc.wstx.")) { + return factory; + } + return null; + } +} diff --git a/src/main/java/org/entur/siri21/util/SiriXml.java b/src/main/java/org/entur/siri21/util/SiriXml.java index e1eb126..41c3f46 100644 --- a/src/main/java/org/entur/siri21/util/SiriXml.java +++ b/src/main/java/org/entur/siri21/util/SiriXml.java @@ -16,6 +16,7 @@ package org.entur.siri21.util; import com.sun.xml.bind.marshaller.NamespacePrefixMapper; +import org.entur.siri.XmlInputFactoryProvider; import uk.org.siri.siri21.Siri; import jakarta.xml.bind.JAXBContext; @@ -51,8 +52,8 @@ private static void init() throws JAXBException { public static Siri parseXml(String xml) throws JAXBException, XMLStreamException { Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - - XMLInputFactory xmlif = XMLInputFactory.newInstance(); + + XMLInputFactory xmlif = XmlInputFactoryProvider.getXmlInputFactory(); XMLStreamReader xmler = xmlif.createXMLStreamReader(new StringReader(xml)); return (Siri) jaxbUnmarshaller.unmarshal(xmler); @@ -60,7 +61,7 @@ public static Siri parseXml(String xml) throws JAXBException, XMLStreamException public static Siri parseXml(InputStream inputStream) throws JAXBException, XMLStreamException { Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - XMLInputFactory xmlif = XMLInputFactory.newInstance(); + XMLInputFactory xmlif = XmlInputFactoryProvider.getXmlInputFactory(); XMLStreamReader xmler = xmlif.createXMLStreamReader(inputStream); return (Siri) jaxbUnmarshaller.unmarshal(xmler); diff --git a/src/main/java/org/rutebanken/siri20/util/SiriXml.java b/src/main/java/org/rutebanken/siri20/util/SiriXml.java index fb9451d..538529f 100644 --- a/src/main/java/org/rutebanken/siri20/util/SiriXml.java +++ b/src/main/java/org/rutebanken/siri20/util/SiriXml.java @@ -31,6 +31,7 @@ import com.sun.xml.bind.marshaller.NamespacePrefixMapper; +import org.entur.siri.XmlInputFactoryProvider; import uk.org.siri.siri20.Siri; public class SiriXml { @@ -53,8 +54,8 @@ private static void init() throws JAXBException { public static Siri parseXml(String xml) throws JAXBException, XMLStreamException { Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - - XMLInputFactory xmlif = XMLInputFactory.newInstance(); + + XMLInputFactory xmlif = XmlInputFactoryProvider.getXmlInputFactory(); XMLStreamReader xmler = xmlif.createXMLStreamReader(new StringReader(xml)); return (Siri) jaxbUnmarshaller.unmarshal(xmler); @@ -62,7 +63,7 @@ public static Siri parseXml(String xml) throws JAXBException, XMLStreamException public static Siri parseXml(InputStream inputStream) throws JAXBException, XMLStreamException { Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - XMLInputFactory xmlif = XMLInputFactory.newInstance(); + XMLInputFactory xmlif = XmlInputFactoryProvider.getXmlInputFactory(); XMLStreamReader xmler = xmlif.createXMLStreamReader(inputStream); return (Siri) jaxbUnmarshaller.unmarshal(xmler);