@ -1,5 +1,5 @@
@@ -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" ) ;
* you may not use this file except in compliance with the License .
@ -63,6 +63,7 @@ import org.springframework.util.StreamUtils;
@@ -63,6 +63,7 @@ import org.springframework.util.StreamUtils;
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 3 . 0
* @param < T > the converted object type
* /
@ -75,11 +76,7 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
@@ -75,11 +76,7 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
( publicID , systemID , base , ns ) - > InputStream . nullInputStream ( ) ;
private static final Set < Class < ? > > SUPPORTED_CLASSES = Set . of (
DOMSource . class ,
SAXSource . class ,
StAXSource . class ,
StreamSource . class ,
Source . class ) ;
DOMSource . class , SAXSource . class , StAXSource . class , StreamSource . class , Source . class ) ;
private final TransformerFactory transformerFactory = TransformerFactory . newInstance ( ) ;
@ -88,10 +85,19 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
@@ -88,10 +85,19 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
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 }
* to { @code text / xml } and { @code application / xml } , and { @code application / * - xml } .
* to { @code text / xml } and { @code application / xml } , and { @code application / * + xml } .
* /
public SourceHttpMessageConverter ( ) {
super ( MediaType . APPLICATION_XML , MediaType . TEXT_XML , new MediaType ( "application" , "*+xml" ) ) ;
@ -104,6 +110,9 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
@@ -104,6 +110,9 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
* /
public void setSupportDtd ( boolean 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
@@ -124,6 +133,9 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
if ( processExternalEntities ) {
this . supportDtd = true ;
}
this . documentBuilderFactory = null ;
this . saxParserFactory = null ;
this . xmlInputFactory = null ;
}
/ * *
@ -165,17 +177,21 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
@@ -165,17 +177,21 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
private DOMSource readDOMSource ( InputStream body , HttpInputMessage inputMessage ) throws IOException {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory . newInstance ( ) ;
documentBuilderFactory . setNamespaceAware ( true ) ;
documentBuilderFactory . setFeature (
"http://apache.org/xml/features/disallow-doctype-decl" , ! isSupportDtd ( ) ) ;
documentBuilderFactory . setFeature (
"http://xml.org/sax/features/external-general-entities" , isProcessExternalEntities ( ) ) ;
DocumentBuilder documentBuilder = documentBuilderFactory . newDocumentBuilder ( ) ;
DocumentBuilderFactory builderFactory = this . documentBuilderFactory ;
if ( builderFactory = = null ) {
builderFactory = DocumentBuilderFactory . newInstance ( ) ;
builderFactory . setNamespaceAware ( true ) ;
builderFactory . setFeature (
"http://apache.org/xml/features/disallow-doctype-decl" , ! isSupportDtd ( ) ) ;
builderFactory . setFeature (
"http://xml.org/sax/features/external-general-entities" , isProcessExternalEntities ( ) ) ;
this . documentBuilderFactory = builderFactory ;
}
DocumentBuilder builder = builderFactory . newDocumentBuilder ( ) ;
if ( ! isProcessExternalEntities ( ) ) {
documentBuilder . setEntityResolver ( NO_OP_ENTITY_RESOLVER ) ;
b uilder. setEntityResolver ( NO_OP_ENTITY_RESOLVER ) ;
}
Document document = documentBuilder . parse ( body ) ;
Document document = b uilder. parse ( body ) ;
return new DOMSource ( document ) ;
}
catch ( NullPointerException ex ) {
@ -197,11 +213,17 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
@@ -197,11 +213,17 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
private SAXSource readSAXSource ( InputStream body , HttpInputMessage inputMessage ) throws IOException {
try {
SAXParserFactory saxParserFactory = SAXParserFactory . newInstance ( ) ;
saxParserFactory . setNamespaceAware ( true ) ;
saxParserFactory . setFeature ( "http://apache.org/xml/features/disallow-doctype-decl" , ! isSupportDtd ( ) ) ;
saxParserFactory . setFeature ( "http://xml.org/sax/features/external-general-entities" , isProcessExternalEntities ( ) ) ;
SAXParser saxParser = saxParserFactory . newSAXParser ( ) ;
SAXParserFactory parserFactory = this . saxParserFactory ;
if ( parserFactory = = null ) {
parserFactory = SAXParserFactory . newInstance ( ) ;
parserFactory . setNamespaceAware ( true ) ;
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 ( ) ;
if ( ! isProcessExternalEntities ( ) ) {
xmlReader . setEntityResolver ( NO_OP_ENTITY_RESOLVER ) ;
@ -217,11 +239,15 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
@@ -217,11 +239,15 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
private Source readStAXSource ( InputStream body , HttpInputMessage inputMessage ) {
try {
XMLInputFactory inputFactory = XMLInputFactory . newInstance ( ) ;
inputFactory . setProperty ( XMLInputFactory . SUPPORT_DTD , isSupportDtd ( ) ) ;
inputFactory . setProperty ( XMLInputFactory . IS_SUPPORTING_EXTERNAL_ENTITIES , isProcessExternalEntities ( ) ) ;
if ( ! isProcessExternalEntities ( ) ) {
inputFactory . setXMLResolver ( NO_OP_XML_RESOLVER ) ;
XMLInputFactory inputFactory = this . xmlInputFactory ;
if ( inputFactory = = null ) {
inputFactory = XMLInputFactory . newInstance ( ) ;
inputFactory . setProperty ( XMLInputFactory . SUPPORT_DTD , isSupportDtd ( ) ) ;
inputFactory . setProperty ( XMLInputFactory . IS_SUPPORTING_EXTERNAL_ENTITIES , isProcessExternalEntities ( ) ) ;
if ( ! isProcessExternalEntities ( ) ) {
inputFactory . setXMLResolver ( NO_OP_XML_RESOLVER ) ;
}
this . xmlInputFactory = inputFactory ;
}
XMLStreamReader streamReader = inputFactory . createXMLStreamReader ( body ) ;
return new StAXSource ( streamReader ) ;