11/*
2- * Copyright 2005-2010 the original author or authors.
2+ * Copyright 2005-2012 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
66 * You may obtain a copy of the License at
77 *
8- * http://www.apache.org/licenses/LICENSE-2.0
8+ * http://www.apache.org/licenses/LICENSE-2.0
99 *
1010 * Unless required by applicable law or agreed to in writing, software
1111 * distributed under the License is distributed on an "AS IS" BASIS,
4343import org .w3c .dom .Node ;
4444
4545/**
46- * Adapter to use the < code> WsdlDefinition</code> interface with the generic < code> DispatcherServlet</code> .
46+ * Adapter to use the {@ code WsdlDefinition} interface with the generic {@ code DispatcherServlet} .
4747 * <p/>
48- * Reads the source from the mapped < code> WsdlDefinition</code> implementation, and writes that as the result to the
49- * < code> HttpServletResponse</code> .
48+ * Reads the source from the mapped {@ code WsdlDefinition} implementation, and writes that as the result to the
49+ * {@ code HttpServletResponse} .
5050 * <p/>
51- * If the property < code> transformLocations</code> is set to < code> true</code> , this adapter will change
52- * < code> location</code> attributes in the WSDL definition to reflect the URL of the incoming request. If the location
51+ * If the property {@ code transformLocations} is set to {@ code true} , this adapter will change
52+ * {@ code location} attributes in the WSDL definition to reflect the URL of the incoming request. If the location
5353 * field in the original WSDL is an absolute path, the scheme, hostname, and port will be changed. If the location is a
5454 * relative path, the scheme, hostname, port, and context path will be prepended. This behavior can be customized by
55- * overriding the < code> transformLocation()</code> method.
55+ * overriding the {@ code transformLocation()} method.
5656 * <p/>
57- * For instance, if the location attribute defined in the WSDL is < code> http://localhost:8080/context/services/myService</code> ,
58- * and the request URI for the WSDL is < code> http://example.com/context/myService.wsdl</code> , the location will be
59- * changed to < code> http://example.com/context/services/myService</code> .
57+ * For instance, if the location attribute defined in the WSDL is {@ code http://localhost:8080/context/services/myService} ,
58+ * and the request URI for the WSDL is {@ code http://example.com/context/myService.wsdl} , the location will be
59+ * changed to {@ code http://example.com/context/services/myService} .
6060 * <p/>
61- * If the location attribute defined in the WSDL is < code> /services/myService</code> , and the request URI for the WSDL
62- * is < code> http://example.com:8080/context/myService.wsdl</code> , the location will be changed to
63- * < code> http://example.com:8080/context/services/myService</code> .
61+ * If the location attribute defined in the WSDL is {@ code /services/myService} , and the request URI for the WSDL
62+ * is {@ code http://example.com:8080/context/myService.wsdl} , the location will be changed to
63+ * {@ code http://example.com:8080/context/services/myService} .
6464 * <p/>
65- * When < code> transformLocations</code> is enabled, all < code> location</code> attributes found in the WSDL definition
66- * are changed by default. This behavior can be customized by changing the < code> locationExpression</code> property,
65+ * When {@ code transformLocations} is enabled, all {@ code location} attributes found in the WSDL definition
66+ * are changed by default. This behavior can be customized by changing the {@ code locationExpression} property,
6767 * which is an XPath expression that matches the attributes to change.
6868 *
6969 * @author Arjen Poutsma
7575 */
7676public class WsdlDefinitionHandlerAdapter extends TransformerObjectSupport implements HandlerAdapter , InitializingBean {
7777
78- /** Default XPath expression used for extracting all < code> location</code> attributes from the WSDL definition. */
78+ /** Default XPath expression used for extracting all {@ code location} attributes from the WSDL definition. */
7979 public static final String DEFAULT_LOCATION_EXPRESSION = "//@location" ;
8080
81+ /** Default XPath expression used for extracting all {@code schemaLocation} attributes from the WSDL definition. */
82+ public static final String DEFAULT_SCHEMA_LOCATION_EXPRESSION = "//@schemaLocation" ;
83+
8184 private static final String CONTENT_TYPE = "text/xml" ;
8285
8386 private static final Log logger = LogFactory .getLog (WsdlDefinitionHandlerAdapter .class );
@@ -86,29 +89,50 @@ public class WsdlDefinitionHandlerAdapter extends TransformerObjectSupport imple
8689
8790 private String locationExpression = DEFAULT_LOCATION_EXPRESSION ;
8891
92+ private String schemaLocationExpression = DEFAULT_SCHEMA_LOCATION_EXPRESSION ;
93+
8994 private XPathExpression locationXPathExpression ;
9095
96+ private XPathExpression schemaLocationXPathExpression ;
97+
9198 private boolean transformLocations = false ;
9299
100+ private boolean transformSchemaLocations = false ;
101+
93102 /**
94- * Sets the XPath expression used for extracting the < code> location</code> attributes from the WSDL 1.1 definition.
103+ * Sets the XPath expression used for extracting the {@ code location} attributes from the WSDL 1.1 definition.
95104 * <p/>
96- * Defaults to <code>DEFAULT_LOCATION_EXPRESSION</code>.
97- *
98- * @see #DEFAULT_LOCATION_EXPRESSION
105+ * Defaults to {@code DEFAULT_LOCATION_EXPRESSION}.
99106 */
100107 public void setLocationExpression (String locationExpression ) {
101108 this .locationExpression = locationExpression ;
102109 }
103110
111+ /**
112+ * Sets the XPath expression used for extracting the {@code schemaLocation} attributes from the WSDL 1.1 definition.
113+ * <p/>
114+ * Defaults to {@code DEFAULT_SCHEMA_LOCATION_EXPRESSION}.
115+ */
116+ public void setSchemaLocationExpression (String schemaLocationExpression ) {
117+ this .schemaLocationExpression = schemaLocationExpression ;
118+ }
119+
104120 /**
105121 * Sets whether relative address locations in the WSDL are to be transformed using the request URI of the incoming
106- * < code> HttpServletRequest</code> . Defaults to < code> false</code> .
122+ * {@ code HttpServletRequest} . Defaults to {@ code false} .
107123 */
108124 public void setTransformLocations (boolean transformLocations ) {
109125 this .transformLocations = transformLocations ;
110126 }
111127
128+ /**
129+ * Sets whether relative address schema locations in the WSDL are to be transformed using the request URI of the
130+ * incoming {@code HttpServletRequest}. Defaults to {@code false}.
131+ */
132+ public void setTransformSchemaLocations (boolean transformSchemaLocations ) {
133+ this .transformSchemaLocations = transformSchemaLocations ;
134+ }
135+
112136 public long getLastModified (HttpServletRequest request , Object handler ) {
113137 Source definitionSource = ((WsdlDefinition ) handler ).getSource ();
114138 return LastModifiedHelper .getLastModified (definitionSource );
@@ -117,17 +141,25 @@ public long getLastModified(HttpServletRequest request, Object handler) {
117141 public ModelAndView handle (HttpServletRequest request , HttpServletResponse response , Object handler )
118142 throws Exception {
119143 if (HttpTransportConstants .METHOD_GET .equals (request .getMethod ())) {
120- response .setContentType (CONTENT_TYPE );
121- Transformer transformer = createTransformer ();
122144 WsdlDefinition definition = (WsdlDefinition ) handler ;
145+
146+ Transformer transformer = createTransformer ();
123147 Source definitionSource = definition .getSource ();
124- if (transformLocations ) {
148+
149+ if (transformLocations || transformSchemaLocations ) {
125150 DOMResult domResult = new DOMResult ();
126151 transformer .transform (definitionSource , domResult );
127152 Document definitionDocument = (Document ) domResult .getNode ();
128- transformLocations (definitionDocument , request );
153+ if (transformLocations ) {
154+ transformLocations (definitionDocument , request );
155+ }
156+ if (transformSchemaLocations ) {
157+ transformSchemaLocations (definitionDocument , request );
158+ }
129159 definitionSource = new DOMSource (definitionDocument );
130160 }
161+
162+ response .setContentType (CONTENT_TYPE );
131163 StreamResult responseResult = new StreamResult (response .getOutputStream ());
132164 transformer .transform (definitionSource , responseResult );
133165 }
@@ -144,22 +176,72 @@ public boolean supports(Object handler) {
144176 public void afterPropertiesSet () throws Exception {
145177 locationXPathExpression =
146178 XPathExpressionFactory .createXPathExpression (locationExpression , expressionNamespaces );
179+ schemaLocationXPathExpression =
180+ XPathExpressionFactory .createXPathExpression (schemaLocationExpression , expressionNamespaces );
181+ }
182+
183+ /**
184+ * Transforms all {@code location} attributes to reflect the server name given {@code HttpServletRequest}.
185+ * Determines the suitable attributes by evaluating the defined XPath expression, and delegates to
186+ * {@code transformLocation} to do the transformation for all attributes that match.
187+ * <p/>
188+ * This method is only called when the {@code transformLocations} property is true.
189+ *
190+ * @see #setLocationExpression(String)
191+ * @see #setTransformLocations(boolean)
192+ * @see #transformLocation(String,javax.servlet.http.HttpServletRequest)
193+ */
194+ protected void transformLocations (Document definitionDocument , HttpServletRequest request ) throws Exception {
195+ transformLocationsInternal (locationXPathExpression , definitionDocument , request );
196+ }
197+
198+ /**
199+ * Transforms all {@code schemaLocation} attributes to reflect the server name given {@code HttpServletRequest}.
200+ * Determines the suitable attributes by evaluating the defined XPath expression, and delegates to
201+ * {@code transformLocation} to do the transformation for all attributes that match.
202+ * <p/>
203+ * This method is only called when the {@code transformSchemaLocations} property is true.
204+ *
205+ * @see #setSchemaLocationExpression(String)
206+ * @see #setTransformSchemaLocations(boolean)
207+ * @see #transformLocation(String,javax.servlet.http.HttpServletRequest)
208+ */
209+ protected void transformSchemaLocations (Document definitionDocument , HttpServletRequest request ) throws Exception {
210+ transformLocationsInternal (schemaLocationXPathExpression , definitionDocument , request );
147211 }
148212
213+ private void transformLocationsInternal (XPathExpression xPathExpression ,
214+ Document definitionDocument ,
215+ HttpServletRequest request ) throws Exception {
216+ List <Node > locationNodes = xPathExpression .evaluateAsNodeList (definitionDocument );
217+ for (Node locationNode : locationNodes ) {
218+ if (locationNode instanceof Attr ) {
219+ Attr location = (Attr ) locationNode ;
220+ if (StringUtils .hasLength (location .getValue ())) {
221+ String newLocation = transformLocation (location .getValue (), request );
222+ if (logger .isDebugEnabled ()) {
223+ logger .debug ("Transforming [" + location .getValue () + "] to [" + newLocation + "]" );
224+ }
225+ location .setValue (newLocation );
226+ }
227+ }
228+ }
229+ }
230+
149231 /**
150232 * Transform the given location string to reflect the given request. If the given location is a full url, the
151233 * scheme, server name, and port are changed. If it is a relative url, the scheme, server name, and port are
152234 * prepended. Can be overridden in subclasses to change this behavior.
153235 * <p/>
154- * For instance, if the location attribute defined in the WSDL is < code> http://localhost:8080/context/services/myService</code> ,
155- * and the request URI for the WSDL is < code> http://example.com:8080 /context/myService.wsdl</code> , the location
156- * will be changed to < code> http://example.com:8080 /context/services/myService</code> .
236+ * For instance, if the location attribute defined in the WSDL is {@ code http://localhost:8080/context/services/myService} ,
237+ * and the request URI for the WSDL is {@ code http://example.com:80 /context/myService.wsdl} , the location
238+ * will be changed to {@ code http://example.com:80 /context/services/myService} .
157239 * <p/>
158- * If the location attribute defined in the WSDL is < code> /services/myService</code> , and the request URI for the
159- * WSDL is < code> http://example.com:8080/context/myService.wsdl</code> , the location will be changed to
160- * < code> http://example.com:8080/context/services/myService</code> .
240+ * If the location attribute defined in the WSDL is {@ code /services/myService} , and the request URI for the
241+ * WSDL is {@ code http://example.com:8080/context/myService.wsdl} , the location will be changed to
242+ * {@ code http://example.com:8080/context/services/myService} .
161243 * <p/>
162- * This method is only called when the < code> transformLocations</code> property is true.
244+ * This method is only called when the {@ code transformLocations} property is true.
163245 */
164246 protected String transformLocation (String location , HttpServletRequest request ) {
165247 StringBuilder url = new StringBuilder (request .getScheme ());
@@ -184,31 +266,4 @@ protected String transformLocation(String location, HttpServletRequest request)
184266 // unknown location, return the original
185267 return location ;
186268 }
187-
188- /**
189- * Transforms all <code>location</code> attributes to reflect the server name given <code>HttpServletRequest</code>.
190- * Determines the suitable attributes by evaluating the defined XPath expression, and delegates to
191- * <code>transformLocation</code> to do the transformation for all attributes that match.
192- * <p/>
193- * This method is only called when the <code>transformLocations</code> property is true.
194- *
195- * @see #setLocationExpression(String)
196- * @see #setTransformLocations(boolean)
197- * @see #transformLocation(String,javax.servlet.http.HttpServletRequest)
198- */
199- protected void transformLocations (Document definitionDocument , HttpServletRequest request ) throws Exception {
200- List <Node > locationNodes = locationXPathExpression .evaluateAsNodeList (definitionDocument );
201- for (Node locationNode : locationNodes ) {
202- if (locationNode instanceof Attr ) {
203- Attr location = (Attr ) locationNode ;
204- if (StringUtils .hasLength (location .getValue ())) {
205- String newLocation = transformLocation (location .getValue (), request );
206- if (logger .isDebugEnabled ()) {
207- logger .debug ("Transforming [" + location .getValue () + "] to [" + newLocation + "]" );
208- }
209- location .setValue (newLocation );
210- }
211- }
212- }
213- }
214269}
0 commit comments