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