001: package org.enhydra.shark.toolagent;
002:
003: import java.util.ArrayList;
004: import java.util.HashMap;
005: import java.util.Iterator;
006: import java.util.List;
007: import java.util.Map;
008: import java.util.Set;
009: import java.util.Vector;
010:
011: import javax.wsdl.Binding;
012: import javax.wsdl.Operation;
013: import javax.wsdl.Port;
014: import javax.wsdl.Service;
015: import javax.wsdl.extensions.soap.SOAPAddress;
016: import javax.xml.namespace.QName;
017: import javax.xml.rpc.Call;
018: import javax.xml.rpc.encoding.Deserializer;
019: import javax.xml.rpc.encoding.DeserializerFactory;
020:
021: import org.apache.axis.Constants;
022: import org.apache.axis.encoding.ser.SimpleDeserializer;
023: import org.apache.axis.wsdl.gen.Parser;
024: import org.apache.axis.wsdl.symbolTable.BaseType;
025: import org.apache.axis.wsdl.symbolTable.BindingEntry;
026: import org.apache.axis.wsdl.symbolTable.Parameter;
027: import org.apache.axis.wsdl.symbolTable.Parameters;
028: import org.apache.axis.wsdl.symbolTable.ServiceEntry;
029: import org.apache.axis.wsdl.symbolTable.SymTabEntry;
030: import org.apache.axis.wsdl.symbolTable.SymbolTable;
031: import org.apache.axis.wsdl.symbolTable.TypeEntry;
032: import org.enhydra.shark.api.client.wfmc.wapi.WMConnectInfo;
033: import org.enhydra.shark.api.client.wfmc.wapi.WMSessionHandle;
034: import org.enhydra.shark.api.client.wfservice.WMEntity;
035: import org.enhydra.shark.api.internal.toolagent.AppParameter;
036: import org.enhydra.shark.api.internal.toolagent.ApplicationBusy;
037: import org.enhydra.shark.api.internal.toolagent.ApplicationNotDefined;
038: import org.enhydra.shark.api.internal.toolagent.ApplicationNotStarted;
039: import org.enhydra.shark.api.internal.toolagent.ToolAgentGeneralException;
040: import org.enhydra.shark.xpdl.XPDLConstants;
041:
042: /**
043: * Tool agent that executes WEB Service using SOAP. When calling invoke method, the wsdl
044: * document location is given as application name, the first parameter that is passed has
045: * to represent the WEB service method to be called.
046: */
047: public class SOAPToolAgent extends AbstractToolAgent {
048:
049: public void invokeApplication(WMSessionHandle shandle, long handle,
050: WMEntity appInfo, WMEntity toolInfo,
051: String applicationName, String procInstId, String assId,
052: AppParameter[] parameters, Integer appMode)
053: throws ApplicationNotStarted, ApplicationNotDefined,
054: ApplicationBusy, ToolAgentGeneralException {
055:
056: super
057: .invokeApplication(shandle, handle, appInfo, toolInfo,
058: applicationName, procInstId, assId, parameters,
059: appMode);
060:
061: try {
062: status = APP_STATUS_RUNNING;
063:
064: if (appName == null || appName.trim().length() == 0) {
065: readParamsFromExtAttributes((String) parameters[0].the_value);
066: }
067:
068: AppParameter[] aps = new AppParameter[parameters.length - 1];
069: System.arraycopy(parameters, 1, aps, 0, aps.length);
070:
071: String operationName = (String) aps[0].the_value;
072: String portName = null;
073: try {
074: portName = operationName.substring(operationName
075: .indexOf("(") + 1, operationName.indexOf(")"));
076: operationName = operationName.substring(0,
077: operationName.indexOf("("));
078: } catch (Exception ignored) {
079: }
080:
081: Parser wsdlParser = null;
082: wsdlParser = new Parser();
083: cus.info(shandle,
084: "SOAPToolAgent -> Reading WSDL document from '"
085: + appName + "'");
086: wsdlParser.run(appName);
087:
088: HashMap map = invokeMethod(wsdlParser, operationName,
089: portName, aps);
090:
091: // print result
092: cus.info(shandle, "SOAPToolAgent -> Result:");
093: for (Iterator it = map.keySet().iterator(); it.hasNext();) {
094: String name = (String) it.next();
095: cus.info(shandle, " " + name + "="
096: + map.get(name));
097: }
098:
099: prepareResult(parameters, map);
100: cus.info(shandle, "\nSOAPToolAgent -> Done!");
101:
102: status = APP_STATUS_FINISHED;
103:
104: } catch (Throwable ex) {
105: cus.error(shandle, "SOAPToolAgent -> application "
106: + appName + " terminated incorrectly: " + ex);
107: status = APP_STATUS_INVALID;
108: throw new ToolAgentGeneralException(ex);
109: }
110: }
111:
112: public String getInfo(WMSessionHandle shandle)
113: throws ToolAgentGeneralException {
114: String i = "Executes WEB service operation."
115: + "\nWhen you map XPDL application to this tool agent, you should set application "
116: + "\nname to the location of the WSDL file that defines WEB service to be called."
117: + "\nAlso, this tool agent requires that the first parameter defined in XPDL Application's "
118: + "\nformal parameters represent the name of WEB service operation to be called."
119: + "\n"
120: + "\nThis tool agent is able to understand the extended attribute with the following name:"
121: + "\n * AppName - value of this attribute should represent the location of WSDL file where WEB service is defined"
122: + "\n"
123: + "\n NOTE: Tool agent will read extended attributes only if they are called through"
124: + "\n Default tool agent (not by shark directly) and this is the case when information "
125: + "\n on which tool agent to start for XPDL application definition is not contained in mappings";
126: return i;
127: }
128:
129: /**
130: */
131: public HashMap invokeMethod(Parser wsdlParser,
132: String operationName, String portName, AppParameter[] args)
133: throws Exception {
134: String serviceNS = null;
135: String serviceName = null;
136: String operationQName = null;
137:
138: cus.info(shandle,
139: "SOAPToolAgent -> Preparing Axis dynamic invocation");
140: Service service = getService(wsdlParser, serviceNS, serviceName);
141: Operation operation = null;
142: org.apache.axis.client.Service dpf = new org.apache.axis.client.Service(
143: wsdlParser, service.getQName());
144:
145: List inputs = new ArrayList();
146: Port port = getPort(service.getPorts(), portName);
147: if (portName == null) {
148: portName = port.getName();
149: }
150: Binding binding = port.getBinding();
151: Call call = dpf.createCall(QName.valueOf(portName), QName
152: .valueOf(operationName));
153: // ((org.apache.axis.client.Call)call).setTimeout(new Integer(15*1000));
154: // Output types and names
155: List outNames = new ArrayList();
156:
157: // Input types and names
158: List inNames = new ArrayList();
159: List inTypes = new ArrayList();
160: SymbolTable symbolTable = wsdlParser.getSymbolTable();
161: BindingEntry bEntry = symbolTable.getBindingEntry(binding
162: .getQName());
163: Parameters parameters = null;
164: Iterator i = bEntry.getParameters().keySet().iterator();
165:
166: while (i.hasNext()) {
167: Operation o = (Operation) i.next();
168: if (o.getName().equals(operationName)) {
169: operation = o;
170: parameters = (Parameters) bEntry.getParameters().get(o);
171: break;
172: }
173: }
174: if ((operation == null) || (parameters == null)) {
175: throw new RuntimeException(operationName
176: + " was not found.");
177: }
178:
179: // loop over paramters and set up in/out params
180: for (int j = 0; j < parameters.list.size(); ++j) {
181: Parameter p = (Parameter) parameters.list.get(j);
182:
183: if (p.getMode() == 1) { // IN
184: inNames.add(p.getQName().getLocalPart());
185: inTypes.add(p);
186: } else if (p.getMode() == 2) { // OUT
187: outNames.add(p.getQName().getLocalPart());
188: } else if (p.getMode() == 3) { // INOUT
189: inNames.add(p.getQName().getLocalPart());
190: inTypes.add(p);
191: outNames.add(p.getQName().getLocalPart());
192: }
193: }
194:
195: // set output type
196: if (parameters.returnParam != null) {
197: // Get the QName for the return Type
198: QName returnType = org.apache.axis.wsdl.toJava.Utils
199: .getXSIType(parameters.returnParam);
200: QName returnQName = parameters.returnParam.getQName();
201:
202: outNames.add(returnQName.getLocalPart());
203: }
204:
205: if (inNames.size() > args.length - 1)
206: throw new RuntimeException("Need " + inNames.size()
207: + " arguments!!!");
208:
209: for (int pos = 0; pos < inNames.size(); ++pos) {
210: AppParameter arg = args[pos + 1];
211: Parameter p = (Parameter) inTypes.get(pos);
212: inputs.add(getParamData((org.apache.axis.client.Call) call,
213: p, arg));
214: }
215: cus.info(shandle, "SOAPToolAgent -> Executing operation "
216: + operationName + " with parameters:");
217: for (int j = 0; j < inputs.size(); j++) {
218: cus.info(shandle, " " + inNames.get(j) + "="
219: + inputs.get(j));
220: }
221: java.lang.Object ret = call.invoke(inputs.toArray());
222: Map outputs = call.getOutputParams();
223: HashMap map = new HashMap();
224:
225: for (int pos = 0; pos < outNames.size(); ++pos) {
226: String name = (String) outNames.get(pos);
227: java.lang.Object value = outputs.get(name);
228:
229: if ((value == null) && (pos == 0)) {
230: map.put(name, ret);
231: } else {
232: map.put(name, value);
233: }
234: }
235: return map;
236: }
237:
238: private void prepareResult(AppParameter[] context, HashMap hashret)
239: throws Exception {
240: int n = 0;
241: Set set = hashret.entrySet();
242: Iterator it = set.iterator();
243:
244: java.lang.Object[] val = new java.lang.Object[hashret.size()];
245: while (it.hasNext()) {
246: Map.Entry mapentry = (Map.Entry) it.next();
247: val[n] = (java.lang.Object) mapentry.getValue();
248: n++;
249: }
250:
251: if (context != null) {
252: int en = 0;
253: for (int i = 0; i < context.length; i++) {
254: if (context[i].the_mode
255: .equals(XPDLConstants.FORMAL_PARAMETER_MODE_OUT)
256: || context[i].the_mode
257: .equals(XPDLConstants.FORMAL_PARAMETER_MODE_INOUT)) {
258: context[i].the_value = convertToProperType(val[en],
259: context[i].the_class);
260: en++;
261: }
262: }
263: }
264: }
265:
266: private Object convertToProperType(Object toConvert,
267: Class desiredType) throws Exception {
268: if (desiredType.isInstance(toConvert))
269: return toConvert;
270:
271: if (desiredType.equals(Long.class)) {
272: return new Long((new Double(toConvert.toString()))
273: .longValue());
274: } else if (desiredType.equals(Boolean.class)) {
275: return new Boolean(toConvert.toString());
276: } else if (desiredType.equals(Double.class)) {
277: return new Double(toConvert.toString());
278: } else if (desiredType.equals(java.util.Date.class)) {
279: return new java.util.Date(toConvert.toString());
280: }
281: return toConvert;
282: }
283:
284: /**
285: */
286: private static java.lang.Object getParamData(
287: org.apache.axis.client.Call c, Parameter p, AppParameter ap)
288: throws Exception {
289: // Get the QName representing the parameter type
290: QName paramType = org.apache.axis.wsdl.toJava.Utils
291: .getXSIType(p);
292: String arg = null;
293:
294: TypeEntry type = p.getType();
295: if (type instanceof BaseType && ((BaseType) type).isBaseType()) {
296: DeserializerFactory factory = c.getTypeMapping()
297: .getDeserializer(paramType);
298: Deserializer deserializer = factory
299: .getDeserializerAs(Constants.AXIS_SAX);
300: if (deserializer instanceof SimpleDeserializer) {
301: java.lang.Object obj = ap.the_value;
302: arg = String.valueOf(obj);
303: return ((SimpleDeserializer) deserializer)
304: .makeValue(arg);
305: }
306: }
307: throw new RuntimeException("don't know how to convert '" + arg
308: + "' into " + c);
309: }
310:
311: /**
312: */
313: public static Service getService(Parser wsdlParser,
314: String serviceNS, String serviceName) throws Exception {
315: QName serviceQName = null;
316: if (serviceNS != null && serviceName != null) {
317: serviceQName = new QName(serviceNS, serviceName);
318: }
319: ServiceEntry serviceEntry = (ServiceEntry) getSymTabEntry(
320: wsdlParser, serviceQName, ServiceEntry.class);
321: return serviceEntry.getService();
322: }
323:
324: /**
325: */
326: public static Port getPort(Map ports, String portName)
327: throws Exception {
328: Iterator valueIterator = ports.keySet().iterator();
329: while (valueIterator.hasNext()) {
330: String name = (String) valueIterator.next();
331: if ((portName == null) || (portName.length() == 0)) {
332: Port port = (Port) ports.get(name);
333: List list = port.getExtensibilityElements();
334:
335: for (int i = 0; (list != null) && (i < list.size()); i++) {
336: java.lang.Object obj = list.get(i);
337: if (obj instanceof SOAPAddress) {
338: return port;
339: }
340: }
341: } else if ((name != null) && name.equals(portName)) {
342: return (Port) ports.get(name);
343: }
344: }
345: return null;
346: }
347:
348: /**
349: */
350: public static SymTabEntry getSymTabEntry(Parser wsdlParser,
351: QName qname, Class cls) {
352: HashMap map = wsdlParser.getSymbolTable().getHashMap();
353: Iterator iterator = map.entrySet().iterator();
354:
355: while (iterator.hasNext()) {
356: Map.Entry entry = (Map.Entry) iterator.next();
357: QName key = (QName) entry.getKey();
358: Vector v = (Vector) entry.getValue();
359:
360: if ((qname == null) || qname.equals(key)) {
361: for (int i = 0; i < v.size(); ++i) {
362: SymTabEntry symTabEntry = (SymTabEntry) v
363: .elementAt(i);
364:
365: if (cls.isInstance(symTabEntry)) {
366: return symTabEntry;
367: }
368: }
369: }
370: }
371: return null;
372: }
373:
374: public static void main(String[] args) {
375: SOAPToolAgent soapTA = new SOAPToolAgent();
376: test1(soapTA);
377: test2(soapTA);
378: test3(soapTA);
379: test4(soapTA);
380: }
381:
382: public static void test1(SOAPToolAgent soapTA) {
383: try {
384:
385: WMSessionHandle handle = soapTA.connect(new WMConnectInfo(
386: "", "", "", ""));
387:
388: String appName = "http://www.ebi.ac.uk/xembl/XEMBL.wsdl";
389: AppParameter[] aps = new AppParameter[5];
390:
391: AppParameter ap = new AppParameter();
392: ap.the_value = "";
393: ap.the_mode = "IN";
394: ap.the_class = String.class;
395: aps[0] = ap;
396:
397: ap = new AppParameter();
398: ap.the_value = "getNucSeq";
399: ap.the_mode = "IN";
400: ap.the_class = String.class;
401: aps[1] = ap;
402:
403: ap = new AppParameter();
404: ap.the_value = "Bsml";
405: ap.the_actual_name = "nuc_format";
406: ap.the_formal_name = "format";
407: ap.the_mode = "IN";
408: ap.the_class = String.class;
409: aps[2] = ap;
410:
411: ap = new AppParameter();
412: ap.the_value = "HSERPG U83300 AC000057";
413: ap.the_actual_name = "nuc_ids";
414: ap.the_formal_name = "ids";
415: ap.the_mode = "IN";
416: ap.the_class = String.class;
417: aps[3] = ap;
418:
419: ap = new AppParameter();
420: ap.the_value = null;
421: ap.the_actual_name = "nuc_formula";
422: ap.the_formal_name = "formula";
423: ap.the_mode = "OUT";
424: ap.the_class = String.class;
425: aps[4] = ap;
426:
427: soapTA.invokeApplication(null, handle.getId(), null, null,
428: appName, "1", "1", aps, new Integer(0));
429: } catch (Exception ex) {
430: ex.printStackTrace();
431: }
432: }
433:
434: public static void test2(SOAPToolAgent soapTA) {
435: try {
436: WMSessionHandle handle = soapTA.connect(new WMConnectInfo(
437: "", "", "", ""));
438:
439: String appName = "http://samples.gotdotnet.com/quickstart/aspplus/samples/services/MathService/VB/MathService.asmx?WSDL";
440: AppParameter[] aps = new AppParameter[5];
441:
442: AppParameter ap = new AppParameter();
443: ap.the_value = "";
444: ap.the_mode = "IN";
445: ap.the_class = String.class;
446: aps[0] = ap;
447:
448: ap = new AppParameter();
449: ap.the_value = "Add";
450: ap.the_mode = "IN";
451: ap.the_class = String.class;
452: aps[1] = ap;
453:
454: ap = new AppParameter();
455: ap.the_value = new Double(3);
456: ap.the_actual_name = "par1";
457: ap.the_formal_name = "p1";
458: ap.the_mode = "IN";
459: ap.the_class = Double.class;
460: aps[2] = ap;
461:
462: ap = new AppParameter();
463: ap.the_value = new Double(44);
464: ap.the_actual_name = "par2";
465: ap.the_formal_name = "p2";
466: ap.the_mode = "IN";
467: ap.the_class = Double.class;
468: aps[3] = ap;
469:
470: ap = new AppParameter();
471: ap.the_value = null;
472: ap.the_actual_name = "res";
473: ap.the_formal_name = "r";
474: ap.the_mode = "OUT";
475: ap.the_class = Double.class;
476: aps[4] = ap;
477:
478: soapTA.invokeApplication(null, handle.getId(), null, null,
479: appName, "1", "1", aps, new Integer(0));
480: } catch (Exception ex) {
481: ex.printStackTrace();
482: }
483: }
484:
485: public static void test3(SOAPToolAgent soapTA) {
486: try {
487: WMSessionHandle handle = soapTA.connect(new WMConnectInfo(
488: "", "", "", ""));
489:
490: String appName = "http://www.xmethods.net/sd/2001/TemperatureService.wsdl";
491: AppParameter[] aps = new AppParameter[4];
492:
493: AppParameter ap = new AppParameter();
494: ap.the_value = "";
495: ap.the_mode = "IN";
496: ap.the_class = String.class;
497: aps[0] = ap;
498:
499: ap = new AppParameter();
500: ap.the_value = "getTemp";
501: ap.the_mode = "IN";
502: ap.the_class = String.class;
503: aps[1] = ap;
504:
505: ap = new AppParameter();
506: ap.the_value = "02067";
507: ap.the_actual_name = "par1";
508: ap.the_formal_name = "p1";
509: ap.the_mode = "IN";
510: ap.the_class = String.class;
511: aps[2] = ap;
512:
513: ap = new AppParameter();
514: ap.the_value = null;
515: ap.the_actual_name = "res";
516: ap.the_formal_name = "r";
517: ap.the_mode = "OUT";
518: ap.the_class = Double.class;
519: aps[3] = ap;
520:
521: soapTA.invokeApplication(null, handle.getId(), null, null,
522: appName, "1", "1", aps, new Integer(0));
523: } catch (Exception ex) {
524: ex.printStackTrace();
525: }
526: }
527:
528: public static void test4(SOAPToolAgent soapTA) {
529: try {
530: WMSessionHandle handle = soapTA.connect(new WMConnectInfo(
531: "", "", "", ""));
532:
533: String appName = "http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl";
534: AppParameter[] aps = new AppParameter[4];
535:
536: AppParameter ap = new AppParameter();
537: ap.the_value = "";
538: ap.the_mode = "IN";
539: ap.the_class = String.class;
540: aps[0] = ap;
541:
542: ap = new AppParameter();
543: ap.the_value = "getQuote";
544: ap.the_mode = "IN";
545: ap.the_class = String.class;
546: aps[1] = ap;
547:
548: ap = new AppParameter();
549: ap.the_value = "IBM";
550: ap.the_actual_name = "par1";
551: ap.the_formal_name = "p1";
552: ap.the_mode = "IN";
553: ap.the_class = String.class;
554: aps[2] = ap;
555:
556: ap = new AppParameter();
557: ap.the_value = null;
558: ap.the_actual_name = "res";
559: ap.the_formal_name = "r";
560: ap.the_mode = "OUT";
561: ap.the_class = Double.class;
562: aps[3] = ap;
563:
564: soapTA.invokeApplication(null, handle.getId(), null, null,
565: appName, "1", "1", aps, new Integer(0));
566: } catch (Exception ex) {
567: ex.printStackTrace();
568: }
569: }
570:
571: // java samples.client.DynamicInvoker http://mssoapinterop.org/asmx/xsd/round4XSD.wsdl
572: // echoString "Hello World!!!"
573: }
|