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.testcase;
14  
15  import java.io.File;
16  import java.io.IOException;
17  import java.util.ArrayList;
18  import java.util.HashMap;
19  import java.util.HashSet;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import org.apache.log4j.Logger;
25  
26  import com.eviware.soapui.SoapUI;
27  import com.eviware.soapui.config.LoadTestConfig;
28  import com.eviware.soapui.config.TestCaseConfig;
29  import com.eviware.soapui.config.TestStepConfig;
30  import com.eviware.soapui.config.WsrmVersionTypeConfig;
31  import com.eviware.soapui.impl.wsdl.AbstractTestPropertyHolderWsdlModelItem;
32  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
33  import com.eviware.soapui.impl.wsdl.loadtest.LoadTestAssertion;
34  import com.eviware.soapui.impl.wsdl.loadtest.WsdlLoadTest;
35  import com.eviware.soapui.impl.wsdl.loadtest.assertions.TestStepStatusAssertion;
36  import com.eviware.soapui.impl.wsdl.panels.teststeps.amf.AMFTestRunListener;
37  import com.eviware.soapui.impl.wsdl.support.wsrm.WsrmTestRunListener;
38  import com.eviware.soapui.impl.wsdl.support.wsrm.WsrmUtils;
39  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
40  import com.eviware.soapui.impl.wsdl.teststeps.registry.HttpRequestStepFactory;
41  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepFactory;
42  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepRegistry;
43  import com.eviware.soapui.model.ModelItem;
44  import com.eviware.soapui.model.support.ModelSupport;
45  import com.eviware.soapui.model.testsuite.LoadTest;
46  import com.eviware.soapui.model.testsuite.TestCase;
47  import com.eviware.soapui.model.testsuite.TestCaseRunContext;
48  import com.eviware.soapui.model.testsuite.TestCaseRunner;
49  import com.eviware.soapui.model.testsuite.TestRunListener;
50  import com.eviware.soapui.model.testsuite.TestStep;
51  import com.eviware.soapui.support.StringUtils;
52  import com.eviware.soapui.support.UISupport;
53  import com.eviware.soapui.support.action.swing.ActionList;
54  import com.eviware.soapui.support.action.swing.DefaultActionList;
55  import com.eviware.soapui.support.resolver.ResolveDialog;
56  import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
57  import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
58  import com.eviware.soapui.support.types.StringToObjectMap;
59  
60  /***
61   * TestCase implementation for WSDL projects
62   * 
63   * @author Ole.Matzura
64   */
65  
66  public class WsdlTestCase extends AbstractTestPropertyHolderWsdlModelItem<TestCaseConfig> implements TestCase
67  {
68  	private final static Logger logger = Logger.getLogger( WsdlTestCase.class );
69  	public final static String KEEP_SESSION_PROPERTY = WsdlTestCase.class.getName() + "@keepSession";
70  	public final static String FAIL_ON_ERROR_PROPERTY = WsdlTestCase.class.getName() + "@failOnError";
71  	public final static String FAIL_ON_ERRORS_PROPERTY = WsdlTestCase.class.getName() + "@failOnErrors";
72  	public final static String DISCARD_OK_RESULTS = WsdlTestCase.class.getName() + "@discardOkResults";
73  	public final static String SETUP_SCRIPT_PROPERTY = WsdlTestCase.class.getName() + "@setupScript";
74  	public final static String TEARDOWN_SCRIPT_PROPERTY = WsdlTestCase.class.getName() + "@tearDownScript";
75  	public static final String TIMEOUT_PROPERTY = WsdlTestCase.class.getName() + "@timeout";
76  	public static final String SEARCH_PROPERTIES_PROPERTY = WsdlTestCase.class.getName() + "@searchProperties";
77  
78  	private final WsdlTestSuite testSuite;
79  	private List<WsdlTestStep> testSteps = new ArrayList<WsdlTestStep>();
80  	private List<WsdlLoadTest> loadTests = new ArrayList<WsdlLoadTest>();
81  	private Set<TestRunListener> testRunListeners = new HashSet<TestRunListener>();
82  	private DefaultActionList createActions;
83  	private final boolean forLoadTest;
84  	private SoapUIScriptEngine setupScriptEngine;
85  	private SoapUIScriptEngine tearDownScriptEngine;
86  	/***
87  	 * runFromHereContext is used only for run from here action
88  	 */
89  	private StringToObjectMap runFromHereContext = new StringToObjectMap();
90  	public WsdlTestCase( WsdlTestSuite testSuite, TestCaseConfig config, boolean forLoadTest )
91  	{
92  		super( config, testSuite, "/testCase.gif" );
93  
94  		this.testSuite = testSuite;
95  		this.forLoadTest = forLoadTest;
96  
97  		List<TestStepConfig> testStepConfigs = config.getTestStepList();
98  		List<TestStepConfig> removed = new ArrayList<TestStepConfig>();
99  		for( TestStepConfig tsc : testStepConfigs )
100 		{
101 			WsdlTestStep testStep = createTestStepFromConfig( tsc );
102 			if( testStep != null )
103 			{
104 				ensureUniqueName( testStep );
105 				testSteps.add( testStep );
106 			}
107 			else
108 			{
109 				removed.add( tsc );
110 			}
111 		}
112 
113 		if( removed.size() > 0 )
114 		{
115 			testStepConfigs.removeAll( removed );
116 		}
117 
118 		if( !forLoadTest )
119 		{
120 			List<LoadTestConfig> loadTestConfigs = config.getLoadTestList();
121 			for( LoadTestConfig tsc : loadTestConfigs )
122 			{
123 				WsdlLoadTest loadTest = buildLoadTest( tsc );
124 				loadTests.add( loadTest );
125 			}
126 		}
127 
128 		// init default configs
129 		if( !config.isSetFailOnError() )
130 			config.setFailOnError( true );
131 
132 		if( !config.isSetFailTestCaseOnErrors() )
133 			config.setFailTestCaseOnErrors( true );
134 
135 		if( !config.isSetKeepSession() )
136 			config.setKeepSession( false );
137 
138 		if( !config.isSetMaxResults() )
139 			config.setMaxResults( 0 );
140 
141 		for( TestRunListener listener : SoapUI.getListenerRegistry().getListeners( TestRunListener.class ) )
142 		{
143 			addTestRunListener( listener );
144 		}
145 
146 		if( !getConfig().isSetProperties() )
147 			getConfig().addNewProperties();
148 
149 		setPropertiesConfig( getConfig().getProperties() );
150 
151 		WsrmTestRunListener wsrmListener = new WsrmTestRunListener();
152 
153 		addTestRunListener( wsrmListener );
154 		addTestRunListener( new AMFTestRunListener() );
155 	}
156 
157 	public boolean isForLoadTest()
158 	{
159 		return forLoadTest;
160 	}
161 
162 	public WsdlLoadTest buildLoadTest( LoadTestConfig tsc )
163 	{
164 		return new WsdlLoadTest( this, tsc );
165 	}
166 
167 	public boolean getKeepSession()
168 	{
169 		return getConfig().getKeepSession();
170 	}
171 
172 	public void setKeepSession( boolean keepSession )
173 	{
174 		boolean old = getKeepSession();
175 		if( old != keepSession )
176 		{
177 			getConfig().setKeepSession( keepSession );
178 			notifyPropertyChanged( KEEP_SESSION_PROPERTY, old, keepSession );
179 		}
180 	}
181 
182 	public void setSetupScript( String script )
183 	{
184 		String oldScript = getSetupScript();
185 
186 		if( !getConfig().isSetSetupScript() )
187 			getConfig().addNewSetupScript();
188 
189 		getConfig().getSetupScript().setStringValue( script );
190 		if( setupScriptEngine != null )
191 			setupScriptEngine.setScript( script );
192 
193 		notifyPropertyChanged( SETUP_SCRIPT_PROPERTY, oldScript, script );
194 	}
195 
196 	public String getSetupScript()
197 	{
198 		return getConfig().isSetSetupScript() ? getConfig().getSetupScript().getStringValue() : null;
199 	}
200 
201 	public void setTearDownScript( String script )
202 	{
203 		String oldScript = getTearDownScript();
204 
205 		if( !getConfig().isSetTearDownScript() )
206 			getConfig().addNewTearDownScript();
207 
208 		getConfig().getTearDownScript().setStringValue( script );
209 		if( tearDownScriptEngine != null )
210 			tearDownScriptEngine.setScript( script );
211 
212 		notifyPropertyChanged( TEARDOWN_SCRIPT_PROPERTY, oldScript, script );
213 	}
214 
215 	public String getTearDownScript()
216 	{
217 		return getConfig().isSetTearDownScript() ? getConfig().getTearDownScript().getStringValue() : null;
218 	}
219 
220 	public boolean getFailOnError()
221 	{
222 		return getConfig().getFailOnError();
223 	}
224 
225 	public boolean getFailTestCaseOnErrors()
226 	{
227 		return getConfig().getFailTestCaseOnErrors();
228 	}
229 
230 	public void setFailOnError( boolean failOnError )
231 	{
232 		boolean old = getFailOnError();
233 		if( old != failOnError )
234 		{
235 			getConfig().setFailOnError( failOnError );
236 			notifyPropertyChanged( FAIL_ON_ERROR_PROPERTY, old, failOnError );
237 		}
238 	}
239 
240 	public void setFailTestCaseOnErrors( boolean failTestCaseOnErrors )
241 	{
242 		boolean old = getFailTestCaseOnErrors();
243 		if( old != failTestCaseOnErrors )
244 		{
245 			getConfig().setFailTestCaseOnErrors( failTestCaseOnErrors );
246 			notifyPropertyChanged( FAIL_ON_ERRORS_PROPERTY, old, failTestCaseOnErrors );
247 		}
248 	}
249 
250 	public boolean getSearchProperties()
251 	{
252 		return getConfig().getSearchProperties();
253 	}
254 
255 	public void setSearchProperties( boolean searchProperties )
256 	{
257 		boolean old = getSearchProperties();
258 		if( old != searchProperties )
259 		{
260 			getConfig().setSearchProperties( searchProperties );
261 			notifyPropertyChanged( SEARCH_PROPERTIES_PROPERTY, old, searchProperties );
262 		}
263 	}
264 
265 	public boolean getDiscardOkResults()
266 	{
267 		return getConfig().getDiscardOkResults();
268 	}
269 
270 	public void setDiscardOkResults( boolean discardOkResults )
271 	{
272 		boolean old = getDiscardOkResults();
273 		if( old != discardOkResults )
274 		{
275 			getConfig().setDiscardOkResults( discardOkResults );
276 			notifyPropertyChanged( DISCARD_OK_RESULTS, old, discardOkResults );
277 		}
278 	}
279 
280 	public int getMaxResults()
281 	{
282 		return getConfig().getMaxResults();
283 	}
284 
285 	public void setMaxResults( int maxResults )
286 	{
287 		int old = getMaxResults();
288 		if( old != maxResults )
289 		{
290 			getConfig().setMaxResults( maxResults );
291 			notifyPropertyChanged( "maxResults", old, maxResults );
292 		}
293 	}
294 
295 	private WsdlTestStep createTestStepFromConfig( TestStepConfig tsc )
296 	{
297 		WsdlTestStepFactory factory = WsdlTestStepRegistry.getInstance().getFactory( tsc.getType() );
298 		if( factory != null )
299 		{
300 			WsdlTestStep testStep = factory.buildTestStep( this, tsc, forLoadTest );
301 			return testStep;
302 		}
303 		else
304 		{
305 			logger.error( "Failed to create test step for [" + tsc.getName() + "]" );
306 			return null;
307 		}
308 	}
309 
310 	private boolean ensureUniqueName( WsdlTestStep testStep )
311 	{
312 		String name = testStep.getName();
313 		while( name == null || getTestStepByName( name.trim() ) != null )
314 		{
315 			if( name == null )
316 				name = testStep.getName();
317 			else
318 			{
319 				int cnt = 0;
320 
321 				while( getTestStepByName( name.trim() ) != null )
322 				{
323 					cnt++ ;
324 					name = testStep.getName() + " " + cnt;
325 				}
326 
327 				if( cnt == 0 )
328 					break;
329 			}
330 
331 			name = UISupport.prompt( "TestStep name must be unique, please specify new name for step\n" + "["
332 					+ testStep.getName() + "] in TestCase [" + getTestSuite().getProject().getName() + "->"
333 					+ getTestSuite().getName() + "->" + getName() + "]", "Change TestStep name", name );
334 
335 			if( name == null )
336 				return false;
337 		}
338 
339 		if( !name.equals( testStep.getName() ) )
340 			testStep.setName( name );
341 
342 		return true;
343 	}
344 
345 	public WsdlLoadTest addNewLoadTest( String name )
346 	{
347 		WsdlLoadTest loadTest = buildLoadTest( getConfig().addNewLoadTest() );
348 		loadTest.setStartDelay( 0 );
349 		loadTest.setName( name );
350 		loadTests.add( loadTest );
351 
352 		loadTest.addAssertion( TestStepStatusAssertion.STEP_STATUS_TYPE, LoadTestAssertion.ANY_TEST_STEP, false );
353 
354 		( getTestSuite() ).fireLoadTestAdded( loadTest );
355 
356 		return loadTest;
357 	}
358 
359 	public void removeLoadTest( WsdlLoadTest loadTest )
360 	{
361 		int ix = loadTests.indexOf( loadTest );
362 
363 		loadTests.remove( ix );
364 
365 		try
366 		{
367 			( getTestSuite() ).fireLoadTestRemoved( loadTest );
368 		}
369 		finally
370 		{
371 			loadTest.release();
372 			getConfig().removeLoadTest( ix );
373 		}
374 	}
375 
376 	public WsdlTestSuite getTestSuite()
377 	{
378 		return testSuite;
379 	}
380 
381 	public WsdlTestStep cloneStep( WsdlTestStep testStep, String name )
382 	{
383 		return testStep.clone( this, name );
384 	}
385 
386 	public WsdlTestStep getTestStepAt( int index )
387 	{
388 		return testSteps.get( index );
389 	}
390 
391 	public int getTestStepCount()
392 	{
393 		return testSteps.size();
394 	}
395 
396 	public WsdlLoadTest getLoadTestAt( int index )
397 	{
398 		return loadTests.get( index );
399 	}
400 
401 	public LoadTest getLoadTestByName( String loadTestName )
402 	{
403 		return ( LoadTest )getWsdlModelItemByName( loadTests, loadTestName );
404 	}
405 
406 	public int getLoadTestCount()
407 	{
408 		return loadTests.size();
409 	}
410 
411 	public WsdlTestStep addTestStep( TestStepConfig stepConfig )
412 	{
413 		return insertTestStep( stepConfig, -1, true );
414 	}
415 
416 	public WsdlTestStep addTestStep( String type, String name )
417 	{
418 		TestStepConfig newStepConfig = WsdlTestStepRegistry.getInstance().getFactory( type ).createNewTestStep( this,
419 				name );
420 		if( newStepConfig != null )
421 		{
422 			return addTestStep( newStepConfig );
423 		}
424 		else
425 			return null;
426 	}
427 
428 	public WsdlTestStep addTestStep( String type, String name, String endpoint, String method )
429 	{
430 		TestStepConfig newStepConfig = ( ( HttpRequestStepFactory )WsdlTestStepRegistry.getInstance().getFactory( type ) )
431 				.createNewTestStep( this, name, endpoint, method );
432 		if( newStepConfig != null )
433 		{
434 			return addTestStep( newStepConfig );
435 		}
436 		else
437 			return null;
438 	}
439 
440 	public WsdlTestStep insertTestStep( String type, String name, int index )
441 	{
442 		TestStepConfig newStepConfig = WsdlTestStepRegistry.getInstance().getFactory( type ).createNewTestStep( this,
443 				name );
444 		if( newStepConfig != null )
445 		{
446 			return insertTestStep( newStepConfig, index, false );
447 		}
448 		else
449 			return null;
450 	}
451 
452 	public WsdlTestStep importTestStep( WsdlTestStep testStep, String name, int index, boolean createCopy )
453 	{
454 		testStep.beforeSave();
455 		TestStepConfig newStepConfig = ( TestStepConfig )testStep.getConfig().copy();
456 		newStepConfig.setName( name );
457 
458 		WsdlTestStep result = insertTestStep( newStepConfig, index, createCopy );
459 		if( result == null )
460 			return null;
461 
462 		if( createCopy )
463 			ModelSupport.unsetIds( result );
464 
465 		resolveTestCase();
466 		return result;
467 	}
468 
469 	private void resolveTestCase()
470 	{
471 		ResolveDialog resolver = new ResolveDialog( "Validate TestCase", "Checks TestCase for inconsistencies", null );
472 		resolver.setShowOkMessage( false );
473 		resolver.resolve( this );
474 	}
475 
476 	public WsdlTestStep[] importTestSteps( WsdlTestStep[] testSteps, int index, boolean createCopies )
477 	{
478 		TestStepConfig[] newStepConfigs = new TestStepConfig[testSteps.length];
479 
480 		for( int c = 0; c < testSteps.length; c++ )
481 		{
482 			testSteps[c].beforeSave();
483 			newStepConfigs[c] = ( TestStepConfig )testSteps[c].getConfig().copy();
484 		}
485 
486 		WsdlTestStep[] result = insertTestSteps( newStepConfigs, index, createCopies );
487 
488 		resolveTestCase();
489 		return result;
490 	}
491 
492 	public WsdlTestStep insertTestStep( TestStepConfig stepConfig, int ix )
493 	{
494 		return insertTestStep( stepConfig, ix, true );
495 	}
496 
497 	public WsdlTestStep insertTestStep( TestStepConfig stepConfig, int ix, boolean clearIds )
498 	{
499 		TestStepConfig newStepConfig = ix == -1 ? getConfig().addNewTestStep() : getConfig().insertNewTestStep( ix );
500 		newStepConfig.set( stepConfig );
501 		WsdlTestStep testStep = createTestStepFromConfig( newStepConfig );
502 
503 		if( !ensureUniqueName( testStep ) )
504 		{
505 			testStep.release();
506 			getConfig().getTestStepList().remove( newStepConfig );
507 			return null;
508 		}
509 
510 		if( clearIds )
511 			ModelSupport.unsetIds( testStep );
512 
513 		if( ix == -1 )
514 			testSteps.add( testStep );
515 		else
516 			testSteps.add( ix, testStep );
517 
518 		testStep.afterLoad();
519 
520 		if( getTestSuite() != null )
521 			( getTestSuite() ).fireTestStepAdded( testStep, ix == -1 ? testSteps.size() - 1 : ix );
522 
523 		notifyPropertyChanged( "testSteps", null, testStep );
524 
525 		return testStep;
526 	}
527 
528 	public WsdlTestStep[] insertTestSteps( TestStepConfig[] stepConfig, int ix, boolean clearIds )
529 	{
530 		WsdlTestStep[] result = new WsdlTestStep[stepConfig.length];
531 
532 		for( int c = 0; c < stepConfig.length; c++ )
533 		{
534 			TestStepConfig newStepConfig = ix == -1 ? getConfig().addNewTestStep() : getConfig()
535 					.insertNewTestStep( ix + c );
536 			newStepConfig.set( stepConfig[c] );
537 			WsdlTestStep testStep = createTestStepFromConfig( newStepConfig );
538 
539 			if( !ensureUniqueName( testStep ) )
540 				return null;
541 
542 			if( clearIds )
543 				ModelSupport.unsetIds( testStep );
544 
545 			if( ix == -1 )
546 				testSteps.add( testStep );
547 			else
548 				testSteps.add( ix + c, testStep );
549 
550 			result[c] = testStep;
551 		}
552 
553 		for( int c = 0; c < result.length; c++ )
554 		{
555 			result[c].afterLoad();
556 
557 			if( getTestSuite() != null )
558 				( getTestSuite() ).fireTestStepAdded( result[c], getIndexOfTestStep( result[c] ) );
559 
560 			notifyPropertyChanged( "testSteps", null, result[c] );
561 		}
562 
563 		return result;
564 	}
565 
566 	public void removeTestStep( WsdlTestStep testStep )
567 	{
568 		int ix = testSteps.indexOf( testStep );
569 		if( ix == -1 )
570 		{
571 			logger.error( "TestStep [" + testStep.getName() + "] passed to removeTestStep in testCase [" + getName()
572 					+ "] not found" );
573 			return;
574 		}
575 
576 		testSteps.remove( ix );
577 
578 		try
579 		{
580 			( getTestSuite() ).fireTestStepRemoved( testStep, ix );
581 		}
582 		finally
583 		{
584 			notifyPropertyChanged( "testSteps", testStep, null );
585 
586 			testStep.release();
587 
588 			for( int c = 0; c < getConfig().sizeOfTestStepArray(); c++ )
589 			{
590 				if( testStep.getConfig() == getConfig().getTestStepArray( c ) )
591 				{
592 					getConfig().removeTestStep( c );
593 					break;
594 				}
595 			}
596 		}
597 	}
598 
599 	public WsdlTestCaseRunner run( StringToObjectMap properties, boolean async )
600 	{
601 		WsdlTestCaseRunner runner = new WsdlTestCaseRunner( this, properties );
602 		runner.start( async );
603 		return runner;
604 	}
605 
606 	public void addTestRunListener( TestRunListener listener )
607 	{
608 		if( listener == null )
609 			throw new RuntimeException( "listener must not be null" );
610 
611 		testRunListeners.add( listener );
612 	}
613 
614 	public void removeTestRunListener( TestRunListener listener )
615 	{
616 		testRunListeners.remove( listener );
617 	}
618 
619 	public TestRunListener[] getTestRunListeners()
620 	{
621 		return testRunListeners.toArray( new TestRunListener[testRunListeners.size()] );
622 	}
623 
624 	public Map<String, TestStep> getTestSteps()
625 	{
626 		Map<String, TestStep> result = new HashMap<String, TestStep>();
627 		for( TestStep testStep : testSteps )
628 			result.put( testStep.getName(), testStep );
629 
630 		return result;
631 	}
632 
633 	public Map<String, LoadTest> getLoadTests()
634 	{
635 		Map<String, LoadTest> result = new HashMap<String, LoadTest>();
636 		for( LoadTest loadTest : loadTests )
637 			result.put( loadTest.getName(), loadTest );
638 
639 		return result;
640 	}
641 
642 	public int getIndexOfTestStep( TestStep step )
643 	{
644 		return testSteps.indexOf( step );
645 	}
646 
647 	/***
648 	 * Moves a step by the specified offset, a bit awkward since xmlbeans doesn't
649 	 * support reordering of arrays, we need to create copies of the contained
650 	 * XmlObjects
651 	 * 
652 	 * @param ix
653 	 * @param offset
654 	 */
655 
656 	public void moveTestStep( int ix, int offset )
657 	{
658 		if( offset == 0 )
659 			return;
660 		WsdlTestStep step = testSteps.get( ix );
661 
662 		if( ix + offset >= testSteps.size() )
663 			offset = testSteps.size() - ix - 1;
664 
665 		testSteps.remove( ix );
666 		testSteps.add( ix + offset, step );
667 
668 		TestStepConfig[] configs = new TestStepConfig[testSteps.size()];
669 
670 		TestCaseConfig conf = getConfig();
671 		for( int c = 0; c < testSteps.size(); c++ )
672 		{
673 			if( offset > 0 )
674 			{
675 				if( c < ix )
676 					configs[c] = ( TestStepConfig )conf.getTestStepArray( c ).copy();
677 				else if( c < ( ix + offset ) )
678 					configs[c] = ( TestStepConfig )conf.getTestStepArray( c + 1 ).copy();
679 				else if( c == ix + offset )
680 					configs[c] = ( TestStepConfig )conf.getTestStepArray( ix ).copy();
681 				else
682 					configs[c] = ( TestStepConfig )conf.getTestStepArray( c ).copy();
683 			}
684 			else
685 			{
686 				if( c < ix + offset )
687 					configs[c] = ( TestStepConfig )conf.getTestStepArray( c ).copy();
688 				else if( c == ix + offset )
689 					configs[c] = ( TestStepConfig )conf.getTestStepArray( ix ).copy();
690 				else if( c <= ix )
691 					configs[c] = ( TestStepConfig )conf.getTestStepArray( c - 1 ).copy();
692 				else
693 					configs[c] = ( TestStepConfig )conf.getTestStepArray( c ).copy();
694 			}
695 		}
696 
697 		conf.setTestStepArray( configs );
698 		for( int c = 0; c < configs.length; c++ )
699 		{
700 			( testSteps.get( c ) ).resetConfigOnMove( conf.getTestStepArray( c ) );
701 		}
702 
703 		( getTestSuite() ).fireTestStepMoved( step, ix, offset );
704 	}
705 
706 	public int getIndexOfLoadTest( LoadTest loadTest )
707 	{
708 		return loadTests.indexOf( loadTest );
709 	}
710 
711 	public int getTestStepIndexByName( String stepName )
712 	{
713 		for( int c = 0; c < testSteps.size(); c++ )
714 		{
715 			if( testSteps.get( c ).getName().equals( stepName ) )
716 				return c;
717 		}
718 
719 		return -1;
720 	}
721 
722 	@SuppressWarnings( "unchecked" )
723 	public <T extends TestStep> T findPreviousStepOfType( TestStep referenceStep, Class<T> stepClass )
724 	{
725 		int currentStepIndex = getIndexOfTestStep( referenceStep );
726 		int ix = currentStepIndex - 1;
727 		while( ix >= 0 && !stepClass.isAssignableFrom( getTestStepAt( ix ).getClass() ) )
728 		{
729 			ix-- ;
730 		}
731 
732 		return ( T )( ix < 0 ? null : getTestStepAt( ix ) );
733 	}
734 
735 	@SuppressWarnings( "unchecked" )
736 	public <T extends TestStep> T findNextStepOfType( TestStep referenceStep, Class<T> stepClass )
737 	{
738 		int currentStepIndex = getIndexOfTestStep( referenceStep );
739 		int ix = currentStepIndex + 1;
740 		while( ix < getTestStepCount() && !stepClass.isAssignableFrom( getTestStepAt( ix ).getClass() ) )
741 		{
742 			ix++ ;
743 		}
744 
745 		return ( T )( ix >= getTestStepCount() ? null : getTestStepAt( ix ) );
746 	}
747 
748 	public List<TestStep> getTestStepList()
749 	{
750 		List<TestStep> result = new ArrayList<TestStep>();
751 		for( TestStep step : testSteps )
752 			result.add( step );
753 
754 		return result;
755 	}
756 
757 	@SuppressWarnings( "unchecked" )
758 	public <T extends TestStep> List<T> getTestStepsOfType( Class<T> stepType )
759 	{
760 		List<T> result = new ArrayList<T>();
761 		for( TestStep step : testSteps )
762 			if( step.getClass().isAssignableFrom( stepType ) )
763 				result.add( ( T )step );
764 
765 		return result;
766 	}
767 
768 	public WsdlTestStep getTestStepByName( String stepName )
769 	{
770 		return ( WsdlTestStep )getWsdlModelItemByName( testSteps, stepName );
771 	}
772 
773 	public WsdlLoadTest cloneLoadTest( WsdlLoadTest loadTest, String name )
774 	{
775 		loadTest.beforeSave();
776 
777 		LoadTestConfig loadTestConfig = getConfig().addNewLoadTest();
778 		loadTestConfig.set( loadTest.getConfig().copy() );
779 
780 		WsdlLoadTest newLoadTest = buildLoadTest( loadTestConfig );
781 		newLoadTest.setName( name );
782 		ModelSupport.unsetIds( newLoadTest );
783 		newLoadTest.afterLoad();
784 		loadTests.add( newLoadTest );
785 
786 		( getTestSuite() ).fireLoadTestAdded( newLoadTest );
787 
788 		return newLoadTest;
789 	}
790 
791 	@Override
792 	public void release()
793 	{
794 		super.release();
795 
796 		for( WsdlTestStep testStep : testSteps )
797 			testStep.release();
798 
799 		for( WsdlLoadTest loadTest : loadTests )
800 			loadTest.release();
801 
802 		testRunListeners.clear();
803 
804 		if( setupScriptEngine != null )
805 			setupScriptEngine.release();
806 
807 		if( tearDownScriptEngine != null )
808 			tearDownScriptEngine.release();
809 	}
810 
811 	public ActionList getCreateActions()
812 	{
813 		return createActions;
814 	}
815 
816 	public void resetConfigOnMove( TestCaseConfig testCaseConfig )
817 	{
818 		setConfig( testCaseConfig );
819 		int mod = 0;
820 
821 		List<TestStepConfig> configs = getConfig().getTestStepList();
822 		for( int c = 0; c < configs.size(); c++ )
823 		{
824 			if( WsdlTestStepRegistry.getInstance().hasFactory( configs.get( c ) ) )
825 			{
826 				( testSteps.get( c - mod ) ).resetConfigOnMove( configs.get( c ) );
827 			}
828 			else
829 				mod++ ;
830 		}
831 
832 		List<LoadTestConfig> loadTestConfigs = getConfig().getLoadTestList();
833 		for( int c = 0; c < loadTestConfigs.size(); c++ )
834 		{
835 			loadTests.get( c ).resetConfigOnMove( loadTestConfigs.get( c ) );
836 		}
837 
838 		setPropertiesConfig( testCaseConfig.getProperties() );
839 	}
840 
841 	public List<LoadTest> getLoadTestList()
842 	{
843 		List<LoadTest> result = new ArrayList<LoadTest>();
844 		for( LoadTest loadTest : loadTests )
845 			result.add( loadTest );
846 
847 		return result;
848 	}
849 
850 	public Object runSetupScript( TestCaseRunContext runContext, TestCaseRunner runner ) throws Exception
851 	{
852 		String script = getSetupScript();
853 		if( StringUtils.isNullOrEmpty( script ) )
854 			return null;
855 
856 		if( setupScriptEngine == null )
857 		{
858 			setupScriptEngine = SoapUIScriptEngineRegistry.create( this );
859 			setupScriptEngine.setScript( script );
860 		}
861 
862 		setupScriptEngine.setVariable( "testCase", this );
863 		setupScriptEngine.setVariable( "context", runContext );
864 		setupScriptEngine.setVariable( "testRunner", runner );
865 		setupScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
866 		return setupScriptEngine.run();
867 	}
868 
869 	public Object runTearDownScript( TestCaseRunContext runContext, TestCaseRunner runner ) throws Exception
870 	{
871 		String script = getTearDownScript();
872 		if( StringUtils.isNullOrEmpty( script ) )
873 			return null;
874 
875 		if( tearDownScriptEngine == null )
876 		{
877 			tearDownScriptEngine = SoapUIScriptEngineRegistry.create( this );
878 			tearDownScriptEngine.setScript( script );
879 		}
880 
881 		tearDownScriptEngine.setVariable( "context", runContext );
882 		tearDownScriptEngine.setVariable( "testCase", this );
883 		tearDownScriptEngine.setVariable( "testRunner", runner );
884 		tearDownScriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
885 		return tearDownScriptEngine.run();
886 	}
887 
888 	public List<? extends ModelItem> getChildren()
889 	{
890 		List<ModelItem> result = new ArrayList<ModelItem>();
891 		result.addAll( getTestStepList() );
892 		result.addAll( getLoadTestList() );
893 		return result;
894 	}
895 
896 	@Override
897 	public void setName( String name )
898 	{
899 		String oldLabel = getLabel();
900 
901 		super.setName( name );
902 
903 		String label = getLabel();
904 		if( oldLabel != null && !oldLabel.equals( label ) )
905 		{
906 			notifyPropertyChanged( LABEL_PROPERTY, oldLabel, label );
907 		}
908 	}
909 
910 	public String getLabel()
911 	{
912 		String name = getName();
913 		if( isDisabled() )
914 			return name + " (disabled)";
915 		else
916 			return name;
917 	}
918 
919 	public boolean isDisabled()
920 	{
921 		return getConfig().getDisabled();
922 	}
923 
924 	public void setDisabled( boolean disabled )
925 	{
926 		String oldLabel = getLabel();
927 
928 		boolean oldDisabled = isDisabled();
929 		if( oldDisabled == disabled )
930 			return;
931 
932 		if( disabled )
933 			getConfig().setDisabled( disabled );
934 		else if( getConfig().isSetDisabled() )
935 			getConfig().unsetDisabled();
936 
937 		notifyPropertyChanged( DISABLED_PROPERTY, oldDisabled, disabled );
938 
939 		String label = getLabel();
940 		if( !oldLabel.equals( label ) )
941 			notifyPropertyChanged( LABEL_PROPERTY, oldLabel, label );
942 	}
943 
944 	public long getTimeout()
945 	{
946 		return getConfig().getTimeout();
947 	}
948 
949 	public void setTimeout( long timeout )
950 	{
951 		long old = getTimeout();
952 		getConfig().setTimeout( timeout );
953 		notifyPropertyChanged( TIMEOUT_PROPERTY, old, timeout );
954 	}
955 
956 	public void exportTestCase( File file )
957 	{
958 		try
959 		{
960 			this.getConfig().newCursor().save( file );
961 		}
962 		catch( IOException e )
963 		{
964 			e.printStackTrace();
965 		}
966 	}
967 
968 	public void afterCopy( WsdlTestSuite oldTestSuite, WsdlTestCase oldTestCase )
969 	{
970 		for( WsdlTestStep testStep : testSteps )
971 			testStep.afterCopy( oldTestSuite, oldTestCase );
972 	}
973 
974 	public void setWsrmEnabled( boolean enabled )
975 	{
976 		getConfig().setWsrmEnabled( enabled );
977 	}
978 
979 	public void setWsrmAckTo( String ackTo )
980 	{
981 		getConfig().setWsrmAckTo( ackTo );
982 	}
983 
984 	public void setWsrmExpires( Long expires )
985 	{
986 		getConfig().setWsrmExpires( expires );
987 	}
988 
989 	public void setWsrmVersion( String version )
990 	{
991 		getConfig().setWsrmVersion( WsrmVersionTypeConfig.Enum.forString( version ) );
992 	}
993 
994 	public boolean getWsrmEnabled()
995 	{
996 		return getConfig().getWsrmEnabled();
997 	}
998 
999 	public String getWsrmAckTo()
1000 	{
1001 		return getConfig().getWsrmAckTo();
1002 	}
1003 
1004 	public long getWsrmExpires()
1005 	{
1006 		return getConfig().getWsrmExpires();
1007 	}
1008 
1009 	public String getWsrmVersion()
1010 	{
1011 		if( getConfig().getWsrmVersion() == null )
1012 			return WsrmVersionTypeConfig.X_1_0.toString();
1013 		return getConfig().getWsrmVersion().toString();
1014 	}
1015 
1016 	public String getWsrmVersionNamespace()
1017 	{
1018 		return WsrmUtils.getWsrmVersionNamespace( getConfig().getWsrmVersion() );
1019 	}
1020 
1021 	public void setAmfAuthorisation( boolean enabled )
1022 	{
1023 		getConfig().setAmfAuthorisation( enabled );
1024 	}
1025 
1026 	public boolean getAmfAuthorisation()
1027 	{
1028 		return getConfig().getAmfAuthorisation();
1029 	}
1030 
1031 	public void setAmfLogin( String login )
1032 	{
1033 		getConfig().setAmfLogin( login );
1034 	}
1035 
1036 	public String getAmfLogin()
1037 	{
1038 		if( getConfig().getAmfLogin() == null )
1039 			return "";
1040 		else
1041 			return getConfig().getAmfLogin();
1042 	}
1043 
1044 	public void setAmfPassword( String password )
1045 	{
1046 		getConfig().setAmfPassword( password );
1047 	}
1048 
1049 	public String getAmfPassword()
1050 	{
1051 		if( getConfig().getAmfPassword() == null )
1052 			return "";
1053 		else
1054 			return getConfig().getAmfPassword();
1055 	}
1056 
1057 	public void setAmfEndpoint( String endpoint )
1058 	{
1059 		getConfig().setAmfEndpoint( endpoint );
1060 	}
1061 
1062 	public String getAmfEndpoint()
1063 	{
1064 		if( getConfig().getAmfEndpoint() == null )
1065 			return "";
1066 		else
1067 			return getConfig().getAmfEndpoint();
1068 	}
1069 
1070 	
1071 	public StringToObjectMap getRunFromHereContext()
1072 	{
1073 		return runFromHereContext;
1074 	}
1075 
1076 	public void setRunFromHereContext( StringToObjectMap runFromHereContext )
1077 	{
1078 		this.runFromHereContext = new StringToObjectMap(runFromHereContext);
1079 	}
1080 }