1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.mock;
14
15 import java.util.Collections;
16 import java.util.LinkedList;
17 import java.util.List;
18
19 import javax.servlet.http.HttpServletRequest;
20 import javax.servlet.http.HttpServletResponse;
21 import javax.wsdl.BindingOperation;
22 import javax.wsdl.Part;
23 import javax.xml.namespace.QName;
24
25 import org.apache.xmlbeans.XmlObject;
26 import org.mortbay.jetty.Request;
27 import org.w3c.dom.Element;
28 import org.w3c.dom.Node;
29 import org.w3c.dom.NodeList;
30
31 import com.eviware.soapui.SoapUI;
32 import com.eviware.soapui.impl.wsdl.WsdlOperation;
33 import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
34 import com.eviware.soapui.model.mock.MockResult;
35 import com.eviware.soapui.model.mock.MockRunListener;
36 import com.eviware.soapui.model.mock.MockRunner;
37 import com.eviware.soapui.support.xml.XmlUtils;
38
39 public class WsdlMockRunner implements MockRunner
40 {
41 private final WsdlMockService mockService;
42 private List<WsdlMockResult> mockResults = Collections.synchronizedList( new LinkedList<WsdlMockResult>());
43 private int maxResults = 100;
44 private int removed = 0;
45 private WsdlMockRunContext mockContext;
46
47 public WsdlMockRunner( WsdlMockService mockService ) throws Exception
48 {
49 this.mockService = mockService;
50
51 mockContext = new WsdlMockRunContext( mockService );
52
53 SoapUI.getMockEngine().startMockService( this );
54
55 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
56
57 for( MockRunListener listener : mockRunListeners )
58 {
59 listener.onMockRunnerStart( this );
60 }
61 }
62
63 public WsdlMockRunContext getMockContext()
64 {
65 return mockContext;
66 }
67
68 public void addMockResult( WsdlMockResult mockResult )
69 {
70 mockResults.add( mockResult );
71 if( mockResults.size() > maxResults )
72 {
73 mockResults.remove( 0 );
74 removed++;
75 }
76 }
77
78 public void stop()
79 {
80 SoapUI.getMockEngine().stopMockService( this );
81
82 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
83
84 for( MockRunListener listener : mockRunListeners )
85 {
86 listener.onMockRunnerStop( this );
87 }
88 }
89
90 public WsdlMockService getMockService()
91 {
92 return mockService;
93 }
94
95 public WsdlMockResult dispatchRequest( HttpServletRequest request, HttpServletResponse response ) throws DispatchException
96 {
97 WsdlMockResult result = null;
98 MockRunListener[] mockRunListeners = mockService.getMockRunListeners();
99
100 try
101 {
102 for( MockRunListener listener : mockRunListeners )
103 {
104 listener.onMockRequest( this, request, response );
105 }
106
107 long timestamp = System.currentTimeMillis();
108 String soapAction = request.getHeader( "SOAPAction" );
109
110 WsdlMockRequest mockRequest = new WsdlMockRequest( request, response, mockContext );
111
112 SoapVersion soapVersion = mockRequest.getSoapVersion();
113 if( soapVersion == null )
114 throw new DispatchException( "Unrecognized SOAP Version" );
115
116 XmlObject contentElm = mockRequest.getContentElement();
117 if( contentElm == null )
118 throw new DispatchException( "Missing content element in body" );
119
120 QName contentQName = XmlUtils.getQName( contentElm.getDomNode() );
121 NodeList contentChildNodes = null;
122
123 for( int c = 0; c < mockService.getMockOperationCount(); c++ )
124 {
125 WsdlMockOperation mockOperation = ( WsdlMockOperation ) mockService.getMockOperationAt( c );
126 WsdlOperation wsdlOperation = ( WsdlOperation ) mockOperation.getOperation();
127 if( wsdlOperation == null )
128 continue;
129
130 if( mockService.isRequireSoapVersion() &&
131 wsdlOperation.getInterface().getSoapVersion() != mockRequest.getSoapVersion() )
132 {
133 continue;
134 }
135
136 String action = "\"" + wsdlOperation.getAction() + "\"";
137
138
139 if( (soapAction == null && wsdlOperation.getAction() == null ) ||
140 (action.equals( soapAction ) || wsdlOperation.getAction().equals( soapAction ) ))
141 {
142 QName qname = wsdlOperation.getRequestBodyElementQName();
143
144 if( !qname.equals( contentQName ))
145 continue;
146
147 long startTime = 0;
148
149
150 if( wsdlOperation.getStyle().equals( WsdlOperation.STYLE_DOCUMENT ))
151 {
152
153 startTime = System.nanoTime();
154 result = mockOperation.dispatchRequest( mockRequest, response );
155 }
156 else if( wsdlOperation.getStyle().equals( WsdlOperation.STYLE_RPC ))
157 {
158 BindingOperation bindingOperation = wsdlOperation.getBindingOperation();
159 List<Part> parts = bindingOperation.getOperation().getInput().getMessage().getOrderedParts( null );
160
161 if( contentChildNodes == null )
162 contentChildNodes = XmlUtils.getChildElements( ( Element ) contentElm.getDomNode() );
163
164 int i = 0;
165
166 if( parts.size() > 0 )
167 {
168 for( ; i < contentChildNodes.getLength() && !parts.isEmpty(); i++ )
169 {
170 Node item = contentChildNodes.item( i );
171 if( item.getNodeType() != Node.ELEMENT_NODE )
172 continue;
173
174 int j=0;
175 while ((j<parts.size()) && (!item.getNodeName().equals( parts.get( j ).getName())))
176 {
177 j++;
178 }
179
180 if (j==parts.size())
181 break;
182
183 parts.remove( j );
184 }
185 }
186
187
188 if( i == contentChildNodes.getLength() && parts.isEmpty() )
189 {
190 startTime = System.nanoTime();
191 result = mockOperation.dispatchRequest( mockRequest, response );
192 }
193 }
194
195 if( startTime == 0 )
196 {
197 throw new DispatchException( "Failed to find matching operation for request" );
198 }
199 else
200 {
201 ((Request)request).setHandled( true );
202 result.setTimeTaken( ( System.nanoTime() - startTime ) / 1000000 );
203 result.setTimestamp( timestamp );
204 addMockResult( result );
205 return result;
206 }
207 }
208 }
209
210 throw new DispatchException( "Missing operation for soapAction [" + soapAction + "] and body element [" +
211 contentQName + "] with SOAP Version [" + mockRequest.getSoapVersion() + "]" );
212 }
213 catch( Exception e )
214 {
215 e.printStackTrace();
216
217 if( e instanceof DispatchException )
218 throw (DispatchException)e;
219
220 throw new DispatchException( e );
221 }
222 finally
223 {
224 if( result != null )
225 {
226 for( MockRunListener listener : mockRunListeners )
227 {
228 listener.onMockResult( result );
229 }
230 }
231 }
232 }
233
234 public MockResult getMockResultAt( int index )
235 {
236 return index <= removed ? null : mockResults.get( index-removed );
237 }
238
239 public int getMockResultCount()
240 {
241 return mockResults.size() + removed;
242 }
243 }