1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package com.izforge.soapdtc.servlet;
24
25 import com.izforge.soapdtc.SoapMessageUtils;
26 import org.dom4j.Document;
27 import org.dom4j.DocumentFactory;
28 import org.dom4j.Element;
29 import org.dom4j.Namespace;
30 import org.dom4j.io.XPP3Reader;
31
32 import java.io.IOException;
33 import java.io.Writer;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37
38 /**
39 * A WSDL provider that takes advantage of WSDL-DTC descriptions to generate WSDL documents.
40 * A WSDL-DTC document captures the essence of a Document/Literal WSDL descrption and makes it
41 * easier to write WSDL documents. The generated WSDL document will be a WSDL 1.1 SOAP 1.2 binding.
42 *
43 * <strong>Warning: WSDL-DTC is still experimental!</strong>
44 *
45 * @author Julien Ponge (julien.ponge@gmail.com)
46 */
47 public class WsdlDtcProvider implements IWsdlProvider
48 {
49 private String resource;
50
51 private String endpointURL;
52
53 private String wsdl;
54
55 private Document wsdlDOM;
56
57 private static final String WSDL_NS_URI = "http://schemas.xmlsoap.org/wsdl/";
58 private static final String WSOAP12_NS_URI = "http://schemas.xmlsoap.org/wsdl/soap12/";
59 private static final String XSD_NS_URI = "http://www.w3.org/2001/XMLSchema";
60 private static final String WSDL_DTC_NS_URI = "http://www.izforge.com/soap-dtc/wsdl-dtc";
61
62 /**
63 * Constructor.
64 *
65 * @param resource the path to a resource containing the WSDL-DTC document.
66 * @param endpointURL the service endpoint URL.
67 */
68 public WsdlDtcProvider(String resource, String endpointURL)
69 {
70 this.resource = resource;
71 this.endpointURL = endpointURL;
72 }
73
74
75 public void writeWsdl(Writer writer) throws IOException
76 {
77 writer.write(getWsdl());
78 }
79
80 /**
81 * Returns the string representation of the WSDL document.
82 * @return the WSDL document.
83 */
84 protected String getWsdl()
85 {
86 if (wsdl == null)
87 {
88 generateWsdl();
89 }
90 return wsdl;
91 }
92
93
94 /**
95 * Returns the DOM4J representation of the WSDL document.
96 * @return the WSDL document.
97 */
98 protected Document getWsdlDOM()
99 {
100 return wsdlDOM;
101 }
102
103 /**
104 * Generates the WSDL document from the WSDL-DTC specification.
105 */
106 protected void generateWsdl()
107 {
108 DocumentFactory factory = DocumentFactory.getInstance();
109
110 SoapMessageUtils.configureDocumentFactoryXPathNamespaceURIs(factory);
111 SoapMessageUtils.registerDocumentFactoryXPathNamespaceURIs(factory, "xsd", XSD_NS_URI);
112 SoapMessageUtils.registerDocumentFactoryXPathNamespaceURIs(factory, "wsdl", WSDL_NS_URI);
113 SoapMessageUtils.registerDocumentFactoryXPathNamespaceURIs(factory, "wsoap12", WSOAP12_NS_URI);
114 SoapMessageUtils.registerDocumentFactoryXPathNamespaceURIs(factory, "wsdl-dtc", WSDL_DTC_NS_URI);
115
116 XPP3Reader reader = new XPP3Reader();
117 Document doc;
118 try
119 {
120 doc = reader.read(getClass().getResourceAsStream(resource));
121 }
122 catch (Exception e)
123 {
124 e.printStackTrace();
125 wsdl = "Could not generate a WSDL document...";
126 return;
127 }
128 String endpointName = doc.valueOf("wsdl-dtc:specification/wsdl-dtc:endpoint/wsdl-dtc:name/text()");
129 String endpointNS = doc.valueOf("wsdl-dtc:specification/wsdl-dtc:endpoint/wsdl-dtc:namespace/text()");
130
131
132
133
134 Document wsdlDoc = factory.createDocument();
135 Element wsdlRoot = wsdlDoc.addElement("wsdl:definitions", WSDL_NS_URI);
136 wsdlRoot.addNamespace("tns", endpointNS);
137 wsdlRoot.addNamespace("wsoap12", WSOAP12_NS_URI);
138 wsdlRoot.addNamespace("wsdl", WSDL_NS_URI);
139 wsdlRoot.addNamespace("xsd", XSD_NS_URI);
140 wsdlRoot.addAttribute("targetNamespace", doc.valueOf("//wsdl-dtc:endpoint/wsdl-dtc:namespace/text()"));
141
142
143
144
145 List<Namespace> namespaces = doc.getRootElement().additionalNamespaces();
146 for (Namespace ns : namespaces)
147 {
148 wsdlRoot.addNamespace(ns.getPrefix(), ns.getURI());
149 }
150
151
152
153
154 Element types = wsdlRoot.addElement("wsdl:types", WSDL_NS_URI);
155 types.add((Element)doc.selectSingleNode("//xsd:schema").clone());
156
157
158
159
160 List<Element> operationNodes = doc.selectNodes("//wsdl-dtc:operation");
161 Map<String, Element> inputWsdlMessages = new HashMap<String, Element>();
162 Map<String, Element> outputWsdlMessages = new HashMap<String, Element>();
163 for (Element operationElement : operationNodes)
164 {
165 Element inBody = (Element) operationElement.selectSingleNode("wsdl-dtc:input/wsdl-dtc:body");
166 if (inBody != null)
167 {
168 Element message = factory.createElement("wsdl:message", WSDL_NS_URI);
169 message.addAttribute("name", operationElement.attributeValue("name") + "In");
170 List<Element> parts = inBody.selectNodes("wsdl-dtc:part");
171 for (Element part : parts)
172 {
173 message.addElement("wsdl:part", WSDL_NS_URI).addAttribute("name", part.attributeValue("name")).addAttribute("element", part.attributeValue("element"));
174 }
175 wsdlRoot.add(message);
176 inputWsdlMessages.put(operationElement.attributeValue("name"), message);
177 }
178
179 Element outBody = (Element) operationElement.selectSingleNode("wsdl-dtc:output/wsdl-dtc:body");
180 if (outBody != null)
181 {
182 Element message = factory.createElement("wsdl:message", WSDL_NS_URI);
183 message.addAttribute("name", operationElement.attributeValue("name") + "Out");
184 List<Element> parts = outBody.selectNodes("wsdl-dtc:part");
185 for (Element part : parts)
186 {
187 message.addElement("wsdl:part", WSDL_NS_URI).addAttribute("name", part.attributeValue("name")).addAttribute("element", part.attributeValue("element"));
188 }
189 wsdlRoot.add(message);
190 outputWsdlMessages.put(operationElement.attributeValue("name"), message);
191 }
192 }
193
194
195
196
197 Element portType = wsdlRoot.addElement("wsdl:portType", WSDL_NS_URI);
198 portType.addAttribute("name", endpointName + "PortType");
199 for (Element operationElement : operationNodes)
200 {
201 Element op = portType.addElement("wsdl:operation", WSDL_NS_URI).addAttribute("name", operationElement.attributeValue("name"));
202 Element in = inputWsdlMessages.get(operationElement.attributeValue("name"));
203 Element out = outputWsdlMessages.get(operationElement.attributeValue("name"));
204
205 if (in != null)
206 {
207 op.addElement("wsdl:input").addAttribute("message", "tns:" + in.attributeValue("name"));
208 }
209 if (out != null)
210 {
211 op.addElement("wsdl:output").addAttribute("message", "tns:" + out.attributeValue("name"));
212 }
213 }
214
215
216
217
218 Element binding = wsdlRoot.addElement("wsdl:binding", WSDL_NS_URI);
219 binding.addAttribute("name", endpointName + "Soap12Binding");
220 binding.addAttribute("type", "tns:" + portType.attributeValue("name"));
221 Element bbind = binding.addElement("wsoap12:binding", WSOAP12_NS_URI);
222 bbind.addAttribute("transport", "http://schemas.xmlsoap.org/soap/http");
223 bbind.addAttribute("style", "document");
224 for (Element operationElement : operationNodes)
225 {
226 Element op = binding.addElement("wsdl:operation", WSDL_NS_URI).addAttribute("name", operationElement.attributeValue("name"));
227 Element in = inputWsdlMessages.get(operationElement.attributeValue("name"));
228 Element out = outputWsdlMessages.get(operationElement.attributeValue("name"));
229
230 Element bop = op.addElement("wsoap12:operation", WSOAP12_NS_URI);
231 bop.addAttribute("soapAction", operationElement.attributeValue("soapAction"));
232 bop.addAttribute("soapActionRequired", "true");
233 bop.addAttribute("style", "document");
234 if (in != null)
235 {
236 Element input = op.addElement("wsdl:input");
237
238 List<Element> headerParts = operationElement.selectNodes("wsdl-dtc:input/wsdl-dtc:header/wsdl-dtc:part");
239 for (Element headerPart : headerParts)
240 {
241 Element h = input.addElement("wsoap12:header", WSOAP12_NS_URI);
242 h.addAttribute("message", headerPart.attributeValue("type"));
243 h.addAttribute("part", headerPart.attributeValue("name"));
244 h.addAttribute("use", "literal");
245 }
246
247 input.addElement("wsoap12:body", WSOAP12_NS_URI).addAttribute("use", "literal");
248 }
249 if (out != null)
250 {
251 Element output = op.addElement("wsdl:output");
252
253 List<Element> headerParts = operationElement.selectNodes("wsdl-dtc:output/wsdl-dtc:header/wsdl-dtc:part");
254 for (Element headerPart : headerParts)
255 {
256 Element h = output.addElement("wsoap12:header", WSOAP12_NS_URI);
257 h.addAttribute("message", headerPart.attributeValue("type"));
258 h.addAttribute("part", headerPart.attributeValue("name"));
259 h.addAttribute("use", "literal");
260 }
261
262 output.addElement("wsoap12:body", WSOAP12_NS_URI).addAttribute("use", "literal");
263 }
264 }
265
266
267
268
269 Element service = wsdlRoot.addElement("wsdl:service", WSDL_NS_URI).addAttribute("name", endpointName);
270 Element port = service.addElement("wsdl:port", WSDL_NS_URI);
271 port.addAttribute("name", endpointName + "Soap12");
272 port.addAttribute("binding", "tns:" + endpointName + "Soap12Binding");
273 port.addElement("wsoap12:address", WSOAP12_NS_URI).addAttribute("location", endpointURL);
274
275
276
277
278 wsdlDOM = wsdlDoc;
279 wsdl = wsdlDoc.asXML();
280 }
281 }