View Javadoc

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