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.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 import org.springframework.util.Assert;
26 import org.springframework.ws.context.MessageContext;
27 import org.springframework.ws.soap.SoapHeaderElement;
28 import org.springframework.ws.soap.SoapMessage;
29 import org.springframework.ws.soap.addressing.core.EndpointReference;
30 import org.springframework.ws.soap.addressing.core.MessageAddressingProperties;
31 import org.springframework.ws.soap.addressing.messageid.MessageIdStrategy;
32 import org.springframework.ws.soap.addressing.version.AddressingVersion;
33 import org.springframework.ws.soap.server.SoapEndpointInterceptor;
34 import org.springframework.ws.transport.WebServiceConnection;
35 import org.springframework.ws.transport.WebServiceMessageSender;
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 (!requestMap.hasRequiredProperties()) {
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("Request " + messageContext.getRequest() + "] has [" + replyEpr +
123 "] reply address; reply [" + messageContext.getResponse() + "] discarded");
124 }
125 messageContext.clearResponse();
126 return true;
127 }
128 return false;
129 }
130
131 private boolean handleAnonymousAddress(MessageContext messageContext, EndpointReference replyEpr) {
132 if (version.hasAnonymousAddress(replyEpr)) {
133 if (logger.isDebugEnabled()) {
134 logger.debug("Request " + messageContext.getRequest() + "] has [" + replyEpr +
135 "] reply address; sending in-band reply [" + messageContext.getResponse() + "]");
136 }
137 return true;
138 }
139 return false;
140 }
141
142 private void sendOutOfBand(MessageContext messageContext, EndpointReference replyEpr) throws IOException {
143 if (logger.isDebugEnabled()) {
144 logger.debug("Request " + messageContext.getRequest() + "] has [" + replyEpr +
145 "] reply address; sending out-of-band reply [" + messageContext.getResponse() + "]");
146 }
147
148 boolean supported = false;
149 for (int i = 0; i < messageSenders.length; i++) {
150 if (messageSenders[i].supports(replyEpr.getAddress())) {
151 supported = true;
152 WebServiceConnection connection = null;
153 try {
154 connection = messageSenders[i].createConnection(replyEpr.getAddress());
155 connection.send(messageContext.getResponse());
156 break;
157 }
158 finally {
159 messageContext.clearResponse();
160 if (connection != null) {
161 connection.close();
162 }
163 }
164 }
165 }
166 if (!supported && logger.isWarnEnabled()) {
167 logger.warn("Could not send out-of-band response to [" + replyEpr.getAddress() + "]. " +
168 "Configure WebServiceMessageSenders which support this uri.");
169 }
170 }
171
172 private URI getMessageId(SoapMessage response) {
173 URI responseMessageId = messageIdStrategy.newMessageId(response);
174 if (logger.isTraceEnabled()) {
175 logger.trace("Generated reply MessageID [" + responseMessageId + "] for [" + response + "]");
176 }
177 return responseMessageId;
178 }
179
180 public boolean understands(SoapHeaderElement header) {
181 return version.understands(header);
182 }
183 }