21 |
|
|
22 |
package nongnu.cashews.wsdl; |
package nongnu.cashews.wsdl; |
23 |
|
|
24 |
|
import java.net.URISyntaxException; |
25 |
|
|
26 |
import java.util.ArrayList; |
import java.util.ArrayList; |
27 |
|
import java.util.HashMap; |
28 |
|
import java.util.LinkedList; |
29 |
import java.util.List; |
import java.util.List; |
30 |
|
import java.util.Map; |
31 |
import java.util.logging.Handler; |
import java.util.logging.Handler; |
32 |
import java.util.logging.Logger; |
import java.util.logging.Logger; |
33 |
|
|
34 |
|
import javax.xml.namespace.QName; |
35 |
|
|
36 |
|
import nongnu.cashews.commons.PairMap; |
37 |
|
|
38 |
|
import nongnu.cashews.language.grounding.MessagePart; |
39 |
|
import nongnu.cashews.language.grounding.SoapMessage; |
40 |
import nongnu.cashews.language.grounding.SoapOperation; |
import nongnu.cashews.language.grounding.SoapOperation; |
41 |
|
|
42 |
import nongnu.cashews.xml.XmlBaseHandler; |
import nongnu.cashews.xml.XmlBaseHandler; |
61 |
* The WSDL namespace. |
* The WSDL namespace. |
62 |
*/ |
*/ |
63 |
public static final String |
public static final String |
64 |
WSDL_NAMESPACE = ""; |
WSDL_NAMESPACE = "http://schemas.xmlsoap.org/wsdl/"; |
65 |
|
|
66 |
|
/** |
67 |
|
* The WSDL SOAP namespace. |
68 |
|
*/ |
69 |
|
public static final String |
70 |
|
WSDL_SOAP_NAMESPACE = "http://schemas.xmlsoap.org/wsdl/soap/"; |
71 |
|
|
72 |
/** |
/** |
73 |
* The resulting list of operations. |
* The resulting list of operations. |
81 |
* parsing process. |
* parsing process. |
82 |
*/ |
*/ |
83 |
private Logger wsdlLogger; |
private Logger wsdlLogger; |
84 |
|
|
85 |
|
/** |
86 |
|
* The current SOAP message being created. |
87 |
|
*/ |
88 |
|
private SoapMessage currentMessage; |
89 |
|
|
90 |
|
/** |
91 |
|
* A map of parsed SOAP messages. |
92 |
|
*/ |
93 |
|
private Map<String,SoapMessage> messages; |
94 |
|
|
95 |
|
/** |
96 |
|
* A map of parsed port types. |
97 |
|
*/ |
98 |
|
private Map<String,List<SoapOperation>> portTypeMap; |
99 |
|
|
100 |
|
/** |
101 |
|
* A map of parsed SOAP operations. |
102 |
|
*/ |
103 |
|
private PairMap<String,String,SoapOperation> operationMap; |
104 |
|
|
105 |
|
/** |
106 |
|
* The current port type name. |
107 |
|
*/ |
108 |
|
private String currentPortTypeName; |
109 |
|
|
110 |
|
/** |
111 |
|
* The current operation name. |
112 |
|
*/ |
113 |
|
private String currentOperationName; |
114 |
|
|
115 |
|
/** |
116 |
|
* The current SOAP operation. |
117 |
|
*/ |
118 |
|
private SoapOperation currentOperation; |
119 |
|
|
120 |
/** |
/** |
121 |
* Constructs a new <code>WSDLHandler</code>, using the specified |
* Constructs a new <code>WSDLHandler</code>, using the specified |
122 |
* handler for log messages. |
* handler for log messages. |
139 |
{ |
{ |
140 |
super.startDocument(); |
super.startDocument(); |
141 |
operations = new ArrayList<SoapOperation>(); |
operations = new ArrayList<SoapOperation>(); |
142 |
|
currentMessage = null; |
143 |
|
messages = new HashMap<String,SoapMessage>(); |
144 |
|
operationMap = new PairMap<String,String,SoapOperation>(); |
145 |
|
portTypeMap = new HashMap<String,List<SoapOperation>>(); |
146 |
|
currentPortTypeName = null; |
147 |
|
currentOperationName = null; |
148 |
|
currentOperation = null; |
149 |
} |
} |
150 |
|
|
151 |
/** |
/** |
164 |
throws SAXException |
throws SAXException |
165 |
{ |
{ |
166 |
super.startElement(uri, localName, qName, attributes); |
super.startElement(uri, localName, qName, attributes); |
167 |
|
if (uri.equals(WSDL_NAMESPACE)) |
168 |
|
{ |
169 |
|
if (localName.equals("message")) |
170 |
|
{ |
171 |
|
String name = attributes.getValue("","name"); |
172 |
|
if (name == null) |
173 |
|
wsdlLogger.severe("Required message name not found."); |
174 |
|
else |
175 |
|
{ |
176 |
|
currentMessage = new SoapMessage(null, name); |
177 |
|
messages.put(name, currentMessage); |
178 |
|
} |
179 |
|
} |
180 |
|
else if (localName.equals("part")) |
181 |
|
{ |
182 |
|
String name = attributes.getValue("","name"); |
183 |
|
String type = attributes.getValue("","type"); |
184 |
|
if (name == null) |
185 |
|
wsdlLogger.severe("Required part name not found."); |
186 |
|
else |
187 |
|
{ |
188 |
|
try |
189 |
|
{ |
190 |
|
MessagePart part = |
191 |
|
new MessagePart(name); |
192 |
|
part.setName(null, name); |
193 |
|
if (type != null) |
194 |
|
part.setType(parseQName(type)); |
195 |
|
currentMessage.addPart(part); |
196 |
|
wsdlLogger.fine("Added part: " + part); |
197 |
|
} |
198 |
|
catch (URISyntaxException e) |
199 |
|
{ |
200 |
|
wsdlLogger.severe("Couldn't interprete name " + name + |
201 |
|
" as URI."); |
202 |
|
} |
203 |
|
} |
204 |
|
} |
205 |
|
else if (localName.equals("portType")) |
206 |
|
{ |
207 |
|
String value = attributes.getValue("","name"); |
208 |
|
if (value == null) |
209 |
|
wsdlLogger.severe("Required port type name not found."); |
210 |
|
else |
211 |
|
{ |
212 |
|
currentPortTypeName = value; |
213 |
|
portTypeMap.put(currentPortTypeName, |
214 |
|
new LinkedList<SoapOperation>()); |
215 |
|
wsdlLogger.fine("Port type found: " + currentPortTypeName); |
216 |
|
} |
217 |
|
} |
218 |
|
else if (localName.equals("operation") && currentPortTypeName != null) |
219 |
|
{ |
220 |
|
String value = attributes.getValue("","name"); |
221 |
|
if (value == null) |
222 |
|
wsdlLogger.severe("Required port type operation name " + |
223 |
|
"not found."); |
224 |
|
else |
225 |
|
{ |
226 |
|
currentOperationName = value; |
227 |
|
currentOperation = new SoapOperation(); |
228 |
|
operationMap.put(currentPortTypeName, currentOperationName, |
229 |
|
currentOperation); |
230 |
|
List<SoapOperation> operationList = |
231 |
|
portTypeMap.get(currentPortTypeName); |
232 |
|
if (operationList == null) |
233 |
|
wsdlLogger.severe("Current port type name is not in the " + |
234 |
|
"parsed port types map."); |
235 |
|
else |
236 |
|
operationList.add(currentOperation); |
237 |
|
wsdlLogger.fine("Port type operation found: " + |
238 |
|
currentOperationName); |
239 |
|
} |
240 |
|
} |
241 |
|
else if (localName.equals("input") && currentOperationName != null) |
242 |
|
{ |
243 |
|
QName message = parseQName(attributes.getValue("", "message")); |
244 |
|
SoapMessage input = messages.get(message.getLocalPart()); |
245 |
|
if (input == null) |
246 |
|
wsdlLogger.severe("Operation " + currentOperationName + |
247 |
|
" references non-existant message as input."); |
248 |
|
else |
249 |
|
currentOperation.setInputMessage(input); |
250 |
|
} |
251 |
|
else if (localName.equals("output") && currentOperationName != null) |
252 |
|
{ |
253 |
|
QName message = parseQName(attributes.getValue("", "message")); |
254 |
|
SoapMessage output = messages.get(message.getLocalPart()); |
255 |
|
if (output == null) |
256 |
|
wsdlLogger.severe("Operation " + currentOperationName + |
257 |
|
" references non-existant message as output."); |
258 |
|
else |
259 |
|
currentOperation.setOutputMessage(output); |
260 |
|
} |
261 |
|
else if (localName.equals("port")) |
262 |
|
{ |
263 |
|
String name = attributes.getValue("","name"); |
264 |
|
if (name == null) |
265 |
|
wsdlLogger.severe("No port name specified in the service."); |
266 |
|
else |
267 |
|
{ |
268 |
|
currentPortTypeName = name; |
269 |
|
wsdlLogger.fine("Port " + name + |
270 |
|
" encountered in the service."); |
271 |
|
} |
272 |
|
} |
273 |
|
} |
274 |
|
else if (uri.equals(WSDL_SOAP_NAMESPACE)) |
275 |
|
{ |
276 |
|
if (localName.equals("address")) |
277 |
|
{ |
278 |
|
String location = attributes.getValue("","location"); |
279 |
|
if (location == null) |
280 |
|
wsdlLogger.severe("No location specified."); |
281 |
|
else |
282 |
|
{ |
283 |
|
List<SoapOperation> operationList = |
284 |
|
portTypeMap.get(currentPortTypeName); |
285 |
|
if (operationList == null) |
286 |
|
wsdlLogger.severe("Current port type name, " + |
287 |
|
currentPortTypeName + |
288 |
|
", is not in the " + |
289 |
|
"parsed port types map."); |
290 |
|
else |
291 |
|
for (SoapOperation op : operationList) |
292 |
|
{ |
293 |
|
try |
294 |
|
{ |
295 |
|
op.setEndpoint(location); |
296 |
|
op.setNamespace(location); |
297 |
|
} |
298 |
|
catch (URISyntaxException e) |
299 |
|
{ |
300 |
|
wsdlLogger.severe("Location URL, " + location + |
301 |
|
", is invalid."); |
302 |
|
} |
303 |
|
} |
304 |
|
} |
305 |
|
} |
306 |
|
} |
307 |
} |
} |
308 |
|
|
309 |
/** |
/** |
339 |
throws SAXException |
throws SAXException |
340 |
{ |
{ |
341 |
super.endElement(uri, localName, qName); |
super.endElement(uri, localName, qName); |
342 |
|
if (uri.equals(WSDL_NAMESPACE)) |
343 |
|
{ |
344 |
|
if (localName.equals("message")) |
345 |
|
wsdlLogger.fine("Created SOAP message: " + currentMessage); |
346 |
|
else if (localName.equals("portType")) |
347 |
|
currentPortTypeName = null; |
348 |
|
else if (localName.equals("operation") && currentOperationName != null) |
349 |
|
{ |
350 |
|
currentOperationName = null; |
351 |
|
wsdlLogger.fine("Created SOAP operation: " + currentOperation); |
352 |
|
} |
353 |
|
} |
354 |
} |
} |
355 |
|
|
356 |
/** |
/** |
363 |
return operations; |
return operations; |
364 |
} |
} |
365 |
|
|
366 |
|
/** |
367 |
|
* Parses a <code>QName</code> from a string. |
368 |
|
* |
369 |
|
* @param qname the qualified name in <code>String</code> form to parse. |
370 |
|
* @return the parsed <code>QName</code>. |
371 |
|
*/ |
372 |
|
private QName parseQName(String qname) |
373 |
|
{ |
374 |
|
String[] parts = qname.split(":"); |
375 |
|
/* FIXME: Add namespace lookup */ |
376 |
|
return new QName(null,parts[1],parts[0]); |
377 |
|
} |
378 |
|
|
379 |
|
/** |
380 |
|
* Captures the end of the document and sets up the final |
381 |
|
* state. |
382 |
|
*/ |
383 |
|
public void endDocument() |
384 |
|
{ |
385 |
|
for (SoapOperation op : operationMap.values()) |
386 |
|
operations.add(op); |
387 |
|
} |
388 |
|
|
389 |
} |
} |