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.panels.testcase;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.Dimension;
18  import java.awt.dnd.DnDConstants;
19  import java.awt.dnd.DragSource;
20  import java.awt.event.ActionEvent;
21  import java.text.SimpleDateFormat;
22  import java.util.Date;
23  
24  import javax.swing.AbstractAction;
25  import javax.swing.Action;
26  import javax.swing.BorderFactory;
27  import javax.swing.Box;
28  import javax.swing.JButton;
29  import javax.swing.JComponent;
30  import javax.swing.JList;
31  import javax.swing.JPanel;
32  import javax.swing.JProgressBar;
33  import javax.swing.JScrollPane;
34  import javax.swing.JTabbedPane;
35  import javax.swing.JTextArea;
36  import javax.swing.JToggleButton;
37  import javax.swing.JToolBar;
38  import javax.swing.ListModel;
39  import javax.swing.SwingConstants;
40  import javax.swing.SwingUtilities;
41  import javax.swing.text.Document;
42  
43  import com.eviware.soapui.SoapUI;
44  import com.eviware.soapui.config.TestStepConfig;
45  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
46  import com.eviware.soapui.impl.wsdl.actions.testcase.AddNewLoadTestAction;
47  import com.eviware.soapui.impl.wsdl.actions.testcase.TestCaseOptionsAction;
48  import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunContext;
49  import com.eviware.soapui.impl.wsdl.panels.support.MockTestRunner;
50  import com.eviware.soapui.impl.wsdl.panels.support.ProgressBarTestCaseAdapter;
51  import com.eviware.soapui.impl.wsdl.panels.testcase.actions.SetCredentialsAction;
52  import com.eviware.soapui.impl.wsdl.panels.testcase.actions.SetEndpointAction;
53  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
54  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.PropertyHolderTable;
55  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
56  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
57  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner;
58  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
59  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepFactory;
60  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepRegistry;
61  import com.eviware.soapui.model.ModelItem;
62  import com.eviware.soapui.model.support.TestRunListenerAdapter;
63  import com.eviware.soapui.model.testsuite.LoadTestRunner;
64  import com.eviware.soapui.model.testsuite.TestCaseRunContext;
65  import com.eviware.soapui.model.testsuite.TestCaseRunner;
66  import com.eviware.soapui.model.testsuite.TestStep;
67  import com.eviware.soapui.model.testsuite.TestStepResult;
68  import com.eviware.soapui.monitor.support.TestMonitorListenerAdapter;
69  import com.eviware.soapui.settings.UISettings;
70  import com.eviware.soapui.support.DocumentListenerAdapter;
71  import com.eviware.soapui.support.StringUtils;
72  import com.eviware.soapui.support.UISupport;
73  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
74  import com.eviware.soapui.support.components.GroovyEditorComponent;
75  import com.eviware.soapui.support.components.GroovyEditorInspector;
76  import com.eviware.soapui.support.components.JComponentInspector;
77  import com.eviware.soapui.support.components.JFocusableComponentInspector;
78  import com.eviware.soapui.support.components.JInspectorPanel;
79  import com.eviware.soapui.support.components.JInspectorPanelFactory;
80  import com.eviware.soapui.support.components.JUndoableTextArea;
81  import com.eviware.soapui.support.components.JXToolBar;
82  import com.eviware.soapui.support.dnd.DropType;
83  import com.eviware.soapui.support.dnd.JListDragAndDropable;
84  import com.eviware.soapui.support.dnd.SoapUIDragAndDropHandler;
85  import com.eviware.soapui.support.swing.ComponentBag;
86  import com.eviware.soapui.support.types.StringToObjectMap;
87  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
88  
89  /***
90   * WsdlTestCase desktop panel
91   * 
92   * @author Ole.Matzura
93   */
94  
95  public class WsdlTestCaseDesktopPanel extends ModelItemDesktopPanel<WsdlTestCase>
96  {
97  	private JProgressBar progressBar;
98  	private JTestStepList testStepList;
99  	private InternalTestRunListener testRunListener = new InternalTestRunListener();
100 	private JButton runButton;
101 	private JButton cancelButton;
102 	private TestCaseRunner runner;
103 	private JButton setEndpointButton;
104 	private JButton setCredentialsButton;
105 	private JButton optionsButton;
106 	private ComponentBag stateDependantComponents = new ComponentBag();
107 	private JTestCaseTestRunLog testCaseLog;
108 	private JToggleButton loopButton;
109 	private ProgressBarTestCaseAdapter progressBarAdapter;
110 	private InternalTestMonitorListener testMonitorListener;
111 	public boolean canceled;
112 	private JTextArea descriptionArea;
113 	private PropertyHolderTable propertiesTable;
114 	private GroovyEditorComponent tearDownGroovyEditor;
115 	private GroovyEditorComponent setupGroovyEditor;
116 	private JInspectorPanel testStepListInspectorPanel;
117 	private JButton createLoadTestButton;
118 	private JInspectorPanel inspectorPanel;
119 
120 	public WsdlTestCaseDesktopPanel( WsdlTestCase testCase )
121 	{
122 		super( testCase );
123 
124 		buildUI();
125 
126 		setPreferredSize( new Dimension( 400, 550 ) );
127 		setRunningState();
128 
129 		testCase.addTestRunListener( testRunListener );
130 		progressBarAdapter = new ProgressBarTestCaseAdapter( progressBar, testCase );
131 		testMonitorListener = new InternalTestMonitorListener();
132 
133 		SoapUI.getTestMonitor().addTestMonitorListener( testMonitorListener );
134 
135 		DragSource dragSource = DragSource.getDefaultDragSource();
136 		SoapUIDragAndDropHandler dragAndDropHandler = new SoapUIDragAndDropHandler( new ModelItemListDragAndDropable(
137 				getTestStepList().getTestStepList(), testCase ), DropType.BEFORE_AND_AFTER );
138 
139 		dragSource.createDefaultDragGestureRecognizer( getTestStepList().getTestStepList(),
140 				DnDConstants.ACTION_COPY_OR_MOVE, dragAndDropHandler );
141 	}
142 
143 	/***
144 	 * There are three states: - enabled, no testcases or testschedules running -
145 	 * enabled, standalone testcase running - disabled, testschedule is running
146 	 */
147 
148 	private void setRunningState()
149 	{
150 		stateDependantComponents.setEnabled( !SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) );
151 	}
152 
153 	private void buildUI()
154 	{
155 		JPanel panel = new JPanel( new BorderLayout() );
156 
157 		panel.add( buildToolbar(), BorderLayout.PAGE_START );
158 		panel.add( buildRunnerBar(), BorderLayout.CENTER );
159 
160 		add( panel, BorderLayout.NORTH );
161 
162 		inspectorPanel = JInspectorPanelFactory.build( buildContent() );
163 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildTestLog(), "TestCase Log",
164 				"TestCase Execution Log", true ) );
165 		inspectorPanel.setDefaultDividerLocation( 0.7F );
166 		inspectorPanel.setCurrentInspector( "TestCase Log" );
167 
168 		if( StringUtils.hasContent( getModelItem().getDescription() )
169 				&& getModelItem().getSettings().getBoolean( UISettings.SHOW_DESCRIPTIONS ) )
170 		{
171 			testStepListInspectorPanel.setCurrentInspector( "Description" );
172 		}
173 
174 		add( inspectorPanel.getComponent(), BorderLayout.CENTER );
175 	}
176 
177 	protected JTestStepList getTestStepList()
178 	{
179 		return testStepList;
180 	}
181 
182 	private JComponent buildTestLog()
183 	{
184 		testCaseLog = new JTestCaseTestRunLog( getModelItem() );
185 		stateDependantComponents.add( testCaseLog );
186 		return testCaseLog;
187 	}
188 
189 	private JComponent buildContent()
190 	{
191 		JTabbedPane tabs = new JTabbedPane( JTabbedPane.TOP );
192 		testStepListInspectorPanel = JInspectorPanelFactory.build( buildTestStepList(), SwingConstants.BOTTOM );
193 
194 		tabs.addTab( "TestSteps", testStepListInspectorPanel.getComponent() );
195 
196 		addTabs( tabs, testStepListInspectorPanel );
197 		tabs.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
198 
199 		return UISupport.createTabPanel( tabs, true );
200 	}
201 
202 	protected JComponent buildTestStepList()
203 	{
204 		JPanel p = new JPanel( new BorderLayout() );
205 		JXToolBar toolbar = UISupport.createToolbar();
206 
207 		WsdlTestStepFactory[] factories = WsdlTestStepRegistry.getInstance().getFactories();
208 		for( WsdlTestStepFactory factory : factories )
209 		{
210 			toolbar.addFixed( UISupport.createToolbarButton( new AddWsdlTestStepAction( factory ) ) );
211 		}
212 
213 		p.add( toolbar, BorderLayout.NORTH );
214 		testStepList = new JTestStepList( getModelItem() );
215 		stateDependantComponents.add( testStepList );
216 
217 		p.add( new JScrollPane( testStepList ), BorderLayout.CENTER );
218 
219 		return p;
220 	}
221 
222 	protected void addTabs( JTabbedPane tabs, JInspectorPanel inspectorPanel )
223 	{
224 		inspectorPanel.addInspector( new JFocusableComponentInspector<JPanel>( buildDescriptionPanel(), descriptionArea,
225 				"Description", "TestCase Description", true ) );
226 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildPropertiesPanel(), "Properties",
227 				"TestCase level properties", true ) );
228 		inspectorPanel.addInspector( new GroovyEditorInspector( buildSetupScriptPanel(), "Setup Script",
229 				"Script to run before tunning a TestCase" ) );
230 		inspectorPanel.addInspector( new GroovyEditorInspector( buildTearDownScriptPanel(), "TearDown Script",
231 				"Script to run after a TestCase Run" ) );
232 	}
233 
234 	protected GroovyEditorComponent buildTearDownScriptPanel()
235 	{
236 		tearDownGroovyEditor = new GroovyEditorComponent( new TearDownScriptGroovyEditorModel(), null );
237 		return tearDownGroovyEditor;
238 	}
239 
240 	protected GroovyEditorComponent buildSetupScriptPanel()
241 	{
242 		setupGroovyEditor = new GroovyEditorComponent( new SetupScriptGroovyEditorModel(), null );
243 		return setupGroovyEditor;
244 	}
245 
246 	protected JComponent buildPropertiesPanel()
247 	{
248 		JPanel panel = new JPanel( new BorderLayout() );
249 		propertiesTable = buildPropertiesTable();
250 		panel.add( new JScrollPane( propertiesTable ), BorderLayout.CENTER );
251 		return panel;
252 	}
253 
254 	protected PropertyHolderTable buildPropertiesTable()
255 	{
256 		return new PropertyHolderTable( getModelItem() );
257 	}
258 
259 	private JPanel buildDescriptionPanel()
260 	{
261 		JPanel panel = new JPanel( new BorderLayout() );
262 		descriptionArea = new JUndoableTextArea( getModelItem().getDescription() );
263 		descriptionArea.getDocument().addDocumentListener( new DocumentListenerAdapter()
264 		{
265 			public void update( Document document )
266 			{
267 				getModelItem().setDescription( descriptionArea.getText() );
268 			}
269 		} );
270 
271 		panel.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
272 		panel.add( new JScrollPane( descriptionArea ), BorderLayout.CENTER );
273 		UISupport.addTitledBorder( panel, "TestCase Description" );
274 
275 		return panel;
276 	}
277 
278 	private Component buildToolbar()
279 	{
280 		JToolBar toolbar = UISupport.createToolbar();
281 
282 		runButton = UISupport.createToolbarButton( new RunTestCaseAction() );
283 		optionsButton = UISupport.createToolbarButton( SwingActionDelegate.createDelegate(
284 				TestCaseOptionsAction.SOAPUI_ACTION_ID, getModelItem(), null, "/options.gif" ) );
285 		optionsButton.setText( null );
286 		cancelButton = UISupport.createToolbarButton( new CancelRunTestCaseAction(), false );
287 
288 		loopButton = new JToggleButton( UISupport.createImageIcon( "/loop.gif" ) );
289 		loopButton.setPreferredSize( UISupport.getPreferredButtonSize() );
290 		loopButton.setToolTipText( "Loop TestCase continuously" );
291 
292 		setCredentialsButton = UISupport.createToolbarButton( new SetCredentialsAction( getModelItem() ) );
293 		setEndpointButton = UISupport.createToolbarButton( new SetEndpointAction( getModelItem() ) );
294 
295 		stateDependantComponents.add( runButton );
296 		stateDependantComponents.add( optionsButton );
297 		stateDependantComponents.add( cancelButton );
298 		stateDependantComponents.add( setCredentialsButton );
299 		stateDependantComponents.add( setEndpointButton );
300 
301 		createLoadTestButton = UISupport.createToolbarButton( SwingActionDelegate.createDelegate(
302 				AddNewLoadTestAction.SOAPUI_ACTION_ID, getModelItem(), null, "/loadTest.gif" ) );
303 
304 		addToolbarActions( toolbar );
305 
306 		toolbar.add( Box.createHorizontalGlue() );
307 		toolbar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.TESTCASEEDITOR_HELP_URL ) ) );
308 
309 		return toolbar;
310 	}
311 
312 	protected void addToolbarActions( JToolBar toolbar )
313 	{
314 		toolbar.add( runButton );
315 		toolbar.add( cancelButton );
316 		toolbar.add( loopButton );
317 		toolbar.addSeparator();
318 		toolbar.add( setCredentialsButton );
319 		toolbar.add( setEndpointButton );
320 		toolbar.addSeparator();
321 		toolbar.add( createLoadTestButton );
322 		toolbar.addSeparator();
323 		toolbar.add( optionsButton );
324 	}
325 
326 	private Component buildRunnerBar()
327 	{
328 		progressBar = new JProgressBar( 0, getModelItem().getTestStepCount() );
329 		return UISupport.createProgressBarPanel( progressBar, 10, false );
330 	}
331 
332 	private final class InternalTestMonitorListener extends TestMonitorListenerAdapter
333 	{
334 		public void loadTestStarted( LoadTestRunner runner )
335 		{
336 			setRunningState();
337 		}
338 
339 		public void loadTestFinished( LoadTestRunner runner )
340 		{
341 			setRunningState();
342 		}
343 	}
344 
345 	public class InternalTestRunListener extends TestRunListenerAdapter
346 	{
347 		private SimpleDateFormat dateFormat;
348 
349 		public InternalTestRunListener()
350 		{
351 			dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS" );
352 		}
353 
354 		public void beforeRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
355 		{
356 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
357 				return;
358 
359 			runButton.setEnabled( false );
360 			cancelButton.setEnabled( true );
361 			testStepList.setEnabled( false );
362 			testStepList.setSelectedIndex( -1 );
363 			testCaseLog.clear();
364 
365 			testCaseLog.addText( "Test started at " + dateFormat.format( new Date() ) );
366 
367 			WsdlTestCaseDesktopPanel.this.beforeRun();
368 
369 			if( runner == null )
370 				runner = testRunner;
371 		}
372 
373 		public synchronized void beforeStep( TestCaseRunner testRunner, TestCaseRunContext runContext,
374 				final TestStep testStep )
375 		{
376 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
377 				return;
378 
379 			if( testStep != null )
380 			{
381 				if( SwingUtilities.isEventDispatchThread() )
382 				{
383 					testStepList.setSelectedValue( testStep, true );
384 				}
385 				else
386 				{
387 					SwingUtilities.invokeLater( new Runnable()
388 					{
389 						public void run()
390 						{
391 				testStepList.setSelectedValue( testStep, true );
392 		}
393 					} );
394 				}
395 			}
396 		}
397 
398 		public void afterRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
399 		{
400 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
401 				return;
402 
403 			WsdlTestCaseRunner wsdlRunner = ( WsdlTestCaseRunner )testRunner;
404 
405 			if( testRunner.getStatus() == TestCaseRunner.Status.CANCELED )
406 				testCaseLog.addText( "TestCase canceled [" + testRunner.getReason() + "], time taken = "
407 						+ wsdlRunner.getTimeTaken() );
408 			else if( testRunner.getStatus() == TestCaseRunner.Status.FAILED )
409 			{
410 				String msg = wsdlRunner.getReason();
411 				if( wsdlRunner.getError() != null )
412 				{
413 					if( msg != null )
414 						msg += ":";
415 
416 					msg += wsdlRunner.getError();
417 				}
418 
419 				testCaseLog.addText( "TestCase failed [" + msg + "], time taken = " + wsdlRunner.getTimeTaken() );
420 			}
421 			else
422 				testCaseLog.addText( "TestCase finished with status [" + testRunner.getStatus() + "], time taken = "
423 						+ wsdlRunner.getTimeTaken() );
424 
425 			runner = null;
426 
427 			JToggleButton loopButton = ( JToggleButton )runContext.getProperty( "loopButton" );
428 			if( loopButton != null && loopButton.isSelected() && testRunner.getStatus() == TestCaseRunner.Status.FINISHED )
429 			{
430 				SwingUtilities.invokeLater( new Runnable()
431 				{
432 					public void run()
433 					{
434 						runTestCase();
435 					}
436 				} );
437 			}
438 			else
439 			{
440 				WsdlTestCaseDesktopPanel.this.afterRun();
441 			}
442 		}
443 
444 		public void afterStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult stepResult )
445 		{
446 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
447 				return;
448 
449 			testCaseLog.addTestStepResult( stepResult );
450 		}
451 	}
452 
453 	protected void runTestCase()
454 	{
455 		if( canceled )
456 		{
457 			// make sure state is correct
458 			runButton.setEnabled( true );
459 			cancelButton.setEnabled( false );
460 			testStepList.setEnabled( true );
461 			return;
462 		}
463 
464 		StringToObjectMap properties = new StringToObjectMap();
465 		properties.put( "loopButton", loopButton );
466 		properties.put( TestCaseRunContext.INTERACTIVE, Boolean.TRUE );
467 		runner = getModelItem().run( properties, true );
468 	}
469 
470 	public class RunTestCaseAction extends AbstractAction
471 	{
472 		public RunTestCaseAction()
473 		{
474 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif" ) );
475 			putValue( Action.SHORT_DESCRIPTION, "Runs this testcase" );
476 		}
477 
478 		public void actionPerformed( ActionEvent e )
479 		{
480 			canceled = false;
481 			runTestCase();
482 		}
483 	}
484 
485 	public class CancelRunTestCaseAction extends AbstractAction
486 	{
487 		public CancelRunTestCaseAction()
488 		{
489 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stop_testcase.gif" ) );
490 			putValue( Action.SHORT_DESCRIPTION, "Stops running this testcase" );
491 		}
492 
493 		public void actionPerformed( ActionEvent e )
494 		{
495 			if( runner != null )
496 				runner.cancel( "canceled in UI" );
497 
498 			canceled = true;
499 		}
500 	}
501 
502 	public boolean onClose( boolean canCancel )
503 	{
504 		if( canCancel )
505 		{
506 			if( runner != null && runner.getStatus() == TestCaseRunner.Status.RUNNING )
507 			{
508 				Boolean retval = UISupport.confirmOrCancel( "Cancel running TestCase?", "Cancel Run" );
509 
510 				if( retval == null )
511 					return false;
512 				if( retval.booleanValue() )
513 				{
514 					runner.cancel( null );
515 				}
516 			}
517 		}
518 		else
519 		{
520 			if( runner != null && runner.getStatus() == TestCaseRunner.Status.RUNNING )
521 			{
522 				runner.cancel( null );
523 			}
524 		}
525 
526 		SoapUI.getTestMonitor().removeTestMonitorListener( testMonitorListener );
527 		getModelItem().removeTestRunListener( testRunListener );
528 		testStepList.release();
529 		progressBarAdapter.release();
530 		propertiesTable.release();
531 		inspectorPanel.release();
532 
533 		setupGroovyEditor.getEditor().release();
534 		tearDownGroovyEditor.getEditor().release();
535 
536 		testCaseLog.release();
537 
538 		return release();
539 	}
540 
541 	public boolean dependsOn( ModelItem modelItem )
542 	{
543 		return modelItem == getModelItem() || modelItem == getModelItem().getTestSuite()
544 				|| modelItem == getModelItem().getTestSuite().getProject();
545 	}
546 
547 	protected void beforeRun()
548 	{
549 	}
550 
551 	protected void afterRun()
552 	{
553 		runButton.setEnabled( true );
554 		cancelButton.setEnabled( false );
555 		testStepList.setEnabled( true );
556 	}
557 
558 	private class SetupScriptGroovyEditorModel extends AbstractGroovyEditorModel
559 	{
560 		@Override
561 		public Action createRunAction()
562 		{
563 			return new AbstractAction()
564 			{
565 
566 				public void actionPerformed( ActionEvent e )
567 				{
568 					try
569 					{
570 						MockTestRunner mockTestRunner = new MockTestRunner( WsdlTestCaseDesktopPanel.this.getModelItem(), SoapUI.ensureGroovyLog() );
571 						WsdlTestCaseDesktopPanel.this.getModelItem().runSetupScript( new MockTestRunContext( mockTestRunner, null ), mockTestRunner );
572 					}
573 					catch( Exception e1 )
574 					{
575 						UISupport.showErrorMessage( e1 );
576 					}
577 				}
578 			};
579 		}
580 
581 		public SetupScriptGroovyEditorModel()
582 		{
583 			super( new String[] { "log", "testCase", "context", "testRunner" }, WsdlTestCaseDesktopPanel.this.getModelItem(), "Setup" );
584 		}
585 
586 		public String getScript()
587 		{
588 			return WsdlTestCaseDesktopPanel.this.getModelItem().getSetupScript();
589 		}
590 
591 		public void setScript( String text )
592 		{
593 			WsdlTestCaseDesktopPanel.this.getModelItem().setSetupScript( text );
594 		}
595 	}
596 
597 	private class TearDownScriptGroovyEditorModel extends AbstractGroovyEditorModel
598 	{
599 		@Override
600 		public Action createRunAction()
601 		{
602 			return new AbstractAction()
603 			{
604 
605 				public void actionPerformed( ActionEvent e )
606 				{
607 					try
608 					{
609 						MockTestRunner mockTestRunner = new MockTestRunner( WsdlTestCaseDesktopPanel.this.getModelItem(), SoapUI.ensureGroovyLog() );
610 						WsdlTestCaseDesktopPanel.this.getModelItem().runTearDownScript( new MockTestRunContext( mockTestRunner, null ), mockTestRunner );
611 					}
612 					catch( Exception e1 )
613 					{
614 						UISupport.showErrorMessage( e1 );
615 					}
616 				}
617 			};
618 		}
619 
620 		public TearDownScriptGroovyEditorModel()
621 		{
622 			super( new String[] { "log", "testCase", "context", "testRunner" }, WsdlTestCaseDesktopPanel.this.getModelItem(), "TearDown" );
623 		}
624 
625 		public String getScript()
626 		{
627 			return WsdlTestCaseDesktopPanel.this.getModelItem().getTearDownScript();
628 		}
629 
630 		public void setScript( String text )
631 		{
632 			WsdlTestCaseDesktopPanel.this.getModelItem().setTearDownScript( text );
633 		}
634 	}
635 
636 	private class AddWsdlTestStepAction extends AbstractAction implements Runnable
637 	{
638 		private final WsdlTestStepFactory factory;
639 
640 		public AddWsdlTestStepAction( WsdlTestStepFactory factory )
641 		{
642 			this.factory = factory;
643 			putValue( SMALL_ICON, UISupport.createImageIcon( factory.getTestStepIconPath() ) );
644 			putValue( SHORT_DESCRIPTION, "Create a new " + factory.getTestStepName() + " TestStep" );
645 		}
646 
647 		public void actionPerformed( ActionEvent e )
648 		{
649 			SwingActionDelegate.invoke( this );
650 		}
651 
652 		public void run()
653 		{
654 			int ix = testStepList.getTestStepList().getSelectedIndex();
655 
656 			String name = UISupport.prompt( "Specify name for new step", ix == -1 ? "Add Step" : "Insert Step", factory
657 					.getTestStepName() );
658 			if( name != null )
659 			{
660 				TestStepConfig newTestStepConfig = factory.createNewTestStep( getModelItem(), name );
661 				if( newTestStepConfig != null )
662 				{
663 					WsdlTestStep testStep = getModelItem().insertTestStep( newTestStepConfig, ix );
664 					if( testStep != null )
665 						UISupport.selectAndShow( testStep );
666 				}
667 			}
668 		}
669 	}
670 
671 	public static class ModelItemListDragAndDropable extends JListDragAndDropable<JList>
672 	{
673 		public ModelItemListDragAndDropable( JList list, WsdlTestCase testCase )
674 		{
675 			super( list, testCase );
676 		}
677 
678 		@Override
679 		public ModelItem getModelItemAtRow( int row )
680 		{
681 			return ( ModelItem )getList().getModel().getElementAt( row );
682 		}
683 
684 		@Override
685 		public int getModelItemRow( ModelItem modelItem )
686 		{
687 			ListModel model = getList().getModel();
688 
689 			for( int c = 0; c < model.getSize(); c++ )
690 			{
691 				if( model.getElementAt( c ) == modelItem )
692 					return c;
693 			}
694 
695 			return -1;
696 		}
697 
698 		public Component getRenderer( ModelItem modelItem )
699 		{
700 			return getList().getCellRenderer().getListCellRendererComponent( getList(), modelItem,
701 					getModelItemRow( modelItem ), true, true );
702 		}
703 
704 		@Override
705 		public void setDragInfo( String dropInfo )
706 		{
707 			super.setDragInfo( dropInfo == null || dropInfo.length() == 0 ? null : dropInfo );
708 		}
709 	}
710 }