This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch coheigea/CXF-7641 in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 16198e1cfcfa3023799db874aaa8872e3fb84d8e Author: Colm O hEigeartaigh <[email protected]> AuthorDate: Fri Oct 16 14:12:44 2026 +0100 CXF-7641: Reduce allocations in CachingXmlEventWriter --- .../cxf/staxutils/CachingXmlEventWriter.java | 25 ++++++++++++++++------ .../org/apache/cxf/staxutils/StaxUtilsTest.java | 23 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/org/apache/cxf/staxutils/CachingXmlEventWriter.java b/core/src/main/java/org/apache/cxf/staxutils/CachingXmlEventWriter.java index 9900ee0308f..de4d7b02672 100644 --- a/core/src/main/java/org/apache/cxf/staxutils/CachingXmlEventWriter.java +++ b/core/src/main/java/org/apache/cxf/staxutils/CachingXmlEventWriter.java @@ -157,12 +157,12 @@ public class CachingXmlEventWriter implements XMLStreamWriter { } public void setDefaultNamespace(String ns) throws XMLStreamException { - curContext.addNs("", ns); + addNs("", ns); } public void writeNamespace(String pfx, String ns) throws XMLStreamException { - curContext.addNs(pfx, ns); + addNs(pfx, ns); if (StringUtils.isEmpty(pfx)) { addEvent(factory.createNamespace(ns)); } else { @@ -179,7 +179,18 @@ public class CachingXmlEventWriter implements XMLStreamWriter { } } public void setPrefix(String pfx, String uri) throws XMLStreamException { - curContext.addNs(pfx, uri); + addNs(pfx, uri); + } + + /** + * Elements share their parent's namespace context until they declare a namespace, + * to avoid allocating a context per element when buffering large documents. + */ + private void addNs(String pfx, String ns) { + if (!contexts.isEmpty() && curContext == contexts.peek()) { + curContext = new NSContext(curContext); + } + curContext.addNs(pfx, ns); } @@ -211,7 +222,6 @@ public class CachingXmlEventWriter implements XMLStreamWriter { public void writeStartElement(String name) throws XMLStreamException { elNames.push(lastStart); contexts.push(curContext); - curContext = new NSContext(curContext); lastStart = new QName(name); Set<javax.xml.stream.events.Attribute> atSet = Collections.emptySet(); Set<javax.xml.stream.events.Namespace> nsSet = Collections.emptySet(); @@ -220,7 +230,6 @@ public class CachingXmlEventWriter implements XMLStreamWriter { public void writeStartElement(String name, String ns) throws XMLStreamException { elNames.push(lastStart); contexts.push(curContext); - curContext = new NSContext(curContext); lastStart = new QName(ns, name); Set<javax.xml.stream.events.Attribute> atSet = Collections.emptySet(); Set<javax.xml.stream.events.Namespace> nsSet = Collections.emptySet(); @@ -229,7 +238,6 @@ public class CachingXmlEventWriter implements XMLStreamWriter { public void writeStartElement(String pfx, String name, String ns) throws XMLStreamException { elNames.push(lastStart); contexts.push(curContext); - curContext = new NSContext(curContext); lastStart = new QName(ns, name, pfx); Set<javax.xml.stream.events.Attribute> atSet = Collections.emptySet(); Set<javax.xml.stream.events.Namespace> nsSet = Collections.emptySet(); @@ -238,12 +246,15 @@ public class CachingXmlEventWriter implements XMLStreamWriter { public static class NSContext implements NamespaceContext { NamespaceContext parent; - Map<String, String> map = new HashMap<>(); + Map<String, String> map = Collections.emptyMap(); public NSContext(NamespaceContext p) { parent = p; } public void addNs(String pfx, String ns) { + if (map.isEmpty()) { + map = new HashMap<>(); + } map.put(pfx, ns); } diff --git a/core/src/test/java/org/apache/cxf/staxutils/StaxUtilsTest.java b/core/src/test/java/org/apache/cxf/staxutils/StaxUtilsTest.java index 54b1c0ba657..ac0a54c98af 100644 --- a/core/src/test/java/org/apache/cxf/staxutils/StaxUtilsTest.java +++ b/core/src/test/java/org/apache/cxf/staxutils/StaxUtilsTest.java @@ -61,6 +61,7 @@ import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -443,6 +444,28 @@ public class StaxUtilsTest { assertEquals(-1, idx); } + @Test + public void testCachingXmlEventWriterNamespaceScope() throws Exception { + CachingXmlEventWriter writer = new CachingXmlEventWriter(); + writer.writeStartElement("root"); + writer.writeStartElement("a", "first", "urn:a"); + writer.writeNamespace("a", "urn:a"); + writer.writeStartElement("child"); + assertEquals("urn:a", writer.getNamespaceContext().getNamespaceURI("a")); + assertEquals("a", writer.getPrefix("urn:a")); + writer.writeEndElement(); + writer.writeEndElement(); + assertNull(writer.getNamespaceContext().getNamespaceURI("a")); + writer.writeStartElement("second"); + assertNull(writer.getNamespaceContext().getNamespaceURI("a")); + assertNull(writer.getPrefix("urn:a")); + writer.setPrefix("b", "urn:b"); + assertEquals("urn:b", writer.getNamespaceContext().getNamespaceURI("b")); + writer.writeEndElement(); + assertNull(writer.getNamespaceContext().getNamespaceURI("b")); + writer.writeEndElement(); + } + @Test public void testCopyWithEmptyNamespace() throws Exception { StringBuilder in = new StringBuilder(128);
