1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.soap.addressing.server;
18
19 import java.io.IOException;
20 import java.net.URI;
21
22 import org.springframework.util.Assert;
23 import org.springframework.ws.context.MessageContext;
24 import org.springframework.ws.soap.SoapHeaderElement;
25 import org.springframework.ws.soap.SoapMessage;
26 import org.springframework.ws.soap.addressing.core.EndpointReference;
27 import org.springframework.ws.soap.addressing.core.MessageAddressingProperties;
28 import org.springframework.ws.soap.addressing.messageid.MessageIdStrategy;
29 import org.springframework.ws.soap.addressing.version.AddressingVersion;
30 import org.springframework.ws.soap.server.SoapEndpointInterceptor;
31 import org.springframework.ws.transport.WebServiceConnection;
32 import org.springframework.ws.transport.WebServiceMessageSender;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37
38
39
40
41
42
43
44 class AddressingEndpointInterceptor implements SoapEndpointInterceptor {
45
46 private static final Log logger = LogFactory.getLog(AddressingEndpointInterceptor.class);
47
48 private final AddressingVersion version;
49
50 private final MessageIdStrategy messageIdStrategy;
51
52 private final WebServiceMessageSender[] messageSenders;
53
54 private URI replyAction;
55
56 private URI faultAction;
57
58 AddressingEndpointInterceptor(AddressingVersion version,
59 MessageIdStrategy messageIdStrategy,
60 WebServiceMessageSender[] messageSenders,
61 URI replyAction,
62 URI faultAction) {
63 Assert.notNull(version, "version must not be null");
64 Assert.notNull(messageIdStrategy, "messageIdStrategy must not be null");
65 Assert.notNull(messageSenders, "'messageSenders' must not be null");
66 this.version = version;
67 this.messageIdStrategy = messageIdStrategy;
68 this.messageSenders = messageSenders;
69 this.replyAction = replyAction;
70 this.faultAction = faultAction;
71 }
72
73 public final boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
74 Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest());
75 SoapMessage request = (SoapMessage) messageContext.getRequest();
76 MessageAddressingProperties requestMap = version.getMessageAddressingProperties(request);
77 if (!version.hasRequiredProperties(requestMap)) {
78 version.addMessageAddressingHeaderRequiredFault((SoapMessage) messageContext.getResponse());
79 return false;
80 }
81 if (messageIdStrategy.isDuplicate(requestMap.getMessageId())) {
82 version.addInvalidAddressingHeaderFault((SoapMessage) messageContext.getResponse());
83 return false;
84 }
85 return true;
86 }
87
88 public final boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
89 return handleResponseOrFault(messageContext, false);
90 }
91
92 public final boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
93 return handleResponseOrFault(messageContext, true);
94 }
95
96 private boolean handleResponseOrFault(MessageContext messageContext, boolean isFault) throws Exception {
97 Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest());
98 Assert.isInstanceOf(SoapMessage.class, messageContext.getResponse());
99 MessageAddressingProperties requestMap =
100 version.getMessageAddressingProperties((SoapMessage) messageContext.getRequest());
101 EndpointReference replyEpr = !isFault ? requestMap.getReplyTo() : requestMap.getFaultTo();
102 if (handleNoneAddress(messageContext, replyEpr)) {
103 return false;
104 }
105 SoapMessage reply = (SoapMessage) messageContext.getResponse();
106 URI replyMessageId = getMessageId(reply);
107 URI action = isFault ? faultAction : replyAction;
108 MessageAddressingProperties replyMap = requestMap.getReplyProperties(replyEpr, action, replyMessageId);
109 version.addAddressingHeaders(reply, replyMap);
110 if (handleAnonymousAddress(messageContext, replyEpr)) {
111 return true;
112 }
113 else {
114 sendOutOfBand(messageContext, replyEpr);
115 return false;
116 }
117 }
118
119 private boolean handleNoneAddress(MessageContext messageContext, EndpointReference replyEpr) {
120 if (replyEpr == null || version.hasNoneAddress(replyEpr)) {
121 if (logger.isDebugEnabled()) {
122 logger.debug(
123 "Request [" + messageContext.getRequest() + "] has [" + replyEpr + "] reply address; reply [" +
124 messageContext.getResponse() + "] discarded");
125 }
126 messageContext.clearResponse();
127 return true;
128 }
129 return false;
130 }
131
132 private boolean handleAnonymousAddress(MessageContext messageContext, EndpointReference replyEpr) {
133 if (version.hasAnonymousAddress(replyEpr)) {
134 if (logger.isDebugEnabled()) {
135 logger.debug("Request [" + messageContext.getRequest() + "] has [" + replyEpr +
136 "] reply address; sending in-band reply [" + messageContext.getResponse() + "]");
137 }
138 return true;
139 }
140 return false;
141 }
142
143 private void sendOutOfBand(MessageContext messageContext, EndpointReference replyEpr) throws IOException {
144 if (logger.isDebugEnabled()) {
145 logger.debug("Request [" + messageContext.getRequest() + "] has [" + replyEpr +
146 "] reply address; sending out-of-band reply [" + messageContext.getResponse() + "]");
147 }
148
149 boolean supported = false;
150 for (WebServiceMessageSender messageSender : messageSenders) {
151 if (messageSender.supports(replyEpr.getAddress())) {
152 supported = true;
153 WebServiceConnection connection = null;
154 try {
155 connection = messageSender.createConnection(replyEpr.getAddress());
156 connection.send(messageContext.getResponse());
157 break;
158 }
159 finally {
160 messageContext.clearResponse();
161 if (connection != null) {
162 connection.close();
163 }
164 }
165 }
166 }
167 if (!supported && logger.isWarnEnabled()) {
168 logger.warn("Could not send out-of-band response to [" + replyEpr.getAddress() + "]. " +
169 "Configure WebServiceMessageSenders which support this uri.");
170 }
171 }
172
173 private URI getMessageId(SoapMessage response) {
174 URI responseMessageId = messageIdStrategy.newMessageId(response);
175 if (logger.isTraceEnabled()) {
176 logger.trace("Generated reply MessageID [" + responseMessageId + "] for [" + response + "]");
177 }
178 return responseMessageId;
179 }
180
181 public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) {
182 }
183
184 public boolean understands(SoapHeaderElement header) {
185 return version.understands(header);
186 }
187 }