Source code: org/embl/ebi/escience/scuflworkers/wsdl/WSDLBasedProcessor.java
1 /**
2 * This file is a component of the Taverna project,
3 * and is licensed under the GNU LGPL.
4 * Copyright Tom Oinn, EMBL-EBI
5 */
6 package org.embl.ebi.escience.scuflworkers.wsdl;
7
8 import javax.wsdl.Binding;
9 import javax.wsdl.Operation;
10 import javax.wsdl.Port; // ambiguous with: org.embl.ebi.escience.scufl.Port
11 import javax.wsdl.Service; // ambiguous with: javax.xml.rpc.Service
12 import javax.wsdl.extensions.soap.SOAPAddress;
13 import javax.xml.namespace.QName;
14 import javax.xml.rpc.Call;
15 import org.apache.axis.wsdl.gen.Parser;
16 import org.apache.axis.wsdl.symbolTable.*;
17 import org.embl.ebi.escience.scufl.*;
18
19 // Utility Imports
20 import java.util.*;
21
22
23
24
25 /**
26 * A processor based on an operation defined within
27 * a WSDL file accessible to the class at construction
28 * time.
29 * @author Tom Oinn
30 */
31 public class WSDLBasedProcessor extends Processor implements java.io.Serializable {
32
33 // Fields used by the configuration operations
34 // Output types and names
35 Vector outNames = new Vector();
36 Vector outTypes = new Vector();
37 // Input types and names
38 Vector inNames = new Vector();
39 Vector inTypes = new Vector();
40 // WSDL Parser
41 Parser wsdlParser = null;
42 // Call object to invoke this processor
43 Call call = null;
44
45 private String wsdlLocation = null;
46 /**
47 * Get the WSDL location for this processor
48 */
49 public String getWSDLLocation() {
50 return this.wsdlLocation;
51 }
52
53 private String operationName = null;
54 /**
55 * Get the operation name for this processor
56 */
57 public String getOperationName() {
58 return this.operationName;
59 }
60
61 /**
62 * Construct a new processor from the given WSDL definition
63 * and operation name, delegates to superclass then instantiates
64 * ports based on WSDL inspection.
65 */
66 public WSDLBasedProcessor(ScuflModel model, String name, String wsdlLocation, String operationName)
67 throws ProcessorCreationException,
68 DuplicateProcessorNameException {
69 super(model, name);
70 this.wsdlLocation = wsdlLocation;
71 this.operationName = operationName;
72 // Load the WSDL document
73 try {
74 wsdlParser = new Parser();
75 int retryCount = 3;
76 int retryDelay = 1000;
77 boolean loaded = false;
78 while (retryCount > 0 && !loaded) {
79 try {
80 wsdlParser.run(wsdlLocation);
81 loaded = true;
82 }
83 catch (Exception ex2) {
84 retryCount--;
85 if (retryCount > 0) {
86 Thread.sleep(retryDelay);
87 }
88 else {
89 throw ex2;
90 }
91 }
92 }
93 }
94 catch (Exception ex) {
95 ProcessorCreationException pce = new ProcessorCreationException("Unable to load wsdl!");
96 pce.initCause(ex);
97 pce.printStackTrace();
98 throw pce;
99 }
100
101 // Set up input and output vectors and create the Call object
102 configureFor(operationName);
103
104 // Build ports from the input and output vectors
105 try {
106 for (int i = 0; i < outNames.size(); i++) {
107 String outName = (String)outNames.get(i);
108 OutputPort outputPort = new OutputPort(this, outName);
109 outputPort.setSyntacticType(xsdTypeToInternalType(((Parameter)outTypes.get(i)).getType().getQName().getLocalPart()));
110 addPort(outputPort);
111 }
112 for (int i = 0; i < inNames.size(); i++) {
113 String inName = (String)inNames.get(i);
114 InputPort inputPort = new InputPort(this, inName);
115 inputPort.setSyntacticType(xsdTypeToInternalType(((Parameter)inTypes.get(i)).getType().getQName().getLocalPart()));
116 addPort(inputPort);
117 }
118 }
119 catch (DuplicatePortNameException dpne) {
120 ProcessorCreationException pce = new ProcessorCreationException("Duplicate port names!");
121 pce.initCause(dpne);
122 throw pce;
123 }
124 catch (PortCreationException portce) {
125 ProcessorCreationException pce = new ProcessorCreationException("Port creation failure!");
126 pce.initCause(portce);
127 throw pce;
128 }
129 }
130
131 /**
132 * Load information from the WSDL parser to populate the input and
133 * output vectors and create the Call object
134 */
135 private void configureFor(String operationName)
136 throws ProcessorCreationException {
137 try {
138 String portName = null;
139 Service service = ((ServiceEntry)getSymTabEntry(null, ServiceEntry.class)).getService();
140 Port port = selectPort(service.getPorts(), portName);
141 portName = port.getName();
142 Binding binding = port.getBinding();
143 org.apache.axis.client.Service dpf = new org.apache.axis.client.Service(wsdlParser, service.getQName());
144 this.call = dpf.createCall(QName.valueOf(portName), QName.valueOf(operationName));
145
146 SymbolTable symbolTable = wsdlParser.getSymbolTable();
147 BindingEntry bEntry = symbolTable.getBindingEntry(binding.getQName());
148
149 // Iterate over the binding entry searching for the operation
150 // specified in the argument to the invokeMethod call.
151 Operation operation = null;
152 Parameters parameters = null;
153 for (Iterator i = bEntry.getParameters().keySet().iterator(); i.hasNext(); ) {
154 Operation o = (Operation) i.next();
155 if (o.getName().equals(operationName)) {
156 operation = o;
157 parameters = (Parameters) bEntry.getParameters().get(o);
158 // Populate the input and output descriptions
159 for (int j = 0; j < parameters.list.size(); j++) {
160 Parameter p = (Parameter) parameters.list.get(j);
161 if (p.getMode() == 1) { // IN
162 inNames.add(p.getQName().getLocalPart());
163 inTypes.add(p);
164 } else if (p.getMode() == 2) { // OUT
165 outNames.add(p.getQName().getLocalPart());
166 outTypes.add(p);
167 } else if (p.getMode() == 3) { // INOUT
168 inNames.add(p.getQName().getLocalPart());
169 inTypes.add(p);
170 outNames.add(p.getQName().getLocalPart());
171 outTypes.add(p);
172 }
173 }
174 // Set output type
175 if (parameters.returnParam != null) {
176 // Get the QName for the return Type
177 QName returnType = org.apache.axis.wsdl.toJava.Utils.getXSIType(parameters.returnParam);
178 QName returnQName = parameters.returnParam.getQName();
179 outNames.add(returnQName.getLocalPart());
180 outTypes.add((Parameter)parameters.returnParam);
181 }
182 // Break out of the loop
183 break;
184 }
185 }
186 if ((operation == null) || (parameters == null)) {
187 throw new RuntimeException(operationName + " was not found.");
188 }
189
190 }
191 catch (Exception e) {
192 e.printStackTrace();
193 ProcessorCreationException pce = new ProcessorCreationException("Problem initialising from wsdl...");
194 pce.initCause(e);
195 throw pce;
196 }
197 }
198
199 /**
200 * Convert an XSD type into a Baclava type string
201 */
202 public String xsdTypeToInternalType(String xsdType) {
203 // System.out.println("Type conversion requested for "+xsdType);
204 // Can cope with String types and nested strings
205 if (xsdType.startsWith("ArrayOf_")) {
206 return ("l("+xsdTypeToInternalType(xsdType.replaceFirst("ArrayOf_",""))+")");
207 }
208 else if (xsdType.startsWith("ArrayOf")) {
209 return ("l("+xsdTypeToInternalType(xsdType.replaceFirst("ArrayOf",""))+")");
210 }
211 else if (xsdType.equalsIgnoreCase("base64")) {
212 return "'application/octet-stream'";
213 }
214 else {
215 return "'text/plain'";
216 /**
217 if (xsdType.equalsIgnoreCase("string")) {
218 return "'text/plain'";
219 }
220 else {
221 return "'text/x-xsd-unknown-type-"+xsdType+"'";
222 }
223 */
224 }
225 }
226
227
228
229 /**
230 * Get the properties for this processor for display purposes
231 */
232 public Properties getProperties() {
233 Properties props = new Properties();
234 props.put("wsdlLocation",getWSDLLocation());
235 props.put("operation",getOperationName());
236 return props;
237 }
238
239 /**
240 * Method getSymTabEntry
241 * Search the symbol table for an entry with the specified
242 * class and optionally QName. If the QName is not specified
243 * then examine all entries.
244 */
245 public SymTabEntry getSymTabEntry(QName qname, Class cls) {
246 HashMap map = wsdlParser.getSymbolTable().getHashMap();
247 Iterator iterator = map.entrySet().iterator();
248
249 while (iterator.hasNext()) {
250 Map.Entry entry = (Map.Entry) iterator.next();
251 QName key = (QName) entry.getKey();
252 Vector v = (Vector) entry.getValue();
253
254 if ((qname == null) || qname.equals(qname)) {
255 for (int i = 0; i < v.size(); ++i) {
256 SymTabEntry symTabEntry = (SymTabEntry) v.elementAt(i);
257
258 if (cls.isInstance(symTabEntry)) {
259 return symTabEntry;
260 }
261 }
262 }
263 }
264 return null;
265 }
266
267 /**
268 * Given a map of ports, iterate across it until either
269 * a port matching the portName parameter is found or until
270 * any port is found with a SOAPAddress extensibility element.
271 * Return null if no such port can be located.
272 */
273 public Port selectPort(Map ports, String portName) throws Exception {
274 Iterator valueIterator = ports.keySet().iterator();
275 while (valueIterator.hasNext()) {
276 String name = (String) valueIterator.next();
277 if ((portName == null) || (portName.length() == 0)) {
278 Port port = (Port) ports.get(name);
279 List list = port.getExtensibilityElements();
280 for (int i = 0; (list != null) && (i < list.size()); i++) {
281 Object obj = list.get(i);
282 if (obj instanceof SOAPAddress) {
283 return port;
284 }
285 }
286 } else if ((name != null) && name.equals(portName)) {
287 return (Port) ports.get(name);
288 }
289 }
290 return null;
291 }
292
293 }