View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
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 		// add ws-a action
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 }