1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.mock;
14
15 import java.beans.PropertyChangeEvent;
16 import java.beans.PropertyChangeListener;
17 import java.io.File;
18 import java.io.IOException;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import javax.swing.ImageIcon;
23
24 import org.apache.log4j.Logger;
25
26 import com.eviware.soapui.SoapUI;
27 import com.eviware.soapui.config.MockOperationConfig;
28 import com.eviware.soapui.config.MockOperationDispatchStyleConfig;
29 import com.eviware.soapui.config.MockResponseConfig;
30 import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
31 import com.eviware.soapui.impl.wsdl.WsdlInterface;
32 import com.eviware.soapui.impl.wsdl.WsdlOperation;
33 import com.eviware.soapui.impl.wsdl.WsdlProject;
34 import com.eviware.soapui.impl.wsdl.mock.dispatch.MockOperationDispatchRegistry;
35 import com.eviware.soapui.impl.wsdl.mock.dispatch.MockOperationDispatcher;
36 import com.eviware.soapui.impl.wsdl.support.CompressedStringSupport;
37 import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
38 import com.eviware.soapui.model.ModelItem;
39 import com.eviware.soapui.model.iface.Interface;
40 import com.eviware.soapui.model.iface.Operation;
41 import com.eviware.soapui.model.mock.MockOperation;
42 import com.eviware.soapui.model.mock.MockResponse;
43 import com.eviware.soapui.model.support.InterfaceListenerAdapter;
44 import com.eviware.soapui.model.support.ModelSupport;
45 import com.eviware.soapui.model.support.ProjectListenerAdapter;
46 import com.eviware.soapui.settings.WsdlSettings;
47 import com.eviware.soapui.support.UISupport;
48 import com.eviware.soapui.support.resolver.ChangeOperationResolver;
49 import com.eviware.soapui.support.resolver.ImportInterfaceResolver;
50 import com.eviware.soapui.support.resolver.RemoveTestStepResolver;
51 import com.eviware.soapui.support.resolver.ResolveContext;
52
53 /***
54 * A WsdlMockOperation in a WsdlMockService
55 *
56 * @author ole.matzura
57 */
58
59 public class WsdlMockOperation extends AbstractWsdlModelItem<MockOperationConfig> implements MockOperation,
60 PropertyChangeListener
61 {
62 @SuppressWarnings("unused")
63 private final static Logger log = Logger.getLogger(WsdlMockOperation.class);
64
65 public final static String DISPATCH_STYLE_PROPERTY = WsdlMockOperation.class.getName() + "@dispatchstyle";
66 public final static String DEFAULT_RESPONSE_PROPERTY = WsdlMockOperation.class.getName() + "@defaultresponse";
67 public final static String DISPATCH_PATH_PROPERTY = WsdlMockOperation.class.getName() + "@dispatchpath";
68 public final static String OPERATION_PROPERTY = WsdlMockOperation.class.getName() + "@operation";
69
70 private WsdlOperation operation;
71 private MockOperationDispatcher dispatcher;
72 private List<WsdlMockResponse> responses = new ArrayList<WsdlMockResponse>();
73 private InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
74 private InternalProjectListener projectListener = new InternalProjectListener();
75 private ImageIcon oneWayIcon;
76 private ImageIcon notificationIcon;
77 private ImageIcon solicitResponseIcon;
78
79 public WsdlMockOperation(WsdlMockService mockService, MockOperationConfig config)
80 {
81 super(config, mockService, "/mockOperation.gif");
82
83 Interface iface = mockService.getProject().getInterfaceByName(config.getInterface());
84 if (iface == null)
85 {
86 SoapUI.log.warn("Missing interface [" + config.getInterface() + "] for MockOperation in project");
87 }
88 else
89 {
90 operation = (WsdlOperation) iface.getOperationByName(config.getOperation());
91 }
92
93 List<MockResponseConfig> responseConfigs = config.getResponseList();
94 for (MockResponseConfig responseConfig : responseConfigs)
95 {
96 WsdlMockResponse wsdlMockResponse = new WsdlMockResponse(this, responseConfig);
97 wsdlMockResponse.addPropertyChangeListener(this);
98 responses.add(wsdlMockResponse);
99 }
100
101 initData(config);
102 }
103
104 private void initData(MockOperationConfig config)
105 {
106 if (!config.isSetName())
107 config.setName(operation == null ? "<missing operation>" : operation.getName());
108
109 if (!config.isSetDefaultResponse() && responses.size() > 0)
110 setDefaultResponse(responses.get(0).getName());
111
112 if (!config.isSetDispatchStyle())
113 config.setDispatchStyle(MockOperationDispatchStyleConfig.SEQUENCE);
114
115 if (!getConfig().isSetDispatchConfig())
116 getConfig().addNewDispatchConfig();
117
118 dispatcher = MockOperationDispatchRegistry.buildDispatcher(config.getDispatchStyle().toString(), this);
119
120 if (operation != null)
121 {
122 operation.getInterface().getProject().addProjectListener(projectListener);
123 operation.getInterface().addInterfaceListener(interfaceListener);
124 operation.getInterface().addPropertyChangeListener(WsdlInterface.NAME_PROPERTY, this);
125 }
126
127 oneWayIcon = UISupport.createImageIcon("/onewaymockoperation.gif");
128 notificationIcon = UISupport.createImageIcon("/mocknotificationoperation.gif");
129 solicitResponseIcon = UISupport.createImageIcon("/mocksolicitresponseoperation.gif");
130 }
131
132 public WsdlMockOperation(WsdlMockService mockService, MockOperationConfig config, WsdlOperation operation)
133 {
134 super(config, mockService, "/mockOperation.gif");
135 this.operation = operation;
136
137 config.setInterface(operation.getInterface().getName());
138 config.setOperation(operation.getName());
139
140 initData(config);
141 interfaceListener = new InternalInterfaceListener();
142 }
143
144 @Override
145 public ImageIcon getIcon()
146 {
147 if (operation != null)
148 {
149 if (isOneWay())
150 {
151 return oneWayIcon;
152 }
153 else if (isNotification())
154 {
155 return notificationIcon;
156 }
157 else if (isSolicitResponse())
158 {
159 return solicitResponseIcon;
160 }
161 }
162
163 return super.getIcon();
164 }
165
166 public WsdlMockService getMockService()
167 {
168 return (WsdlMockService) getParent();
169 }
170
171 public WsdlMockResponse getMockResponseAt(int index)
172 {
173 return responses.get(index);
174 }
175
176 public WsdlOperation getOperation()
177 {
178 return operation;
179 }
180
181 public WsdlMockResponse getMockResponseByName(String name)
182 {
183 return (WsdlMockResponse) getWsdlModelItemByName(responses, name);
184 }
185
186 public int getMockResponseCount()
187 {
188 return responses.size();
189 }
190
191 public WsdlMockResponse addNewMockResponse(MockResponseConfig responseConfig)
192 {
193 WsdlMockResponse mockResponse = new WsdlMockResponse(this, responseConfig);
194
195 responses.add(mockResponse);
196 if (responses.size() == 1)
197 setDefaultResponse(mockResponse.getName());
198
199
200 WsdlUtils.setDefaultWsaAction(mockResponse.getWsaConfig(), true);
201
202 (getMockService()).fireMockResponseAdded(mockResponse);
203 notifyPropertyChanged("mockResponses", null, mockResponse);
204
205 return mockResponse;
206 }
207
208 public WsdlMockResponse addNewMockResponse(String name, boolean createResponse)
209 {
210 MockResponseConfig responseConfig = getConfig().addNewResponse();
211 responseConfig.setName(name);
212 responseConfig.addNewResponseContent();
213
214 if (createResponse && getOperation() != null && getOperation().isBidirectional())
215 {
216 boolean createOptional = SoapUI.getSettings().getBoolean(
217 WsdlSettings.XML_GENERATION_ALWAYS_INCLUDE_OPTIONAL_ELEMENTS);
218 CompressedStringSupport.setString(responseConfig.getResponseContent(), getOperation().createResponse(
219 createOptional));
220 }
221
222 return addNewMockResponse(responseConfig);
223 }
224
225 public void removeMockResponse(WsdlMockResponse mockResponse)
226 {
227 int ix = responses.indexOf(mockResponse);
228 responses.remove(ix);
229 mockResponse.removePropertyChangeListener(this);
230
231 try
232 {
233 (getMockService()).fireMockResponseRemoved(mockResponse);
234 }
235 finally
236 {
237 mockResponse.release();
238 getConfig().removeResponse(ix);
239 }
240 }
241
242 public WsdlMockResult dispatchRequest(WsdlMockRequest request) throws DispatchException
243 {
244 try
245 {
246 request.setOperation(getOperation());
247 WsdlMockResult result = new WsdlMockResult(request);
248
249 if (getMockResponseCount() == 0)
250 throw new DispatchException("Missing MockResponse(s) in MockOperation [" + getName() + "]");
251
252 result.setMockOperation(this);
253 WsdlMockResponse response = dispatcher.selectMockResponse(request, result);
254 if (response == null)
255 {
256 response = getMockResponseByName(getDefaultResponse());
257 }
258
259 if (response == null)
260 {
261 throw new DispatchException("Failed to find MockResponse");
262 }
263
264 result.setMockResponse(response);
265 response.execute(request, result);
266
267 return result;
268 }
269 catch (Throwable e)
270 {
271 if (e instanceof DispatchException)
272 throw (DispatchException) e;
273 else
274 throw new DispatchException(e);
275 }
276 }
277
278 @Override
279 public void release()
280 {
281 super.release();
282
283 if (dispatcher != null)
284 dispatcher.release();
285
286 for (WsdlMockResponse response : responses)
287 {
288 response.removePropertyChangeListener(this);
289 response.release();
290 }
291
292 if (operation != null)
293 {
294 operation.getInterface().getProject().removeProjectListener(projectListener);
295 operation.getInterface().removeInterfaceListener(interfaceListener);
296 operation.getInterface().removePropertyChangeListener(WsdlInterface.NAME_PROPERTY, this);
297 }
298 }
299
300 public String getDispatchStyle()
301 {
302 return String.valueOf(getConfig().isSetDispatchStyle() ? getConfig().getDispatchStyle()
303 : MockOperationDispatchStyleConfig.SEQUENCE);
304 }
305
306 public MockOperationDispatcher setDispatchStyle(String dispatchStyle)
307 {
308 String old = getDispatchStyle();
309 if (dispatcher != null && dispatchStyle.equals(old))
310 return dispatcher;
311
312 getConfig().setDispatchStyle(MockOperationDispatchStyleConfig.Enum.forString(dispatchStyle));
313
314 if (dispatcher != null)
315 {
316 dispatcher.release();
317 }
318
319 if (!getConfig().isSetDispatchConfig())
320 getConfig().addNewDispatchConfig();
321
322 dispatcher = MockOperationDispatchRegistry.buildDispatcher(dispatchStyle, this);
323
324 notifyPropertyChanged(DISPATCH_STYLE_PROPERTY, old, dispatchStyle);
325
326 return dispatcher;
327 }
328
329 public String getDispatchPath()
330 {
331 return getConfig().getDispatchPath();
332 }
333
334 public void setDispatchPath(String dispatchPath)
335 {
336 String old = getDispatchPath();
337 getConfig().setDispatchPath(dispatchPath);
338 notifyPropertyChanged(DISPATCH_PATH_PROPERTY, old, dispatchPath);
339 }
340
341 public String getWsdlOperationName()
342 {
343 return operation == null ? null : operation.getName();
344 }
345
346 public String getDefaultResponse()
347 {
348 return getConfig().getDefaultResponse();
349 }
350
351 public void setDefaultResponse(String defaultResponse)
352 {
353 String old = getDefaultResponse();
354 getConfig().setDefaultResponse(defaultResponse);
355 notifyPropertyChanged(DEFAULT_RESPONSE_PROPERTY, old, defaultResponse);
356 }
357
358 public List<MockResponse> getMockResponses()
359 {
360 return new ArrayList<MockResponse>(responses);
361 }
362
363 public void propertyChange(PropertyChangeEvent arg0)
364 {
365 if (arg0.getPropertyName().equals(WsdlMockResponse.NAME_PROPERTY))
366 {
367 if (arg0.getOldValue().equals(getDefaultResponse()))
368 setDefaultResponse(arg0.getNewValue().toString());
369 }
370 else if (arg0.getPropertyName().equals(WsdlInterface.NAME_PROPERTY))
371 {
372 getConfig().setInterface(arg0.getNewValue().toString());
373 }
374 }
375
376 public WsdlMockResult getLastMockResult()
377 {
378 WsdlMockResult result = null;
379
380 for (WsdlMockResponse response : responses)
381 {
382 WsdlMockResult mockResult = response.getMockResult();
383 if (mockResult != null)
384 {
385 if (result == null || result.getTimestamp() > mockResult.getTimestamp())
386 result = mockResult;
387 }
388 }
389
390 return result;
391 }
392
393 public void setOperation(WsdlOperation operation)
394 {
395 WsdlOperation oldOperation = getOperation();
396
397 if (operation == null)
398 {
399 getConfig().unsetInterface();
400 getConfig().unsetOperation();
401 }
402 else
403 {
404 getConfig().setInterface(operation.getInterface().getName());
405 getConfig().setOperation(operation.getName());
406 }
407
408 this.operation = operation;
409
410 notifyPropertyChanged(OPERATION_PROPERTY, oldOperation, operation);
411 }
412
413 public MockOperationDispatcher getMockOperationDispatcher()
414 {
415 return dispatcher;
416 }
417
418 private class InternalInterfaceListener extends InterfaceListenerAdapter
419 {
420 @Override
421 public void operationUpdated(Operation operation)
422 {
423 if (operation == WsdlMockOperation.this.operation)
424 getConfig().setOperation(operation.getName());
425 }
426
427 @Override
428 public void operationRemoved(Operation operation)
429 {
430 if (operation == WsdlMockOperation.this.operation)
431 getMockService().removeMockOperation(WsdlMockOperation.this);
432 }
433 }
434
435 private class InternalProjectListener extends ProjectListenerAdapter
436 {
437 @Override
438 public void interfaceRemoved(Interface iface)
439 {
440 if (operation.getInterface() == iface)
441 getMockService().removeMockOperation(WsdlMockOperation.this);
442 }
443
444 @Override
445 public void interfaceUpdated(Interface iface)
446 {
447 if (operation.getInterface() == iface)
448 getConfig().setInterface(iface.getName());
449 }
450 }
451
452 public boolean isOneWay()
453 {
454 return operation == null ? false : operation.isOneWay();
455 }
456
457 public boolean isNotification()
458 {
459 return operation == null ? false : operation.isNotification();
460 }
461
462 public boolean isSolicitResponse()
463 {
464 return operation == null ? false : operation.isSolicitResponse();
465 }
466
467 public boolean isUnidirectional()
468 {
469 return operation == null ? false : operation.isUnidirectional();
470 }
471
472 public boolean isBidirectional()
473 {
474 return !isUnidirectional();
475 }
476
477 public List<? extends ModelItem> getChildren()
478 {
479 return responses;
480 }
481
482 public void exportMockOperation(File file)
483 {
484 try
485 {
486 this.getConfig().newCursor().save(file);
487 }
488 catch (IOException e)
489 {
490 e.printStackTrace();
491 }
492 }
493
494 }