View Javadoc

1   package org.codehaus.xfire.wsdl11.builder;
2   
3   import java.util.ArrayList;
4   import java.util.HashMap;
5   import java.util.Iterator;
6   import java.util.List;
7   import java.util.Map;
8   import java.io.OutputStream;
9   import java.io.IOException;
10  
11  import javax.wsdl.Binding;
12  import javax.wsdl.BindingInput;
13  import javax.wsdl.BindingOperation;
14  import javax.wsdl.Definition;
15  import javax.wsdl.Input;
16  import javax.wsdl.Message;
17  import javax.wsdl.Output;
18  import javax.wsdl.Part;
19  import javax.wsdl.Port;
20  import javax.wsdl.PortType;
21  import javax.wsdl.WSDLException;
22  import javax.wsdl.extensions.soap.SOAPHeader;
23  import javax.xml.namespace.QName;
24  
25  import org.codehaus.xfire.service.MessageHeaderInfo;
26  import org.codehaus.xfire.service.MessageInfo;
27  import org.codehaus.xfire.service.MessagePartInfo;
28  import org.codehaus.xfire.service.OperationInfo;
29  import org.codehaus.xfire.service.Service;
30  import org.codehaus.xfire.soap.SoapConstants;
31  import org.codehaus.xfire.transport.Transport;
32  import org.codehaus.xfire.transport.TransportManager;
33  import org.codehaus.xfire.wsdl.SchemaType;
34  import org.codehaus.xfire.wsdl.WSDLWriter;
35  import org.codehaus.xfire.wsdl11.WSDL11ParameterBinding;
36  import org.codehaus.xfire.wsdl11.WSDL11Transport;
37  import org.codehaus.xfire.XFireRuntimeException;
38  import org.codehaus.yom.Attribute;
39  import org.codehaus.yom.Element;
40  
41  import com.ibm.wsdl.extensions.soap.SOAPHeaderImpl;
42  
43  /***
44   * WSDL
45   *
46   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
47   */
48  public class WSDLBuilder
49      extends org.codehaus.xfire.wsdl11.builder.AbstractWSDL
50      implements WSDLWriter
51  {
52      private PortType portType;
53  
54      private Binding binding;
55  
56      private TransportManager transportManager;
57  
58      private Map wsdlOps = new HashMap();
59  
60      private WSDL11ParameterBinding paramBinding;
61  
62      private List declaredParameters = new ArrayList();
63  
64      public WSDLBuilder(Service service,
65                         TransportManager transportManager,
66                         WSDL11ParameterBinding paramBinding) throws WSDLException
67      {
68          super(service);
69  
70          this.transportManager = transportManager;
71          this.paramBinding = paramBinding;
72  
73      }
74  
75      public void write(OutputStream out) throws IOException
76      {
77          try
78          {
79              PortType portType = createAbstractInterface();
80  
81              createConcreteInterface(portType);
82  
83              writeDocument();
84          } catch (WSDLException e)
85          {
86              throw new XFireRuntimeException("error creating wsdl", e);
87          }
88          super.write(out);
89      }
90  
91      public PortType createAbstractInterface()
92          throws WSDLException
93      {
94          Service service = getService();
95          Definition def = getDefinition();
96  
97          QName portName = new QName(getInfo().getTargetNamespace(), getInfo().getPortType());
98  
99          portType = def.createPortType();
100         portType.setQName(portName);
101         portType.setUndefined(false);
102         def.addPortType(portType);
103 
104         // Create Abstract operations
105         for (Iterator itr = service.getServiceInfo().getOperations().iterator(); itr.hasNext();)
106         {
107             OperationInfo op = (OperationInfo) itr.next();
108 
109             // Create input message
110             Message req = createInputMessage(op);
111             def.addMessage(req);
112 
113             // Create output message if we have an out MEP
114             Message res = null;
115             if (op.getMEP().equals(SoapConstants.MEP_ROBUST_IN_OUT))
116             {
117                 res = createOutputMessage(op);
118                 def.addMessage(res);
119             }
120 
121             javax.wsdl.Operation wsdlOp = createOperation(op, req, res);
122             wsdlOp.setUndefined(false);
123             portType.addOperation(wsdlOp);
124 
125             wsdlOps.put(op.getName(), wsdlOp);
126         }
127 
128         return portType;
129     }
130 
131     public void createConcreteInterface(PortType portType)
132     {
133         Service service = getService();
134         Definition def = getDefinition();
135 
136         QName name = new QName(getInfo().getTargetNamespace(), getInfo().getServiceName());
137 
138         // Create a concrete instance for each transport.
139         javax.wsdl.Service wsdlService = def.createService();
140         wsdlService.setQName(name);
141 
142         for (Iterator itr = transportManager.getTransports(service.getName()).iterator(); itr.hasNext();)
143         {
144             Object transportObj = (Transport) itr.next();
145 
146             if (!(transportObj instanceof WSDL11Transport))
147             {
148                 continue;
149             }
150 
151             WSDL11Transport transport = (WSDL11Transport) transportObj;
152 
153             Binding transportBinding = transport.createBinding(this, portType, paramBinding);
154 
155             for (Iterator oitr = service.getServiceInfo().getOperations().iterator(); oitr.hasNext();)
156             {
157                 // todo: move out of the first loop, we'll be creating req/res
158                 // multiple times otherwise
159                 OperationInfo op = (OperationInfo) oitr.next();
160 
161                 javax.wsdl.Operation wsdlOp = (javax.wsdl.Operation) wsdlOps.get(op.getName());
162 
163                 BindingOperation bop = transport.createBindingOperation(this, portType, wsdlOp, paramBinding);
164                 transportBinding.addBindingOperation(bop);
165 
166                 createHeaders(op, bop);
167             }
168 
169             Port transportPort = transport.createPort(this, transportBinding);
170 
171             def.addBinding(transportBinding);
172             wsdlService.addPort(transportPort);
173         }
174 
175         def.addService(wsdlService);
176 
177     }
178 
179     private void createHeaders(OperationInfo op, BindingOperation bop)
180     {
181         List inputHeaders = op.getInputMessage().getMessageHeaders();
182         if (inputHeaders.size() == 0)
183         {
184             return;
185         }
186 
187         BindingInput bindingInput = bop.getBindingInput();
188 
189         Message reqHeaders = createHeaderMessages(op.getInputMessage());
190         getDefinition().addMessage(reqHeaders);
191 
192         for (Iterator headerItr = reqHeaders.getParts().values().iterator(); headerItr.hasNext();)
193         {
194             Part headerInfo = (Part) headerItr.next();
195 
196             SOAPHeader soapHeader = new SOAPHeaderImpl();
197             soapHeader.setMessage(reqHeaders.getQName());
198             soapHeader.setPart(headerInfo.getName());
199             soapHeader.setUse(paramBinding.getUse());
200 
201             bindingInput.addExtensibilityElement(soapHeader);
202         }
203     }
204 
205     private Message createOutputMessage(OperationInfo op)
206     {
207         // response message
208         Message res = getDefinition().createMessage();
209         res.setQName(new QName(getInfo().getTargetNamespace(), op.getName() + "Response"));
210 
211         res.setUndefined(false);
212 
213         paramBinding.createOutputParts(this, res, op);
214 
215         return res;
216     }
217 
218     private Message createInputMessage(OperationInfo op)
219     {
220         Message req = getDefinition().createMessage();
221         req.setQName(new QName(getInfo().getTargetNamespace(), op.getName() + "Request"));
222         req.setUndefined(false);
223 
224         paramBinding.createInputParts(this, req, op);
225 
226         return req;
227     }
228 
229     private Message createHeaderMessages(MessageInfo msgInfo)
230     {
231         Message msg = getDefinition().createMessage();
232 
233         msg.setQName(new QName(getInfo().getTargetNamespace(), msgInfo.getName().getLocalPart() + "Headers"));
234         msg.setUndefined(false);
235 
236         for (Iterator itr = msgInfo.getMessageHeaders().iterator(); itr.hasNext();)
237         {
238             MessageHeaderInfo header = (MessageHeaderInfo) itr.next();
239 
240             Part part = createPart(header);
241 
242             msg.addPart(part);
243         }
244 
245         return msg;
246     }
247 
248     public Part createPart(MessageHeaderInfo header)
249     {
250         return createPart(header.getName(), header.getTypeClass(), header.getSchemaType());
251     }
252 
253     public Part createPart(MessagePartInfo part)
254     {
255         return createPart(part.getName(), part.getTypeClass(), part.getSchemaType());
256     }
257 
258     public Part createPart(QName pName, Class clazz, SchemaType type)
259     {
260         addDependency(type);
261 
262         QName schemaTypeName = type.getSchemaType();
263 
264         Part part = getDefinition().createPart();
265         part.setName(pName.getLocalPart());
266 
267         if (!type.isAbstract())
268         {
269             String prefix = getNamespacePrefix(schemaTypeName.getNamespaceURI());
270             addNamespace(prefix, schemaTypeName.getNamespaceURI());
271 
272             part.setElementName(schemaTypeName);
273 
274             return part;
275         }
276 
277         if (!declaredParameters.contains(pName))
278         {
279             Element schemaEl = createSchemaType(getInfo().getTargetNamespace());
280 
281             Element element = new Element(AbstractWSDL.elementQ, SoapConstants.XSD);
282             schemaEl.appendChild(element);
283 
284             String prefix = getNamespacePrefix(schemaTypeName.getNamespaceURI());
285             addNamespace(prefix, schemaTypeName.getNamespaceURI());
286 
287             if (type.isAbstract())
288             {
289                 element.addAttribute(new Attribute("name", pName.getLocalPart()));
290                 element.addAttribute(new Attribute("type",
291                                                    prefix + ":" + schemaTypeName.getLocalPart()));
292             }
293 
294             declaredParameters.add(pName);
295         }
296 
297         part.setElementName(pName);
298 
299         return part;
300     }
301 
302     public javax.wsdl.Operation createOperation(OperationInfo op, Message req, Message res)
303     {
304         Definition def = getDefinition();
305         javax.wsdl.Operation wsdlOp = def.createOperation();
306 
307         Input input = def.createInput();
308         input.setMessage(req);
309         input.setName(req.getQName().getLocalPart());
310         wsdlOp.setInput(input);
311 
312         if (res != null)
313         {
314             Output output = def.createOutput();
315             output.setMessage(res);
316             output.setName(res.getQName().getLocalPart());
317             wsdlOp.setOutput(output);
318         }
319 
320         wsdlOp.setName(op.getName());
321 
322         return wsdlOp;
323     }
324 }