Skip to content

Commit 6cdff3e

Browse files
committed
SWS-706 - Jaxp13XPathTemplate should support StreamSources with only a systemId if it's a valid URL
1 parent 95ac668 commit 6cdff3e

File tree

7 files changed

+214
-53
lines changed

7 files changed

+214
-53
lines changed

core/src/main/java/org/springframework/ws/server/endpoint/AbstractXomPayloadEndpoint.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,17 @@ public void streamSource(Reader reader) throws IOException {
187187
throw new XomParsingException(ex);
188188
}
189189
}
190+
191+
public void source(String systemId) throws Exception {
192+
try {
193+
Builder builder = new Builder();
194+
Document document = builder.build(systemId);
195+
element = document.getRootElement();
196+
}
197+
catch (ParsingException ex) {
198+
throw new XomParsingException(ex);
199+
}
200+
}
190201
}
191202

192203
private static class XomParsingException extends NestedRuntimeException {

core/src/main/java/org/springframework/ws/server/endpoint/adapter/method/jaxb/AbstractJaxb2PayloadMethodProcessor.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.io.OutputStream;
2222
import java.io.Reader;
2323
import java.io.Writer;
24+
import java.net.URL;
2425
import java.util.concurrent.ConcurrentHashMap;
2526
import java.util.concurrent.ConcurrentMap;
2627
import javax.xml.bind.JAXBContext;
@@ -38,6 +39,7 @@
3839
import javax.xml.transform.Result;
3940
import javax.xml.transform.Source;
4041
import javax.xml.transform.sax.SAXSource;
42+
import javax.xml.transform.stream.StreamResult;
4143
import javax.xml.transform.stream.StreamSource;
4244

4345
import org.springframework.util.Assert;
@@ -227,6 +229,10 @@ public void streamSource(InputStream inputStream) throws IOException, JAXBExcept
227229
public void streamSource(Reader reader) throws IOException, JAXBException {
228230
result = unmarshaller.unmarshal(reader);
229231
}
232+
233+
public void source(String systemId) throws Exception {
234+
result = unmarshaller.unmarshal(new URL(systemId));
235+
}
230236
}
231237

232238
private class JaxbElementSourceCallback<T> implements TraxUtils.SourceCallback {
@@ -265,6 +271,10 @@ public void streamSource(InputStream inputStream) throws IOException, JAXBExcept
265271
public void streamSource(Reader reader) throws IOException, JAXBException {
266272
result = unmarshaller.unmarshal(new StreamSource(reader), declaredType);
267273
}
274+
275+
public void source(String systemId) throws Exception {
276+
result = unmarshaller.unmarshal(new StreamSource(systemId), declaredType);
277+
}
268278
}
269279

270280
private class Jaxb2ResultCallback implements TraxUtils.ResultCallback {
@@ -301,6 +311,10 @@ public void streamResult(OutputStream outputStream) throws JAXBException {
301311
public void streamResult(Writer writer) throws JAXBException {
302312
marshaller.marshal(jaxbElement, writer);
303313
}
314+
315+
public void result(String systemId) throws Exception {
316+
marshaller.marshal(jaxbElement, new StreamResult(systemId));
317+
}
304318
}
305319

306320
private class JaxbStreamingPayload implements StreamingPayload {

core/src/main/java/org/springframework/ws/server/endpoint/support/PayloadRootUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ public void streamSource(InputStream inputStream) throws Exception {
143143
public void streamSource(Reader reader) throws Exception {
144144
// Do nothing
145145
}
146+
147+
public void source(String systemId) throws Exception {
148+
// Do nothing
149+
}
146150
}
147151

148152

xml/src/main/java/org/springframework/xml/transform/TraxUtils.java

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import javax.xml.transform.stream.StreamResult;
3737
import javax.xml.transform.stream.StreamSource;
3838

39+
import org.springframework.util.StringUtils;
3940
import org.springframework.util.xml.StaxUtils;
4041

4142
import org.w3c.dom.Document;
@@ -207,86 +208,92 @@ else if (node != null) {
207208
public static void doWithSource(Source source, SourceCallback callback) throws Exception {
208209
if (source instanceof DOMSource) {
209210
callback.domSource(((DOMSource) source).getNode());
211+
return;
210212
}
211213
else if (isStaxSource(source)) {
212214
XMLStreamReader streamReader = getXMLStreamReader(source);
213215
if (streamReader != null) {
214216
callback.staxSource(streamReader);
217+
return;
215218
}
216219
else {
217220
XMLEventReader eventReader = getXMLEventReader(source);
218221
if (eventReader != null) {
219222
callback.staxSource(eventReader);
220-
}
221-
else {
222-
throw new IllegalArgumentException(
223-
"StAX source contains neither XMLStreamReader nor XMLEventReader");
223+
return;
224224
}
225225
}
226226
}
227227
else if (source instanceof SAXSource) {
228228
SAXSource saxSource = (SAXSource) source;
229229
callback.saxSource(saxSource.getXMLReader(), saxSource.getInputSource());
230+
return;
230231
}
231232
else if (source instanceof StreamSource) {
232233
StreamSource streamSource = (StreamSource) source;
233234
if (streamSource.getInputStream() != null) {
234235
callback.streamSource(streamSource.getInputStream());
236+
return;
235237
}
236238
else if (streamSource.getReader() != null) {
237239
callback.streamSource(streamSource.getReader());
238-
}
239-
else {
240-
throw new IllegalArgumentException("StreamSource contains neither InputStream nor Reader");
240+
return;
241241
}
242242
}
243+
if (StringUtils.hasLength(source.getSystemId())) {
244+
String systemId = source.getSystemId();
245+
callback.source(systemId);
246+
}
243247
else {
244248
throw new IllegalArgumentException("Unknown Source type: " + source.getClass());
245249
}
246250
}
247251

248252
/**
249-
* Performs the given {@linkplain ResultCallback callback} operation on a {@link Result}. Supports both the JAXP 1.4
250-
* {@link StAXResult} and the Spring 3.0 {@link StaxUtils#createStaxResult StaxSource}.
253+
* Performs the given {@linkplain org.springframework.xml.transform.TraxUtils.ResultCallback callback} operation on a {@link javax.xml.transform.Result}. Supports both the JAXP 1.4
254+
* {@link javax.xml.transform.stax.StAXResult} and the Spring 3.0 {@link org.springframework.util.xml.StaxUtils#createStaxResult StaxSource}.
251255
*
252256
* @param result result to look at
253257
* @param callback the callback to invoke for each kind of result
254258
*/
255259
public static void doWithResult(Result result, ResultCallback callback) throws Exception{
256260
if (result instanceof DOMResult) {
257261
callback.domResult(((DOMResult) result).getNode());
262+
return;
258263
}
259264
else if (isStaxResult(result)) {
260265
XMLStreamWriter streamWriter = getXMLStreamWriter(result);
261266
if (streamWriter != null) {
262267
callback.staxResult(streamWriter);
268+
return;
263269
}
264270
else {
265271
XMLEventWriter eventWriter = getXMLEventWriter(result);
266272
if (eventWriter != null) {
267273
callback.staxResult(eventWriter);
268-
}
269-
else {
270-
throw new IllegalArgumentException(
271-
"StAX result contains neither XMLStreamWriter nor XMLEventWriter");
274+
return;
272275
}
273276
}
274277
}
275278
else if (result instanceof SAXResult) {
276279
SAXResult saxSource = (SAXResult) result;
277280
callback.saxResult(saxSource.getHandler(), saxSource.getLexicalHandler());
281+
return;
278282
}
279283
else if (result instanceof StreamResult) {
280284
StreamResult streamSource = (StreamResult) result;
281285
if (streamSource.getOutputStream() != null) {
282286
callback.streamResult(streamSource.getOutputStream());
287+
return;
283288
}
284289
else if (streamSource.getWriter() != null) {
285290
callback.streamResult(streamSource.getWriter());
291+
return;
286292
}
287-
else {
288-
throw new IllegalArgumentException("StreamResult contains neither OutputStream nor Writer");
289-
}
293+
}
294+
if (StringUtils.hasLength(result.getSystemId())) {
295+
String systemId = result.getSystemId();
296+
callback.result(systemId);
290297
}
291298
else {
292299
throw new IllegalArgumentException("Unknown Result type: " + result.getClass());
@@ -344,6 +351,15 @@ public interface SourceCallback {
344351
* @param reader the reader
345352
*/
346353
void streamSource(Reader reader) throws Exception;
354+
355+
/**
356+
* Perform an operation on the system identifier contained in any {@link Source}.
357+
*
358+
* @param systemId the system identifier
359+
*/
360+
void source(String systemId) throws Exception;
361+
362+
347363
}
348364

349365
/**
@@ -398,6 +414,14 @@ public interface ResultCallback {
398414
* @param writer the writer
399415
*/
400416
void streamResult(Writer writer) throws Exception;
417+
418+
/**
419+
* Perform an operation on the system identifier contained in any {@link Result}.
420+
*
421+
* @param systemId the system identifier
422+
*/
423+
void result(String systemId) throws Exception;
424+
401425
}
402426

403427

xml/src/main/java/org/springframework/xml/xpath/Jaxp13XPathTemplate.java

Lines changed: 82 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,40 @@
1616

1717
package org.springframework.xml.xpath;
1818

19+
import java.io.InputStream;
20+
import java.io.Reader;
1921
import java.util.ArrayList;
2022
import java.util.List;
2123
import javax.xml.namespace.QName;
24+
import javax.xml.stream.XMLEventReader;
25+
import javax.xml.stream.XMLStreamException;
26+
import javax.xml.stream.XMLStreamReader;
2227
import javax.xml.transform.Source;
2328
import javax.xml.transform.TransformerException;
24-
import javax.xml.transform.dom.DOMSource;
25-
import javax.xml.transform.sax.SAXSource;
26-
import javax.xml.transform.stream.StreamSource;
29+
import javax.xml.transform.dom.DOMResult;
2730
import javax.xml.xpath.XPath;
2831
import javax.xml.xpath.XPathConstants;
32+
import javax.xml.xpath.XPathExpressionException;
2933
import javax.xml.xpath.XPathFactory;
3034
import javax.xml.xpath.XPathFactoryConfigurationException;
3135

32-
import org.springframework.util.xml.StaxUtils;
3336
import org.springframework.xml.namespace.SimpleNamespaceContext;
37+
import org.springframework.xml.transform.StaxSource;
38+
import org.springframework.xml.transform.TransformerHelper;
39+
import org.springframework.xml.transform.TraxUtils;
3440

3541
import org.w3c.dom.DOMException;
42+
import org.w3c.dom.Document;
3643
import org.w3c.dom.Element;
3744
import org.w3c.dom.Node;
3845
import org.w3c.dom.NodeList;
3946
import org.xml.sax.InputSource;
47+
import org.xml.sax.XMLReader;
4048

4149
/**
4250
* Implementation of {@link XPathOperations} that uses JAXP 1.3. JAXP 1.3 is part of Java SE since 1.5.
4351
* <p/>
44-
* Namespaces can be set using the <code>namespaces</code> property.
52+
* Namespaces can be set using the {@code namespaces} property.
4553
*
4654
* @author Arjen Poutsma
4755
* @see #setNamespaces(java.util.Map)
@@ -128,47 +136,87 @@ private Object evaluate(String expression, Source context, QName returnType) thr
128136
xpath.setNamespaceContext(namespaceContext);
129137
}
130138
try {
131-
if (StaxUtils.isStaxSource(context)) {
132-
Element element = getRootElement(context);
133-
return xpath.evaluate(expression, element, returnType);
134-
}
135-
else if (context instanceof SAXSource) {
136-
SAXSource saxSource = (SAXSource) context;
137-
return xpath.evaluate(expression, saxSource.getInputSource(), returnType);
138-
}
139-
else if (context instanceof DOMSource) {
140-
DOMSource domSource = (DOMSource) context;
141-
return xpath.evaluate(expression, domSource.getNode(), returnType);
142-
}
143-
else if (context instanceof StreamSource) {
144-
StreamSource streamSource = (StreamSource) context;
145-
InputSource inputSource;
146-
if (streamSource.getInputStream() != null) {
147-
inputSource = new InputSource(streamSource.getInputStream());
148-
}
149-
else if (streamSource.getReader() != null) {
150-
inputSource = new InputSource(streamSource.getReader());
151-
}
152-
else {
153-
throw new IllegalArgumentException("StreamSource contains neither InputStream nor Reader");
154-
}
155-
return xpath.evaluate(expression, inputSource, returnType);
156-
}
157-
else {
158-
throw new IllegalArgumentException("context type unknown");
159-
}
139+
EvaluationCallback callback = new EvaluationCallback(xpath, expression, returnType);
140+
TraxUtils.doWithSource(context, callback);
141+
return callback.result;
160142
}
161143
catch (javax.xml.xpath.XPathException ex) {
162144
throw new XPathException("Could not evaluate XPath expression [" + expression + "]", ex);
163145
}
164146
catch (TransformerException ex) {
165147
throw new XPathException("Could not transform context to DOM Node", ex);
166148
}
149+
catch (Exception ex) {
150+
throw new XPathException(ex.getMessage(), ex);
151+
}
167152
}
168153

169154
private synchronized XPath createXPath() {
170155
return xpathFactory.newXPath();
171156
}
172157

158+
private static class EvaluationCallback implements TraxUtils.SourceCallback {
159+
160+
private final XPath xpath;
161+
162+
private final String expression;
163+
164+
private final QName returnType;
165+
166+
private final TransformerHelper transformerHelper = new TransformerHelper();
167+
168+
private Object result;
169+
170+
private EvaluationCallback(XPath xpath, String expression, QName returnType) {
171+
this.xpath = xpath;
172+
this.expression = expression;
173+
this.returnType = returnType;
174+
}
175+
176+
public void domSource(Node node) throws XPathExpressionException {
177+
result = xpath.evaluate(expression, node, returnType);
178+
}
179+
180+
public void saxSource(XMLReader reader, InputSource inputSource) throws XPathExpressionException {
181+
inputSource(inputSource);
182+
}
183+
184+
public void staxSource(XMLEventReader eventReader)
185+
throws XPathExpressionException, XMLStreamException, TransformerException {
186+
Element element = getRootElement(new StaxSource(eventReader));
187+
domSource(element);
188+
}
189+
190+
public void staxSource(XMLStreamReader streamReader) throws TransformerException, XPathExpressionException {
191+
Element element = getRootElement(new StaxSource(streamReader));
192+
domSource(element);
193+
}
194+
195+
public void streamSource(InputStream inputStream) throws XPathExpressionException {
196+
inputSource(new InputSource(inputStream));
197+
}
198+
199+
public void streamSource(Reader reader) throws XPathExpressionException {
200+
inputSource(new InputSource(reader));
201+
}
202+
203+
public void source(String systemId) throws XPathExpressionException {
204+
inputSource(new InputSource(systemId));
205+
}
206+
207+
private void inputSource(InputSource inputSource) throws XPathExpressionException {
208+
result = xpath.evaluate(expression, inputSource, returnType);
209+
}
210+
211+
private Element getRootElement(Source source) throws TransformerException {
212+
DOMResult domResult = new DOMResult();
213+
transformerHelper.transform(source, domResult);
214+
Document document = (Document) domResult.getNode();
215+
return document.getDocumentElement();
216+
}
217+
218+
}
219+
220+
173221

174222
}

0 commit comments

Comments
 (0)