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