View Javadoc

1   /*
2    * Copyright 2005-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.client.support.destination;
18  
19  import java.io.IOException;
20  import java.net.URI;
21  import java.util.HashMap;
22  import java.util.Map;
23  import javax.xml.transform.Transformer;
24  import javax.xml.transform.TransformerException;
25  import javax.xml.transform.TransformerFactory;
26  import javax.xml.transform.dom.DOMResult;
27  
28  import org.w3c.dom.Document;
29  
30  import org.springframework.core.io.Resource;
31  import org.springframework.util.Assert;
32  import org.springframework.ws.client.WebServiceIOException;
33  import org.springframework.ws.client.WebServiceTransformerException;
34  import org.springframework.xml.transform.ResourceSource;
35  import org.springframework.xml.xpath.XPathExpression;
36  import org.springframework.xml.xpath.XPathExpressionFactory;
37  
38  /**
39   * Implementation of the {@link DestinationProvider} that resolves a destination URI from a WSDL file.
40   * <p/>
41   * The extraction relies on an XPath expression to locate the URI. By default, the {@link
42   * #DEFAULT_WSDL_LOCATION_EXPRESSION} will be used, but this expression can be overridden by setting the {@link
43   * #setLocationExpression(String) locationExpression} property.
44   *
45   * @author Tareq Abed Rabbo
46   * @author Arjen Poutsma
47   * @since 1.5.4
48   */
49  public class Wsdl11DestinationProvider extends AbstractCachingDestinationProvider {
50  
51      /** Default XPath expression used for extracting all <code>location</code> attributes from the WSDL definition. */
52      public static final String DEFAULT_WSDL_LOCATION_EXPRESSION =
53              "/wsdl:definitions/wsdl:service/wsdl:port/soap:address/@location";
54  
55      private static TransformerFactory transformerFactory = TransformerFactory.newInstance();
56  
57      private Map<String, String> expressionNamespaces = new HashMap<String, String>();
58  
59      private XPathExpression locationXPathExpression;
60  
61      private Resource wsdlResource;
62  
63      public Wsdl11DestinationProvider() {
64          expressionNamespaces.put("wsdl", "http://schemas.xmlsoap.org/wsdl/");
65          expressionNamespaces.put("soap", "http://schemas.xmlsoap.org/wsdl/soap/");
66          expressionNamespaces.put("soap12", "http://schemas.xmlsoap.org/wsdl/soap12/");
67  
68          locationXPathExpression = XPathExpressionFactory
69                  .createXPathExpression(DEFAULT_WSDL_LOCATION_EXPRESSION, expressionNamespaces);
70      }
71  
72      /** Sets a WSDL location from which the service destination <code>URI</code> will be resolved. */
73      public void setWsdl(Resource wsdlResource) {
74          Assert.notNull(wsdlResource, "'wsdl' must not be null");
75          Assert.isTrue(wsdlResource.exists(), wsdlResource + " does not exist");
76          this.wsdlResource = wsdlResource;
77      }
78  
79      /**
80       * Sets the XPath expression to use when extracting the service location <code>URI</code> from a WSDL.
81       * <p/>
82       * The expression can use the following bound prefixes: <blockquote> <table> <tr><th>Prefix</th><th>Namespace</th></tr>
83       * <tr><td><code>wsdl</code></td><td><code>http://schemas.xmlsoap.org/wsdl/</code></td></tr>
84       * <tr><td><code>soap</code></td><td><code>http://schemas.xmlsoap.org/wsdl/soap/</code></td></tr>
85       * <tr><td><code>soap12</code></td><td><code>http://schemas.xmlsoap.org/wsdl/soap12/</code></td></tr>
86       * </table></blockquote>
87       * <p/>
88       * Defaults to {@link #DEFAULT_WSDL_LOCATION_EXPRESSION}.
89       */
90      public void setLocationExpression(String expression) {
91          Assert.hasText(expression, "'expression' must not be empty");
92          locationXPathExpression = XPathExpressionFactory
93                  .createXPathExpression(expression, expressionNamespaces);
94      }
95  
96      @Override
97      protected URI lookupDestination() {
98          try {
99              DOMResult result = new DOMResult();
100             Transformer transformer = transformerFactory.newTransformer();
101             transformer.transform(new ResourceSource(wsdlResource), result);
102             Document definitionDocument = (Document) result.getNode();
103             String location = locationXPathExpression.evaluateAsString(definitionDocument);
104             if (logger.isDebugEnabled()) {
105                 logger.debug("Found location [" + location + "] in " + wsdlResource);
106             }
107             return location != null ? URI.create(location) : null;
108         }
109         catch (IOException ex) {
110             throw new WebServiceIOException("Error extracting location from WSDL [" + wsdlResource + "]", ex);
111         }
112         catch (TransformerException ex) {
113             throw new WebServiceTransformerException("Error extracting location from WSDL [" + wsdlResource + "]", ex);
114         }
115     }
116 
117 }