001: package org.objectweb.celtix.bus.bindings;
002:
003: import java.lang.annotation.Annotation;
004: import java.util.ArrayList;
005: import java.util.Collection;
006: import java.util.HashMap;
007: import java.util.Iterator;
008: import java.util.List;
009: import java.util.Map;
010:
011: import javax.jws.WebParam;
012: import javax.jws.WebParam.Mode;
013: import javax.jws.WebResult;
014: import javax.jws.soap.SOAPBinding;
015: import javax.jws.soap.SOAPBinding.Style;
016: import javax.wsdl.BindingInput;
017: import javax.wsdl.BindingOperation;
018: import javax.wsdl.BindingOutput;
019: import javax.wsdl.Input;
020: import javax.wsdl.Message;
021: import javax.wsdl.Operation;
022: import javax.wsdl.Output;
023: import javax.wsdl.Part;
024: import javax.wsdl.extensions.soap.SOAPBody;
025: import javax.wsdl.extensions.soap.SOAPHeader;
026: import javax.wsdl.extensions.soap.SOAPOperation;
027: import javax.xml.namespace.QName;
028:
029: public class WSDLOperationInfo {
030: BindingOperation bindingOp;
031: WSDLMetaDataCache cache;
032:
033: SOAPBinding.Style style;
034: SOAPBinding.Use use;
035: SOAPBinding.ParameterStyle paramStyle;
036: String soapAction;
037: String targetNs;
038: QName requestWrapperQName;
039: QName responseWrapperQName;
040: WebResult result;
041: List<OperationWebParam> params;
042:
043: public WSDLOperationInfo(WSDLMetaDataCache c, BindingOperation op) {
044: cache = c;
045: bindingOp = op;
046: }
047:
048: public String getName() {
049: return bindingOp.getName();
050: }
051:
052: public boolean isOneWay() {
053: return getMessage(true) != null && getMessage(false) == null;
054: }
055:
056: public SOAPBinding.Style getSOAPStyle() {
057: if (style == null) {
058: SOAPOperation soapOperation = getExtensibilityElement(
059: bindingOp.getExtensibilityElements(),
060: SOAPOperation.class);
061: if (soapOperation != null
062: && soapOperation.getStyle() != null
063: && !"".equals(soapOperation.getStyle())) {
064: style = SOAPBinding.Style.valueOf(soapOperation
065: .getStyle().toUpperCase());
066: }
067: if (style == null) {
068: style = cache.getStyle();
069: }
070: }
071: return style;
072: }
073:
074: public SOAPBinding.Use getSOAPUse() {
075: if (use == null) {
076: SOAPBody body = getSOAPBody(true);
077:
078: if (body != null && body.getUse() != null
079: && !"".equals(body.getUse())) {
080: use = SOAPBinding.Use.valueOf(body.getUse()
081: .toUpperCase());
082: }
083: if (use == null) {
084: use = SOAPBinding.Use.LITERAL;
085: }
086: }
087: return use;
088: }
089:
090: public String getOperationName() {
091: return getName();
092: }
093:
094: public String getSOAPAction() {
095: if (soapAction == null) {
096: SOAPOperation soapOp = getExtensibilityElement(bindingOp
097: .getExtensibilityElements(), SOAPOperation.class);
098: if (soapOp != null) {
099: soapAction = soapOp.getSoapActionURI();
100: }
101: if (soapAction == null) {
102: soapAction = "";
103: }
104: }
105: return soapAction;
106: }
107:
108: public String getTargetNamespace() {
109: if (targetNs == null) {
110: SOAPBody soapBody = getSOAPBody(true);
111: if (soapBody != null) {
112: targetNs = soapBody.getNamespaceURI();
113: }
114: if (targetNs == null) {
115: targetNs = cache.getTargetNamespace();
116: }
117: }
118: return targetNs;
119: }
120:
121: public SOAPBinding.ParameterStyle getSOAPParameterStyle() {
122: if (paramStyle == null) {
123: if (isDocLitWrapped()
124: || getSOAPStyle() == SOAPBinding.Style.RPC) {
125: paramStyle = SOAPBinding.ParameterStyle.WRAPPED;
126: } else {
127: paramStyle = SOAPBinding.ParameterStyle.BARE;
128: }
129: }
130: return paramStyle;
131: }
132:
133: public WebResult getWebResult() {
134: if (params == null) {
135: initParams();
136: }
137: return result;
138: }
139:
140: public WebParam getWebParam(int index) {
141: if (params == null) {
142: initParams();
143: }
144: return params.get(index);
145: }
146:
147: public int getParamsLength() {
148: if (params == null) {
149: initParams();
150: }
151: return params.size();
152: }
153:
154: public QName getWebResultQName() {
155: WebResult res = getWebResult();
156: if (null != res) {
157: if (getSOAPStyle() == Style.DOCUMENT) {
158: if ("".equals(res.name())) {
159: return new QName(res.targetNamespace(), "return");
160: }
161: return new QName(res.targetNamespace(), res.name());
162: } else {
163: return new QName("", res.partName());
164: }
165: }
166: return new QName("", "");
167: }
168:
169: public QName getRequestWrapperQName() {
170: if (requestWrapperQName == null) {
171: if (getSOAPParameterStyle() == SOAPBinding.ParameterStyle.BARE
172: || getSOAPStyle() == SOAPBinding.Style.RPC) {
173: requestWrapperQName = new QName("", "");
174: } else {
175: Message msg = getMessage(true);
176: List parts = msg.getOrderedParts(null);
177: Part part = (Part) parts.get(0);
178: requestWrapperQName = part.getElementName();
179: }
180: }
181: return requestWrapperQName;
182: }
183:
184: public QName getResponseWrapperQName() {
185: if (responseWrapperQName == null) {
186: if (getSOAPParameterStyle() == SOAPBinding.ParameterStyle.BARE
187: || getSOAPStyle() == SOAPBinding.Style.RPC) {
188: responseWrapperQName = new QName("", "");
189: } else {
190: Message msg = getMessage(false);
191: if (msg != null) {
192: List parts = msg.getOrderedParts(null);
193: Part part = (Part) parts.get(0);
194: responseWrapperQName = part.getElementName();
195: } else {
196: responseWrapperQName = new QName("", "");
197: }
198: }
199: }
200: return responseWrapperQName;
201: }
202:
203: private boolean isDocLitWrapped() {
204: boolean flag = getSOAPStyle() == SOAPBinding.Style.DOCUMENT
205: && getSOAPUse() == SOAPBinding.Use.LITERAL;
206: if (!flag) {
207: return false;
208: }
209: Message msg = getMessage(true);
210: if (msg == null) {
211: return false;
212: }
213: List parts = msg.getOrderedParts(null);
214: if (parts.size() != 1) {
215: return false;
216: }
217: Part part = (Part) parts.get(0);
218: QName element = part.getElementName();
219: if (element == null
220: || !element.getLocalPart().equals(
221: bindingOp.getOperation().getName())) {
222: return false;
223: }
224: //REVISIT check for squence
225:
226: msg = getMessage(true);
227: if (msg != null) {
228: parts = msg.getOrderedParts(null);
229: if (parts.size() != 1) {
230: flag = false;
231: } else {
232: part = (Part) parts.get(0);
233: element = part.getElementName();
234: if (element == null
235: || !element.getLocalPart().startsWith(
236: bindingOp.getOperation().getName())) {
237: flag = false;
238: }
239: //REVISIT check for squence
240: }
241: }
242: return true;
243: }
244:
245: private Message getMessage(boolean isInput) {
246: Operation operation = bindingOp.getOperation();
247: if (operation == null) {
248: return null;
249: }
250:
251: if (isInput) {
252: final Input input = operation.getInput();
253: return input == null ? null : input.getMessage();
254: }
255: final Output output = operation.getOutput();
256: return output == null ? null : output.getMessage();
257: }
258:
259: private SOAPBody getSOAPBody(boolean input) {
260: List elements = null;
261: if (input) {
262: BindingInput bindingInput = bindingOp.getBindingInput();
263: if (bindingInput == null) {
264: return null;
265: }
266: elements = bindingInput.getExtensibilityElements();
267: } else {
268: BindingOutput bindingOutput = bindingOp.getBindingOutput();
269: if (bindingOutput == null) {
270: return null;
271: }
272: elements = bindingOutput.getExtensibilityElements();
273: }
274: return getExtensibilityElement(elements, SOAPBody.class);
275: }
276:
277: private void initRPCLitParam(List<OperationWebParam> parms,
278: Map<String, OperationWebParam> parmMap, Operation operation) {
279:
280: Input input = operation.getInput();
281: Output output = operation.getOutput();
282: if (input == null) {
283: //unsupported op type, output only
284: return;
285: }
286: Collection parts = input.getMessage().getParts().values();
287: for (Iterator i = parts.iterator(); i.hasNext();) {
288: Part part = (Part) i.next();
289: OperationWebParam p = new OperationWebParam(part.getName(),
290: part.getName(), Mode.IN, "", cache
291: .getTargetNamespace());
292: parms.add(p);
293: parmMap.put(part.getName(), p);
294: }
295: if (output != null) {
296: parts = output.getMessage().getParts().values();
297: for (Iterator i = parts.iterator(); i.hasNext();) {
298: Part part = (Part) i.next();
299:
300: OperationWebParam p = parmMap.get(part.getName());
301: if (p == null) {
302: p = new OperationWebParam(part.getName(), part
303: .getName(), Mode.OUT, "", cache
304: .getTargetNamespace());
305: parms.add(p);
306: parmMap.put(part.getName(), p);
307: } else {
308: p.setMode(Mode.INOUT);
309: }
310: }
311: }
312: }
313:
314: private void initDocLitBareParam(List<OperationWebParam> parms,
315: Map<String, OperationWebParam> parmMap, Operation operation) {
316:
317: Input input = operation.getInput();
318: Output output = operation.getOutput();
319: Collection parts = input.getMessage().getParts().values();
320: for (Iterator i = parts.iterator(); i.hasNext();) {
321: Part part = (Part) i.next();
322: OperationWebParam p = new OperationWebParam(part
323: .getElementName().getLocalPart(), part.getName(),
324: Mode.IN, part.getElementName().getNamespaceURI());
325: parms.add(p);
326: parmMap.put(part.getName(), p);
327: }
328: if (output != null) {
329: parts = output.getMessage().getParts().values();
330: for (Iterator i = parts.iterator(); i.hasNext();) {
331: Part part = (Part) i.next();
332:
333: OperationWebParam p = parmMap.get(part.getName());
334: if (p == null) {
335: p = new OperationWebParam(part.getElementName()
336: .getLocalPart(), part.getName(), Mode.OUT,
337: part.getElementName().getNamespaceURI());
338: parms.add(p);
339: parmMap.put(part.getName(), p);
340: } else {
341: p.setMode(Mode.INOUT);
342: }
343: }
344: }
345: }
346:
347: private void initDocLitWrappedParam(List<OperationWebParam> parms,
348: Map<String, OperationWebParam> parmMap, Operation operation) {
349: //REVISIT - how to handle the wrapped docs/lit cases. Must dig into schema and stuff.
350: }
351:
352: private synchronized void initParams() {
353: List<OperationWebParam> parms = new ArrayList<OperationWebParam>();
354: Map<String, OperationWebParam> parmMap = new HashMap<String, OperationWebParam>();
355:
356: Operation operation = bindingOp.getOperation();
357: if (operation != null) {
358: SOAPBinding.Style st = getSOAPStyle();
359:
360: if (st == SOAPBinding.Style.RPC) {
361: initRPCLitParam(parms, parmMap, operation);
362: } else {
363: // DOC style
364: if (isDocLitWrapped()) {
365: initDocLitWrappedParam(parms, parmMap, operation);
366: } else {
367: initDocLitBareParam(parms, parmMap, operation);
368: }
369: }
370:
371: // Set the header flags
372: BindingInput bindingInput = bindingOp.getBindingInput();
373: if (bindingInput != null) {
374: javax.wsdl.Message message = operation.getInput()
375: .getMessage();
376: List elements = bindingInput.getExtensibilityElements();
377: for (Iterator i = elements.iterator(); i.hasNext();) {
378: Object extensibilityElement = i.next();
379: Part part = getPartFromSOAPHeader(message,
380: extensibilityElement);
381: if (part != null) {
382: OperationWebParam p = parmMap.get(part
383: .getName());
384: if (p != null) {
385: p.setHeader(true);
386: }
387: }
388: }
389: }
390: BindingOutput bindingOutput = bindingOp.getBindingOutput();
391: if (bindingOutput != null) {
392: javax.wsdl.Message message = operation.getOutput()
393: .getMessage();
394: List elements = bindingOutput
395: .getExtensibilityElements();
396: for (Iterator i = elements.iterator(); i.hasNext();) {
397: Object extensibilityElement = i.next();
398: Part part = getPartFromSOAPHeader(message,
399: extensibilityElement);
400: if (part != null) {
401: OperationWebParam p = parmMap.get(part
402: .getName());
403: if (p != null) {
404: p.setHeader(true);
405: }
406: }
407: }
408: }
409: }
410:
411: OperationWebParam returnVal = null;
412: for (OperationWebParam p : parms) {
413: if (p.mode() == Mode.INOUT) {
414: break;
415: } else if (p.mode() == Mode.OUT) {
416: returnVal = p;
417: break;
418: }
419: }
420: if (returnVal != null) {
421: parms.remove(returnVal);
422: result = new OperationWebResult(returnVal);
423: }
424:
425: params = parms;
426: }
427:
428: private Part getPartFromSOAPHeader(Message message,
429: Object extensibilityElement) {
430: Part part = null;
431: if (extensibilityElement instanceof SOAPHeader) {
432: SOAPHeader soapHeader = (SOAPHeader) extensibilityElement;
433: QName msgName = soapHeader.getMessage();
434: if (message.getQName().equals(msgName)) {
435: part = message.getPart(soapHeader.getPart());
436: }
437: } else if (extensibilityElement instanceof SOAPHeader) {
438: SOAPHeader soapHeader = (SOAPHeader) extensibilityElement;
439: QName msgName = soapHeader.getMessage();
440: if (message.getQName().equals(msgName)) {
441: part = message.getPart(soapHeader.getPart());
442: }
443: }
444: return part;
445: }
446:
447: private static <T> T getExtensibilityElement(List elements,
448: Class<T> type) {
449: for (Iterator i = elements.iterator(); i.hasNext();) {
450: Object element = i.next();
451: if (type.isInstance(element)) {
452: return type.cast(element);
453: }
454: }
455: return null;
456: }
457:
458: private class OperationWebResult implements WebResult {
459: OperationWebParam parm;
460:
461: public OperationWebResult(OperationWebParam p) {
462: parm = p;
463: }
464:
465: public String name() {
466: return parm.name();
467: }
468:
469: public String targetNamespace() {
470: return parm.webResultTargetNamespace();
471: }
472:
473: public boolean header() {
474: return parm.header();
475: }
476:
477: public String partName() {
478: return parm.partName();
479: }
480:
481: public Class<? extends Annotation> annotationType() {
482: return WebResult.class;
483: }
484: }
485:
486: private class OperationWebParam implements WebParam {
487: Mode md;
488: String name;
489: String targetNs;
490: String webResultTNS;
491: boolean isHeader;
492: String partname;
493:
494: public OperationWebParam(String n, String pn, Mode m, String ns) {
495: this (n, pn, m, ns, ns);
496: }
497:
498: public OperationWebParam(String n, String pn, Mode m,
499: String ns, String wrns) {
500: name = n;
501: md = m;
502: targetNs = ns;
503: partname = pn;
504: webResultTNS = wrns;
505: }
506:
507: public String name() {
508: return name;
509: }
510:
511: public Mode mode() {
512: return md;
513: }
514:
515: public void setMode(Mode m) {
516: md = m;
517: }
518:
519: public String targetNamespace() {
520: return targetNs;
521: }
522:
523: public String webResultTargetNamespace() {
524: return webResultTNS;
525: }
526:
527: public boolean header() {
528: return isHeader;
529: }
530:
531: public void setHeader(boolean b) {
532: isHeader = b;
533: }
534:
535: public String partName() {
536: return partname;
537: }
538:
539: public Class<? extends Annotation> annotationType() {
540: return WebParam.class;
541: }
542:
543: }
544: }
|