/* * Copyright 2005-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.ws.client.support.destination; import java.io.IOException; import java.net.URI; import java.util.HashMap; import java.util.Map; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; import org.w3c.dom.Document; import org.springframework.core.io.Resource; import org.springframework.util.Assert; import org.springframework.ws.client.WebServiceIOException; import org.springframework.ws.client.WebServiceTransformerException; import org.springframework.xml.transform.ResourceSource; import org.springframework.xml.xpath.XPathExpression; import org.springframework.xml.xpath.XPathExpressionFactory; /** * Implementation of the {@link DestinationProvider} that resolves a destination URI from a WSDL file. * * <p>The extraction relies on an XPath expression to locate the URI. By default, the {@link * #DEFAULT_WSDL_LOCATION_EXPRESSION} will be used, but this expression can be overridden by setting the {@link * #setLocationExpression(String) locationExpression} property. * * @author Tareq Abed Rabbo * @author Arjen Poutsma * @since 1.5.4 */ public class Wsdl11DestinationProvider extends AbstractCachingDestinationProvider { /** Default XPath expression used for extracting all {@code location} attributes from the WSDL definition. */ public static final String DEFAULT_WSDL_LOCATION_EXPRESSION = "/wsdl:definitions/wsdl:service/wsdl:port/soap:address/@location"; private static TransformerFactory transformerFactory = TransformerFactory.newInstance(); private Map<String, String> expressionNamespaces = new HashMap<String, String>(); private XPathExpression locationXPathExpression; private Resource wsdlResource; public Wsdl11DestinationProvider() { expressionNamespaces.put("wsdl", "http://schemas.xmlsoap.org/wsdl/"); expressionNamespaces.put("soap", "http://schemas.xmlsoap.org/wsdl/soap/"); expressionNamespaces.put("soap12", "http://schemas.xmlsoap.org/wsdl/soap12/"); locationXPathExpression = XPathExpressionFactory .createXPathExpression(DEFAULT_WSDL_LOCATION_EXPRESSION, expressionNamespaces); } /** Sets a WSDL location from which the service destination {@code URI} will be resolved. */ public void setWsdl(Resource wsdlResource) { Assert.notNull(wsdlResource, "'wsdl' must not be null"); Assert.isTrue(wsdlResource.exists(), wsdlResource + " does not exist"); this.wsdlResource = wsdlResource; } /** * Sets the XPath expression to use when extracting the service location {@code URI} from a WSDL. * * <p>The expression can use the following bound prefixes: <blockquote> <table> <tr><th>Prefix</th><th>Namespace</th></tr> * <tr><td>{@code wsdl}</td><td>{@code http://schemas.xmlsoap.org/wsdl/}</td></tr> * <tr><td>{@code soap}</td><td>{@code http://schemas.xmlsoap.org/wsdl/soap/}</td></tr> * <tr><td>{@code soap12}</td><td>{@code http://schemas.xmlsoap.org/wsdl/soap12/}</td></tr> * </table></blockquote> * * <p>Defaults to {@link #DEFAULT_WSDL_LOCATION_EXPRESSION}. */ public void setLocationExpression(String expression) { Assert.hasText(expression, "'expression' must not be empty"); locationXPathExpression = XPathExpressionFactory .createXPathExpression(expression, expressionNamespaces); } @Override protected URI lookupDestination() { try { DOMResult result = new DOMResult(); Transformer transformer = transformerFactory.newTransformer(); transformer.transform(new ResourceSource(wsdlResource), result); Document definitionDocument = (Document) result.getNode(); String location = locationXPathExpression.evaluateAsString(definitionDocument); if (logger.isDebugEnabled()) { logger.debug("Found location [" + location + "] in " + wsdlResource); } return location != null ? URI.create(location) : null; } catch (IOException ex) { throw new WebServiceIOException("Error extracting location from WSDL [" + wsdlResource + "]", ex); } catch (TransformerException ex) { throw new WebServiceTransformerException("Error extracting location from WSDL [" + wsdlResource + "]", ex); } } }