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
105 for (Iterator itr = service.getServiceInfo().getOperations().iterator(); itr.hasNext();)
106 {
107 OperationInfo op = (OperationInfo) itr.next();
108
109
110 Message req = createInputMessage(op);
111 def.addMessage(req);
112
113
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
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
158
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
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 }