/*
* soapUI, copyright (C) 2004-2011 eviware.com
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui.impl.wsdl.teststeps;
import java.util.ArrayList;
import java.util.List;
import javax.swing.SwingUtilities;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.TestStepConfig;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
import com.eviware.soapui.model.support.DefaultTestStepProperty;
import com.eviware.soapui.model.testsuite.TestCaseRunContext;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestStepResult;
import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.xml.XmlObjectConfigurationBuilder;
import com.eviware.soapui.support.xml.XmlObjectConfigurationReader;
/**
* TestStep that delays execution for a number of milliseconds
*
* @author ole.matzura
*/
public class WsdlDelayTestStep extends WsdlTestStepWithProperties implements PropertyExpansionContainer
{
private static final String DEFAULT_DELAY = "1000";
private static final int DELAY_CHUNK = 100;
private int delay = 0;
private String delayString = WsdlDelayTestStep.DEFAULT_DELAY;
private int timeWaited = 0;
private boolean canceled;
private boolean running;
public WsdlDelayTestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
{
super( testCase, config, false, forLoadTest );
if( !forLoadTest )
{
setIcon( UISupport.createImageIcon( "/wait.gif" ) );
}
if( config.getConfig() == null )
{
if( !forLoadTest )
saveDelay( config );
}
else
{
readConfig( config );
}
addProperty( new DefaultTestStepProperty( "delay", true, new DefaultTestStepProperty.PropertyHandlerAdapter()
{
@Override
public String getValue( DefaultTestStepProperty property )
{
return getDelayString();
}
@Override
public void setValue( DefaultTestStepProperty property, String value )
{
setDelayString( value );
}
}, this ) );
}
private void readConfig( TestStepConfig config )
{
XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader( config.getConfig() );
delayString = reader.readString( "delay", DEFAULT_DELAY );
}
@Override
public String getLabel()
{
String str = running ? super.getName() + " [" + ( delay - timeWaited ) + "ms]" : super.getName() + " ["
+ delayString + "]";
if( isDisabled() )
str += " (disabled)";
return str;
}
@Override
public String getDefaultSourcePropertyName()
{
return "delay";
}
@Override
public String getDefaultTargetPropertyName()
{
return "delay";
}
public PropertyExpansion[] getPropertyExpansions()
{
List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
result.addAll( PropertyExpansionUtils.extractPropertyExpansions( this, this, "delayString" ) );
return result.toArray( new PropertyExpansion[result.size()] );
}
private void saveDelay( TestStepConfig config )
{
XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
builder.add( "delay", delayString );
config.setConfig( builder.finish() );
}
@Override
public void resetConfigOnMove( TestStepConfig config )
{
super.resetConfigOnMove( config );
readConfig( config );
}
public void setDelayString( String delayString )
{
if( this.delayString.equals( delayString ) )
return;
String oldLabel = getLabel();
this.delayString = delayString;
saveDelay( getConfig() );
notifyPropertyChanged( WsdlTestStep.LABEL_PROPERTY, oldLabel, getLabel() );
}
public String getDelayString()
{
return delayString;
}
public int getDelay()
{
try
{
return Integer.parseInt( PropertyExpander.expandProperties( this, delayString ) );
}
catch( NumberFormatException e )
{
return -1;
}
}
public void setDelay( int delay )
{
String oldLabel = getLabel();
this.delayString = String.valueOf( delay );
saveDelay( getConfig() );
notifyPropertyChanged( WsdlTestStep.LABEL_PROPERTY, oldLabel, getLabel() );
}
public TestStepResult run( TestCaseRunner testRunner, TestCaseRunContext context )
{
WsdlTestStepResult result = new WsdlTestStepResult( this );
result.startTimer();
String oldLabel = getLabel();
try
{
canceled = false;
running = true;
try
{
delay = Integer.parseInt( PropertyExpander.expandProperties( context, delayString ) );
}
catch( NumberFormatException e )
{
delay = Integer.parseInt( DEFAULT_DELAY );
}
// sleep in chunks for canceling
final long stopTime = System.currentTimeMillis() + delay;
int lastUpdate = 0;
while( !canceled && timeWaited < delay )
{
if( timeWaited - lastUpdate > 1000 && context.getProperty( TestCaseRunContext.LOAD_TEST_RUNNER ) == null )
{
String newLabel = getLabel();
if( !UISupport.isHeadless() )
{
final String finalOldLabel = oldLabel, finalNewLabel = newLabel;
SwingUtilities.invokeLater( new Runnable()
{
public void run()
{
notifyPropertyChanged( WsdlTestStep.LABEL_PROPERTY, finalOldLabel, finalNewLabel );
}
} );
}
oldLabel = newLabel;
lastUpdate = timeWaited;
}
Thread.sleep( Math.min( DELAY_CHUNK, delay - timeWaited ) );
timeWaited = delay - ( int )( ( stopTime - System.currentTimeMillis() ) );
}
}
catch( InterruptedException e )
{
SoapUI.logError( e );
}
result.stopTimer();
result.setStatus( canceled ? TestStepStatus.CANCELED : TestStepStatus.OK );
timeWaited = 0;
running = false;
if( context.getProperty( TestCaseRunContext.LOAD_TEST_RUNNER ) == null )
notifyPropertyChanged( WsdlTestStep.LABEL_PROPERTY, oldLabel, getLabel() );
return result;
}
@Override
public boolean cancel()
{
canceled = true;
return true;
}
}