/* * Copyright 2002-2017 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.config; import java.util.List; import org.w3c.dom.Element; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.ExpressionFactoryBean; import org.springframework.integration.config.xml.AbstractOutboundGatewayParser; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.springframework.integration.ws.DefaultSoapHeaderMapper; import org.springframework.integration.ws.MarshallingWebServiceOutboundGateway; import org.springframework.integration.ws.SimpleWebServiceOutboundGateway; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; /** * Parser for the <outbound-gateway/> element in the 'ws' namespace. * * @author Mark Fisher * @author Jonas Partner * @author Gunnar Hillert * @author Artem Bilan * */ public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayParser { @Override protected String getGatewayClassName(Element element) { return ((StringUtils.hasText(element.getAttribute("marshaller"))) ? MarshallingWebServiceOutboundGateway.class : SimpleWebServiceOutboundGateway.class).getName(); } @Override protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(this.getGatewayClassName(element)); String uri = element.getAttribute("uri"); String destinationProvider = element.getAttribute("destination-provider"); List<Element> uriVariableElements = DomUtils.getChildElementsByTagName(element, "uri-variable"); if (StringUtils.hasText(destinationProvider) == StringUtils.hasText(uri)) { parserContext.getReaderContext().error( "Exactly one of 'uri' or 'destination-provider' is required.", element); } if (StringUtils.hasText(destinationProvider)) { if (!CollectionUtils.isEmpty(uriVariableElements)) { parserContext.getReaderContext().error("No 'uri-variable' sub-elements are allowed when " + "a 'destination-provider' reference has been provided.", element); } builder.addConstructorArgReference(destinationProvider); } else { builder.addConstructorArgValue(uri); if (!CollectionUtils.isEmpty(uriVariableElements)) { ManagedMap<String, Object> uriVariableExpressions = new ManagedMap<String, Object>(); for (Element uriVariableElement : uriVariableElements) { String name = uriVariableElement.getAttribute("name"); String expression = uriVariableElement.getAttribute("expression"); BeanDefinitionBuilder factoryBeanBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class); factoryBeanBuilder.addConstructorArgValue(expression); uriVariableExpressions.put(name, factoryBeanBuilder.getBeanDefinition()); } builder.addPropertyValue("uriVariableExpressions", uriVariableExpressions); } } IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout", "sendTimeout"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-empty-responses"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encode-uri"); this.postProcessGateway(builder, element, parserContext); IntegrationNamespaceUtils.configureHeaderMapper(element, builder, parserContext, DefaultSoapHeaderMapper.class, null); return builder; } @Override protected void postProcessGateway(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) { String marshallerRef = element.getAttribute("marshaller"); String unmarshallerRef = element.getAttribute("unmarshaller"); if (StringUtils.hasText(marshallerRef)) { builder.addConstructorArgReference(marshallerRef); if (StringUtils.hasText(unmarshallerRef)) { builder.addConstructorArgReference(unmarshallerRef); } } else { String sourceExtractorRef = element.getAttribute("source-extractor"); if (StringUtils.hasText(sourceExtractorRef)) { builder.addConstructorArgReference(sourceExtractorRef); } else { builder.addConstructorArgValue(null); } } IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "request-callback"); String webServiceTemplateRef = element.getAttribute("web-service-template"); if (StringUtils.hasText(webServiceTemplateRef)) { builder.addPropertyReference("webServiceTemplate", webServiceTemplateRef); return; } String messageFactoryRef = element.getAttribute("message-factory"); if (StringUtils.hasText(messageFactoryRef)) { builder.addConstructorArgReference(messageFactoryRef); } IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "fault-message-resolver"); String messageSenderRef = element.getAttribute("message-sender"); String messageSenderListRef = element.getAttribute("message-senders"); if (StringUtils.hasText(messageSenderRef) && StringUtils.hasText(messageSenderListRef)) { parserContext.getReaderContext().error( "Only one of message-sender or message-senders should be specified.", element); } if (StringUtils.hasText(messageSenderRef)) { builder.addPropertyReference("messageSender", messageSenderRef); } if (StringUtils.hasText(messageSenderListRef)) { builder.addPropertyReference("messageSenders", messageSenderListRef); } String interceptorRef = element.getAttribute("interceptor"); String interceptorListRef = element.getAttribute("interceptors"); if (StringUtils.hasText(interceptorRef) && StringUtils.hasText(interceptorListRef)) { parserContext.getReaderContext().error( "Only one of interceptor or interceptors should be specified.", element); } if (StringUtils.hasText(interceptorRef)) { builder.addPropertyReference("interceptors", interceptorRef); } if (StringUtils.hasText(interceptorListRef)) { builder.addPropertyReference("interceptors", interceptorListRef); } if (StringUtils.hasText(marshallerRef) || StringUtils.hasText(unmarshallerRef)) { String extractPayload = element.getAttribute("extract-payload"); if (StringUtils.hasText(extractPayload)) { parserContext.getReaderContext() .warning("Setting 'extract-payload' attribute has no effect when used with " + "a marshalling Web Service Outbound Gateway.", element); } } else { IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); } } }