View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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.panels.mockoperation;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.Dimension;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.ItemEvent;
20  import java.awt.event.ItemListener;
21  import java.beans.PropertyChangeEvent;
22  import java.beans.PropertyChangeListener;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import javax.swing.AbstractAction;
27  import javax.swing.AbstractListModel;
28  import javax.swing.Action;
29  import javax.swing.BorderFactory;
30  import javax.swing.JComboBox;
31  import javax.swing.JComponent;
32  import javax.swing.JLabel;
33  import javax.swing.JList;
34  import javax.swing.JPanel;
35  import javax.swing.JScrollPane;
36  import javax.swing.ListCellRenderer;
37  import javax.swing.ListModel;
38  
39  import org.apache.xmlbeans.XmlObject;
40  
41  import com.eviware.soapui.SoapUI;
42  import com.eviware.soapui.config.DispatchStyleConfig;
43  import com.eviware.soapui.config.DispatchStyleConfig.Enum;
44  import com.eviware.soapui.impl.wsdl.WsdlInterface;
45  import com.eviware.soapui.impl.wsdl.WsdlOperation;
46  import com.eviware.soapui.impl.wsdl.actions.mockoperation.NewMockResponseAction;
47  import com.eviware.soapui.impl.wsdl.actions.mockoperation.OpenRequestForMockOperationAction;
48  import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
49  import com.eviware.soapui.impl.wsdl.mock.WsdlMockOperation;
50  import com.eviware.soapui.impl.wsdl.mock.WsdlMockRequest;
51  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResponse;
52  import com.eviware.soapui.impl.wsdl.mock.WsdlMockResult;
53  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditor;
54  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.GroovyEditorModel;
55  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
56  import com.eviware.soapui.model.ModelItem;
57  import com.eviware.soapui.model.iface.Interface;
58  import com.eviware.soapui.model.iface.Operation;
59  import com.eviware.soapui.model.mock.MockOperation;
60  import com.eviware.soapui.model.mock.MockResponse;
61  import com.eviware.soapui.model.mock.MockServiceListener;
62  import com.eviware.soapui.model.settings.Settings;
63  import com.eviware.soapui.model.support.InterfaceListenerAdapter;
64  import com.eviware.soapui.model.support.ProjectListenerAdapter;
65  import com.eviware.soapui.model.util.ModelItemNames;
66  import com.eviware.soapui.support.UISupport;
67  import com.eviware.soapui.support.action.swing.ActionList;
68  import com.eviware.soapui.support.action.swing.ActionSupport;
69  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
70  import com.eviware.soapui.support.components.JComponentInspector;
71  import com.eviware.soapui.support.components.JInspectorPanel;
72  import com.eviware.soapui.support.components.JXToolBar;
73  import com.eviware.soapui.support.swing.ExtendedComboBoxModel;
74  import com.eviware.soapui.support.swing.ModelItemListMouseListener;
75  import com.eviware.soapui.support.types.StringList;
76  import com.eviware.soapui.support.xml.XmlUtils;
77  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
78  import com.jgoodies.forms.builder.ButtonBarBuilder;
79  
80  /***
81   * DesktopPanel for WsdlGroovyTestSteps
82   * 
83   * @author Ole.Matzura
84   */
85  
86  public class WsdlMockOperationDesktopPanel extends ModelItemDesktopPanel<WsdlMockOperation>
87  {
88  	private JList responseList;
89  	private JComboBox interfaceCombo;
90  	private JComboBox operationCombo;
91  	private JComboBox dispatchCombo;
92  	private JPanel dispatchPanel;
93  	private InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
94  	private InternalProjectListener projectListener = new InternalProjectListener();
95  	private WsdlInterface currentInterface;
96  	private JPanel groovyEditorPanel;
97  	private JPanel xpathEditorPanel;
98  	private JComboBox defaultResponseCombo;
99  	private ResponseListModel responseListModel;
100 	private GroovyEditor xpathEditor;
101 	private GroovyEditor groovyEditor;
102 	private JComponentInspector dispatchInspector;
103 
104 	public WsdlMockOperationDesktopPanel(WsdlMockOperation mockOperation)
105 	{
106 		super( mockOperation );
107 		
108 		buildUI();
109 		setPreferredSize( new Dimension( 600, 440 ));
110 		
111 		mockOperation.getMockService().getProject().addProjectListener( projectListener );
112 		
113 		WsdlOperation operation = getModelItem().getOperation();
114 		if( operation != null )
115 		{
116 			currentInterface = operation.getInterface();
117 			currentInterface.addInterfaceListener( interfaceListener );
118 		}
119 	}
120 
121 	private void buildUI()
122 	{
123 		add( buildToolbar(), BorderLayout.NORTH );
124 		
125       JInspectorPanel inspectorPanel = new JInspectorPanel( buildResponseList() );
126       inspectorPanel.setDefaultDividerLocation( 0.5F );
127       dispatchInspector = new JComponentInspector( 
128 				      			buildDispatchEditor(), "Dispatch (" + getModelItem().getDispatchStyle().toString() + ")", 
129 				      			"Configures current dispatch style", true );
130 		inspectorPanel.addInspector( dispatchInspector);
131       inspectorPanel.activate( dispatchInspector );
132 		
133       add( inspectorPanel, BorderLayout.CENTER );
134 	}
135 
136 	private JComponent buildResponseList()
137 	{
138 		responseListModel = new ResponseListModel();
139 		responseList = new JList( responseListModel );
140 		responseList.addMouseListener( new ModelItemListMouseListener() {
141 
142 			@Override
143 			protected ActionList getActionsForRow( JList list, int row )
144 			{
145 				ActionList actions = super.getActionsForRow( list, row );
146 				
147 				actions.insertAction( SwingActionDelegate.createDelegate( NewMockResponseAction.SOAPUI_ACTION_ID, getModelItem(), null, 
148 							"/addToMockService.gif"	), 0 );
149 				
150 				actions.insertAction( SwingActionDelegate.createDelegate( OpenRequestForMockOperationAction.SOAPUI_ACTION_ID, getModelItem(), null, 
151 							"/open_request.gif"), 1 );
152 				
153 				if( actions.getActionCount() > 2 )
154 					actions.insertAction( ActionSupport.SEPARATOR_ACTION, 2 );
155 				
156 				return actions;
157 			}
158 		} );
159 		responseList.setCellRenderer( new ResponseListCellRenderer() );
160 		
161 		JScrollPane scrollPane = new JScrollPane( responseList );
162 		UISupport.addTitledBorder( scrollPane, "MockResponses" );
163 		return scrollPane;
164 	}
165 
166 	private JComponent buildDispatchEditor()
167 	{
168 		buildGroovyEditor();
169 		buildXPathEditor();
170 		
171 		dispatchPanel = new JPanel( new BorderLayout() );
172 		dispatchPanel.setOpaque( true );
173 		ButtonBarBuilder builder = new ButtonBarBuilder();
174 		builder.addFixed( new JLabel( "Dispatch: ") );
175 		builder.addRelatedGap();
176 		dispatchCombo = new JComboBox( new Object[] { "Sequence", "Random", "XPath", "Script"} );
177 		
178 		dispatchCombo.addItemListener( new ItemListener() {
179 
180 			public void itemStateChanged( ItemEvent e )
181 			{
182 				if( dispatchPanel.getComponentCount() > 1 )
183 					dispatchPanel.remove( 1 );
184 				
185 				String item = ( String ) dispatchCombo.getSelectedItem();
186 				if( item.equalsIgnoreCase( "Script" ))
187 				{
188 					getModelItem().setDispatchStyle( DispatchStyleConfig.SCRIPT );
189 					dispatchPanel.add( groovyEditorPanel );
190 					groovyEditor.getEditArea().setText( getModelItem().getDispatchPath() );
191 					defaultResponseCombo.setEnabled( true );
192 				}
193 				else if( item.equalsIgnoreCase( "XPath" ))
194 				{
195 					getModelItem().setDispatchStyle( DispatchStyleConfig.XPATH );
196 					dispatchPanel.add( xpathEditorPanel );
197 					xpathEditor.getEditArea().setText( getModelItem().getDispatchPath() );
198 					defaultResponseCombo.setEnabled( true );
199 				}
200 				else if( item.equalsIgnoreCase( "Sequence" ))
201 				{
202 					getModelItem().setDispatchStyle( DispatchStyleConfig.SEQUENCE );
203 					defaultResponseCombo.setEnabled( false );
204 				}
205 				else if( item.equalsIgnoreCase( "Random" ))
206 				{
207 					getModelItem().setDispatchStyle( DispatchStyleConfig.RANDOM );
208 					defaultResponseCombo.setEnabled( false );
209 				}
210 				
211 				dispatchPanel.revalidate();
212 				dispatchPanel.repaint();
213 				
214 				Enum dispatchStyle = getModelItem().getDispatchStyle();
215 				if( dispatchInspector != null && dispatchStyle != null )
216 					dispatchInspector.setTitle( "Dispatch (" + dispatchStyle + ")" );
217 			}} );
218 		
219 		builder.addFixed( dispatchCombo );
220 		
221 		builder.addUnrelatedGap();
222 		builder.addFixed( new JLabel( "Default Response: ") );
223 		builder.addRelatedGap();
224 		
225 		ModelItemNames<MockResponse> names = new ModelItemNames<MockResponse>(getModelItem().getMockResponses());
226 		defaultResponseCombo = new JComboBox( new ExtendedComboBoxModel( names.getNames() ) );
227 		defaultResponseCombo.setPreferredSize( new Dimension( 150, 20 ) );
228 		defaultResponseCombo.addItemListener( new ItemListener() {
229 
230 			public void itemStateChanged( ItemEvent e )
231 			{
232 				Object selectedItem = defaultResponseCombo.getSelectedItem();
233 				getModelItem().setDefaultResponse( ( String ) selectedItem );
234 			}} );
235 		
236 		builder.addFixed( defaultResponseCombo );
237 		builder.setBorder( BorderFactory.createEmptyBorder( 2, 3, 3, 3 ) );
238 		
239 		dispatchPanel.add( builder.getPanel(), BorderLayout.NORTH );
240 		
241 		// init data
242 		defaultResponseCombo.setSelectedItem( getModelItem().getDefaultResponse() );
243 		DispatchStyleConfig.Enum dispatchStyle = getModelItem().getDispatchStyle();
244 		if( dispatchStyle.equals( DispatchStyleConfig.SEQUENCE ))
245 		{
246 			dispatchCombo.setSelectedItem( "Sequence" );
247 			defaultResponseCombo.setEnabled( false );
248 		}
249 		else if( dispatchStyle.equals( DispatchStyleConfig.RANDOM ))
250 		{
251 			dispatchCombo.setSelectedItem( "Random" );
252 			defaultResponseCombo.setEnabled( false );
253 		}
254 		else if( dispatchStyle.equals( DispatchStyleConfig.SCRIPT ))
255 		{
256 			dispatchCombo.setSelectedItem( "Script" );
257 		}
258 		else if( dispatchStyle.equals( DispatchStyleConfig.XPATH ))
259 		{
260 			dispatchCombo.setSelectedItem( "XPath" );
261 		}
262 		
263 		return dispatchPanel;
264 	}
265 
266 	private void buildXPathEditor()
267 	{
268 		xpathEditorPanel = new JPanel( new BorderLayout() );
269 		DispatchXPathGroovyEditorModel editorModel = new DispatchXPathGroovyEditorModel();
270 		xpathEditor = new GroovyEditor( editorModel );
271 		xpathEditorPanel.add( new JScrollPane( xpathEditor), BorderLayout.CENTER );
272 		xpathEditorPanel.add( buildXPathEditorToolbar( editorModel ), BorderLayout.PAGE_START );
273 	}
274 	
275 	public GroovyEditor getXPathEditor()
276 	{
277 		return xpathEditor;
278 	}
279 
280 	protected JXToolBar buildXPathEditorToolbar( DispatchXPathGroovyEditorModel editorModel )
281 	{
282 		JXToolBar toolbar = UISupport.createToolbar();
283 		toolbar.addSpace( 3 );
284 		toolbar.addFixed( UISupport.createToolbarButton( editorModel.getRunAction() ));
285 		toolbar.addGlue();
286 		toolbar.addFixed( createActionButton( new ShowOnlineHelpAction(HelpUrls.MOCKOPERATION_XPATHDISPATCH_HELP_URL), true ) );
287 		return toolbar;
288 	}
289 
290 	private void buildGroovyEditor()
291 	{
292 		groovyEditorPanel = new JPanel( new BorderLayout() );
293 		DispatchScriptGroovyEditorModel editorModel = new DispatchScriptGroovyEditorModel();
294 		groovyEditor = new GroovyEditor( editorModel );
295 		groovyEditorPanel.add( new JScrollPane( groovyEditor ), BorderLayout.CENTER );
296 		groovyEditorPanel.add( buildGroovyEditorToolbar( editorModel ), BorderLayout.PAGE_START );
297 	}
298 
299 	protected JXToolBar buildGroovyEditorToolbar( DispatchScriptGroovyEditorModel editorModel )
300 	{
301 		JXToolBar toolbar = UISupport.createToolbar();
302 		toolbar.addSpace( 3 );
303 		toolbar.addFixed( UISupport.createToolbarButton( editorModel.getRunAction() ));
304 		toolbar.addGlue();
305 		
306 		JLabel label = new JLabel("<html>Script is invoked with <code>log</code>, <code>context</code>, " +
307 				"<code>requestContext</code>, <code>mockRequest</code> and <code>mockOperation</code> variables</html>");
308 		label.setToolTipText( label.getText() );
309 		label.setMaximumSize( label.getPreferredSize() );
310 		
311 		toolbar.add( label);
312 		toolbar.addFixed( createActionButton( new ShowOnlineHelpAction(HelpUrls.MOCKOPERATION_SCRIPTDISPATCH_HELP_URL), true ) );
313 		return toolbar;
314 	}
315 
316 	private Component buildToolbar()
317 	{
318 		JXToolBar toolbar = UISupport.createToolbar();
319 		toolbar.addSpace( 3 );
320 		
321 		toolbar.addFixed( UISupport.createToolbarButton( 
322 					SwingActionDelegate.createDelegate( NewMockResponseAction.SOAPUI_ACTION_ID, getModelItem(), null, 
323 							"/addToMockService.gif"	)));
324 		toolbar.addFixed( UISupport.createToolbarButton(
325 					SwingActionDelegate.createDelegate( OpenRequestForMockOperationAction.SOAPUI_ACTION_ID, getModelItem(), null, 
326 								"/open_request.gif") ));
327 		toolbar.addUnrelatedGap();
328 		
329 		ModelItemNames<Interface> names = new ModelItemNames<Interface>(getModelItem().getMockService().getProject().getInterfaces());
330 		interfaceCombo = new JComboBox( names.getNames() );
331 		interfaceCombo.setSelectedIndex( -1 );
332 		interfaceCombo.addItemListener( new InterfaceComboListener() );
333 		
334 		toolbar.addLabeledFixed( "Interface", interfaceCombo );
335 		toolbar.addUnrelatedGap();
336 		operationCombo = new JComboBox( new ExtendedComboBoxModel() );
337 		operationCombo.setPreferredSize( new Dimension( 150, 20 ) );
338 		operationCombo.addItemListener( new OperationComboListener() );
339 		
340 		toolbar.addLabeledFixed( "Operation", operationCombo );
341 		
342 		WsdlOperation operation = getModelItem().getOperation();
343 		interfaceCombo.setSelectedItem( operation == null ? null : operation.getInterface().getName() );
344 		operationCombo.setSelectedItem( operation == null ? null : operation.getName() );
345 		
346 		toolbar.addGlue();
347 		toolbar.addFixed( createActionButton( new ShowOnlineHelpAction(HelpUrls.MOCKOPERATION_HELP_URL), true ) );
348 			
349 		return toolbar;
350 	}
351 	
352 	public boolean onClose( boolean canCancel )
353 	{
354 		if( currentInterface != null )
355 			currentInterface.removeInterfaceListener( interfaceListener );
356 		
357 		getModelItem().getMockService().getProject().removeProjectListener( projectListener );
358 		responseListModel.release();
359 		
360 		groovyEditor.release();
361 		xpathEditor.release();
362 		
363 		return release();
364 	}
365 	
366 	public boolean dependsOn(ModelItem modelItem)
367 	{
368 		return modelItem == getModelItem() || modelItem == getModelItem().getMockService()
369 				|| modelItem == getModelItem().getMockService().getProject();
370 	}
371 	
372 	private final class OperationComboListener implements ItemListener
373 	{
374 		public void itemStateChanged( ItemEvent e )
375 		{
376 			WsdlInterface iface = getModelItem().getMockService().getProject().getInterfaceByName( interfaceCombo.getSelectedItem().toString() );
377 			WsdlOperation operation = iface.getOperationByName( operationCombo.getSelectedItem().toString() );
378 			getModelItem().setOperation( operation );
379 		}
380 	}
381 
382 	private final class InterfaceComboListener implements ItemListener
383 	{
384 		public void itemStateChanged( ItemEvent e )
385 		{
386 			if( currentInterface != null )
387 			{
388 				currentInterface.removeInterfaceListener( interfaceListener );
389 			}
390 			
391 			Object selectedItem = interfaceCombo.getSelectedItem();
392 			if( selectedItem == null )
393 			{
394 				operationCombo.setModel( new ExtendedComboBoxModel() );
395 				currentInterface = null;
396 			}
397 			else
398 			{
399 				currentInterface = getModelItem().getMockService().getProject().getInterfaceByName( selectedItem.toString() );
400 				ModelItemNames<Operation> names = new ModelItemNames<Operation>( currentInterface.getOperations() );
401 				operationCombo.setModel( new ExtendedComboBoxModel( names.getNames()) );
402 				
403 				currentInterface.addInterfaceListener( interfaceListener );
404 			}
405 		}
406 	}
407 
408 	private final class InternalProjectListener extends ProjectListenerAdapter
409 	{
410 		@Override
411 		public void interfaceAdded( Interface iface )
412 		{
413 			interfaceCombo.addItem( iface.getName() );
414 		}
415 
416 		@Override
417 		public void interfaceRemoved( Interface iface )
418 		{
419 			if( interfaceCombo.getSelectedItem().equals( iface.getName() ))
420 			{
421 				getModelItem().setOperation( null );
422 			}
423 		}
424 	}
425 
426 	private final class InternalInterfaceListener extends InterfaceListenerAdapter
427 	{
428 		@Override
429 		public void operationAdded( Operation operation )
430 		{
431 			operationCombo.addItem( operation.getName() );
432 		}
433 
434 		@Override
435 		public void operationRemoved( Operation operation )
436 		{
437 			Object selectedItem = operationCombo.getSelectedItem();
438 			operationCombo.removeItem( operation.getName() );
439 			
440 			if( selectedItem.equals( operation.getName() ))
441 			{
442 				getModelItem().setOperation( null );
443 				interfaceCombo.setSelectedIndex( -1 );
444 			}
445 		}
446 
447 		@Override
448 		public void operationUpdated( Operation operation )
449 		{
450 			ExtendedComboBoxModel model = ((ExtendedComboBoxModel)operationCombo.getModel());
451 			int ix = model.getIndexOf( operation.getName() );
452 			if( ix != -1 )
453 			{
454 				model.setElementAt( operation.getName(), ix );
455 			}
456 		}
457 	}
458 
459 	public class DispatchScriptGroovyEditorModel implements GroovyEditorModel
460 	{
461 		private RunScriptAction runScriptAction = new RunScriptAction();
462 		
463 		public String[] getKeywords()
464 		{
465 			return new String[] { "mockRequest", "context", "requestContext", "log", "mockOperation" };
466 		}
467 
468 		public Action getRunAction()
469 		{
470 			return runScriptAction;
471 		}
472 
473 		public String getScript()
474 		{
475 			return getModelItem().getDispatchPath();
476 		}
477 
478 		public Settings getSettings()
479 		{
480 			return getModelItem().getSettings();
481 		}
482 
483 		public void setScript( String text )
484 		{
485 			getModelItem().setDispatchPath( text );
486 		}
487 	}
488 	
489 	public class DispatchXPathGroovyEditorModel implements GroovyEditorModel
490 	{
491 		private RunXPathAction runXPathAction = new RunXPathAction();
492 
493 		public String[] getKeywords()
494 		{
495 			return new String[] { "define", "namespace"};
496 		}
497 
498 		public Action getRunAction()
499 		{
500 			return runXPathAction;
501 		}
502 
503 		public String getScript()
504 		{
505 			return getModelItem().getDispatchPath();
506 		}
507 
508 		public Settings getSettings()
509 		{
510 			return getModelItem().getSettings();
511 		}
512 
513 		public void setScript( String text )
514 		{
515 			getModelItem().setDispatchPath( text );
516 		}
517 	}
518 
519 	public class ResponseListModel extends AbstractListModel implements ListModel, MockServiceListener, PropertyChangeListener
520 	{
521 		private List<WsdlMockResponse> responses = new ArrayList<WsdlMockResponse>();
522 		
523 		public ResponseListModel()
524 		{
525 			for( int c = 0; c < getModelItem().getMockResponseCount(); c++ )
526 			{
527 				WsdlMockResponse mockResponse = ( WsdlMockResponse ) getModelItem().getMockResponseAt( c );
528 				mockResponse.addPropertyChangeListener( this );
529 				
530 				responses.add( mockResponse);
531 			}
532 			
533 			getModelItem().getMockService().addMockServiceListener( this );
534 		}
535 		
536 		public Object getElementAt( int arg0 )
537 		{
538 			return responses.get( arg0 );
539 		}
540 
541 		public int getSize()
542 		{
543 			return responses.size();
544 		}
545 
546 		public void mockOperationAdded( MockOperation operation )
547 		{
548 			
549 		}
550 
551 		public void mockOperationRemoved( MockOperation operation )
552 		{
553 			
554 		}
555 
556 		public void mockResponseAdded( MockResponse response )
557 		{
558 			if( response.getMockOperation() != getModelItem() )
559 				return;
560 			
561 			responses.add( ( WsdlMockResponse ) response );
562 			response.addPropertyChangeListener( this );
563 			fireIntervalAdded( this, responses.size()-1, responses.size()-1 );
564 			
565 			defaultResponseCombo.addItem( response.getName() );
566 		}
567 
568 		public void mockResponseRemoved( MockResponse response )
569 		{
570 			if( response.getMockOperation() != getModelItem() )
571 				return;
572 			
573 			int ix = responses.indexOf( response );
574 			responses.remove( ix );
575 			response.removePropertyChangeListener( this );
576 			fireIntervalRemoved( this, ix, ix );
577 			
578 			defaultResponseCombo.removeItem( response.getName() );
579 		}
580 
581 		public void propertyChange( PropertyChangeEvent arg0 )
582 		{
583 			if( arg0.getPropertyName().equals( WsdlMockOperation.NAME_PROPERTY ))
584 			{
585 				int ix = responses.indexOf( arg0.getSource() );
586 				fireContentsChanged( this, ix, ix );
587 				
588 				ExtendedComboBoxModel model = ( ExtendedComboBoxModel ) defaultResponseCombo.getModel();
589 				model.setElementAt( arg0.getNewValue(), ix );
590 				
591 				if( model.getSelectedItem().equals( arg0.getOldValue()  ))
592 						model.setSelectedItem( arg0.getNewValue() );
593 			}
594 		}
595 		
596 		public void release()
597 		{
598 			for( WsdlMockResponse operation : responses )
599 			{
600 				operation.removePropertyChangeListener( this );
601 			}
602 			
603 			getModelItem().getMockService().removeMockServiceListener( this );
604 		}
605 	}
606 	
607 	private final static class ResponseListCellRenderer extends JLabel implements ListCellRenderer
608 	{
609 		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
610 				boolean cellHasFocus)
611 		{
612 			MockResponse testStep = (MockResponse) value;
613 			setText(testStep.getName());
614 			setIcon(testStep.getIcon());
615 
616 			if (isSelected)
617 			{
618 				setBackground(list.getSelectionBackground());
619 				setForeground(list.getSelectionForeground());
620 			}
621 			else
622 			{
623 				setBackground(list.getBackground());
624 				setForeground(list.getForeground());
625 			}
626 
627 			setEnabled(list.isEnabled());
628 			setFont(list.getFont());
629 			setOpaque(true);
630 			setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
631 
632 			return this;
633 		}
634 	}
635 	
636 	private class RunScriptAction extends AbstractAction
637 	{
638 		public RunScriptAction()
639 		{
640 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_groovy_script.gif" ));
641 			putValue( Action.SHORT_DESCRIPTION, "Runs this script using a mockRequest and context" );
642 		}
643 		
644 		public void actionPerformed( ActionEvent e )
645 		{
646 			WsdlMockResult lastMockResult = getModelItem().getLastMockResult();
647 			WsdlMockRequest mockRequest = lastMockResult == null ? null : lastMockResult.getMockRequest();
648 
649 			try
650 			{
651 				Object retVal = getModelItem().evaluateDispatchScript( mockRequest );
652 				UISupport.showInfoMessage( "Script returned [" + retVal + "]" );
653 			}
654 			catch( Exception e1 )
655 			{
656 				UISupport.showErrorMessage( e1 );
657 			}
658 		}}
659 	
660 	private class RunXPathAction extends AbstractAction
661 	{
662 		public RunXPathAction()
663 		{
664 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_groovy_script.gif" ));
665 			putValue( Action.SHORT_DESCRIPTION, "Evaluates this xpath expression against the latest request" );
666 		}
667 		
668 		public void actionPerformed( ActionEvent e )
669 		{
670 			WsdlMockResult lastMockResult = getModelItem().getLastMockResult();
671 			if( lastMockResult == null )
672 			{
673 				UISupport.showErrorMessage( "Missing last request to select from" );
674 				return;
675 			}
676 			
677 			try
678 			{
679 				XmlObject[] retVal = getModelItem().evaluateDispatchXPath( lastMockResult.getMockRequest() );
680 				StringList list = new StringList();
681 				for( XmlObject xmlObject : retVal )
682 				{
683 					list.add( XmlUtils.getNodeValue( xmlObject.getDomNode() ) );
684 				}
685 				
686 				UISupport.showInfoMessage( "XPath returned " + list.toString() );
687 			}
688 			catch( Exception e1 )
689 			{
690 				SoapUI.logError( e1 );
691 			}
692 		}}
693 }