Skip to content

Commit b87a93a

Browse files
committed
1 parent 4999b38 commit b87a93a

17 files changed

+1402
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright 2007 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ws.soap.addressing;
18+
19+
import javax.xml.transform.TransformerException;
20+
21+
import org.apache.commons.logging.Log;
22+
import org.apache.commons.logging.LogFactory;
23+
import org.springframework.core.JdkVersion;
24+
import org.springframework.util.Assert;
25+
import org.springframework.ws.context.MessageContext;
26+
import org.springframework.ws.server.EndpointInterceptor;
27+
import org.springframework.ws.server.EndpointInvocationChain;
28+
import org.springframework.ws.soap.SoapMessage;
29+
import org.springframework.ws.soap.addressing.messageid.MessageIdProvider;
30+
import org.springframework.ws.soap.addressing.messageid.UidMessageIdProvider;
31+
import org.springframework.ws.soap.addressing.messageid.UuidMessageIdProvider;
32+
import org.springframework.ws.soap.server.SoapEndpointInvocationChain;
33+
import org.springframework.ws.soap.server.SoapEndpointMapping;
34+
import org.springframework.xml.transform.TransformerObjectSupport;
35+
36+
/** @author Arjen Poutsma */
37+
public abstract class AbstractWsAddressingMapping extends TransformerObjectSupport implements SoapEndpointMapping {
38+
39+
protected final Log logger = LogFactory.getLog(getClass());
40+
41+
private String[] actorsOrRoles;
42+
43+
private MessageIdProvider messageIdProvider;
44+
45+
private AddressingHelper[] helpers = new AddressingHelper[]{new AddressingHelper(new WsAddressing200408())};
46+
47+
private EndpointInterceptor[] preInterceptors;
48+
49+
private EndpointInterceptor[] postInterceptors;
50+
51+
private static final Object MISSING_HEADER_ENDPOINT = new Object();
52+
53+
/** Protected constructor */
54+
protected AbstractWsAddressingMapping() {
55+
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_15) {
56+
messageIdProvider = new UuidMessageIdProvider();
57+
}
58+
else {
59+
messageIdProvider = new UidMessageIdProvider();
60+
}
61+
}
62+
63+
public final void setActorOrRole(String actorOrRole) {
64+
Assert.notNull(actorOrRole, "actorOrRole must not be null");
65+
actorsOrRoles = new String[]{actorOrRole};
66+
}
67+
68+
public final void setActorsOrRoles(String[] actorsOrRoles) {
69+
Assert.notEmpty(actorsOrRoles, "actorsOrRoles must not be empty");
70+
this.actorsOrRoles = actorsOrRoles;
71+
}
72+
73+
/**
74+
* Sets the message id provider used for creating WS-Addressing MessageIds. By default, the {@link
75+
* UuidMessageIdProvider} is used on Java 5 and higher, and the {@link UidMessageIdProvider} on Java 1.4 and lower.
76+
*/
77+
public final void setMessageIdProvider(MessageIdProvider messageIdProvider) {
78+
this.messageIdProvider = messageIdProvider;
79+
}
80+
81+
public final void setVersions(WsAddressingVersion[] versions) {
82+
Assert.notEmpty(versions, "specifications must not be empty");
83+
helpers = new AddressingHelper[versions.length];
84+
for (int i = 0; i < versions.length; i++) {
85+
helpers[i] = new AddressingHelper(versions[i]);
86+
}
87+
}
88+
89+
public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws TransformerException {
90+
Assert.isTrue(messageContext.getResponse() instanceof SoapMessage,
91+
"WsAddressingMapping requires a SoapMessage request");
92+
SoapMessage request = (SoapMessage) messageContext.getRequest();
93+
for (int i = 0; i < helpers.length; i++) {
94+
if (!helpers[i].supports(request)) {
95+
continue;
96+
}
97+
MessageAddressingProperties map = helpers[i].getMessageAddressingProperties(request);
98+
Object endpoint;
99+
if (map.isValid()) {
100+
endpoint = getEndpointInternal(map);
101+
}
102+
else {
103+
// Set a 'fake' endpoint, so that the invocation will continue, but result in a MissingHeader fault
104+
// returned by the interceptor
105+
endpoint = MISSING_HEADER_ENDPOINT;
106+
}
107+
if (endpoint == null) {
108+
return null;
109+
}
110+
return new SoapEndpointInvocationChain(endpoint, null, actorsOrRoles);
111+
}
112+
return null;
113+
}
114+
115+
protected abstract Object getEndpointInternal(MessageAddressingProperties map);
116+
117+
118+
}
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/*
2+
* Copyright 2007 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ws.soap.addressing;
18+
19+
import java.util.Collections;
20+
import java.util.Iterator;
21+
import java.util.List;
22+
import java.util.Locale;
23+
import java.util.Properties;
24+
import javax.xml.namespace.QName;
25+
import javax.xml.transform.Transformer;
26+
import javax.xml.transform.TransformerException;
27+
import javax.xml.transform.dom.DOMResult;
28+
import javax.xml.transform.dom.DOMSource;
29+
30+
import org.springframework.util.StringUtils;
31+
import org.springframework.ws.soap.SoapFault;
32+
import org.springframework.ws.soap.SoapHeader;
33+
import org.springframework.ws.soap.SoapHeaderElement;
34+
import org.springframework.ws.soap.SoapMessage;
35+
import org.springframework.ws.soap.soap11.Soap11Body;
36+
import org.springframework.ws.soap.soap12.Soap12Body;
37+
import org.springframework.ws.soap.soap12.Soap12Fault;
38+
import org.springframework.xml.transform.TransformerObjectSupport;
39+
import org.springframework.xml.xpath.XPathExpression;
40+
import org.springframework.xml.xpath.XPathExpressionFactory;
41+
import org.w3c.dom.Document;
42+
import org.w3c.dom.Element;
43+
import org.w3c.dom.Node;
44+
45+
/** @author Arjen Poutsma */
46+
class AddressingHelper extends TransformerObjectSupport {
47+
48+
private final WsAddressingVersion version;
49+
50+
private final XPathExpression toExpression;
51+
52+
private XPathExpression actionExpression;
53+
54+
private XPathExpression messageIdExpression;
55+
56+
private XPathExpression fromExpression;
57+
58+
private XPathExpression replyToExpression;
59+
60+
private XPathExpression faultToExpression;
61+
62+
private XPathExpression addressExpression;
63+
64+
private XPathExpression referencePropertiesExpression;
65+
66+
private XPathExpression referenceParametersExpression;
67+
68+
public AddressingHelper(WsAddressingVersion version) {
69+
this.version = version;
70+
Properties namespaces = new Properties();
71+
namespaces.setProperty(version.getNamespacePrefix(), version.getNamespaceUri());
72+
toExpression = createNormalizedExpression(version.getToName(), namespaces);
73+
actionExpression = createNormalizedExpression(version.getActionName(), namespaces);
74+
messageIdExpression = createNormalizedExpression(version.getMessageIdName(), namespaces);
75+
fromExpression = createExpression(version.getFromName(), namespaces);
76+
replyToExpression = createExpression(version.getReplyToName(), namespaces);
77+
faultToExpression = createExpression(version.getFaultToName(), namespaces);
78+
addressExpression = createNormalizedExpression(version.getAddressName(), namespaces);
79+
if (version.getReferencePropertiesName() != null) {
80+
referencePropertiesExpression = createChildrenExpression(version.getReferencePropertiesName(), namespaces);
81+
}
82+
if (version.getReferenceParametersName() != null) {
83+
referenceParametersExpression = createChildrenExpression(version.getReferenceParametersName(), namespaces);
84+
}
85+
}
86+
87+
private XPathExpression createExpression(QName name, Properties namespaces) {
88+
String expression = name.getPrefix() + ":" + name.getLocalPart();
89+
return XPathExpressionFactory.createXPathExpression(expression, namespaces);
90+
}
91+
92+
private XPathExpression createNormalizedExpression(QName name, Properties namespaces) {
93+
String expression = "normalize-space(" + name.getPrefix() + ":" + name.getLocalPart() + ")";
94+
return XPathExpressionFactory.createXPathExpression(expression, namespaces);
95+
}
96+
97+
private XPathExpression createChildrenExpression(QName name, Properties namespaces) {
98+
String expression = name.getPrefix() + ":" + name.getLocalPart() + "/*";
99+
return XPathExpressionFactory.createXPathExpression(expression, namespaces);
100+
}
101+
102+
public MessageAddressingProperties getMessageAddressingProperties(SoapMessage message) throws TransformerException {
103+
Element headerElement = getSoapHeaderElement(message);
104+
String to = toExpression.evaluateAsString(headerElement);
105+
EndpointReference from = getEndpointReference(fromExpression.evaluateAsNode(headerElement));
106+
EndpointReference replyTo = getEndpointReference(replyToExpression.evaluateAsNode(headerElement));
107+
EndpointReference faultTo = getEndpointReference(faultToExpression.evaluateAsNode(headerElement));
108+
String action = actionExpression.evaluateAsString(headerElement);
109+
String messageId = messageIdExpression.evaluateAsString(headerElement);
110+
return new MessageAddressingProperties(to, from, replyTo, faultTo, action, messageId);
111+
}
112+
113+
/** Given a ReplyTo, FaultTo, or From node, returns an endpoint reference. */
114+
private EndpointReference getEndpointReference(Node node) {
115+
if (node == null) {
116+
return null;
117+
}
118+
String address = addressExpression.evaluateAsString(node);
119+
if (!StringUtils.hasLength(address)) {
120+
return null;
121+
}
122+
List referenceProperties = referencePropertiesExpression != null ?
123+
referencePropertiesExpression.evaluateAsNodeList(node) : Collections.EMPTY_LIST;
124+
List referenceParameters = referenceParametersExpression != null ?
125+
referenceParametersExpression.evaluateAsNodeList(node) : Collections.EMPTY_LIST;
126+
return new EndpointReference(address, referenceProperties, referenceParameters);
127+
}
128+
129+
public SoapFault addMessageHeaderRequiredFault(SoapMessage message) {
130+
return addAddressingFault(message, version.getMessageHeaderRequiredName(),
131+
version.getMessageHeaderRequiredText());
132+
}
133+
134+
public SoapFault addDestinationUnreachableFault(SoapMessage message) {
135+
return addAddressingFault(message, version.getDestinationUnreachableName(),
136+
version.getDestinationUnreachableText());
137+
}
138+
139+
public SoapFault addActionNotSupportedFault(SoapMessage message, String action) {
140+
return addAddressingFault(message, version.getActionNotSupportedName(),
141+
version.getActionNotSupportedText(action));
142+
}
143+
144+
private SoapFault addAddressingFault(SoapMessage message, QName subcode, String reason) {
145+
if (message.getSoapBody() instanceof Soap11Body) {
146+
Soap11Body soapBody = (Soap11Body) message.getSoapBody();
147+
return soapBody.addFault(subcode, reason, Locale.ENGLISH);
148+
}
149+
else {
150+
Soap12Body soapBody = (Soap12Body) message.getSoapBody();
151+
Soap12Fault soapFault = (Soap12Fault) soapBody.addClientOrSenderFault(reason, Locale.ENGLISH);
152+
soapFault.addFaultSubcode(subcode);
153+
return soapFault;
154+
}
155+
}
156+
157+
private Element getSoapHeaderElement(SoapMessage message) throws TransformerException {
158+
SoapHeader header = message.getSoapHeader();
159+
if (header.getSource() instanceof DOMSource) {
160+
DOMSource domSource = (DOMSource) header.getSource();
161+
if (domSource.getNode() != null && domSource.getNode().getNodeType() == Node.ELEMENT_NODE) {
162+
return (Element) domSource.getNode();
163+
}
164+
}
165+
Transformer transformer = createTransformer();
166+
DOMResult domResult = new DOMResult();
167+
transformer.transform(message.getSoapHeader().getSource(), domResult);
168+
Document document = (Document) domResult.getNode();
169+
return document.getDocumentElement();
170+
}
171+
172+
public boolean hasNoneAddress(EndpointReference reference) {
173+
String none = version.getNoneUri();
174+
return none != null && none.equals(reference.getAddress());
175+
}
176+
177+
public boolean hasAnonymousAddress(EndpointReference reference) {
178+
String anonymous = version.getAnonymousUri();
179+
return anonymous != null && anonymous.equals(reference.getAddress());
180+
}
181+
182+
public void addAddressingHeaders(SoapMessage response, MessageAddressingProperties map)
183+
throws TransformerException {
184+
SoapHeader header = response.getSoapHeader();
185+
SoapHeaderElement messageId = header.addHeaderElement(version.getMessageIdName());
186+
messageId.setText(map.getMessageId());
187+
SoapHeaderElement relatesTo = header.addHeaderElement(version.getRelatesToName());
188+
relatesTo.setText(map.getRelatesTo());
189+
SoapHeaderElement to = header.addHeaderElement(version.getToName());
190+
to.setText(map.getTo());
191+
to.setMustUnderstand(true);
192+
Transformer transformer = createTransformer();
193+
for (Iterator iterator = map.getReferenceParameters().iterator(); iterator.hasNext();) {
194+
Node node = (Node) iterator.next();
195+
DOMSource source = new DOMSource(node);
196+
transformer.transform(source, header.getResult());
197+
}
198+
for (Iterator iterator = map.getReferenceProperties().iterator(); iterator.hasNext();) {
199+
Node node = (Node) iterator.next();
200+
DOMSource source = new DOMSource(node);
201+
transformer.transform(source, header.getResult());
202+
}
203+
}
204+
205+
public boolean supports(SoapMessage message) {
206+
SoapHeader header = message.getSoapHeader();
207+
if (header != null) {
208+
for (Iterator iterator = header.examineAllHeaderElements(); iterator.hasNext();) {
209+
SoapHeaderElement headerElement = (SoapHeaderElement) iterator.next();
210+
if (version.getNamespaceUri().equals(headerElement.getName().getNamespaceURI())) {
211+
return true;
212+
}
213+
}
214+
}
215+
return false;
216+
217+
}
218+
219+
public boolean understands(SoapHeaderElement header) {
220+
return version.getNamespaceUri().equals(header.getName().getNamespaceURI());
221+
}
222+
}

0 commit comments

Comments
 (0)