1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.wsdl.wsdl11.builder;
18
19 import java.io.IOException;
20 import java.util.Iterator;
21 import java.util.List;
22 import javax.wsdl.Definition;
23 import javax.wsdl.Fault;
24 import javax.wsdl.Input;
25 import javax.wsdl.Message;
26 import javax.wsdl.Operation;
27 import javax.wsdl.OperationType;
28 import javax.wsdl.Output;
29 import javax.wsdl.Part;
30 import javax.wsdl.PortType;
31 import javax.wsdl.Service;
32 import javax.wsdl.Types;
33 import javax.wsdl.WSDLException;
34 import javax.wsdl.extensions.schema.Schema;
35 import javax.xml.namespace.QName;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39
40 import org.w3c.dom.Document;
41 import org.w3c.dom.Element;
42 import org.xml.sax.SAXException;
43
44 import org.springframework.beans.factory.InitializingBean;
45 import org.springframework.core.io.Resource;
46 import org.springframework.util.Assert;
47 import org.springframework.util.StringUtils;
48 import org.springframework.ws.wsdl.wsdl11.DynamicWsdl11Definition;
49 import org.springframework.xml.namespace.QNameUtils;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public class XsdBasedSoap11Wsdl4jDefinitionBuilder extends AbstractSoap11Wsdl4jDefinitionBuilder
89 implements InitializingBean {
90
91
92 public static final String DEFAULT_REQUEST_SUFFIX = "Request";
93
94
95 public static final String DEFAULT_RESPONSE_SUFFIX = "Response";
96
97
98 public static final String DEFAULT_FAULT_SUFFIX = "Fault";
99
100
101 public static final String DEFAULT_SCHEMA_PREFIX = "schema";
102
103
104 public static final String DEFAULT_PREFIX = "tns";
105
106
107 public static final String SERVICE_SUFFIX = "Service";
108
109 private Resource schemaResource;
110
111 private XsdSchemaHelper schemaHelper;
112
113 private String schemaLocation;
114
115 private String targetNamespace;
116
117 private String portTypeName;
118
119 private String schemaPrefix = DEFAULT_SCHEMA_PREFIX;
120
121 private String prefix = DEFAULT_PREFIX;
122
123 private String requestSuffix = DEFAULT_REQUEST_SUFFIX;
124
125 private String responseSuffix = DEFAULT_RESPONSE_SUFFIX;
126
127 private String faultSuffix = DEFAULT_FAULT_SUFFIX;
128
129 private boolean followIncludeImport = false;
130
131
132
133
134
135
136 public void setRequestSuffix(String requestSuffix) {
137 this.requestSuffix = requestSuffix;
138 }
139
140
141
142
143
144
145 public void setResponseSuffix(String responseSuffix) {
146 this.responseSuffix = responseSuffix;
147 }
148
149
150
151
152
153
154 public void setFaultSuffix(String faultSuffix) {
155 this.faultSuffix = faultSuffix;
156 }
157
158
159 public void setPortTypeName(String portTypeName) {
160 this.portTypeName = portTypeName;
161 }
162
163
164 public void setTargetNamespace(String targetNamespace) {
165 this.targetNamespace = targetNamespace;
166 }
167
168
169
170
171
172
173 public void setSchemaPrefix(String schemaPrefix) {
174 this.schemaPrefix = schemaPrefix;
175 }
176
177
178
179
180
181
182 public void setPrefix(String prefix) {
183 this.prefix = prefix;
184 }
185
186
187 public void setSchema(Resource schemaResource) {
188 Assert.notNull(schemaResource, "'schema' must not be null");
189 Assert.isTrue(schemaResource.exists(), "schema \"" + schemaResource + "\" does not exit");
190 this.schemaResource = schemaResource;
191 }
192
193
194
195
196
197 public void setSchemaLocation(String schemaLocation) {
198 Assert.hasLength(schemaLocation, "'schemaLocation' must not be empty");
199 this.schemaLocation = schemaLocation;
200 }
201
202
203
204
205
206 public void setFollowIncludeImport(boolean followIncludeImport) {
207 this.followIncludeImport = followIncludeImport;
208 }
209
210 public final void afterPropertiesSet() throws IOException, ParserConfigurationException, SAXException {
211 Assert.notNull(schemaResource, "'schema' is required");
212 Assert.notNull(portTypeName, "'portTypeName' is required");
213 schemaHelper = new XsdSchemaHelper(schemaResource);
214 if (!StringUtils.hasLength(targetNamespace)) {
215 targetNamespace = schemaHelper.getTargetNamespace();
216 }
217 }
218
219
220 protected void populateDefinition(Definition definition) throws WSDLException {
221 super.populateDefinition(definition);
222 definition.setTargetNamespace(targetNamespace);
223 definition.addNamespace(schemaPrefix, schemaHelper.getTargetNamespace());
224 if (!targetNamespace.equals(schemaHelper.getTargetNamespace())) {
225 definition.addNamespace(prefix, targetNamespace);
226 }
227 }
228
229
230 protected void buildImports(Definition definition) throws WSDLException {
231 }
232
233
234
235
236
237
238
239
240
241 protected void buildTypes(Definition definition) throws WSDLException {
242 Types types = definition.createTypes();
243 Schema schema = (Schema) createExtension(Types.class, XsdSchemaHelper.SCHEMA_NAME);
244 if (!StringUtils.hasLength(schemaLocation)) {
245 schema.setElement(schemaHelper.getSchemaElement());
246 }
247 else {
248 Document document;
249 try {
250 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
251 documentBuilderFactory.setNamespaceAware(true);
252 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
253 document = documentBuilder.newDocument();
254 }
255 catch (ParserConfigurationException ex) {
256 throw new WSDLException(WSDLException.PARSER_ERROR, "Could not create DocumentBuilder", ex);
257 }
258 Element importingSchemaElement = document.createElementNS(XsdSchemaHelper.SCHEMA_NAME.getNamespaceURI(),
259 QNameUtils.toQualifiedName(XsdSchemaHelper.SCHEMA_NAME));
260 schema.setElement(importingSchemaElement);
261 Element importElement = document.createElementNS(XsdSchemaHelper.IMPORT_NAME.getNamespaceURI(),
262 QNameUtils.toQualifiedName(XsdSchemaHelper.IMPORT_NAME));
263 importingSchemaElement.appendChild(importElement);
264 importElement.setAttribute("namespace", schemaHelper.getTargetNamespace());
265 importElement.setAttribute("schemaLocation", schemaLocation);
266 }
267 types.addExtensibilityElement(schema);
268 definition.setTypes(types);
269 }
270
271
272
273
274
275
276
277
278 protected void buildMessages(Definition definition) throws WSDLException {
279 List elementDeclarations = schemaHelper.getElementDeclarations(followIncludeImport);
280 for (Iterator iterator = elementDeclarations.iterator(); iterator.hasNext();) {
281 QName elementName = (QName) iterator.next();
282 if (elementName != null &&
283 (isRequestMessage(elementName) || isResponseMessage(elementName) || isFaultMessage(elementName))) {
284 if (definition.getPrefix(elementName.getNamespaceURI()) == null) {
285 int i = 0;
286 while (true) {
287 String prefix = schemaPrefix + Integer.toString(i);
288 if (!StringUtils.hasLength(definition.getNamespace(prefix))) {
289 definition.addNamespace(prefix, elementName.getNamespaceURI());
290 break;
291 }
292 i++;
293 }
294 }
295 Message message = definition.createMessage();
296 populateMessage(message, elementName);
297 Part part = definition.createPart();
298 populatePart(part, elementName);
299 message.addPart(part);
300 message.setUndefined(false);
301 definition.addMessage(message);
302 }
303 }
304 }
305
306
307
308
309
310
311
312
313
314 protected boolean isRequestMessage(QName name) {
315 return name.getLocalPart().endsWith(requestSuffix);
316 }
317
318
319
320
321
322
323
324
325
326 protected boolean isResponseMessage(QName name) {
327 return name.getLocalPart().endsWith(responseSuffix);
328 }
329
330
331
332
333
334
335
336
337
338 protected boolean isFaultMessage(QName name) {
339 return name.getLocalPart().endsWith(faultSuffix);
340 }
341
342
343
344
345
346
347
348
349
350
351 protected void populateMessage(Message message, QName elementName) throws WSDLException {
352 message.setQName(new QName(targetNamespace, elementName.getLocalPart()));
353 }
354
355
356
357
358
359
360
361
362
363
364
365 protected void populatePart(Part part, QName elementName) throws WSDLException {
366 part.setElementName(elementName);
367 part.setName(elementName.getLocalPart());
368 }
369
370 protected void buildPortTypes(Definition definition) throws WSDLException {
371 PortType portType = definition.createPortType();
372 populatePortType(portType);
373 createOperations(definition, portType);
374 portType.setUndefined(false);
375 definition.addPortType(portType);
376 }
377
378
379
380
381
382
383
384
385
386
387 protected void populatePortType(PortType portType) throws WSDLException {
388 portType.setQName(new QName(targetNamespace, portTypeName));
389 }
390
391 private void createOperations(Definition definition, PortType portType) throws WSDLException {
392 for (Iterator messageIterator = definition.getMessages().values().iterator(); messageIterator.hasNext();) {
393 Message message = (Message) messageIterator.next();
394 for (Iterator partIterator = message.getParts().values().iterator(); partIterator.hasNext();) {
395 Part part = (Part) partIterator.next();
396 if (isRequestMessage(part.getElementName())) {
397 Message requestMessage = message;
398 Message responseMessage = definition.getMessage(getResponseMessageName(requestMessage.getQName()));
399 Message faultMessage = definition.getMessage(getFaultMessageName(requestMessage.getQName()));
400 Operation operation = definition.createOperation();
401 populateOperation(operation, requestMessage, responseMessage);
402 if (requestMessage != null) {
403 Input input = definition.createInput();
404 input.setMessage(requestMessage);
405 input.setName(requestMessage.getQName().getLocalPart());
406 operation.setInput(input);
407 }
408 if (responseMessage != null) {
409 Output output = definition.createOutput();
410 output.setMessage(responseMessage);
411 output.setName(responseMessage.getQName().getLocalPart());
412 operation.setOutput(output);
413 }
414 if (faultMessage != null) {
415 Fault fault = definition.createFault();
416 fault.setMessage(faultMessage);
417 fault.setName(faultMessage.getQName().getLocalPart());
418 operation.addFault(fault);
419 }
420 if (requestMessage != null && responseMessage != null) {
421 operation.setStyle(OperationType.REQUEST_RESPONSE);
422 }
423 else if (requestMessage != null && responseMessage == null) {
424 operation.setStyle(OperationType.ONE_WAY);
425 }
426 else if (requestMessage == null && responseMessage != null) {
427 operation.setStyle(OperationType.NOTIFICATION);
428 }
429 operation.setUndefined(false);
430 portType.addOperation(operation);
431 }
432 }
433 }
434 }
435
436
437
438
439
440
441
442
443
444 protected QName getResponseMessageName(QName requestMessageName) {
445 String localPart = requestMessageName.getLocalPart();
446 if (localPart.endsWith(requestSuffix)) {
447 String prefix = localPart.substring(0, localPart.length() - requestSuffix.length());
448 return new QName(requestMessageName.getNamespaceURI(), prefix + responseSuffix);
449 }
450 else {
451 return null;
452 }
453 }
454
455
456
457
458
459
460
461
462
463 protected QName getFaultMessageName(QName requestMessageName) {
464 String localPart = requestMessageName.getLocalPart();
465 if (localPart.endsWith(requestSuffix)) {
466 String prefix = localPart.substring(0, localPart.length() - requestSuffix.length());
467 return new QName(requestMessageName.getNamespaceURI(), prefix + faultSuffix);
468 }
469 else {
470 return null;
471 }
472 }
473
474
475
476
477
478
479
480
481
482
483
484
485 protected void populateOperation(Operation operation, Message requestMessage, Message responseMessage)
486 throws WSDLException {
487 String localPart = requestMessage.getQName().getLocalPart();
488 String operationName = null;
489 if (localPart.endsWith(requestSuffix)) {
490 operationName = localPart.substring(0, localPart.length() - requestSuffix.length());
491 }
492 else {
493 localPart = responseMessage.getQName().getLocalPart();
494 if (localPart.endsWith(responseSuffix)) {
495 operationName = localPart.substring(0, localPart.length() - responseSuffix.length());
496 }
497 }
498 operation.setName(operationName);
499 }
500
501
502 protected void populateService(Service service) throws WSDLException {
503 service.setQName(new QName(targetNamespace, portTypeName + SERVICE_SUFFIX));
504 }
505 }