Skip to content

Commit a9de688

Browse files
committed
SWS-404
1 parent 208a7bb commit a9de688

File tree

5 files changed

+397
-106
lines changed

5 files changed

+397
-106
lines changed

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,17 @@
1717
package org.springframework.ws.server.endpoint;
1818

1919
import javax.xml.transform.Source;
20+
import javax.xml.transform.TransformerException;
21+
import javax.xml.transform.dom.DOMSource;
2022

2123
import org.dom4j.Document;
2224
import org.dom4j.DocumentHelper;
2325
import org.dom4j.Element;
26+
import org.dom4j.io.DOMReader;
2427
import org.dom4j.io.DocumentResult;
2528
import org.dom4j.io.DocumentSource;
29+
import org.w3c.dom.Node;
30+
2631
import org.springframework.xml.transform.TransformerObjectSupport;
2732

2833
/**
@@ -38,6 +43,17 @@
3843
*/
3944
public abstract class AbstractDom4jPayloadEndpoint extends TransformerObjectSupport implements PayloadEndpoint {
4045

46+
private boolean alwaysTransform = false;
47+
48+
/**
49+
* Set if the request {@link Source} should always be transformed into a new {@link DocumentResult}.
50+
* <p/>
51+
* Default is {@code false}, which is faster.
52+
*/
53+
public void setAlwaysTransform(boolean alwaysTransform) {
54+
this.alwaysTransform = alwaysTransform;
55+
}
56+
4157
public final Source invoke(Source request) throws Exception {
4258
Element requestElement = null;
4359
if (request != null) {
@@ -50,6 +66,38 @@ public final Source invoke(Source request) throws Exception {
5066
return responseElement != null ? new DocumentSource(responseElement) : null;
5167
}
5268

69+
/**
70+
* Returns the payload element of the given source.
71+
* <p/>
72+
* Default implementation checks whether the source is a {@link javax.xml.transform.dom.DOMSource}, and uses a
73+
* {@link org.jdom.input.DOMBuilder} to create a JDOM {@link org.jdom.Element}. In all other cases, or when
74+
* {@linkplain #setAlwaysTransform(boolean) alwaysTransform} is {@code true}, the source is transformed into a
75+
* {@link org.jdom.transform.JDOMResult}, which is more expensive. If the passed source is {@code null}, {@code
76+
* null} is returned.
77+
*
78+
* @param source the source to return the root element of; can be {@code null}
79+
* @return the document element
80+
* @throws javax.xml.transform.TransformerException
81+
* in case of errors
82+
*/
83+
protected Element getDocumentElement(Source source) throws TransformerException {
84+
if (source == null) {
85+
return null;
86+
}
87+
if (!alwaysTransform && source instanceof DOMSource) {
88+
Node node = ((DOMSource) source).getNode();
89+
if (node.getNodeType() == Node.DOCUMENT_NODE) {
90+
DOMReader domReader = new DOMReader();
91+
Document document = domReader.read((org.w3c.dom.Document) node);
92+
return document.getRootElement();
93+
}
94+
}
95+
// we have no other option than to transform
96+
DocumentResult dom4jResult = new DocumentResult();
97+
transform(source, dom4jResult);
98+
return dom4jResult.getDocument().getRootElement();
99+
}
100+
53101
/**
54102
* Template method. Subclasses must implement this. Offers the request payload as a dom4j <code>Element</code>, and
55103
* allows subclasses to return a response <code>Element</code>.

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

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,23 @@
2020
import javax.xml.parsers.DocumentBuilderFactory;
2121
import javax.xml.parsers.ParserConfigurationException;
2222
import javax.xml.transform.Source;
23+
import javax.xml.transform.TransformerException;
2324
import javax.xml.transform.dom.DOMResult;
2425
import javax.xml.transform.dom.DOMSource;
2526

26-
import org.springframework.xml.transform.TransformerObjectSupport;
2727
import org.w3c.dom.Document;
2828
import org.w3c.dom.Element;
29+
import org.w3c.dom.Node;
30+
31+
import org.springframework.xml.transform.TransformerObjectSupport;
2932

3033
/**
3134
* Abstract base class for endpoints that handle the message payload as DOM elements.
3235
* <p/>
33-
* <p>Offers the message payload as a DOM <code>Element</code>, and allows subclasses to create a response by returning
34-
* an <code>Element</code>.
36+
* Offers the message payload as a DOM <code>Element</code>, and allows subclasses to create a response by returning an
37+
* <code>Element</code>.
3538
* <p/>
36-
* <p>An <code>AbstractDomPayloadEndpoint</code> only accept <i>one</i> payload element. Multiple payload elements are
39+
* An <code>AbstractDomPayloadEndpoint</code> only accept <em>one</em> payload element. Multiple payload elements are
3740
* not in accordance with WS-I.
3841
*
3942
* @author Arjen Poutsma
@@ -49,6 +52,8 @@ public abstract class AbstractDomPayloadEndpoint extends TransformerObjectSuppor
4952

5053
private boolean namespaceAware = true;
5154

55+
private boolean alwaysTransform = false;
56+
5257
/** Set whether or not the XML parser should be XML namespace aware. Default is <code>true</code>. */
5358
public void setNamespaceAware(boolean namespaceAware) {
5459
this.namespaceAware = namespaceAware;
@@ -59,26 +64,24 @@ public void setValidating(boolean validating) {
5964
this.validating = validating;
6065
}
6166

67+
/**
68+
* Set if the request {@link Source} should always be transformed into a new {@link DOMResult}.
69+
* <p/>
70+
* Default is {@code false}, which is faster.
71+
*/
72+
public void setAlwaysTransform(boolean alwaysTransform) {
73+
this.alwaysTransform = alwaysTransform;
74+
}
75+
6276
public final Source invoke(Source request) throws Exception {
6377
if (documentBuilderFactory == null) {
6478
documentBuilderFactory = createDocumentBuilderFactory();
6579
}
6680
DocumentBuilder documentBuilder = createDocumentBuilder(documentBuilderFactory);
67-
Element requestElement = null;
68-
if (request != null) {
69-
Document requestDocument = documentBuilder.newDocument();
70-
DOMResult domResult = new DOMResult(requestDocument);
71-
transform(request, domResult);
72-
requestElement = (Element) requestDocument.getFirstChild();
73-
}
81+
Element requestElement = getDocumentElement(request, documentBuilder);
7482
Document responseDocument = documentBuilder.newDocument();
7583
Element responseElement = invokeInternal(requestElement, responseDocument);
76-
if (responseElement != null) {
77-
return new DOMSource(responseElement);
78-
}
79-
else {
80-
return null;
81-
}
84+
return responseElement != null ? new DOMSource(responseElement) : null;
8285
}
8386

8487
/**
@@ -109,6 +112,39 @@ protected DocumentBuilderFactory createDocumentBuilderFactory() throws ParserCon
109112
return factory;
110113
}
111114

115+
/**
116+
* Returns the payload element of the given source.
117+
* <p/>
118+
* Default implementation checks whether the source is a {@link DOMSource}, and returns the {@linkplain
119+
* DOMSource#getNode() node} of that. In all other cases, or when {@linkplain #setAlwaysTransform(boolean)
120+
* alwaysTransform} is {@code true}, the source is transformed into a {@link DOMResult}, which is more expensive. If
121+
* the passed source is {@code null}, {@code null} is returned.
122+
*
123+
* @param source the source to return the root element of; can be {@code null}
124+
* @param documentBuilder the document builder to be used for transformations
125+
* @return the document element
126+
* @throws TransformerException in case of errors
127+
*/
128+
protected Element getDocumentElement(Source source, DocumentBuilder documentBuilder) throws TransformerException {
129+
if (source == null) {
130+
return null;
131+
}
132+
if (!alwaysTransform && source instanceof DOMSource) {
133+
Node node = ((DOMSource) source).getNode();
134+
if (node.getNodeType() == Node.ELEMENT_NODE) {
135+
return (Element) node;
136+
}
137+
else if (node.getNodeType() == Node.DOCUMENT_NODE) {
138+
return ((Document) node).getDocumentElement();
139+
}
140+
}
141+
// we have no other option than to transform
142+
Document requestDocument = documentBuilder.newDocument();
143+
DOMResult domResult = new DOMResult(requestDocument);
144+
transform(source, domResult);
145+
return requestDocument.getDocumentElement();
146+
}
147+
112148
/**
113149
* Template method that subclasses must implement to process the request.
114150
* <p/>
@@ -123,4 +159,5 @@ protected DocumentBuilderFactory createDocumentBuilderFactory() throws ParserCon
123159
* @return the response element. Can be <code>null</code> to specify no response.
124160
*/
125161
protected abstract Element invokeInternal(Element requestElement, Document responseDocument) throws Exception;
162+
126163
}

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

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@
1717
package org.springframework.ws.server.endpoint;
1818

1919
import javax.xml.transform.Source;
20+
import javax.xml.transform.TransformerException;
21+
import javax.xml.transform.dom.DOMSource;
2022

23+
import org.jdom.Document;
2124
import org.jdom.Element;
25+
import org.jdom.input.DOMBuilder;
2226
import org.jdom.transform.JDOMResult;
2327
import org.jdom.transform.JDOMSource;
28+
import org.w3c.dom.Node;
29+
2430
import org.springframework.xml.transform.TransformerObjectSupport;
2531

2632
/**
@@ -37,17 +43,56 @@
3743
*/
3844
public abstract class AbstractJDomPayloadEndpoint extends TransformerObjectSupport implements PayloadEndpoint {
3945

46+
private boolean alwaysTransform = false;
47+
48+
/**
49+
* Set if the request {@link Source} should always be transformed into a new {@link JDOMResult}.
50+
* <p/>
51+
* Default is {@code false}, which is faster.
52+
*/
53+
public void setAlwaysTransform(boolean alwaysTransform) {
54+
this.alwaysTransform = alwaysTransform;
55+
}
56+
4057
public final Source invoke(Source request) throws Exception {
41-
Element requestElement = null;
42-
if (request != null) {
43-
JDOMResult jdomResult = new JDOMResult();
44-
transform(request, jdomResult);
45-
requestElement = jdomResult.getDocument().getRootElement();
46-
}
58+
Element requestElement = getDocumentElement(request);
4759
Element responseElement = invokeInternal(requestElement);
4860
return responseElement != null ? new JDOMSource(responseElement) : null;
4961
}
5062

63+
/**
64+
* Returns the payload element of the given source.
65+
* <p/>
66+
* Default implementation checks whether the source is a {@link DOMSource}, and uses a {@link DOMBuilder} to create
67+
* a JDOM {@link Element}. In all other cases, or when {@linkplain #setAlwaysTransform(boolean) alwaysTransform} is
68+
* {@code true}, the source is transformed into a {@link JDOMResult}, which is more expensive. If the passed source
69+
* is {@code null}, {@code null} is returned.
70+
*
71+
* @param source the source to return the root element of; can be {@code null}
72+
* @return the document element
73+
* @throws TransformerException in case of errors
74+
*/
75+
protected Element getDocumentElement(Source source) throws TransformerException {
76+
if (source == null) {
77+
return null;
78+
}
79+
if (!alwaysTransform && source instanceof DOMSource) {
80+
Node node = ((DOMSource) source).getNode();
81+
DOMBuilder domBuilder = new DOMBuilder();
82+
if (node.getNodeType() == Node.ELEMENT_NODE) {
83+
return domBuilder.build((org.w3c.dom.Element) node);
84+
}
85+
else if (node.getNodeType() == Node.DOCUMENT_NODE) {
86+
Document document = domBuilder.build((org.w3c.dom.Document) node);
87+
return document.getRootElement();
88+
}
89+
}
90+
// we have no other option than to transform
91+
JDOMResult jdomResult = new JDOMResult();
92+
transform(source, jdomResult);
93+
return jdomResult.getDocument().getRootElement();
94+
}
95+
5196
/**
5297
* Template method. Subclasses must implement this. Offers the request payload as a JDOM <code>Element</code>, and
5398
* allows subclasses to return a response <code>Element</code>.

0 commit comments

Comments
 (0)