17
17
package org .springframework .http .converter .xml ;
18
18
19
19
import java .io .ByteArrayInputStream ;
20
- import java .io .ByteArrayOutputStream ;
21
20
import java .io .IOException ;
22
21
import java .io .InputStream ;
23
22
import java .io .OutputStream ;
23
+ import java .util .HashSet ;
24
+ import java .util .Set ;
24
25
import javax .xml .parsers .DocumentBuilder ;
25
26
import javax .xml .parsers .DocumentBuilderFactory ;
26
27
import javax .xml .parsers .ParserConfigurationException ;
27
- import javax .xml .stream .XMLInputFactory ;
28
- import javax .xml .stream .XMLStreamException ;
29
- import javax .xml .stream .XMLStreamReader ;
30
28
import javax .xml .transform .Result ;
31
29
import javax .xml .transform .Source ;
32
30
import javax .xml .transform .TransformerException ;
33
31
import javax .xml .transform .TransformerFactory ;
34
- import javax .xml .transform .dom .DOMResult ;
35
32
import javax .xml .transform .dom .DOMSource ;
36
33
import javax .xml .transform .sax .SAXSource ;
37
34
import javax .xml .transform .stream .StreamResult ;
43
40
import org .xml .sax .XMLReader ;
44
41
import org .xml .sax .helpers .XMLReaderFactory ;
45
42
46
- import org .springframework .http .HttpHeaders ;
47
43
import org .springframework .http .HttpInputMessage ;
48
44
import org .springframework .http .HttpOutputMessage ;
49
45
import org .springframework .http .MediaType ;
52
48
import org .springframework .http .converter .HttpMessageNotReadableException ;
53
49
import org .springframework .http .converter .HttpMessageNotWritableException ;
54
50
import org .springframework .util .StreamUtils ;
55
- import org .springframework .util .xml .StaxUtils ;
56
51
57
52
/**
58
53
* Implementation of {@link org.springframework.http.converter.HttpMessageConverter}
63
58
*/
64
59
public class SourceHttpMessageConverter <T extends Source > extends AbstractHttpMessageConverter <T > {
65
60
66
- private final TransformerFactory transformerFactory = TransformerFactory . newInstance ( );
61
+ private static final Set < Class <?>> SUPPORTED_CLASSES = new HashSet < Class <?>>( 4 );
67
62
68
- private boolean processExternalEntities = false ;
63
+ static {
64
+ SUPPORTED_CLASSES .add (DOMSource .class );
65
+ SUPPORTED_CLASSES .add (SAXSource .class );
66
+ SUPPORTED_CLASSES .add (StreamSource .class );
67
+ SUPPORTED_CLASSES .add (Source .class );
68
+ }
69
+
70
+
71
+ private final TransformerFactory transformerFactory = TransformerFactory .newInstance ();
72
+
73
+ private boolean processExternalEntities = false ;
69
74
70
- /**
71
- * Sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes}
72
- * to {@code text/xml} and {@code application/xml}, and {@code application/*-xml}.
73
- */
74
- public SourceHttpMessageConverter () {
75
- super (MediaType .APPLICATION_XML , MediaType .TEXT_XML , new MediaType ("application" , "*+xml" ));
76
- }
77
75
76
+ /**
77
+ * Sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes}
78
+ * to {@code text/xml} and {@code application/xml}, and {@code application/*-xml}.
79
+ */
80
+ public SourceHttpMessageConverter () {
81
+ super (MediaType .APPLICATION_XML , MediaType .TEXT_XML , new MediaType ("application" , "*+xml" ));
82
+ }
83
+
84
+
85
+ /**
86
+ * Indicates whether external XML entities are processed when converting to a Source.
87
+ * <p>Default is {@code false}, meaning that external entities are not resolved.
88
+ */
89
+ public void setProcessExternalEntities (boolean processExternalEntities ) {
90
+ this .processExternalEntities = processExternalEntities ;
91
+ }
78
92
79
- /**
80
- * Indicates whether external XML entities are processed when converting
81
- * to a Source.
82
- * <p>Default is {@code false}, meaning that external entities are not resolved.
83
- */
84
- public void setProcessExternalEntities (boolean processExternalEntities ) {
85
- this .processExternalEntities = processExternalEntities ;
86
- }
87
93
88
- @ Override
94
+ @ Override
89
95
public boolean supports (Class <?> clazz ) {
90
- return DOMSource .class .equals (clazz ) || SAXSource .class .equals (clazz )
91
- || StreamSource .class .equals (clazz ) || Source .class .equals (clazz );
96
+ return SUPPORTED_CLASSES .contains (clazz );
92
97
}
93
98
94
- @ Override
95
- protected T readInternal (Class <? extends T > clazz , HttpInputMessage inputMessage )
96
- throws IOException , HttpMessageNotReadableException {
97
-
98
- InputStream body = inputMessage .getBody ();
99
- if (DOMSource .class .equals (clazz )) {
100
- return (T ) readDOMSource (body );
101
- }
102
- else if (StaxUtils .isStaxSourceClass (clazz )) {
103
- return (T ) readStAXSource (body );
104
- }
105
- else if (SAXSource .class .equals (clazz )) {
106
- return (T ) readSAXSource (body );
107
- }
108
- else if (StreamSource .class .equals (clazz ) || Source .class .equals (clazz )) {
109
- return (T ) readStreamSource (body );
110
- }
111
- else {
112
- throw new HttpMessageConversionException ("Could not read class [" + clazz +
113
- "]. Only DOMSource, SAXSource, and StreamSource are supported." );
114
- }
115
- }
116
-
117
- private DOMSource readDOMSource (InputStream body ) throws IOException {
118
- try {
119
- DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory .newInstance ();
120
- documentBuilderFactory .setNamespaceAware (true );
121
- documentBuilderFactory .setFeature ("http://xml.org/sax/features/external-general-entities" , processExternalEntities );
122
- DocumentBuilder documentBuilder = documentBuilderFactory .newDocumentBuilder ();
123
- Document document = documentBuilder .parse (body );
124
- return new DOMSource (document );
125
- }
126
- catch (ParserConfigurationException ex ) {
127
- throw new HttpMessageNotReadableException ("Could not set feature: " + ex .getMessage (), ex );
128
- }
129
- catch (SAXException ex ) {
130
- throw new HttpMessageNotReadableException ("Could not parse document: " + ex .getMessage (), ex );
131
- }
132
- }
133
-
134
- private SAXSource readSAXSource (InputStream body ) throws IOException {
135
- try {
136
- XMLReader reader = XMLReaderFactory .createXMLReader ();
137
- reader .setFeature ("http://xml.org/sax/features/external-general-entities" , processExternalEntities );
138
- byte [] bytes = StreamUtils .copyToByteArray (body );
139
- return new SAXSource (reader , new InputSource (new ByteArrayInputStream (bytes )));
140
- }
141
- catch (SAXException ex ) {
142
- throw new HttpMessageNotReadableException ("Could not parse document: " + ex .getMessage (), ex );
143
- }
144
- }
145
-
146
- private Source readStAXSource (InputStream body ) {
147
- try {
148
- XMLInputFactory inputFactory = XMLInputFactory .newFactory ();
149
- inputFactory .setProperty ("javax.xml.stream.isSupportingExternalEntities" , processExternalEntities );
150
- XMLStreamReader streamReader = inputFactory .createXMLStreamReader (body );
151
- return StaxUtils .createStaxSource (streamReader );
152
- }
153
- catch (XMLStreamException ex ) {
154
- throw new HttpMessageNotReadableException ("Could not parse document: " + ex .getMessage (), ex );
155
- }
156
- }
157
-
158
- private StreamSource readStreamSource (InputStream body ) throws IOException {
159
- byte [] bytes = StreamUtils .copyToByteArray (body );
160
- return new StreamSource (new ByteArrayInputStream (bytes ));
161
- }
99
+ @ Override
100
+ @ SuppressWarnings ("unchecked" )
101
+ protected T readInternal (Class <? extends T > clazz , HttpInputMessage inputMessage )
102
+ throws IOException , HttpMessageNotReadableException {
103
+
104
+ InputStream body = inputMessage .getBody ();
105
+ if (DOMSource .class .equals (clazz )) {
106
+ return (T ) readDOMSource (body );
107
+ }
108
+ else if (SAXSource .class .equals (clazz )) {
109
+ return (T ) readSAXSource (body );
110
+ }
111
+ else if (StreamSource .class .equals (clazz ) || Source .class .equals (clazz )) {
112
+ return (T ) readStreamSource (body );
113
+ }
114
+ else {
115
+ throw new HttpMessageConversionException ("Could not read class [" + clazz +
116
+ "]. Only DOMSource, SAXSource, and StreamSource are supported." );
117
+ }
118
+ }
119
+
120
+ private DOMSource readDOMSource (InputStream body ) throws IOException {
121
+ try {
122
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory .newInstance ();
123
+ documentBuilderFactory .setNamespaceAware (true );
124
+ documentBuilderFactory .setFeature (
125
+ "http://xml.org/sax/features/external-general-entities" , this .processExternalEntities );
126
+ DocumentBuilder documentBuilder = documentBuilderFactory .newDocumentBuilder ();
127
+ Document document = documentBuilder .parse (body );
128
+ return new DOMSource (document );
129
+ }
130
+ catch (ParserConfigurationException ex ) {
131
+ throw new HttpMessageNotReadableException ("Could not set feature: " + ex .getMessage (), ex );
132
+ }
133
+ catch (SAXException ex ) {
134
+ throw new HttpMessageNotReadableException ("Could not parse document: " + ex .getMessage (), ex );
135
+ }
136
+ }
137
+
138
+ private SAXSource readSAXSource (InputStream body ) throws IOException {
139
+ try {
140
+ XMLReader reader = XMLReaderFactory .createXMLReader ();
141
+ reader .setFeature (
142
+ "http://xml.org/sax/features/external-general-entities" , this .processExternalEntities );
143
+ byte [] bytes = StreamUtils .copyToByteArray (body );
144
+ return new SAXSource (reader , new InputSource (new ByteArrayInputStream (bytes )));
145
+ }
146
+ catch (SAXException ex ) {
147
+ throw new HttpMessageNotReadableException ("Could not parse document: " + ex .getMessage (), ex );
148
+ }
149
+ }
150
+
151
+ private StreamSource readStreamSource (InputStream body ) throws IOException {
152
+ byte [] bytes = StreamUtils .copyToByteArray (body );
153
+ return new StreamSource (new ByteArrayInputStream (bytes ));
154
+ }
162
155
163
156
@ Override
164
157
protected Long getContentLength (T t , MediaType contentType ) {
@@ -175,40 +168,40 @@ protected Long getContentLength(T t, MediaType contentType) {
175
168
return null ;
176
169
}
177
170
178
- @ Override
179
- protected void writeInternal (T t , HttpOutputMessage outputMessage )
180
- throws IOException , HttpMessageNotWritableException {
171
+ @ Override
172
+ protected void writeInternal (T t , HttpOutputMessage outputMessage )
173
+ throws IOException , HttpMessageNotWritableException {
181
174
try {
182
- Result result = new StreamResult (outputMessage .getBody ());
175
+ Result result = new StreamResult (outputMessage .getBody ());
183
176
transform (t , result );
184
177
}
185
178
catch (TransformerException ex ) {
186
179
throw new HttpMessageNotWritableException ("Could not transform [" + t + "] to output message" , ex );
187
180
}
188
181
}
189
182
190
- private void transform (Source source , Result result ) throws TransformerException {
191
- this .transformerFactory .newTransformer ().transform (source , result );
192
- }
183
+ private void transform (Source source , Result result ) throws TransformerException {
184
+ this .transformerFactory .newTransformer ().transform (source , result );
185
+ }
193
186
194
187
195
- private static class CountingOutputStream extends OutputStream {
188
+ private static class CountingOutputStream extends OutputStream {
196
189
197
- private long count = 0 ;
190
+ long count = 0 ;
198
191
199
192
@ Override
200
193
public void write (int b ) throws IOException {
201
- count ++;
194
+ this . count ++;
202
195
}
203
196
204
197
@ Override
205
198
public void write (byte [] b ) throws IOException {
206
- count += b .length ;
199
+ this . count += b .length ;
207
200
}
208
201
209
202
@ Override
210
203
public void write (byte [] b , int off , int len ) throws IOException {
211
- count += len ;
204
+ this . count += len ;
212
205
}
213
206
}
214
207
0 commit comments