View Javadoc

1   ///////////////////////////////////////////////////////////////
2   //
3   // © University of Southampton IT Innovation Centre,  2007
4   //
5   // Copyright in this software belongs to the IT Innovation Centre of
6   // 2 Venture Road, Chilworth Science Park, Southampton SO16 7NP, UK.
7   //
8   // This software may not be used, sold, licensed, transferred, copied
9   // or reproduced in whole or in part in any manner or form or in or
10  // on any media by any person other than in accordance with the terms
11  // of the Licence Agreement supplied with the software, or otherwise
12  // without the prior written consent of the copyright owners.
13  //
14  // This software is distributed WITHOUT ANY WARRANTY, without even the
15  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  // PURPOSE, except where stated in the Licence Agreement supplied with
17  // the software.
18  //
19  //      Modified By :          Nikolaos Matskanis
20  //      Modified Date :        19/03/2007
21  //      Modified for Project : NextGRID
22  //
23  ////////////////////////////////////////////////////////////////////////
24  //
25  //     Dependencies : Based on code from Mindswap under the MIT License
26  //
27  //////////////////////////////////////////////////////////////////////////
28  //
29  // The MIT License
30  //
31  // Copyright (c) 2004 Evren Sirin
32  //
33  // Permission is hereby granted, free of charge, to any person obtaining a copy
34  // of this software and associated documentation files (the "Software"), to
35  // deal in the Software without restriction, including without limitation the
36  // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
37  // sell copies of the Software, and to permit persons to whom the Software is
38  // furnished to do so, subject to the following conditions:
39  //
40  // The above copyright notice and this permission notice shall be included in
41  // all copies or substantial portions of the Software.
42  //
43  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
48  // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
49  // IN THE SOFTWARE.
50  
51  package  uk.ac.soton.itinnovation.wsdlutils;
52  
53  
54  import java.io.InputStream;
55  import java.io.ByteArrayInputStream;
56  import java.util.Iterator;
57  import java.util.Vector;
58  
59  import javax.xml.namespace.QName;
60  import javax.xml.soap.SOAPElement;
61  import javax.xml.soap.SOAPException;
62  import javax.xml.parsers.DocumentBuilderFactory;
63  
64  import org.apache.axis.client.Call;
65  import org.apache.axis.constants.Style;
66  import org.apache.axis.message.MessageElement;
67  import org.w3c.dom.Document;
68  import org.w3c.dom.Element;
69  import org.apache.axis.message.SOAPBodyElement;
70  import org.apache.axis.message.SOAPEnvelope;
71  import org.apache.axis.message.SOAPHeaderElement;
72  import org.w3c.dom.Node;
73  import org.w3c.dom.NodeList;
74  
75  
76  import uk.ac.soton.itinnovation.utils.URIUtils;
77  
78  public class WSDLOperation {
79  	public static boolean DEBUG = true;
80  		
81  	private WSDLService service = null;
82  	private Call call = null;
83  	private Vector inputs = new Vector();
84  	private Vector outputs = new Vector();
85  	private String operationName;
86  	private String inputMessageName;
87  	private String outputMessageName;
88  	private String portName;
89  	private String documentation;
90          private Element secToken;
91          private Document requestDocument=null;
92  	private SOAPHeaderElement slaHeader;
93  
94  	public WSDLOperation(Call c) {
95  		this.call = c;
96  	}  
97  
98  	
99  	public WSDLParameter getInput(int i) { 
100 		return (WSDLParameter) getInputs().elementAt(i);
101 	}
102 	public WSDLParameter getInput(String name) { 
103 	    for(int i = 0; i < inputs.size(); i++) {
104 	        WSDLParameter in = (WSDLParameter) inputs.get(i);
105 	        String paramName = in.getName();
106 	        if(paramName.equals(name) || URIUtils.getLocalName(paramName).equals(name))
107 	            return in;
108 	    }
109 		
110 		return null;
111 	}
112 	public WSDLParameter getOutput(int i) { 
113 		return (WSDLParameter) getOutputs().elementAt(i);
114 	}	
115 	public WSDLParameter getOutput(String name) { 
116 	    for(int i = 0; i < outputs.size(); i++) {
117 	        WSDLParameter out = (WSDLParameter) outputs.get(i);
118 	        String paramName = out.getName();
119 	        if( URIUtils.relaxedMatch(paramName, name) )
120 	            return out;
121 	    }
122 		
123 		return null;
124 	}
125 	public Vector getInputs() {	return inputs;	}
126 	public Vector getOutputs() { return outputs; }
127 	void addInput(String name, QName type) { inputs.add(new WSDLParameter(name, type)); }
128 	void addOutput(String name, QName type) { outputs.add(new WSDLParameter(name, type)); }	
129 	
130 	public String getName() { return call.getOperationName().getLocalPart(); }
131 	
132 	public String getOperationName() { return operationName; }
133 	public void setOperationName(String s) { operationName = s; }
134 	public String getPortName() { return portName; }
135 	public void setPortName(String s) { portName = s; }
136 	public String getInputMessageName() { return inputMessageName; }
137 	public void setInputMessageName(String s) { inputMessageName = s; }
138 	public String getOutputMessageName() { return outputMessageName; }
139 	public void setOutputMessageName(String s) { outputMessageName = s; }
140 	public WSDLService getService() { return service; }
141 	public void setService(WSDLService s) { service = s; }
142 	public String getDocumentation() { return documentation; }
143 	public void setDocumentation(String s) { documentation = s; }	
144         public void setRequestDocument(Document doc){ this.requestDocument=doc; }
145 
146         public void addHeader(SOAPHeaderElement param){ call.addHeader(param);}
147         public void setOperationStyle(Style style){ call.setOperationStyle(style);}
148 
149 	public String toString() {
150 		return getName();
151 	}
152 	
153 	public String getDescription() {
154 		String s = getName() + "(";
155 		
156 		for(Iterator i = inputs./*values().*/iterator(); i.hasNext(); ) {
157 			WSDLParameter param = (WSDLParameter) i.next();
158 			s += param.getName() + ":" + param.getType().getLocalPart();
159 			if(i.hasNext())	s += ", ";
160 		}					
161 		s += ") -> (";
162 			
163 		for(Iterator i = outputs./*values().*/iterator(); i.hasNext(); ) {
164 			WSDLParameter param = (WSDLParameter) i.next();
165 			s += param.getName() + ":" + param.getType().getLocalPart();
166 			if(i.hasNext())	s += ", ";
167 		}		
168 		s += ")";
169 
170 		return s;
171 	}
172 	
173 
174         public void setSecToken(Element token){
175                 secToken=token;
176         }
177 	
178         public void setSLAHeader(SOAPHeaderElement header ){
179                 slaHeader=header;
180         }
181 
182 	public void invoke() throws Exception {
183 		SOAPEnvelope request = createRequest();
184                 if (secToken!=null){
185                         request.addHeader(new SOAPHeaderElement(secToken));
186                 }
187                 if (slaHeader!=null){
188                         request.addHeader(slaHeader);
189                 }
190 
191 							
192 		if(DEBUG) {	
193 			System.out.println("Invoke operation " + getDescription());
194 			System.out.println(request);
195 		}
196 			
197 		SOAPEnvelope reply = call.invoke(request);
198 
199 		// TODO Handle SOAPFault message
200 		
201 		
202 		processResult(reply);		
203 	}	
204 	
205         private SOAPElement response=null;
206         public  Iterator getResponse(){
207                 return response.getChildElements();
208                }
209 	private void processResult(SOAPEnvelope reply) throws SOAPException {	
210 		SOAPElement soapBody = reply.getBody();
211 		response = (SOAPElement) soapBody.getChildElements().next();
212 		Iterator messageParts = response.getChildElements();
213 		
214 		for(int i = 0; i < outputs.size(); i++) {
215 			WSDLParameter output = (WSDLParameter) outputs.elementAt(i);
216 			
217 			SOAPElement e = (SOAPElement) messageParts.next();	
218 			output.setTextValue(e.toString());
219 			
220 			if(DEBUG) {
221 				System.out.println("processResult " + e);
222 				System.out.println("getValue " + e.getValue());
223 				System.out.println("getType " + (e.getNodeType() == Node.ELEMENT_NODE));
224 				System.out.println("getValue is null? " + (e.getValue() == null));
225 				System.out.println("result has children? " + e.getChildElements().hasNext());
226 				if(e.getChildElements().hasNext()) {
227 				    Node child = (Node) e.getChildElements().next();
228 					System.out.println("result first child " + child);
229 				}
230 			}	 
231 						
232 			Iterator children = e.getChildElements();
233 			if( children.hasNext() ) {
234 			    Node child = (Node) e.getChildElements().next();
235 			    if( child.getNodeType() == Node.TEXT_NODE ) 
236 					output.setValue( child.toString() );
237 				else
238 					output.setValue( e.toString() );    
239 			}
240 			else
241 			    output.setValue( e.toString() );
242 		}			
243 	}
244 
245 	
246 	private SOAPEnvelope createRequest() throws SOAPException {		
247 		String targetNamespace = call.getOperationName().getNamespaceURI();
248 		String opName = call.getOperationName().getLocalPart();		
249 		SOAPEnvelope envelope = new SOAPEnvelope();
250 	
251 		if(DEBUG) {
252 			System.out.println("Get opName = " + call.getOperationName());
253 			System.out.println("SOAP opName = " +opName);
254 			System.out.println("SOAP Action = " +call.getSOAPActionURI());
255 			System.out.println("SOAP Action used = " + call.useSOAPAction());
256 		}
257 		
258 		envelope.addNamespaceDeclaration("xsi", WSDLConsts.xsiURI);
259 		envelope.addNamespaceDeclaration("xsd",WSDLConsts. xsdURI);
260 		//envelope.addNamespaceDeclaration("ns0", targetNamespace);
261 		
262 		String inputEncodingStyle = "http://schemas.xmlsoap.org/soap/encoding/";
263 		if(inputEncodingStyle != null) {
264 		  envelope.setEncodingStyle(inputEncodingStyle);
265 		  envelope.addAttribute(WSDLConsts.soapURI, "encodingStyle", inputEncodingStyle);
266 		}
267 		  
268 		// FIXME test this feature
269                 SOAPBodyElement soapBody =null;
270                 if (call.getOperationStyle().equals(Style.RPC)){ 
271                         String nsOp = "u" ; 
272                         soapBody = new SOAPBodyElement(
273 				envelope.createName(opName, nsOp, targetNamespace)); 
274                 }
275                 else {
276                         setOperationStyle(Style.DOCUMENT);
277                         if(requestDocument!=null)soapBody = new SOAPBodyElement((Element)requestDocument.getDocumentElement());
278                         else soapBody = new SOAPBodyElement(envelope.createName(opName));
279                 }
280 
281                 envelope.addBodyElement(soapBody);
282 		
283 		for(Iterator i = inputs.iterator(); i.hasNext(); ) {
284 			WSDLParameter param = (WSDLParameter) i.next();
285 			Object paramValue = param.getValue();
286 			
287 			if(paramValue == null) continue;
288 					
289 			SOAPElement soapElement = soapBody.addChildElement(URIUtils.getLocalName(param.getName()), "");
290 			
291 			// TODO treat string, int, float differently
292 		   	if(((String)paramValue).startsWith("<")  ) {
293 		   		if(DEBUG)
294 					System.out.println("Case 1");
295                                 InputStream in=new ByteArrayInputStream(((String)paramValue).getBytes());
296                                 try{
297                                   DocumentBuilderFactory dbf= new org.apache.xerces.jaxp.DocumentBuilderFactoryImpl();
298                                   Document doc=dbf.newDocumentBuilder().parse(in); 
299                                   System.out.println("GOT DOCUMENT\n"+doc);
300 
301                                   Node inputNode=doc.getDocumentElement();
302 		   		  createSOAPElement(soapElement, inputNode);
303                                 }catch(Exception pe){
304                                         throw new SOAPException(pe);
305                                 }
306 		   		if(soapElement.getAttributeValue(WSDLConsts.xsiType) == null) {
307 		   			if(DEBUG) System.out.println("Case 1a");
308 			   		soapElement.addAttribute(WSDLConsts.xsiType, 
309 			   			"u:" + param.getType().getLocalPart());
310 			   	}
311 		   	}
312 		   	else {
313 		   		if(DEBUG){
314 					System.out.println("Case 2 " + param.getType());				
315 					System.out.println("Case 2 " +				paramValue.toString());
316                                 }
317 				soapElement.addAttribute(WSDLConsts.xsiType, "xsd:" + param.getType().getLocalPart());
318 		   		soapElement.addTextNode(paramValue.toString());
319 		   	}
320 			   				
321 		}
322 		
323 		return envelope;	
324 	}
325 	
326 	public void createSOAPElement(SOAPElement parent, Node node) throws SOAPException {
327 		int type = node.getNodeType();
328         
329 		if(type == Node.TEXT_NODE) {
330 		   		if(DEBUG)
331 					System.out.println("Case 3");
332 			
333 			parent.addAttribute(WSDLConsts.xsiType, "xsd:string");
334 			parent.addTextNode(node.getNodeValue());        		
335 		}
336         else if(type == Node.ELEMENT_NODE) {        
337         	SOAPElement soapElement;
338         	
339         	if(!(node.getParentNode() instanceof org.w3c.dom.Document)) {
340 		   		if(DEBUG)
341 					System.out.println("Case 4");
342         		
343 				soapElement = parent.addChildElement(node.getNodeName()); 
344 			}
345 			else {
346 		   		if(DEBUG)
347 					System.out.println("Case 5");
348 					
349 				soapElement = parent;				
350 			}
351 
352             //NamedNodeMap attrs = node.getAttributes();
353                         
354             NodeList children = node.getChildNodes();
355             if (children != null) {
356                 int len = children.getLength();
357                 for (int i = 0; i < len; i++) {
358                     createSOAPElement(soapElement, children.item(i));                    
359                 }
360             }
361         }
362 	}	
363 
364 
365 }