View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.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 void beforeStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStep testStep )
374 		{
375 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
376 				return;
377 
378 			if( testStep != null )
379 				testStepList.setSelectedValue( testStep, true );
380 		}
381 
382 		public void afterRun( TestCaseRunner testRunner, TestCaseRunContext runContext )
383 		{
384 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
385 				return;
386 
387 			WsdlTestCaseRunner wsdlRunner = ( WsdlTestCaseRunner )testRunner;
388 
389 			if( testRunner.getStatus() == TestCaseRunner.Status.CANCELED )
390 				testCaseLog.addText( "TestCase canceled [" + testRunner.getReason() + "], time taken = "
391 						+ wsdlRunner.getTimeTaken() );
392 			else if( testRunner.getStatus() == TestCaseRunner.Status.FAILED )
393 			{
394 				String msg = wsdlRunner.getReason();
395 				if( wsdlRunner.getError() != null )
396 				{
397 					if( msg != null )
398 						msg += ":";
399 
400 					msg += wsdlRunner.getError();
401 				}
402 
403 				testCaseLog.addText( "TestCase failed [" + msg + "], time taken = " + wsdlRunner.getTimeTaken() );
404 			}
405 			else
406 				testCaseLog.addText( "TestCase finished with status [" + testRunner.getStatus() + "], time taken = "
407 						+ wsdlRunner.getTimeTaken() );
408 
409 			runner = null;
410 
411 			JToggleButton loopButton = ( JToggleButton )runContext.getProperty( "loopButton" );
412 			if( loopButton != null && loopButton.isSelected() && testRunner.getStatus() == TestCaseRunner.Status.FINISHED )
413 			{
414 				SwingUtilities.invokeLater( new Runnable()
415 				{
416 					public void run()
417 					{
418 						runTestCase();
419 					}
420 				} );
421 			}
422 			else
423 			{
424 				WsdlTestCaseDesktopPanel.this.afterRun();
425 			}
426 		}
427 
428 		public void afterStep( TestCaseRunner testRunner, TestCaseRunContext runContext, TestStepResult stepResult )
429 		{
430 			if( SoapUI.getTestMonitor().hasRunningLoadTest( getModelItem() ) )
431 				return;
432 
433 			testCaseLog.addTestStepResult( stepResult );
434 		}
435 	}
436 
437 	protected void runTestCase()
438 	{
439 		if( canceled )
440 		{
441 			// make sure state is correct
442 			runButton.setEnabled( true );
443 			cancelButton.setEnabled( false );
444 			testStepList.setEnabled( true );
445 			return;
446 		}
447 
448 		StringToObjectMap properties = new StringToObjectMap();
449 		properties.put( "loopButton", loopButton );
450 		properties.put( TestCaseRunContext.INTERACTIVE, Boolean.TRUE );
451 		runner = getModelItem().run( properties, true );
452 	}
453 
454 	public class RunTestCaseAction extends AbstractAction
455 	{
456 		public RunTestCaseAction()
457 		{
458 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif" ) );
459 			putValue( Action.SHORT_DESCRIPTION, "Runs this testcase" );
460 		}
461 
462 		public void actionPerformed( ActionEvent e )
463 		{
464 			canceled = false;
465 			runTestCase();
466 		}
467 	}
468 
469 	public class CancelRunTestCaseAction extends AbstractAction
470 	{
471 		public CancelRunTestCaseAction()
472 		{
473 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stop_testcase.gif" ) );
474 			putValue( Action.SHORT_DESCRIPTION, "Stops running this testcase" );
475 		}
476 
477 		public void actionPerformed( ActionEvent e )
478 		{
479 			if( runner != null )
480 				runner.cancel( "canceled in UI" );
481 
482 			canceled = true;
483 		}
484 	}
485 
486 	public boolean onClose( boolean canCancel )
487 	{
488 		if( canCancel )
489 		{
490 			if( runner != null && runner.getStatus() == TestCaseRunner.Status.RUNNING )
491 			{
492 				Boolean retval = UISupport.confirmOrCancel( "Cancel running TestCase?", "Cancel Run" );
493 
494 				if( retval == null )
495 					return false;
496 				if( retval.booleanValue() )
497 				{
498 					runner.cancel( null );
499 				}
500 			}
501 		}
502 		else
503 		{
504 			if( runner != null && runner.getStatus() == TestCaseRunner.Status.RUNNING )
505 			{
506 				runner.cancel( null );
507 			}
508 		}
509 
510 		SoapUI.getTestMonitor().removeTestMonitorListener( testMonitorListener );
511 		getModelItem().removeTestRunListener( testRunListener );
512 		testStepList.release();
513 		progressBarAdapter.release();
514 		propertiesTable.release();
515 		inspectorPanel.release();
516 
517 		setupGroovyEditor.getEditor().release();
518 		tearDownGroovyEditor.getEditor().release();
519 
520 		testCaseLog.release();
521 
522 		return release();
523 	}
524 
525 	public boolean dependsOn( ModelItem modelItem )
526 	{
527 		return modelItem == getModelItem() || modelItem == getModelItem().getTestSuite()
528 				|| modelItem == getModelItem().getTestSuite().getProject();
529 	}
530 
531 	protected void beforeRun()
532 	{
533 	}
534 
535 	protected void afterRun()
536 	{
537 		runButton.setEnabled( true );
538 		cancelButton.setEnabled( false );
539 		testStepList.setEnabled( true );
540 	}
541 
542 	private class SetupScriptGroovyEditorModel extends AbstractGroovyEditorModel
543 	{
544 		@Override
545 		public Action createRunAction()
546 		{
547 			return new AbstractAction()
548 			{
549 
550 				public void actionPerformed( ActionEvent e )
551 				{
552 					try
553 					{
554 						MockTestRunner mockTestRunner = new MockTestRunner( WsdlTestCaseDesktopPanel.this.getModelItem(), SoapUI.ensureGroovyLog() );
555 						WsdlTestCaseDesktopPanel.this.getModelItem().runSetupScript( new MockTestRunContext( mockTestRunner, null ), mockTestRunner );
556 					}
557 					catch( Exception e1 )
558 					{
559 						UISupport.showErrorMessage( e1 );
560 					}
561 				}
562 			};
563 		}
564 
565 		public SetupScriptGroovyEditorModel()
566 		{
567 			super( new String[] { "log", "testCase", "context", "testRunner" }, WsdlTestCaseDesktopPanel.this.getModelItem(), "Setup" );
568 		}
569 
570 		public String getScript()
571 		{
572 			return WsdlTestCaseDesktopPanel.this.getModelItem().getSetupScript();
573 		}
574 
575 		public void setScript( String text )
576 		{
577 			WsdlTestCaseDesktopPanel.this.getModelItem().setSetupScript( text );
578 		}
579 	}
580 
581 	private class TearDownScriptGroovyEditorModel extends AbstractGroovyEditorModel
582 	{
583 		@Override
584 		public Action createRunAction()
585 		{
586 			return new AbstractAction()
587 			{
588 
589 				public void actionPerformed( ActionEvent e )
590 				{
591 					try
592 					{
593 						MockTestRunner mockTestRunner = new MockTestRunner( WsdlTestCaseDesktopPanel.this.getModelItem(), SoapUI.ensureGroovyLog() );
594 						WsdlTestCaseDesktopPanel.this.getModelItem().runTearDownScript( new MockTestRunContext( mockTestRunner, null ), mockTestRunner );
595 					}
596 					catch( Exception e1 )
597 					{
598 						UISupport.showErrorMessage( e1 );
599 					}
600 				}
601 			};
602 		}
603 
604 		public TearDownScriptGroovyEditorModel()
605 		{
606 			super( new String[] { "log", "testCase", "context", "testRunner" }, WsdlTestCaseDesktopPanel.this.getModelItem(), "TearDown" );
607 		}
608 
609 		public String getScript()
610 		{
611 			return WsdlTestCaseDesktopPanel.this.getModelItem().getTearDownScript();
612 		}
613 
614 		public void setScript( String text )
615 		{
616 			WsdlTestCaseDesktopPanel.this.getModelItem().setTearDownScript( text );
617 		}
618 	}
619 
620 	private class AddWsdlTestStepAction extends AbstractAction
621 	{
622 		private final WsdlTestStepFactory factory;
623 
624 		public AddWsdlTestStepAction( WsdlTestStepFactory factory )
625 		{
626 			this.factory = factory;
627 			putValue( SMALL_ICON, UISupport.createImageIcon( factory.getTestStepIconPath() ) );
628 			putValue( SHORT_DESCRIPTION, "Create a new " + factory.getTestStepName() + " TestStep" );
629 		}
630 
631 		public void actionPerformed( ActionEvent e )
632 		{
633 			int ix = testStepList.getTestStepList().getSelectedIndex();
634 
635 			String name = UISupport.prompt( "Specify name for new step", ix == -1 ? "Add Step" : "Insert Step", factory
636 					.getTestStepName() );
637 			if( name != null )
638 			{
639 				TestStepConfig newTestStepConfig = factory.createNewTestStep( getModelItem(), name );
640 				if( newTestStepConfig != null )
641 				{
642 					WsdlTestStep testStep = getModelItem().insertTestStep( newTestStepConfig, ix );
643 					if( testStep != null )
644 						UISupport.selectAndShow( testStep );
645 				}
646 			}
647 
648 		}
649 	}
650 
651 	public static class ModelItemListDragAndDropable extends JListDragAndDropable<JList>
652 	{
653 		public ModelItemListDragAndDropable( JList list, WsdlTestCase testCase )
654 		{
655 			super( list, testCase );
656 		}
657 
658 		@Override
659 		public ModelItem getModelItemAtRow( int row )
660 		{
661 			return ( ModelItem )getList().getModel().getElementAt( row );
662 		}
663 
664 		@Override
665 		public int getModelItemRow( ModelItem modelItem )
666 		{
667 			ListModel model = getList().getModel();
668 
669 			for( int c = 0; c < model.getSize(); c++ )
670 			{
671 				if( model.getElementAt( c ) == modelItem )
672 					return c;
673 			}
674 
675 			return -1;
676 		}
677 
678 		public Component getRenderer( ModelItem modelItem )
679 		{
680 			return getList().getCellRenderer().getListCellRendererComponent( getList(), modelItem,
681 					getModelItemRow( modelItem ), true, true );
682 		}
683 
684 		@Override
685 		public void setDragInfo( String dropInfo )
686 		{
687 			super.setDragInfo( dropInfo == null || dropInfo.length() == 0 ? null : dropInfo );
688 		}
689 	}
690 }