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