/* * Copyright 2005-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.ws.soap.addressing.server; import java.io.IOException; import java.net.URI; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import org.springframework.ws.context.MessageContext; import org.springframework.ws.soap.SoapHeaderElement; import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.addressing.core.EndpointReference; import org.springframework.ws.soap.addressing.core.MessageAddressingProperties; import org.springframework.ws.soap.addressing.messageid.MessageIdStrategy; import org.springframework.ws.soap.addressing.version.AddressingVersion; import org.springframework.ws.soap.server.SoapEndpointInterceptor; import org.springframework.ws.transport.WebServiceConnection; import org.springframework.ws.transport.WebServiceMessageSender; /** * {@link SoapEndpointInterceptor} implementation that deals with WS-Addressing headers. Stateful, and instantiated by * the {@link AbstractAddressingEndpointMapping}. * * @author Arjen Poutsma * @since 1.5.0 */ class AddressingEndpointInterceptor implements SoapEndpointInterceptor { private static final Log logger = LogFactory.getLog(AddressingEndpointInterceptor.class); private final AddressingVersion version; private final MessageIdStrategy messageIdStrategy; private final WebServiceMessageSender[] messageSenders; private URI replyAction; private URI faultAction; AddressingEndpointInterceptor(AddressingVersion version, MessageIdStrategy messageIdStrategy, WebServiceMessageSender[] messageSenders, URI replyAction, URI faultAction) { Assert.notNull(version, "version must not be null"); Assert.notNull(messageIdStrategy, "messageIdStrategy must not be null"); Assert.notNull(messageSenders, "'messageSenders' must not be null"); this.version = version; this.messageIdStrategy = messageIdStrategy; this.messageSenders = messageSenders; this.replyAction = replyAction; this.faultAction = faultAction; } @Override public final boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception { Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest()); SoapMessage request = (SoapMessage) messageContext.getRequest(); MessageAddressingProperties requestMap = version.getMessageAddressingProperties(request); if (!version.hasRequiredProperties(requestMap)) { version.addMessageAddressingHeaderRequiredFault((SoapMessage) messageContext.getResponse()); return false; } if (messageIdStrategy.isDuplicate(requestMap.getMessageId())) { version.addInvalidAddressingHeaderFault((SoapMessage) messageContext.getResponse()); return false; } return true; } @Override public final boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception { return handleResponseOrFault(messageContext, false); } @Override public final boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { return handleResponseOrFault(messageContext, true); } private boolean handleResponseOrFault(MessageContext messageContext, boolean isFault) throws Exception { Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest()); Assert.isInstanceOf(SoapMessage.class, messageContext.getResponse()); MessageAddressingProperties requestMap = version.getMessageAddressingProperties((SoapMessage) messageContext.getRequest()); EndpointReference replyEpr = !isFault ? requestMap.getReplyTo() : requestMap.getFaultTo(); if (handleNoneAddress(messageContext, replyEpr)) { return false; } SoapMessage reply = (SoapMessage) messageContext.getResponse(); URI replyMessageId = getMessageId(reply); URI action = isFault ? faultAction : replyAction; MessageAddressingProperties replyMap = requestMap.getReplyProperties(replyEpr, action, replyMessageId); version.addAddressingHeaders(reply, replyMap); if (handleAnonymousAddress(messageContext, replyEpr)) { return true; } else { sendOutOfBand(messageContext, replyEpr); return false; } } private boolean handleNoneAddress(MessageContext messageContext, EndpointReference replyEpr) { if (replyEpr == null || version.hasNoneAddress(replyEpr)) { if (logger.isDebugEnabled()) { logger.debug( "Request [" + messageContext.getRequest() + "] has [" + replyEpr + "] reply address; reply [" + messageContext.getResponse() + "] discarded"); } messageContext.clearResponse(); return true; } return false; } private boolean handleAnonymousAddress(MessageContext messageContext, EndpointReference replyEpr) { if (version.hasAnonymousAddress(replyEpr)) { if (logger.isDebugEnabled()) { logger.debug("Request [" + messageContext.getRequest() + "] has [" + replyEpr + "] reply address; sending in-band reply [" + messageContext.getResponse() + "]"); } return true; } return false; } private void sendOutOfBand(MessageContext messageContext, EndpointReference replyEpr) throws IOException { if (logger.isDebugEnabled()) { logger.debug("Request [" + messageContext.getRequest() + "] has [" + replyEpr + "] reply address; sending out-of-band reply [" + messageContext.getResponse() + "]"); } boolean supported = false; for (WebServiceMessageSender messageSender : messageSenders) { if (messageSender.supports(replyEpr.getAddress())) { supported = true; WebServiceConnection connection = null; try { connection = messageSender.createConnection(replyEpr.getAddress()); connection.send(messageContext.getResponse()); break; } finally { messageContext.clearResponse(); if (connection != null) { connection.close(); } } } } if (!supported && logger.isWarnEnabled()) { logger.warn("Could not send out-of-band response to [" + replyEpr.getAddress() + "]. " + "Configure WebServiceMessageSenders which support this uri."); } } private URI getMessageId(SoapMessage response) { URI responseMessageId = messageIdStrategy.newMessageId(response); if (logger.isTraceEnabled()) { logger.trace("Generated reply MessageID [" + responseMessageId + "] for [" + response + "]"); } return responseMessageId; } @Override public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { } @Override public boolean understands(SoapHeaderElement header) { return version.understands(header); } }