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.wsdl.wsdl11.provider;
18  
19  import java.util.Iterator;
20  import java.util.Properties;
21  import javax.wsdl.Binding;
22  import javax.wsdl.BindingFault;
23  import javax.wsdl.BindingInput;
24  import javax.wsdl.BindingOperation;
25  import javax.wsdl.BindingOutput;
26  import javax.wsdl.Definition;
27  import javax.wsdl.Fault;
28  import javax.wsdl.Input;
29  import javax.wsdl.Output;
30  import javax.wsdl.Port;
31  import javax.wsdl.WSDLException;
32  import javax.wsdl.extensions.ExtensibilityElement;
33  import javax.wsdl.extensions.ExtensionRegistry;
34  import javax.wsdl.extensions.soap.SOAPAddress;
35  import javax.wsdl.extensions.soap.SOAPBinding;
36  import javax.wsdl.extensions.soap.SOAPBody;
37  import javax.wsdl.extensions.soap.SOAPFault;
38  import javax.wsdl.extensions.soap.SOAPOperation;
39  import javax.xml.namespace.QName;
40  
41  import org.springframework.util.Assert;
42  
43  /**
44   * Implementation of the [email protected] BindingsProvider} and [email protected] ServicesProvider} interfaces that are SOAP 1.1 specific.
45   * <p/>
46   * By setting the [email protected] #setSoapActions(java.util.Properties) soapActions} property, the SOAP Actions defined in the
47   * resulting WSDL can be set. Additionaly, the transport uri can be changed from the default HTTP transport by using the
48   * [email protected] #setTransportUri(String) transportUri} property.
49   *
50   * @author Arjen Poutsma
51   * @since 1.5.0
52   */
53  public class Soap11Provider extends DefaultConcretePartProvider {
54  
55      /** The default transport URI, which indicates an HTTP transport. */
56      public static final String DEFAULT_TRANSPORT_URI = "http://schemas.xmlsoap.org/soap/http";
57  
58      /** The prefix of the WSDL SOAP 1.1 namespace. */
59      public static final String SOAP_11_NAMESPACE_PREFIX = "soap";
60  
61      /** The WSDL SOAP 1.1 namespace. */
62      public static final String SOAP_11_NAMESPACE_URI = "http://schemas.xmlsoap.org/wsdl/soap/";
63  
64      private String transportUri = DEFAULT_TRANSPORT_URI;
65  
66      private Properties soapActions = new Properties();
67  
68      private String locationUri;
69  
70      /**
71       * Constructs a new version of the [email protected] Soap11Provider}.
72       * <p/>
73       * Sets the [email protected] #setBindingSuffix(String) binding suffix} to <code>Soap11</code>.
74       */
75      public Soap11Provider() {
76          setBindingSuffix("Soap11");
77      }
78  
79      /**
80       * Returns the SOAP Actions for this binding. Keys are [email protected] BindingOperation#getName() binding operation names};
81       * values are [email protected] javax.wsdl.extensions.soap.SOAPOperation#getSoapActionURI() SOAP Action URIs}.
82       *
83       * @return the soap actions
84       */
85      public Properties getSoapActions() {
86          return soapActions;
87      }
88  
89      /**
90       * Sets the SOAP Actions for this binding. Keys are [email protected] BindingOperation#getName() binding operation names};
91       * values are [email protected] javax.wsdl.extensions.soap.SOAPOperation#getSoapActionURI() SOAP Action URIs}.
92       *
93       * @param soapActions the soap
94       */
95      public void setSoapActions(Properties soapActions) {
96          Assert.notNull(soapActions, "'soapActions' must not be null");
97          this.soapActions = soapActions;
98      }
99  
100     /**
101      * Returns the value used for the binding transport attribute value. Defaults to [email protected] #DEFAULT_TRANSPORT_URI}.
102      *
103      * @return the binding transport value
104      */
105     public String getTransportUri() {
106         return transportUri;
107     }
108 
109     /**
110      * Sets the value used for the binding transport attribute value. Defaults to [email protected] #DEFAULT_TRANSPORT_URI}.
111      *
112      * @param transportUri the binding transport value
113      */
114     public void setTransportUri(String transportUri) {
115         Assert.notNull(transportUri, "'transportUri' must not be null");
116         this.transportUri = transportUri;
117     }
118 
119     /** Returns the value used for the SOAP Address location attribute value. */
120     public String getLocationUri() {
121         return locationUri;
122     }
123 
124     /** Sets the value used for the SOAP Address location attribute value. */
125     public void setLocationUri(String locationUri) {
126         this.locationUri = locationUri;
127     }
128 
129     /**
130      * Called after the [email protected] Binding} has been created, but before any sub-elements are added. Subclasses can override
131      * this method to define the binding name, or add extensions to it.
132      * <p/>
133      * Default implementation calls [email protected] DefaultConcretePartProvider#populateBinding(Definition, Binding)}, adds the
134      * SOAP 1.1 namespace, creates a [email protected] SOAPBinding}, and calls [email protected] #populateSoapBinding(SOAPBinding, Binding)}
135      * sets the binding name to the port type name with the [email protected] #getBindingSuffix() suffix} appended to it.
136      *
137      * @param definition the WSDL4J <code>Definition</code>
138      * @param binding    the WSDL4J <code>Binding</code>
139      */
140     @Override
141     protected void populateBinding(Definition definition, Binding binding) throws WSDLException {
142         definition.addNamespace(SOAP_11_NAMESPACE_PREFIX, SOAP_11_NAMESPACE_URI);
143         super.populateBinding(definition, binding);
144         SOAPBinding soapBinding = (SOAPBinding) createSoapExtension(definition, Binding.class, "binding");
145         populateSoapBinding(soapBinding, binding);
146         binding.addExtensibilityElement(soapBinding);
147     }
148 
149     /**
150      * Called after the [email protected] SOAPBinding} has been created.
151      * <p/>
152      * Default implementation sets the binding style to <code>"document"</code>, and set the transport URI to the [email protected]
153      * #setTransportUri(String) transportUri} property value. Subclasses can override this behavior.
154      *
155      * @param soapBinding the WSDL4J <code>SOAPBinding</code>
156      * @throws WSDLException in case of errors
157      * @see SOAPBinding#setStyle(String)
158      * @see SOAPBinding#setTransportURI(String)
159      * @see #setTransportUri(String)
160      * @see #DEFAULT_TRANSPORT_URI
161      */
162     protected void populateSoapBinding(SOAPBinding soapBinding, Binding binding) throws WSDLException {
163         soapBinding.setStyle("document");
164         soapBinding.setTransportURI(getTransportUri());
165     }
166 
167     /**
168      * Called after the [email protected] BindingFault} has been created. Subclasses can override this method to define the name,
169      * or add extensions to it.
170      * <p/>
171      * Default implementation calls [email protected] DefaultConcretePartProvider#populateBindingFault(Definition, BindingFault,
172      * Fault)}, creates a [email protected] SOAPFault}, and calls [email protected] #populateSoapFault(BindingFault, SOAPFault)}.
173      *
174      * @param definition   the WSDL4J <code>Definition</code>
175      * @param bindingFault the WSDL4J <code>BindingFault</code>
176      * @param fault        the corresponding WSDL4J <code>Fault</code> @throws WSDLException in case of errors
177      */
178     @Override
179     protected void populateBindingFault(Definition definition, BindingFault bindingFault, Fault fault)
180             throws WSDLException {
181         super.populateBindingFault(definition, bindingFault, fault);
182         SOAPFault soapFault = (SOAPFault) createSoapExtension(definition, BindingFault.class, "fault");
183         populateSoapFault(bindingFault, soapFault);
184         bindingFault.addExtensibilityElement(soapFault);
185     }
186 
187     /**
188      * Called after the [email protected] SOAPFault} has been created.
189      * <p/>
190      * Default implementation sets the use style to <code>"literal"</code>, and sets the name equal to the binding
191      * fault. Subclasses can override this behavior.
192      *
193      * @param bindingFault the WSDL4J <code>BindingFault</code>
194      * @param soapFault    the WSDL4J <code>SOAPFault</code>
195      * @throws WSDLException in case of errors
196      * @see SOAPFault#setUse(String)
197      */
198     protected void populateSoapFault(BindingFault bindingFault, SOAPFault soapFault) throws WSDLException {
199         soapFault.setName(bindingFault.getName());
200         soapFault.setUse("literal");
201     }
202 
203     /**
204      * Called after the [email protected] BindingInput} has been created. Subclasses can implement this method to define the name,
205      * or add extensions to it.
206      * <p/>
207      * Default implementation calls [email protected] DefaultConcretePartProvider#populateBindingInput(Definition,
208      * javax.wsdl.BindingInput, javax.wsdl.Input)}, creates a [email protected] SOAPBody}, and calls [email protected]
209      * #populateSoapBody(SOAPBody)}.
210      *
211      * @param definition   the WSDL4J <code>Definition</code>
212      * @param bindingInput the WSDL4J <code>BindingInput</code>
213      * @param input        the corresponding WSDL4J <code>Input</code> @throws WSDLException in case of errors
214      */
215     @Override
216     protected void populateBindingInput(Definition definition, BindingInput bindingInput, Input input)
217             throws WSDLException {
218         super.populateBindingInput(definition, bindingInput, input);
219         SOAPBody soapBody = (SOAPBody) createSoapExtension(definition, BindingInput.class, "body");
220         populateSoapBody(soapBody);
221         bindingInput.addExtensibilityElement(soapBody);
222     }
223 
224     /**
225      * Called after the [email protected] SOAPBody} has been created.
226      * <p/>
227      * Default implementation sets the use style to <code>"literal"</code>. Subclasses can override this behavior.
228      *
229      * @param soapBody the WSDL4J <code>SOAPBody</code>
230      * @throws WSDLException in case of errors
231      * @see SOAPBody#setUse(String)
232      */
233     protected void populateSoapBody(SOAPBody soapBody) throws WSDLException {
234         soapBody.setUse("literal");
235     }
236 
237     /**
238      * Called after the [email protected] BindingOperation} has been created, but before any sub-elements are added. Subclasses can
239      * implement this method to define the binding name, or add extensions to it.
240      * <p/>
241      * Default implementation calls [email protected] DefaultConcretePartProvider#populateBindingOperation(Definition,
242      * BindingOperation)}, creates a [email protected] SOAPOperation}, and calls [email protected] #populateSoapOperation} sets the name of
243      * the binding operation to the name of the operation.
244      *
245      * @param definition       the WSDL4J <code>Definition</code>
246      * @param bindingOperation the WSDL4J <code>BindingOperation</code>
247      * @throws WSDLException in case of errors
248      */
249     @Override
250     protected void populateBindingOperation(Definition definition, BindingOperation bindingOperation)
251             throws WSDLException {
252         super.populateBindingOperation(definition, bindingOperation);
253         SOAPOperation soapOperation =
254                 (SOAPOperation) createSoapExtension(definition, BindingOperation.class, "operation");
255         populateSoapOperation(soapOperation, bindingOperation);
256         bindingOperation.addExtensibilityElement(soapOperation);
257     }
258 
259     /**
260      * Called after the [email protected] SOAPOperation} has been created.
261      * <p/>
262      * Default implementation sets <code>SOAPAction</code> to the corresponding [email protected]
263      * #setSoapActions(java.util.Properties) soapActions} property, and defaults to "".
264      *
265      * @param soapOperation    the WSDL4J <code>SOAPOperation</code>
266      * @param bindingOperation the WSDL4J <code>BindingOperation</code>
267      * @throws WSDLException in case of errors
268      * @see SOAPOperation#setSoapActionURI(String)
269      * @see #setSoapActions(java.util.Properties)
270      */
271     protected void populateSoapOperation(SOAPOperation soapOperation, BindingOperation bindingOperation)
272             throws WSDLException {
273         String bindingOperationName = bindingOperation.getName();
274         String soapAction = getSoapActions().getProperty(bindingOperationName, "");
275         soapOperation.setSoapActionURI(soapAction);
276     }
277 
278     /**
279      * Called after the [email protected] BindingInput} has been created. Subclasses can implement this method to define the name,
280      * or add extensions to it.
281      * <p/>
282      * Default implementation calls [email protected] DefaultConcretePartProvider#populateBindingOutput(Definition, BindingOutput,
283      * Output)}, creates a [email protected] SOAPBody}, and calls [email protected] #populateSoapBody(SOAPBody)}.
284      *
285      * @param definition    the WSDL4J <code>Definition</code>
286      * @param bindingOutput the WSDL4J <code>BindingOutput</code>
287      * @param output        the corresponding WSDL4J <code>Output</code> @throws WSDLException in case of errors
288      */
289     @Override
290     protected void populateBindingOutput(Definition definition, BindingOutput bindingOutput, Output output)
291             throws WSDLException {
292         super.populateBindingOutput(definition, bindingOutput, output);
293         SOAPBody soapBody = (SOAPBody) createSoapExtension(definition, BindingOutput.class, "body");
294         populateSoapBody(soapBody);
295         bindingOutput.addExtensibilityElement(soapBody);
296     }
297 
298     /**
299      * Called after the [email protected] Port} has been created, but before any sub-elements are added. Subclasses can implement
300      * this method to define the port name, or add extensions to it.
301      * <p/>
302      * Default implementation calls [email protected] DefaultConcretePartProvider#populatePort(javax.wsdl.Definition,javax.wsdl.Port)},
303      * creates a [email protected] SOAPAddress}, and calls [email protected] #populateSoapAddress(SOAPAddress)}.
304      *
305      * @param port the WSDL4J <code>Port</code>
306      * @throws WSDLException in case of errors
307      */
308     @Override
309     protected void populatePort(Definition definition, Port port) throws WSDLException {
310         for (Iterator<?> iterator = port.getBinding().getExtensibilityElements().iterator(); iterator.hasNext();) {
311             if (iterator.next() instanceof SOAPBinding) {
312                 // this is a SOAP 1.1 binding, create a SOAP Address for it 
313                 super.populatePort(definition, port);
314                 SOAPAddress soapAddress = (SOAPAddress) createSoapExtension(definition, Port.class, "address");
315                 populateSoapAddress(soapAddress);
316                 port.addExtensibilityElement(soapAddress);
317                 return;
318             }
319         }
320     }
321 
322     /**
323      * Called after the [email protected] SOAPAddress} has been created. Default implementation sets the location URI to the value
324      * set on this builder. Subclasses can override this behavior.
325      *
326      * @param soapAddress the WSDL4J <code>SOAPAddress</code>
327      * @throws WSDLException in case of errors
328      * @see SOAPAddress#setLocationURI(String)
329      * @see #setLocationUri(String)
330      */
331     protected void populateSoapAddress(SOAPAddress soapAddress) throws WSDLException {
332         soapAddress.setLocationURI(getLocationUri());
333     }
334 
335     /**
336      * Creates a SOAP extensibility element.
337      *
338      * @param definition the WSDL4J <code>Definition</code>
339      * @param parentType a class object indicating where in the WSDL definition this extension will exist
340      * @param localName  the local name of the extensibility element
341      * @return the extensibility element
342      * @throws WSDLException in case of errors
343      * @see ExtensionRegistry#createExtension(Class, QName)
344      */
345     private ExtensibilityElement createSoapExtension(Definition definition, Class<?> parentType, String localName)
346             throws WSDLException {
347         return definition.getExtensionRegistry()
348                 .createExtension(parentType, new QName(SOAP_11_NAMESPACE_URI, localName));
349     }
350 
351 }