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.loadtest;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Dimension;
17  import java.awt.event.ActionEvent;
18  import java.awt.event.ItemEvent;
19  import java.awt.event.ItemListener;
20  import java.beans.PropertyChangeEvent;
21  import java.beans.PropertyChangeListener;
22  
23  import javax.swing.AbstractAction;
24  import javax.swing.Action;
25  import javax.swing.BorderFactory;
26  import javax.swing.Box;
27  import javax.swing.JButton;
28  import javax.swing.JComboBox;
29  import javax.swing.JComponent;
30  import javax.swing.JLabel;
31  import javax.swing.JPanel;
32  import javax.swing.JProgressBar;
33  import javax.swing.JSpinner;
34  import javax.swing.JSplitPane;
35  import javax.swing.JTabbedPane;
36  import javax.swing.SpinnerNumberModel;
37  import javax.swing.event.ChangeEvent;
38  import javax.swing.event.ChangeListener;
39  
40  import com.eviware.soapui.SoapUI;
41  import com.eviware.soapui.config.LoadTestLimitTypesConfig;
42  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
43  import com.eviware.soapui.impl.wsdl.actions.loadtest.LoadTestOptionsAction;
44  import com.eviware.soapui.impl.wsdl.loadtest.WsdlLoadTest;
45  import com.eviware.soapui.impl.wsdl.loadtest.WsdlLoadTestRunner;
46  import com.eviware.soapui.impl.wsdl.loadtest.data.actions.ExportStatisticsAction;
47  import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLog;
48  import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategy;
49  import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyFactory;
50  import com.eviware.soapui.impl.wsdl.loadtest.strategy.LoadStrategyRegistry;
51  import com.eviware.soapui.impl.wsdl.panels.support.MockLoadTestRunContext;
52  import com.eviware.soapui.impl.wsdl.panels.support.MockLoadTestRunner;
53  import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
54  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
55  import com.eviware.soapui.model.ModelItem;
56  import com.eviware.soapui.model.support.LoadTestRunListenerAdapter;
57  import com.eviware.soapui.model.testsuite.LoadTestRunContext;
58  import com.eviware.soapui.model.testsuite.LoadTestRunListener;
59  import com.eviware.soapui.model.testsuite.LoadTestRunner;
60  import com.eviware.soapui.model.testsuite.TestRunner.Status;
61  import com.eviware.soapui.support.UISupport;
62  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
63  import com.eviware.soapui.support.components.GroovyEditorComponent;
64  import com.eviware.soapui.support.components.GroovyEditorInspector;
65  import com.eviware.soapui.support.components.JComponentInspector;
66  import com.eviware.soapui.support.components.JInspectorPanel;
67  import com.eviware.soapui.support.components.JInspectorPanelFactory;
68  import com.eviware.soapui.support.components.JXToolBar;
69  import com.eviware.soapui.ui.desktop.DesktopPanel;
70  import com.eviware.soapui.ui.support.DesktopListenerAdapter;
71  import com.eviware.soapui.ui.support.ModelItemDesktopPanel;
72  import com.jgoodies.forms.builder.ButtonBarBuilder;
73  
74  /***
75   * Desktop panel for LoadTests
76   * 
77   * @author Ole.Matzura
78   */
79  
80  public class WsdlLoadTestDesktopPanel extends ModelItemDesktopPanel<WsdlLoadTest> implements PropertyChangeListener
81  {
82  	private static final String SECONDS_LIMIT = "Seconds";
83  	private static final String RUNS_LIMIT = "Total Runs";
84  	private static final String RUNS_PER_THREAD_LIMIT = "Runs per Thread";
85  	private JPanel contentPanel;
86  	@SuppressWarnings( "unused" )
87  	private JSplitPane mainSplit;
88  	@SuppressWarnings( "unused" )
89  	private JTabbedPane mainTabs;
90  	@SuppressWarnings( "unused" )
91  	private JPanel graphPanel;
92  	protected JButton runButton;
93  	protected JButton cancelButton;
94  	protected JButton statisticsGraphButton;
95  	private WsdlLoadTestRunner runner;
96  	protected JSpinner threadsSpinner;
97  	private LoadTestRunListener internalLoadTestListener = new InternalLoadTestListener();
98  	protected JComboBox strategyCombo;
99  	protected JPanel loadStrategyConfigurationPanel;
100 	protected JButton resetButton;
101 	private LoadTestLog loadTestLog;
102 	protected JButton optionsButton;
103 	protected JButton testTimesGraphButton;
104 	@SuppressWarnings( "unused" )
105 	private Object limit;
106 	private JSpinner limitSpinner;
107 	private JComboBox limitTypeCombo;
108 	private SpinnerNumberModel limitSpinnerModel;
109 	protected JProgressBar progressBar;
110 	private StatisticsDesktopPanel statisticsDesktopPanel;
111 	private StatisticsHistoryDesktopPanel statisticsHistoryDesktopPanel;
112 
113 	public boolean loadTestIsRunning;
114 	private InternalDesktopListener desktopListener;
115 	protected JButton exportButton;
116 	private JLoadTestAssertionsTable assertionsTable;
117 	private JStatisticsTable statisticsTable;
118 	private GroovyEditorComponent tearDownGroovyEditor;
119 	private GroovyEditorComponent setupGroovyEditor;
120 	private JInspectorPanel inspectorPanel;
121 
122 	public WsdlLoadTestDesktopPanel( WsdlLoadTest loadTest )
123 	{
124 		super( loadTest );
125 
126 		loadTestLog = loadTest.getLoadTestLog();
127 		loadTest.addPropertyChangeListener( this );
128 		loadTest.addLoadTestRunListener( internalLoadTestListener );
129 
130 		desktopListener = new InternalDesktopListener();
131 		SoapUI.getDesktop().addDesktopListener( desktopListener );
132 
133 		buildUI();
134 	}
135 
136 	private void buildUI()
137 	{
138 		contentPanel = new JPanel( new BorderLayout() );
139 
140 		contentPanel.add( buildToolbar(), BorderLayout.NORTH );
141 		contentPanel.add( buildContent(), BorderLayout.CENTER );
142 
143 		contentPanel.setPreferredSize( new Dimension( 600, 500 ) );
144 	}
145 
146 	private JComponent buildContent()
147 	{
148 		inspectorPanel = JInspectorPanelFactory.build( buildStatistics() );
149 		addInspectors( inspectorPanel );
150 		inspectorPanel.setDefaultDividerLocation( 0.6F );
151 		inspectorPanel.setCurrentInspector( "LoadTest Log" );
152 
153 		return inspectorPanel.getComponent();
154 	}
155 
156 	protected void addInspectors(JInspectorPanel inspectorPanel)
157 	{
158 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildLog(), "LoadTest Log",
159 				"The current LoadTest execution log", true ) );
160 		inspectorPanel.addInspector( new JComponentInspector<JComponent>( buildAssertions(), "LoadTest Assertions",
161 				"The assertions for this LoadTest", true ) );
162 		inspectorPanel.addInspector( new GroovyEditorInspector( buildSetupScriptPanel(), "Setup Script",
163 				"Script to run before tunning a TestCase" ) );
164 		inspectorPanel.addInspector( new GroovyEditorInspector( buildTearDownScriptPanel(), "TearDown Script",
165 				"Script to run after a TestCase Run" ) );
166 	}
167 
168 	protected GroovyEditorComponent buildTearDownScriptPanel()
169 	{
170 		tearDownGroovyEditor = new GroovyEditorComponent( new TearDownScriptGroovyEditorModel(), null );
171 		return tearDownGroovyEditor;
172 	}
173 
174 	protected GroovyEditorComponent buildSetupScriptPanel()
175 	{
176 		setupGroovyEditor = new GroovyEditorComponent( new SetupScriptGroovyEditorModel(), null );
177 		return setupGroovyEditor;
178 	}
179 
180 	protected JComponent buildStatistics()
181 	{
182 		statisticsTable = new JStatisticsTable( getModelItem() );
183 		return statisticsTable;
184 	}
185 
186 	protected JComponent buildLog()
187 	{
188 		JLoadTestLogTable loadTestLogTable = new JLoadTestLogTable( loadTestLog );
189 		return loadTestLogTable;
190 	}
191 
192 	protected JComponent buildAssertions()
193 	{
194 		assertionsTable = new JLoadTestAssertionsTable( getModelItem() );
195 		return assertionsTable;
196 	}
197 
198 	protected JComponent buildToolbar()
199 	{
200 		WsdlLoadTest loadTest = getModelItem();
201 
202 		JXToolBar toolbar = UISupport.createToolbar();
203 
204 		// ButtonBarBuilder builder = new ButtonBarBuilder();
205 		runButton = UISupport.createToolbarButton( new RunLoadTestAction() );
206 		cancelButton = UISupport.createToolbarButton( new CancelRunTestCaseAction(), false );
207 		resetButton = UISupport.createToolbarButton( new ResetAction() );
208 		exportButton = UISupport.createToolbarButton( new ExportStatisticsAction( loadTest.getStatisticsModel() ) );
209 
210 		statisticsGraphButton = UISupport.createToolbarButton( new ShowStatisticsGraphAction() );
211 		testTimesGraphButton = UISupport.createToolbarButton( new ShowTestTimesGraphAction() );
212 
213 		statisticsGraphButton.setEnabled( getModelItem().getHistoryLimit() != 0 );
214 		testTimesGraphButton.setEnabled( getModelItem().getHistoryLimit() != 0 );
215 
216 		AbstractAction optionsDelegate = SwingActionDelegate.createDelegate( LoadTestOptionsAction.SOAPUI_ACTION_ID,
217 				loadTest );
218 		optionsDelegate.putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ) );
219 		optionsButton = UISupport.createToolbarButton( optionsDelegate );
220 
221 		strategyCombo = new JComboBox( LoadStrategyRegistry.getInstance().getStrategies() );
222 		strategyCombo.setToolTipText( "Selects which LoadTest Strategy to use" );
223 		UISupport.setPreferredHeight( strategyCombo, 18 );
224 		strategyCombo.setSelectedItem( loadTest.getLoadStrategy().getType() );
225 		strategyCombo.addItemListener( new ItemListener()
226 		{
227 			public void itemStateChanged( ItemEvent e )
228 			{
229 				Object item = e.getItem();
230 				if( item == null )
231 					return;
232 
233 				setLoadStrategy( item.toString() );
234 			}
235 		} );
236 
237 		toolbar.add( runButton );
238 		toolbar.add( cancelButton );
239 		toolbar.add( statisticsGraphButton );
240 		toolbar.add( testTimesGraphButton );
241 		toolbar.add( resetButton );
242 		toolbar.add( exportButton );
243 
244 		toolbar.add( optionsButton );
245 		toolbar.add( UISupport.createToolbarButton( new ShowOnlineHelpAction( HelpUrls.LOADTESTEDITOR_HELP_URL ) ) );
246 		toolbar.add( Box.createHorizontalGlue() );
247 		buildLimitBar( toolbar );
248 		toolbar.addSeparator();
249 
250 		progressBar = new JProgressBar( 0, 100 );
251 		progressBar.setPreferredSize( new Dimension( 70, 20 ) );
252 
253 		toolbar.addFixed( progressBar );
254 
255 		ButtonBarBuilder builder = new ButtonBarBuilder();
256 
257 		builder.addFixed( new JLabel( "Threads:" ) );
258 		builder.addRelatedGap();
259 
260 		threadsSpinner = new JSpinner( new SpinnerNumberModel( getModelItem().getThreadCount(), 1, 9999, 1 ) );
261 		threadsSpinner.setToolTipText( "Sets the number of threads (\"Virtual Users\") to run this TestCase" );
262 		UISupport.setPreferredHeight( threadsSpinner, 18 );
263 		threadsSpinner.getModel().addChangeListener( new ChangeListener()
264 		{
265 
266 			public void stateChanged( ChangeEvent e )
267 			{
268 				getModelItem().setThreadCount( ( ( SpinnerNumberModel )threadsSpinner.getModel() ).getNumber().intValue() );
269 			}
270 		} );
271 
272 		builder.addFixed( threadsSpinner );
273 		builder.addUnrelatedGap();
274 
275 		LoadStrategy loadStrategy = loadTest.getLoadStrategy();
276 
277 		builder.addFixed( new JLabel( "Strategy" ) );
278 		builder.addRelatedGap();
279 		builder.addFixed( strategyCombo );
280 		builder.addUnrelatedGap();
281 
282 		loadStrategyConfigurationPanel = new JPanel( new BorderLayout() );
283 		loadStrategyConfigurationPanel.add( loadStrategy.getConfigurationPanel(), BorderLayout.CENTER );
284 
285 		builder.addFixed( loadStrategyConfigurationPanel );
286 		builder.setBorder( BorderFactory.createEmptyBorder( 2, 3, 3, 3 ) );
287 
288 		return UISupport.buildPanelWithToolbar( toolbar, builder.getPanel() );
289 	}
290 
291 	public void buildLimitBar( JXToolBar toolbar )
292 	{
293 		limitSpinnerModel = new SpinnerNumberModel( getModelItem().getTestLimit(), 0, Long.MAX_VALUE, 100 );
294 
295 		limitSpinner = new JSpinner( limitSpinnerModel );
296 		limitSpinner.setPreferredSize( new Dimension( 70, 20 ) );
297 		limitSpinner.setToolTipText( "Sets the limit for this test; total number of requests or seconds to run" );
298 		limitSpinner.getModel().addChangeListener( new ChangeListener()
299 		{
300 
301 			public void stateChanged( ChangeEvent e )
302 			{
303 				int intValue = ( ( SpinnerNumberModel )limitSpinner.getModel() ).getNumber().intValue();
304 				getModelItem().setTestLimit( intValue );
305 			}
306 		} );
307 
308 		toolbar.addSeparator();
309 		toolbar.addFixed( new JLabel( "Limit:" ) );
310 		toolbar.addSeparator();
311 		toolbar.addFixed( limitSpinner );
312 		toolbar.addSeparator();
313 
314 		limitTypeCombo = new JComboBox( new String[] { WsdlLoadTestDesktopPanel.RUNS_LIMIT,
315 				WsdlLoadTestDesktopPanel.SECONDS_LIMIT, WsdlLoadTestDesktopPanel.RUNS_PER_THREAD_LIMIT } );
316 
317 		if( getModelItem().getLimitType() == LoadTestLimitTypesConfig.TIME )
318 			limitTypeCombo.setSelectedIndex( 1 );
319 		else if( getModelItem().getLimitType() == LoadTestLimitTypesConfig.COUNT_PER_THREAD )
320 			limitTypeCombo.setSelectedIndex( 2 );
321 
322 		toolbar.addFixed( limitTypeCombo );
323 		toolbar.addSeparator();
324 
325 		limitTypeCombo.addItemListener( new ItemListener()
326 		{
327 			public void itemStateChanged( ItemEvent e )
328 			{
329 				Object item = e.getItem();
330 				if( WsdlLoadTestDesktopPanel.RUNS_LIMIT.equals( item ) )
331 				{
332 					getModelItem().setLimitType( LoadTestLimitTypesConfig.COUNT );
333 				}
334 				else if( WsdlLoadTestDesktopPanel.SECONDS_LIMIT.equals( item ) )
335 				{
336 					getModelItem().setLimitType( LoadTestLimitTypesConfig.TIME );
337 				}
338 				else if( WsdlLoadTestDesktopPanel.RUNS_PER_THREAD_LIMIT.equals( item ) )
339 				{
340 					getModelItem().setLimitType( LoadTestLimitTypesConfig.COUNT_PER_THREAD );
341 				}
342 			}
343 		} );
344 	}
345 
346 	public boolean onClose( boolean canCancel )
347 	{
348 		if( runner != null && runner.getStatus() == Status.RUNNING )
349 		{
350 			if( !UISupport.confirm( "Running test will be canceled when closing window. Close anyway?", "Close LoadTest" ) )
351 				return false;
352 		}
353 
354 		getModelItem().removeLoadTestRunListener( internalLoadTestListener );
355 		getModelItem().removePropertyChangeListener( this );
356 		getModelItem().getStatisticsModel().reset();
357 
358 		if( runner != null && runner.getStatus() == Status.RUNNING )
359 			runner.cancel( "closing window" );
360 
361 		if( statisticsDesktopPanel != null )
362 			SoapUI.getDesktop().closeDesktopPanel( statisticsDesktopPanel );
363 
364 		if( statisticsHistoryDesktopPanel != null )
365 			SoapUI.getDesktop().closeDesktopPanel( statisticsHistoryDesktopPanel );
366 
367 		assertionsTable.release();
368 		loadStrategyConfigurationPanel.removeAll();
369 		SoapUI.getDesktop().removeDesktopListener( desktopListener );
370 
371 		statisticsTable.release();
372 		inspectorPanel.release();
373 
374 		setupGroovyEditor.release();
375 		tearDownGroovyEditor.release();
376 		
377 		return release();
378 	}
379 
380 	public JComponent getComponent()
381 	{
382 		return contentPanel;
383 	}
384 
385 	private final class InternalDesktopListener extends DesktopListenerAdapter
386 	{
387 		public void desktopPanelClosed( DesktopPanel desktopPanel )
388 		{
389 			if( desktopPanel == statisticsDesktopPanel )
390 				statisticsDesktopPanel = null;
391 			else if( desktopPanel == statisticsHistoryDesktopPanel )
392 				statisticsHistoryDesktopPanel = null;
393 		}
394 	}
395 
396 	public class RunLoadTestAction extends AbstractAction
397 	{
398 		public RunLoadTestAction()
399 		{
400 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/run_testcase.gif" ) );
401 			putValue( Action.SHORT_DESCRIPTION, "Runs this LoadTest" );
402 		}
403 
404 		public void actionPerformed( ActionEvent e )
405 		{
406 			WsdlLoadTest loadtest = getModelItem();
407 			if( loadtest.getTestCase().getTestStepCount() == 0 )
408 			{
409 				UISupport.showErrorMessage( "Missing TestSteps for testing!" );
410 				return;
411 			}
412 
413 			if( loadtest.getLimitType() == LoadTestLimitTypesConfig.COUNT
414 					&& loadtest.getTestLimit() < loadtest.getThreadCount() )
415 			{
416 				if( !UISupport.confirm( "The run limit is set to a lower count than number of threads\nRun Anyway?",
417 						"Run LoadTest" ) )
418 				{
419 					return;
420 				}
421 			}
422 
423 			runButton.setEnabled( false );
424 			runner = loadtest.run();
425 		}
426 	}
427 
428 	public class ResetAction extends AbstractAction
429 	{
430 		public ResetAction()
431 		{
432 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/reset_loadtest_statistics.gif" ) );
433 			putValue( Action.SHORT_DESCRIPTION, "Resets statistics for this LoadTest" );
434 		}
435 
436 		public void actionPerformed( ActionEvent e )
437 		{
438 			getModelItem().getStatisticsModel().reset();
439 		}
440 	}
441 
442 	public class ShowStatisticsGraphAction extends AbstractAction
443 	{
444 		public ShowStatisticsGraphAction()
445 		{
446 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stats_graph.gif" ) );
447 			putValue( Action.SHORT_DESCRIPTION, "Shows the statistics graph" );
448 		}
449 
450 		public void actionPerformed( ActionEvent e )
451 		{
452 			if( statisticsDesktopPanel == null )
453 				statisticsDesktopPanel = new StatisticsDesktopPanel( getModelItem() );
454 
455 			UISupport.showDesktopPanel( statisticsDesktopPanel );
456 		}
457 	}
458 
459 	public class ShowTestTimesGraphAction extends AbstractAction
460 	{
461 		public ShowTestTimesGraphAction()
462 		{
463 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/samples_graph.gif" ) );
464 			putValue( Action.SHORT_DESCRIPTION, "Shows the Statistics History graph" );
465 		}
466 
467 		public void actionPerformed( ActionEvent e )
468 		{
469 			if( statisticsHistoryDesktopPanel == null )
470 				statisticsHistoryDesktopPanel = new StatisticsHistoryDesktopPanel( getModelItem() );
471 
472 			UISupport.showDesktopPanel( statisticsHistoryDesktopPanel );
473 		}
474 	}
475 
476 	public class CancelRunTestCaseAction extends AbstractAction
477 	{
478 
479 		public CancelRunTestCaseAction()
480 		{
481 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/stop_testcase.gif" ) );
482 			putValue( Action.SHORT_DESCRIPTION, "Stops running this LoadTest" );
483 		}
484 
485 		public void actionPerformed( ActionEvent e )
486 		{
487 			if( runner != null )
488 			{
489 				runner.cancel( "Canceled" );
490 				cancelButton.setEnabled( false );
491 			}
492 		}
493 	}
494 
495 	public boolean dependsOn( ModelItem modelItem )
496 	{
497 		WsdlLoadTest loadTest = getModelItem();
498 
499 		return modelItem == loadTest || modelItem == loadTest.getTestCase()
500 				|| modelItem == loadTest.getTestCase().getTestSuite()
501 				|| modelItem == loadTest.getTestCase().getTestSuite().getProject();
502 	}
503 
504 	public void setLoadStrategy( String type )
505 	{
506 		LoadStrategyFactory factory = LoadStrategyRegistry.getInstance().getFactory( type );
507 		LoadStrategy loadStrategy = factory.create( getModelItem() );
508 		getModelItem().setLoadStrategy( loadStrategy );
509 		loadStrategyConfigurationPanel.removeAll();
510 		loadStrategyConfigurationPanel.add( loadStrategy.getConfigurationPanel(), BorderLayout.CENTER );
511 		loadStrategyConfigurationPanel.revalidate();
512 	}
513 
514 	private class InternalLoadTestListener extends LoadTestRunListenerAdapter
515 	{
516 		public void beforeLoadTest( LoadTestRunner testRunner, LoadTestRunContext context )
517 		{
518 			loadTestLog.clear();
519 
520 			loadTestIsRunning = true;
521 			if( getModelItem().getTestLimit() > 0 )
522 			{
523 				progressBar.setValue( 0 );
524 				progressBar.setString( null );
525 			}
526 			else
527 			{
528 				progressBar.setString( "..." );
529 			}
530 
531 			progressBar.setStringPainted( true );
532 
533 			runButton.setEnabled( false );
534 			cancelButton.setEnabled( true );
535 			strategyCombo.setEnabled( false );
536 			limitTypeCombo.setEnabled( false );
537 			optionsButton.setEnabled( false );
538 			threadsSpinner.setEnabled( getModelItem().getLoadStrategy().allowThreadCountChangeDuringRun() );
539 
540 			new Thread( new ProgressBarUpdater(), getModelItem().getName() + " ProgressBarUpdater" ).start();
541 		}
542 
543 		public void afterLoadTest( LoadTestRunner testRunner, LoadTestRunContext context )
544 		{
545 			runButton.setEnabled( true );
546 
547 			cancelButton.setEnabled( false );
548 			strategyCombo.setEnabled( true );
549 			limitTypeCombo.setEnabled( true );
550 			threadsSpinner.setEnabled( true );
551 			optionsButton.setEnabled( true );
552 
553 			runner = null;
554 			loadTestIsRunning = false;
555 
556 			if( progressBar.isIndeterminate() )
557 			{
558 				progressBar.setIndeterminate( false );
559 				progressBar.setValue( 0 );
560 			}
561 			else if( testRunner.getStatus() == Status.FINISHED )
562 			{
563 				progressBar.setValue( 100 );
564 			}
565 
566 			if( testRunner.getStatus() == Status.FAILED )
567 			{
568 				UISupport.showErrorMessage( "LoadTest failed; " + testRunner.getReason() );
569 			}
570 		}
571 
572 	}
573 
574 	private class ProgressBarUpdater implements Runnable
575 	{
576 		public void run()
577 		{
578 			while( true )
579 			{
580 				if( !loadTestIsRunning )
581 					break;
582 
583 				if( getModelItem().getTestLimit() == 0 )
584 				{
585 					if( loadTestIsRunning && !progressBar.isIndeterminate() )
586 					{
587 						progressBar.setIndeterminate( true );
588 						progressBar.setString( "..." );
589 					}
590 				}
591 				else 
592 				{
593 					if( loadTestIsRunning && progressBar.isIndeterminate() )
594 					{
595 						progressBar.setIndeterminate( false );
596 						progressBar.setString( null );
597 					}
598 
599 					progressBar.setValue( runner == null ? 0 : ( int )( runner.getProgress()*100 ) );
600 				}
601 
602 				try
603 				{
604 					Thread.sleep( 500 );
605 				}
606 				catch( InterruptedException e )
607 				{
608 					SoapUI.logError( e );
609 				}
610 			}
611 		}
612 	}
613 
614 	public void propertyChange( PropertyChangeEvent evt )
615 	{
616 		if( evt.getPropertyName().equals( WsdlLoadTest.THREADCOUNT_PROPERTY ) )
617 		{
618 			threadsSpinner.setValue( evt.getNewValue() );
619 		}
620 		else if( evt.getPropertyName().equals( WsdlLoadTest.HISTORYLIMIT_PROPERTY ) )
621 		{
622 			long lng = ( Long )evt.getNewValue();
623 
624 			statisticsGraphButton.setEnabled( lng != 0 );
625 			testTimesGraphButton.setEnabled( lng != 0 );
626 		}
627 	}
628 
629 	private class SetupScriptGroovyEditorModel extends AbstractGroovyEditorModel
630 	{
631 		@Override
632 		public Action createRunAction()
633 		{
634 			return new AbstractAction()
635 			{
636 
637 				public void actionPerformed( ActionEvent e )
638 				{
639 					try
640 					{
641 						MockLoadTestRunner mockTestRunner = new MockLoadTestRunner( WsdlLoadTestDesktopPanel.this.getModelItem(), SoapUI.ensureGroovyLog() );
642 						WsdlLoadTestDesktopPanel.this.getModelItem().runSetupScript( new MockLoadTestRunContext( mockTestRunner ), mockTestRunner );
643 					}
644 					catch( Exception e1 )
645 					{
646 						UISupport.showErrorMessage( e1 );
647 					}
648 				}
649 			};
650 		}
651 
652 		public SetupScriptGroovyEditorModel()
653 		{
654 			super( new String[] { "log", "context", "loadTestRunner" }, WsdlLoadTestDesktopPanel.this.getModelItem(), "Setup" );
655 		}
656 
657 		public String getScript()
658 		{
659 			return WsdlLoadTestDesktopPanel.this.getModelItem().getSetupScript();
660 		}
661 
662 		public void setScript( String text )
663 		{
664 			WsdlLoadTestDesktopPanel.this.getModelItem().setSetupScript( text );
665 		}
666 	}
667 
668 	private class TearDownScriptGroovyEditorModel extends AbstractGroovyEditorModel
669 	{
670 		@Override
671 		public Action createRunAction()
672 		{
673 			return new AbstractAction()
674 			{
675 
676 				public void actionPerformed( ActionEvent e )
677 				{
678 					try
679 					{
680 						MockLoadTestRunner mockTestRunner = new MockLoadTestRunner( WsdlLoadTestDesktopPanel.this.getModelItem(), SoapUI.ensureGroovyLog() );
681 						WsdlLoadTestDesktopPanel.this.getModelItem().runTearDownScript( new MockLoadTestRunContext( mockTestRunner ), mockTestRunner );
682 					}
683 					catch( Exception e1 )
684 					{
685 						UISupport.showErrorMessage( e1 );
686 					}
687 				}
688 			};
689 		}
690 
691 		public TearDownScriptGroovyEditorModel()
692 		{
693 			super( new String[] { "log", "context", "loadTestRunner" }, WsdlLoadTestDesktopPanel.this.getModelItem(), "TearDown" );
694 		}
695 
696 		public String getScript()
697 		{
698 			return WsdlLoadTestDesktopPanel.this.getModelItem().getTearDownScript();
699 		}
700 
701 		public void setScript( String text )
702 		{
703 			WsdlLoadTestDesktopPanel.this.getModelItem().setTearDownScript( text );
704 		}
705 	}
706 }