Merge branch '6.1.x'

This commit is contained in:
Juergen Hoeller 2024-05-21 11:17:16 +02:00
commit 6f6e25bd5b
6 changed files with 146 additions and 73 deletions

View File

@ -20,11 +20,14 @@ import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringConfiguredWithAutoProxyingTests { /**
* @author Ramnivas Laddad
* @author Juergen Hoeller
*/
class SpringConfiguredWithAutoProxyingTests {
@Test @Test
void springConfiguredAndAutoProxyUsedTogether() { void springConfiguredAndAutoProxyUsedTogether() {
// instantiation is sufficient to trigger failure if this is going to fail...
new ClassPathXmlApplicationContext("org/springframework/beans/factory/aspectj/springConfigured.xml"); new ClassPathXmlApplicationContext("org/springframework/beans/factory/aspectj/springConfigured.xml");
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -154,7 +154,7 @@ final class PersistenceUnitReader {
/** /**
* Validate the given stream and return a valid DOM document for parsing. * Validate the given stream and return a valid DOM document for parsing.
*/ */
protected Document buildDocument(ErrorHandler handler, InputStream stream) Document buildDocument(ErrorHandler handler, InputStream stream)
throws ParserConfigurationException, SAXException, IOException { throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
@ -168,9 +168,7 @@ final class PersistenceUnitReader {
/** /**
* Parse the validated document and add entries to the given unit info list. * Parse the validated document and add entries to the given unit info list.
*/ */
protected List<SpringPersistenceUnitInfo> parseDocument( void parseDocument(Resource resource, Document document, List<SpringPersistenceUnitInfo> infos) throws IOException {
Resource resource, Document document, List<SpringPersistenceUnitInfo> infos) throws IOException {
Element persistence = document.getDocumentElement(); Element persistence = document.getDocumentElement();
String version = persistence.getAttribute(PERSISTENCE_VERSION); String version = persistence.getAttribute(PERSISTENCE_VERSION);
URL rootUrl = determinePersistenceUnitRootUrl(resource); URL rootUrl = determinePersistenceUnitRootUrl(resource);
@ -179,14 +177,12 @@ final class PersistenceUnitReader {
for (Element unit : units) { for (Element unit : units) {
infos.add(parsePersistenceUnitInfo(unit, version, rootUrl)); infos.add(parsePersistenceUnitInfo(unit, version, rootUrl));
} }
return infos;
} }
/** /**
* Parse the unit info DOM element. * Parse the unit info DOM element.
*/ */
protected SpringPersistenceUnitInfo parsePersistenceUnitInfo( SpringPersistenceUnitInfo parsePersistenceUnitInfo(
Element persistenceUnit, String version, @Nullable URL rootUrl) throws IOException { Element persistenceUnit, String version, @Nullable URL rootUrl) throws IOException {
SpringPersistenceUnitInfo unitInfo = new SpringPersistenceUnitInfo(); SpringPersistenceUnitInfo unitInfo = new SpringPersistenceUnitInfo();
@ -253,7 +249,7 @@ final class PersistenceUnitReader {
/** /**
* Parse the {@code property} XML elements. * Parse the {@code property} XML elements.
*/ */
protected void parseProperties(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) { void parseProperties(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
Element propRoot = DomUtils.getChildElementByTagName(persistenceUnit, PROPERTIES); Element propRoot = DomUtils.getChildElementByTagName(persistenceUnit, PROPERTIES);
if (propRoot == null) { if (propRoot == null) {
return; return;
@ -269,7 +265,7 @@ final class PersistenceUnitReader {
/** /**
* Parse the {@code class} XML elements. * Parse the {@code class} XML elements.
*/ */
protected void parseManagedClasses(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) { void parseManagedClasses(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
List<Element> classes = DomUtils.getChildElementsByTagName(persistenceUnit, MANAGED_CLASS_NAME); List<Element> classes = DomUtils.getChildElementsByTagName(persistenceUnit, MANAGED_CLASS_NAME);
for (Element element : classes) { for (Element element : classes) {
String value = DomUtils.getTextValue(element).trim(); String value = DomUtils.getTextValue(element).trim();
@ -282,7 +278,7 @@ final class PersistenceUnitReader {
/** /**
* Parse the {@code mapping-file} XML elements. * Parse the {@code mapping-file} XML elements.
*/ */
protected void parseMappingFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) { void parseMappingFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
List<Element> files = DomUtils.getChildElementsByTagName(persistenceUnit, MAPPING_FILE_NAME); List<Element> files = DomUtils.getChildElementsByTagName(persistenceUnit, MAPPING_FILE_NAME);
for (Element element : files) { for (Element element : files) {
String value = DomUtils.getTextValue(element).trim(); String value = DomUtils.getTextValue(element).trim();
@ -295,7 +291,7 @@ final class PersistenceUnitReader {
/** /**
* Parse the {@code jar-file} XML elements. * Parse the {@code jar-file} XML elements.
*/ */
protected void parseJarFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) throws IOException { void parseJarFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) throws IOException {
List<Element> jars = DomUtils.getChildElementsByTagName(persistenceUnit, JAR_FILE_URL); List<Element> jars = DomUtils.getChildElementsByTagName(persistenceUnit, JAR_FILE_URL);
for (Element element : jars) { for (Element element : jars) {
String value = DomUtils.getTextValue(element).trim(); String value = DomUtils.getTextValue(element).trim();

View File

@ -37,6 +37,8 @@ import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
import javax.xml.datatype.Duration; import javax.xml.datatype.Duration;
@ -192,7 +194,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
@Nullable @Nullable
private ClassLoader beanClassLoader; private ClassLoader beanClassLoader;
private final Object jaxbContextMonitor = new Object(); private final Lock jaxbContextLock = new ReentrantLock();
@Nullable @Nullable
private volatile JAXBContext jaxbContext; private volatile JAXBContext jaxbContext;
@ -204,6 +206,12 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
private boolean processExternalEntities = false; private boolean processExternalEntities = false;
@Nullable
private volatile SAXParserFactory schemaParserFactory;
@Nullable
private volatile SAXParserFactory sourceParserFactory;
/** /**
* Set multiple JAXB context paths. The given array of context paths gets * Set multiple JAXB context paths. The given array of context paths gets
@ -426,6 +434,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
*/ */
public void setSupportDtd(boolean supportDtd) { public void setSupportDtd(boolean supportDtd) {
this.supportDtd = supportDtd; this.supportDtd = supportDtd;
this.sourceParserFactory = null;
} }
/** /**
@ -450,6 +459,7 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
if (processExternalEntities) { if (processExternalEntities) {
this.supportDtd = true; this.supportDtd = true;
} }
this.sourceParserFactory = null;
} }
/** /**
@ -497,7 +507,9 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
if (context != null) { if (context != null) {
return context; return context;
} }
synchronized (this.jaxbContextMonitor) {
this.jaxbContextLock.lock();
try {
context = this.jaxbContext; context = this.jaxbContext;
if (context == null) { if (context == null) {
try { try {
@ -521,6 +533,9 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
} }
return context; return context;
} }
finally {
this.jaxbContextLock.unlock();
}
} }
private JAXBContext createJaxbContextFromContextPath(String contextPath) throws JAXBException { private JAXBContext createJaxbContextFromContextPath(String contextPath) throws JAXBException {
@ -587,17 +602,24 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
Assert.notEmpty(resources, "No resources given"); Assert.notEmpty(resources, "No resources given");
Assert.hasLength(schemaLanguage, "No schema language provided"); Assert.hasLength(schemaLanguage, "No schema language provided");
Source[] schemaSources = new Source[resources.length]; Source[] schemaSources = new Source[resources.length];
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParserFactory saxParserFactory = this.schemaParserFactory;
if (saxParserFactory == null) {
saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true); saxParserFactory.setNamespaceAware(true);
saxParserFactory.setFeature("http://xml.org/sax/features/namespace-prefixes", true); saxParserFactory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
this.schemaParserFactory = saxParserFactory;
}
SAXParser saxParser = saxParserFactory.newSAXParser(); SAXParser saxParser = saxParserFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader(); XMLReader xmlReader = saxParser.getXMLReader();
for (int i = 0; i < resources.length; i++) { for (int i = 0; i < resources.length; i++) {
Resource resource = resources[i]; Resource resource = resources[i];
Assert.isTrue(resource != null && resource.exists(), () -> "Resource does not exist: " + resource); Assert.isTrue(resource != null && resource.exists(), () -> "Resource does not exist: " + resource);
InputSource inputSource = SaxResourceUtils.createInputSource(resource); InputSource inputSource = SaxResourceUtils.createInputSource(resource);
schemaSources[i] = new SAXSource(xmlReader, inputSource); schemaSources[i] = new SAXSource(xmlReader, inputSource);
} }
SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage); SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage);
if (this.schemaResourceResolver != null) { if (this.schemaResourceResolver != null) {
schemaFactory.setResourceResolver(this.schemaResourceResolver); schemaFactory.setResourceResolver(this.schemaResourceResolver);
@ -886,11 +908,16 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
try { try {
if (xmlReader == null) { if (xmlReader == null) {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParserFactory saxParserFactory = this.sourceParserFactory;
if (saxParserFactory == null) {
saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true); saxParserFactory.setNamespaceAware(true);
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd()); saxParserFactory.setFeature(
String name = "http://xml.org/sax/features/external-general-entities"; "http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
saxParserFactory.setFeature(name, isProcessExternalEntities()); saxParserFactory.setFeature(
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
this.sourceParserFactory = saxParserFactory;
}
SAXParser saxParser = saxParserFactory.newSAXParser(); SAXParser saxParser = saxParserFactory.newSAXParser();
xmlReader = saxParser.getXMLReader(); xmlReader = saxParser.getXMLReader();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -83,9 +83,10 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
private boolean processExternalEntities = false; private boolean processExternalEntities = false;
@Nullable @Nullable
private DocumentBuilderFactory documentBuilderFactory; private volatile DocumentBuilderFactory documentBuilderFactory;
private final Object documentBuilderFactoryMonitor = new Object(); @Nullable
private volatile SAXParserFactory saxParserFactory;
/** /**
@ -94,6 +95,8 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
*/ */
public void setSupportDtd(boolean supportDtd) { public void setSupportDtd(boolean supportDtd) {
this.supportDtd = supportDtd; this.supportDtd = supportDtd;
this.documentBuilderFactory = null;
this.saxParserFactory = null;
} }
/** /**
@ -118,6 +121,8 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
if (processExternalEntities) { if (processExternalEntities) {
this.supportDtd = true; this.supportDtd = true;
} }
this.documentBuilderFactory = null;
this.saxParserFactory = null;
} }
/** /**
@ -137,14 +142,13 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
*/ */
protected Document buildDocument() { protected Document buildDocument() {
try { try {
DocumentBuilder documentBuilder; DocumentBuilderFactory builderFactory = this.documentBuilderFactory;
synchronized (this.documentBuilderFactoryMonitor) { if (builderFactory == null) {
if (this.documentBuilderFactory == null) { builderFactory = createDocumentBuilderFactory();
this.documentBuilderFactory = createDocumentBuilderFactory(); this.documentBuilderFactory = builderFactory;
} }
documentBuilder = createDocumentBuilder(this.documentBuilderFactory); DocumentBuilder builder = createDocumentBuilder(builderFactory);
} return builder.newDocument();
return documentBuilder.newDocument();
} }
catch (ParserConfigurationException ex) { catch (ParserConfigurationException ex) {
throw new UnmarshallingFailureException("Could not create document placeholder: " + ex.getMessage(), ex); throw new UnmarshallingFailureException("Could not create document placeholder: " + ex.getMessage(), ex);
@ -179,11 +183,11 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory) protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory)
throws ParserConfigurationException { throws ParserConfigurationException {
DocumentBuilder documentBuilder = factory.newDocumentBuilder(); DocumentBuilder builder = factory.newDocumentBuilder();
if (!isProcessExternalEntities()) { if (!isProcessExternalEntities()) {
documentBuilder.setEntityResolver(NO_OP_ENTITY_RESOLVER); builder.setEntityResolver(NO_OP_ENTITY_RESOLVER);
} }
return documentBuilder; return builder;
} }
/** /**
@ -193,11 +197,17 @@ public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
* @throws ParserConfigurationException if thrown by JAXP methods * @throws ParserConfigurationException if thrown by JAXP methods
*/ */
protected XMLReader createXmlReader() throws SAXException, ParserConfigurationException { protected XMLReader createXmlReader() throws SAXException, ParserConfigurationException {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParserFactory parserFactory = this.saxParserFactory;
saxParserFactory.setNamespaceAware(true); if (parserFactory == null) {
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd()); parserFactory = SAXParserFactory.newInstance();
saxParserFactory.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities()); parserFactory.setNamespaceAware(true);
SAXParser saxParser = saxParserFactory.newSAXParser(); parserFactory.setFeature(
"http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
parserFactory.setFeature(
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
this.saxParserFactory = parserFactory;
}
SAXParser saxParser = parserFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader(); XMLReader xmlReader = saxParser.getXMLReader();
if (!isProcessExternalEntities()) { if (!isProcessExternalEntities()) {
xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER); xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -61,6 +61,7 @@ import org.springframework.util.ClassUtils;
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 3.0 * @since 3.0
* @see MarshallingHttpMessageConverter * @see MarshallingHttpMessageConverter
*/ */
@ -70,6 +71,9 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
private boolean processExternalEntities = false; private boolean processExternalEntities = false;
@Nullable
private volatile SAXParserFactory sourceParserFactory;
/** /**
* Indicate whether DTD parsing should be supported. * Indicate whether DTD parsing should be supported.
@ -77,6 +81,7 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
*/ */
public void setSupportDtd(boolean supportDtd) { public void setSupportDtd(boolean supportDtd) {
this.supportDtd = supportDtd; this.supportDtd = supportDtd;
this.sourceParserFactory = null;
} }
/** /**
@ -97,6 +102,7 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
if (processExternalEntities) { if (processExternalEntities) {
this.supportDtd = true; this.supportDtd = true;
} }
this.sourceParserFactory = null;
} }
/** /**
@ -156,11 +162,16 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
if (source instanceof StreamSource streamSource) { if (source instanceof StreamSource streamSource) {
InputSource inputSource = new InputSource(streamSource.getInputStream()); InputSource inputSource = new InputSource(streamSource.getInputStream());
try { try {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParserFactory saxParserFactory = this.sourceParserFactory;
if (saxParserFactory == null) {
saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setNamespaceAware(true); saxParserFactory.setNamespaceAware(true);
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd()); saxParserFactory.setFeature(
String featureName = "http://xml.org/sax/features/external-general-entities"; "http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
saxParserFactory.setFeature(featureName, isProcessExternalEntities()); saxParserFactory.setFeature(
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
this.sourceParserFactory = saxParserFactory;
}
SAXParser saxParser = saxParserFactory.newSAXParser(); SAXParser saxParser = saxParserFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader(); XMLReader xmlReader = saxParser.getXMLReader();
if (!isProcessExternalEntities()) { if (!isProcessExternalEntities()) {

View File

@ -63,6 +63,7 @@ import org.springframework.util.StreamUtils;
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 3.0 * @since 3.0
* @param <T> the converted object type * @param <T> the converted object type
*/ */
@ -75,11 +76,7 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
(publicID, systemID, base, ns) -> InputStream.nullInputStream(); (publicID, systemID, base, ns) -> InputStream.nullInputStream();
private static final Set<Class<?>> SUPPORTED_CLASSES = Set.of( private static final Set<Class<?>> SUPPORTED_CLASSES = Set.of(
DOMSource.class, DOMSource.class, SAXSource.class, StAXSource.class, StreamSource.class, Source.class);
SAXSource.class,
StAXSource.class,
StreamSource.class,
Source.class);
private final TransformerFactory transformerFactory = TransformerFactory.newInstance(); private final TransformerFactory transformerFactory = TransformerFactory.newInstance();
@ -88,6 +85,15 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
private boolean processExternalEntities = false; private boolean processExternalEntities = false;
@Nullable
private volatile DocumentBuilderFactory documentBuilderFactory;
@Nullable
private volatile SAXParserFactory saxParserFactory;
@Nullable
private volatile XMLInputFactory xmlInputFactory;
/** /**
* Sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes} * Sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes}
@ -104,6 +110,9 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
*/ */
public void setSupportDtd(boolean supportDtd) { public void setSupportDtd(boolean supportDtd) {
this.supportDtd = supportDtd; this.supportDtd = supportDtd;
this.documentBuilderFactory = null;
this.saxParserFactory = null;
this.xmlInputFactory = null;
} }
/** /**
@ -124,6 +133,9 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
if (processExternalEntities) { if (processExternalEntities) {
this.supportDtd = true; this.supportDtd = true;
} }
this.documentBuilderFactory = null;
this.saxParserFactory = null;
this.xmlInputFactory = null;
} }
/** /**
@ -165,17 +177,21 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
private DOMSource readDOMSource(InputStream body, HttpInputMessage inputMessage) throws IOException { private DOMSource readDOMSource(InputStream body, HttpInputMessage inputMessage) throws IOException {
try { try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory builderFactory = this.documentBuilderFactory;
documentBuilderFactory.setNamespaceAware(true); if (builderFactory == null) {
documentBuilderFactory.setFeature( builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setNamespaceAware(true);
builderFactory.setFeature(
"http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd()); "http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
documentBuilderFactory.setFeature( builderFactory.setFeature(
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities()); "http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); this.documentBuilderFactory = builderFactory;
if (!isProcessExternalEntities()) {
documentBuilder.setEntityResolver(NO_OP_ENTITY_RESOLVER);
} }
Document document = documentBuilder.parse(body); DocumentBuilder builder = builderFactory.newDocumentBuilder();
if (!isProcessExternalEntities()) {
builder.setEntityResolver(NO_OP_ENTITY_RESOLVER);
}
Document document = builder.parse(body);
return new DOMSource(document); return new DOMSource(document);
} }
catch (NullPointerException ex) { catch (NullPointerException ex) {
@ -197,11 +213,17 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
private SAXSource readSAXSource(InputStream body, HttpInputMessage inputMessage) throws IOException { private SAXSource readSAXSource(InputStream body, HttpInputMessage inputMessage) throws IOException {
try { try {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); SAXParserFactory parserFactory = this.saxParserFactory;
saxParserFactory.setNamespaceAware(true); if (parserFactory == null) {
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd()); parserFactory = SAXParserFactory.newInstance();
saxParserFactory.setFeature("http://xml.org/sax/features/external-general-entities", isProcessExternalEntities()); parserFactory.setNamespaceAware(true);
SAXParser saxParser = saxParserFactory.newSAXParser(); parserFactory.setFeature(
"http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
parserFactory.setFeature(
"http://xml.org/sax/features/external-general-entities", isProcessExternalEntities());
this.saxParserFactory = parserFactory;
}
SAXParser saxParser = parserFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader(); XMLReader xmlReader = saxParser.getXMLReader();
if (!isProcessExternalEntities()) { if (!isProcessExternalEntities()) {
xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER); xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
@ -217,12 +239,16 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
private Source readStAXSource(InputStream body, HttpInputMessage inputMessage) { private Source readStAXSource(InputStream body, HttpInputMessage inputMessage) {
try { try {
XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLInputFactory inputFactory = this.xmlInputFactory;
if (inputFactory == null) {
inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, isSupportDtd()); inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, isSupportDtd());
inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, isProcessExternalEntities()); inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, isProcessExternalEntities());
if (!isProcessExternalEntities()) { if (!isProcessExternalEntities()) {
inputFactory.setXMLResolver(NO_OP_XML_RESOLVER); inputFactory.setXMLResolver(NO_OP_XML_RESOLVER);
} }
this.xmlInputFactory = inputFactory;
}
XMLStreamReader streamReader = inputFactory.createXMLStreamReader(body); XMLStreamReader streamReader = inputFactory.createXMLStreamReader(body);
return new StAXSource(streamReader); return new StAXSource(streamReader);
} }