INT-1446 added DefaultSoapHeaderMapper. SimpleWebServiceInboundGateway now delegates to it.
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.integration.ws;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
import org.springframework.integration.mapping.HeaderMapper;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
import org.springframework.xml.namespace.QNameUtils;
|
||||
|
||||
/**
|
||||
* A {@link HeaderMapper} implementation for mapping to and from a SoapHeader.
|
||||
* The {@link #inboundHeaderNames} and {@link #outboundHeaderNames} may be configured.
|
||||
* They accept exact name Strings or simple patterns (e.g. "start*", "*end", or "*").
|
||||
* By default all inbound headers will be accepted, but any outbound header that should
|
||||
* be mapped must be configured explicitly. Note that the outbound mapping only writes
|
||||
* String header values into attributes on the SoapHeader. For anything more advanced,
|
||||
* one should implement the HeaderMapper interface directly.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DefaultSoapHeaderMapper implements HeaderMapper<SoapHeader> {
|
||||
|
||||
private volatile String[] outboundHeaderNames = new String[0];
|
||||
|
||||
private volatile String[] inboundHeaderNames = new String[] { "*" };
|
||||
|
||||
|
||||
public void setOutboundHeaderNames(String[] outboundHeaderNames) {
|
||||
this.outboundHeaderNames = (outboundHeaderNames != null) ? outboundHeaderNames : new String[0];
|
||||
}
|
||||
|
||||
public void setInboundHeaderNames(String[] inboundHeaderNames) {
|
||||
this.inboundHeaderNames = (inboundHeaderNames != null) ? inboundHeaderNames : new String[0];
|
||||
}
|
||||
|
||||
public void fromHeaders(MessageHeaders headers, SoapHeader target) {
|
||||
if (target != null && !CollectionUtils.isEmpty(headers)) {
|
||||
for (String headerName : headers.keySet()) {
|
||||
if (this.shouldMapOutboundHeader(headerName)) {
|
||||
Object value = headers.get(headerName);
|
||||
if (value instanceof String) {
|
||||
QName qname = QNameUtils.parseQNameString(headerName);
|
||||
target.addAttribute(qname, (String) value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> toHeaders(SoapHeader source) {
|
||||
Map<String, Object> headers = new HashMap<String, Object>();
|
||||
if (source != null) {
|
||||
Iterator<?> attributeIter = source.getAllAttributes();
|
||||
while (attributeIter.hasNext()) {
|
||||
Object name = attributeIter.next();
|
||||
if (name instanceof QName) {
|
||||
String qnameString = QNameUtils.toQualifiedName((QName) name);
|
||||
if (this.shouldMapInboundHeader(qnameString)) {
|
||||
String value = source.getAttributeValue((QName) name);
|
||||
if (value != null) {
|
||||
headers.put(qnameString, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Iterator<?> elementIter = source.examineAllHeaderElements();
|
||||
while (elementIter.hasNext()) {
|
||||
Object element = elementIter.next();
|
||||
if (element instanceof SoapHeaderElement) {
|
||||
QName qname = ((SoapHeaderElement) element).getName();
|
||||
String qnameString = QNameUtils.toQualifiedName(qname);
|
||||
if (this.shouldMapInboundHeader(qnameString)) {
|
||||
headers.put(qnameString, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
private boolean shouldMapInboundHeader(String headerName) {
|
||||
return matchesAny(this.inboundHeaderNames, headerName);
|
||||
}
|
||||
|
||||
private boolean shouldMapOutboundHeader(String headerName) {
|
||||
return matchesAny(this.outboundHeaderNames, headerName);
|
||||
}
|
||||
|
||||
private static boolean matchesAny(String[] patterns, String candidate) {
|
||||
if (!ObjectUtils.isEmpty(patterns) && QNameUtils.validateQName(candidate)) {
|
||||
for (String pattern : patterns) {
|
||||
if (PatternMatchUtils.simpleMatch(pattern, candidate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,7 +43,10 @@ public class MarshallingWebServiceInboundGateway extends AbstractMarshallingPayl
|
||||
private final ReentrantLock lifecycleLock = new ReentrantLock();
|
||||
|
||||
private final GatewayDelegate gatewayDelegate = new GatewayDelegate();
|
||||
|
||||
|
||||
private volatile int phase = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>MarshallingWebServiceInboundGateway</code>.
|
||||
* The {@link Marshaller} and {@link Unmarshaller} must be injected using properties.
|
||||
@@ -95,10 +98,34 @@ public class MarshallingWebServiceInboundGateway extends AbstractMarshallingPayl
|
||||
this.gatewayDelegate.setTaskScheduler(taskScheduler);
|
||||
}
|
||||
|
||||
public void setShouldTrack(boolean shouldTrack) {
|
||||
this.gatewayDelegate.setShouldTrack(shouldTrack);
|
||||
}
|
||||
|
||||
public String getComponentName() {
|
||||
return this.gatewayDelegate.getComponentName();
|
||||
}
|
||||
|
||||
public String getComponentType() {
|
||||
return this.gatewayDelegate.getComponentType();
|
||||
}
|
||||
|
||||
public void setAutoStartup(boolean autoStartup) {
|
||||
this.gatewayDelegate.setAutoStartup(autoStartup);
|
||||
}
|
||||
|
||||
public boolean isAutoStartup() {
|
||||
return this.gatewayDelegate.isAutoStartup();
|
||||
}
|
||||
|
||||
public void setPhase(int phase) {
|
||||
this.phase = phase;
|
||||
}
|
||||
|
||||
public int getPhase() {
|
||||
return this.phase;
|
||||
}
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.gatewayDelegate.setBeanName(beanName);
|
||||
}
|
||||
@@ -143,7 +170,7 @@ public class MarshallingWebServiceInboundGateway extends AbstractMarshallingPayl
|
||||
public void start() {
|
||||
this.lifecycleLock.lock();
|
||||
try {
|
||||
if (!gatewayDelegate.isRunning()) {
|
||||
if (!this.gatewayDelegate.isRunning()) {
|
||||
this.gatewayDelegate.start();
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("started " + this);
|
||||
@@ -170,10 +197,6 @@ public class MarshallingWebServiceInboundGateway extends AbstractMarshallingPayl
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAutoStartup() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void stop(Runnable callback) {
|
||||
this.lifecycleLock.lock();
|
||||
try {
|
||||
@@ -185,29 +208,16 @@ public class MarshallingWebServiceInboundGateway extends AbstractMarshallingPayl
|
||||
}
|
||||
}
|
||||
|
||||
public int getPhase() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static class GatewayDelegate extends MessagingGatewaySupport {
|
||||
|
||||
public Object sendAndReceive(Object request) {
|
||||
return super.sendAndReceive(request);
|
||||
}
|
||||
|
||||
public String getComponentType() {
|
||||
return "ws:outbound-gateway";
|
||||
}
|
||||
}
|
||||
|
||||
public String getComponentName() {
|
||||
return this.gatewayDelegate.getComponentName();
|
||||
}
|
||||
|
||||
public String getComponentType() {
|
||||
return this.gatewayDelegate.getComponentType();
|
||||
}
|
||||
|
||||
public void setShouldTrack(boolean shouldTrack) {
|
||||
this.gatewayDelegate.setShouldTrack(shouldTrack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,8 @@
|
||||
|
||||
package org.springframework.integration.ws;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
@@ -30,13 +29,14 @@ import org.springframework.expression.ExpressionException;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.gateway.MessagingGatewaySupport;
|
||||
import org.springframework.integration.mapping.HeaderMapper;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.endpoint.MessageEndpoint;
|
||||
import org.springframework.ws.soap.SoapHeader;
|
||||
import org.springframework.ws.soap.SoapHeaderElement;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.xml.transform.StringSource;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
@@ -51,11 +51,22 @@ public class SimpleWebServiceInboundGateway extends MessagingGatewaySupport impl
|
||||
|
||||
private volatile boolean extractPayload = true;
|
||||
|
||||
private volatile HeaderMapper<SoapHeader> headerMapper = new DefaultSoapHeaderMapper();
|
||||
|
||||
|
||||
public void setExtractPayload(boolean extractPayload) {
|
||||
this.extractPayload = extractPayload;
|
||||
}
|
||||
|
||||
public void setHeaderMapper(HeaderMapper<SoapHeader> headerMapper) {
|
||||
Assert.notNull(headerMapper, "headerMapper must not be null");
|
||||
this.headerMapper = headerMapper;
|
||||
}
|
||||
|
||||
public String getComponentType() {
|
||||
return "ws:outbound-gateway";
|
||||
}
|
||||
|
||||
public void invoke(MessageContext messageContext) throws Exception {
|
||||
try {
|
||||
this.doInvoke(messageContext);
|
||||
@@ -83,21 +94,9 @@ public class SimpleWebServiceInboundGateway extends MessagingGatewaySupport impl
|
||||
}
|
||||
if (request instanceof SoapMessage) {
|
||||
SoapMessage soapMessage = (SoapMessage) request;
|
||||
SoapHeader soapHeader = soapMessage.getSoapHeader();
|
||||
if (soapHeader != null) {
|
||||
Iterator<?> attributeIter = soapHeader.getAllAttributes();
|
||||
while (attributeIter.hasNext()) {
|
||||
QName name = (QName) attributeIter.next();
|
||||
builder.setHeader(name.toString(), soapHeader.getAttributeValue(name));
|
||||
}
|
||||
Iterator<?> elementIter = soapHeader.examineAllHeaderElements();
|
||||
while (elementIter.hasNext()) {
|
||||
Object element = elementIter.next();
|
||||
if (element instanceof SoapHeaderElement) {
|
||||
QName name = ((SoapHeaderElement) element).getName();
|
||||
builder.setHeader(name.toString(), element);
|
||||
}
|
||||
}
|
||||
Map<String, ?> headers = this.headerMapper.toHeaders(soapMessage.getSoapHeader());
|
||||
if (!CollectionUtils.isEmpty(headers)) {
|
||||
builder.copyHeaders(headers);
|
||||
}
|
||||
}
|
||||
Message<?> replyMessage = this.sendAndReceiveMessage(builder.build());
|
||||
@@ -120,17 +119,19 @@ public class SimpleWebServiceInboundGateway extends MessagingGatewaySupport impl
|
||||
+ replyPayload.getClass().getName() + "]");
|
||||
}
|
||||
WebServiceMessage response = messageContext.getResponse();
|
||||
if (response instanceof SoapMessage) {
|
||||
this.headerMapper.fromHeaders(
|
||||
replyMessage.getHeaders(), ((SoapMessage) response).getSoapHeader());
|
||||
}
|
||||
this.transformerSupportDelegate.transformSourceToResult(responseSource, response.getPayloadResult());
|
||||
}
|
||||
}
|
||||
|
||||
private class TransformerSupportDelegate extends TransformerObjectSupport {
|
||||
|
||||
private static class TransformerSupportDelegate extends TransformerObjectSupport {
|
||||
void transformSourceToResult(Source source, Result result) throws TransformerException {
|
||||
this.transform(source, result);
|
||||
}
|
||||
}
|
||||
|
||||
public String getComponentType() {
|
||||
return "ws:outbound-gateway";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ Import-Template:
|
||||
org.springframework.util;version="[3.0.3, 4.0.0)",
|
||||
org.springframework.oxm;version="[1.5.8.A, 3.1.0)",
|
||||
org.springframework.ws.*;version="[1.5.8.A, 2.0.0)",
|
||||
org.springframework.xml.transform;version="[1.5.8.A, 2.0.0)",
|
||||
org.springframework.xml.*;version="[1.5.8.A, 2.0.0)",
|
||||
org.apache.commons.logging;version="[1.1.1, 2.0.0)",
|
||||
org.w3c.dom.*;version="0",
|
||||
javax.xml.*;version="0"
|
||||
|
||||
Reference in New Issue
Block a user