/*
* 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.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.ImageIcon;
import org.apache.log4j.Logger;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.AMFRequestTestStepConfig;
import com.eviware.soapui.config.TestAssertionConfig;
import com.eviware.soapui.config.TestStepConfig;
import com.eviware.soapui.impl.wsdl.MutableTestPropertyHolder;
import com.eviware.soapui.impl.wsdl.panels.teststeps.amf.AMFRequest;
import com.eviware.soapui.impl.wsdl.panels.teststeps.amf.AMFResponse;
import com.eviware.soapui.impl.wsdl.panels.teststeps.amf.AMFSubmit;
import com.eviware.soapui.impl.wsdl.support.AMFMessageExchange;
import com.eviware.soapui.impl.wsdl.support.XmlBeansPropertiesTestPropertyHolder;
import com.eviware.soapui.impl.wsdl.support.assertions.AssertableConfig;
import com.eviware.soapui.impl.wsdl.support.assertions.AssertedXPathsContainer;
import com.eviware.soapui.impl.wsdl.support.assertions.AssertionsSupport;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestRunContext;
import com.eviware.soapui.impl.wsdl.teststeps.assertions.TestAssertionRegistry.AssertableType;
import com.eviware.soapui.model.iface.Interface;
import com.eviware.soapui.model.iface.Request.SubmitException;
import com.eviware.soapui.model.iface.Submit;
import com.eviware.soapui.model.iface.SubmitContext;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
import com.eviware.soapui.model.support.TestStepBeanProperty;
import com.eviware.soapui.model.testsuite.Assertable;
import com.eviware.soapui.model.testsuite.AssertionError;
import com.eviware.soapui.model.testsuite.AssertionsListener;
import com.eviware.soapui.model.testsuite.SamplerTestStep;
import com.eviware.soapui.model.testsuite.TestAssertion;
import com.eviware.soapui.model.testsuite.TestCaseRunContext;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestProperty;
import com.eviware.soapui.model.testsuite.TestPropertyListener;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.model.testsuite.TestStepResult;
import com.eviware.soapui.model.testsuite.TestStepResult.TestStepStatus;
import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
import com.eviware.soapui.support.types.StringToStringMap;
import com.eviware.soapui.support.types.StringToStringsMap;
/**
*
* @author nebojsa.tasic
*/
public class AMFRequestTestStep extends WsdlTestStepWithProperties implements Assertable, MutableTestPropertyHolder,
PropertyChangeListener, SamplerTestStep
{
@SuppressWarnings( "unused" )
private final static Logger log = Logger.getLogger( WsdlTestRequestStep.class );
protected AMFRequestTestStepConfig amfRequestTestStepConfig;
public final static String amfREQUEST = AMFRequestTestStep.class.getName() + "@amfrequest";
public static final String STATUS_PROPERTY = WsdlTestRequest.class.getName() + "@status";
public static final String RESPONSE_PROPERTY = "response";
public static final String REQUEST_PROPERTY = "request";
public static final String HTTP_HEADERS_PROPERTY = AMFRequest.class.getName() + "@request-headers";
public static final String AMF_HEADERS_PROPERTY = AMFRequest.class.getName() + "@amfrequest-amfheaders";
private AMFSubmit submit;
private SoapUIScriptEngine scriptEngine;
private AssertionsSupport assertionsSupport;
private PropertyChangeNotifier notifier;
private XmlBeansPropertiesTestPropertyHolder propertyHolderSupport;
private AMFRequest amfRequest;
public AMFRequestTestStep( WsdlTestCase testCase, TestStepConfig config, boolean forLoadTest )
{
super( testCase, config, true, forLoadTest );
if( getConfig().getConfig() != null )
{
amfRequestTestStepConfig = ( AMFRequestTestStepConfig )getConfig().getConfig().changeType(
AMFRequestTestStepConfig.type );
}
else
{
amfRequestTestStepConfig = ( AMFRequestTestStepConfig )getConfig().addNewConfig().changeType(
AMFRequestTestStepConfig.type );
}
if( amfRequestTestStepConfig.getProperties() == null )
amfRequestTestStepConfig.addNewProperties();
amfRequest = new AMFRequest( this, forLoadTest );
propertyHolderSupport = new XmlBeansPropertiesTestPropertyHolder( this, amfRequestTestStepConfig.getProperties() );
addResponseAsXmlVirtualProperty();
initAssertions();
scriptEngine = SoapUIScriptEngineRegistry.create( this );
scriptEngine.setScript( getScript() );
if( forLoadTest && !isDisabled() )
try
{
scriptEngine.compile();
}
catch( Exception e )
{
SoapUI.logError( e );
}
}
private void addResponseAsXmlVirtualProperty()
{
TestStepBeanProperty responseProperty = new TestStepBeanProperty( WsdlTestStepWithProperties.RESPONSE_AS_XML,
false, amfRequest, "responseContent", this )
{
@Override
public String getDefaultValue()
{
return "";
}
};
propertyHolderSupport.addVirtualProperty( WsdlTestStepWithProperties.RESPONSE_AS_XML, responseProperty );
}
public AMFRequestTestStepConfig getAMFRequestTestStepConfig()
{
return amfRequestTestStepConfig;
}
@Override
public WsdlTestStep clone( WsdlTestCase targetTestCase, String name )
{
beforeSave();
TestStepConfig config = ( TestStepConfig )getConfig().copy();
AMFRequestTestStep result = ( AMFRequestTestStep )targetTestCase.addTestStep( config );
return result;
}
@Override
public void release()
{
super.release();
}
public TestStepResult run( TestCaseRunner runner, TestCaseRunContext runContext )
{
AMFTestStepResult testStepResult = new AMFTestStepResult( this );
testStepResult.startTimer();
runContext.setProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, testStepResult );
try
{
if( !initAmfRequest( runContext ) )
{
throw new SubmitException( "AMF request is not initialised properly !" );
}
submit = amfRequest.submit( runContext, false );
AMFResponse response = submit.getResponse();
if( submit.getStatus() != Submit.Status.CANCELED )
{
if( submit.getStatus() == Submit.Status.ERROR )
{
testStepResult.setStatus( TestStepStatus.FAILED );
testStepResult.addMessage( submit.getError().toString() );
amfRequest.setResponse( null );
}
else if( response == null )
{
testStepResult.setStatus( TestStepStatus.FAILED );
testStepResult.addMessage( "Request is missing response" );
amfRequest.setResponse( null );
}
else
{
runContext.setProperty( AssertedXPathsContainer.ASSERTEDXPATHSCONTAINER_PROPERTY, testStepResult );
amfRequest.setResponse( response );
testStepResult.setTimeTaken( response.getTimeTaken() );
testStepResult.setSize( response.getContentLength() );
switch( amfRequest.getAssertionStatus() )
{
case FAILED :
testStepResult.setStatus( TestStepStatus.FAILED );
break;
case VALID :
testStepResult.setStatus( TestStepStatus.OK );
break;
case UNKNOWN :
testStepResult.setStatus( TestStepStatus.UNKNOWN );
break;
}
testStepResult.setResponse( response, testStepResult.getStatus() != TestStepStatus.FAILED );
}
}
else
{
testStepResult.setStatus( TestStepStatus.CANCELED );
testStepResult.addMessage( "Request was canceled" );
}
if( response != null )
testStepResult.setRequestContent( response.getRequestContent() );
else
testStepResult.setRequestContent( amfRequest.getRequestContent() );
testStepResult.stopTimer();
}
catch( SubmitException e )
{
testStepResult.setStatus( TestStepStatus.FAILED );
testStepResult.addMessage( "SubmitException: " + e );
testStepResult.stopTimer();
}
finally
{
submit = null;
}
if( testStepResult.getStatus() != TestStepStatus.CANCELED )
{
assertResponse( runContext );
AssertionStatus assertionStatus = amfRequest.getAssertionStatus();
switch( assertionStatus )
{
case FAILED :
{
testStepResult.setStatus( TestStepStatus.FAILED );
if( getAssertionCount() == 0 )
{
testStepResult.addMessage( "Invalid/empty response" );
}
else
for( int c = 0; c < getAssertionCount(); c++ )
{
TestAssertion assertion = getAssertionAt( c );
AssertionError[] errors = assertion.getErrors();
if( errors != null )
{
for( AssertionError error : errors )
{
testStepResult.addMessage( "[" + assertion.getName() + "] " + error.getMessage() );
}
}
}
break;
}
// default : testStepResult.setStatus( TestStepStatus.OK ); break;
}
}
if( isDiscardResponse() && !SoapUI.getDesktop().hasDesktopPanel( this ) )
amfRequest.setResponse( null );
return testStepResult;
}
@Override
public boolean cancel()
{
if( submit == null )
return false;
submit.cancel();
return true;
}
public String getDefaultSourcePropertyName()
{
return "Response";
}
private void initAssertions()
{
assertionsSupport = new AssertionsSupport( this, new AssertableConfig()
{
public TestAssertionConfig addNewAssertion()
{
return getAMFRequestTestStepConfig().addNewAssertion();
}
public List<TestAssertionConfig> getAssertionList()
{
return getAMFRequestTestStepConfig().getAssertionList();
}
public void removeAssertion( int ix )
{
getAMFRequestTestStepConfig().removeAssertion( ix );
}
public TestAssertionConfig insertAssertion( TestAssertionConfig source, int ix )
{
TestAssertionConfig conf = getAMFRequestTestStepConfig().insertNewAssertion( ix );
conf.set( source );
return conf;
}
} );
}
private class PropertyChangeNotifier
{
private AssertionStatus oldStatus;
private ImageIcon oldIcon;
public PropertyChangeNotifier()
{
oldStatus = getAssertionStatus();
oldIcon = getIcon();
}
public void notifyChange()
{
AssertionStatus newStatus = getAssertionStatus();
ImageIcon newIcon = getIcon();
if( oldStatus != newStatus )
notifyPropertyChanged( STATUS_PROPERTY, oldStatus, newStatus );
if( oldIcon != newIcon )
notifyPropertyChanged( ICON_PROPERTY, oldIcon, getIcon() );
oldStatus = newStatus;
oldIcon = newIcon;
}
}
public TestAssertion addAssertion( String assertionLabel )
{
PropertyChangeNotifier notifier = new PropertyChangeNotifier();
try
{
WsdlMessageAssertion assertion = assertionsSupport.addWsdlAssertion( assertionLabel );
if( assertion == null )
return null;
if( getAMFRequest().getResponse() != null )
{
assertion.assertResponse( new AMFMessageExchange( this, getAMFRequest().getResponse() ),
new WsdlTestRunContext( this ) );
notifier.notifyChange();
}
return assertion;
}
catch( Exception e )
{
SoapUI.logError( e );
return null;
}
}
public void addAssertionsListener( AssertionsListener listener )
{
assertionsSupport.addAssertionsListener( listener );
}
public TestAssertion cloneAssertion( TestAssertion source, String name )
{
return assertionsSupport.cloneAssertion( source, name );
}
public String getAssertableContent()
{
return getAMFRequest().getResponse() == null ? null : getAMFRequest().getResponse().getContentAsString();
}
public WsdlMessageAssertion importAssertion( WsdlMessageAssertion source, boolean overwrite, boolean createCopy,
String newName )
{
return assertionsSupport.importAssertion( source, overwrite, createCopy, newName );
}
public AssertableType getAssertableType()
{
return AssertableType.RESPONSE;
}
public TestAssertion getAssertionAt( int c )
{
return assertionsSupport.getAssertionAt( c );
}
public TestAssertion getAssertionByName( String name )
{
return assertionsSupport.getAssertionByName( name );
}
public int getAssertionCount()
{
return assertionsSupport.getAssertionCount();
}
public List<TestAssertion> getAssertionList()
{
return new ArrayList<TestAssertion>( assertionsSupport.getAssertionList() );
}
public void propertyChange( PropertyChangeEvent arg0 )
{
if( arg0.getPropertyName().equals( TestAssertion.CONFIGURATION_PROPERTY )
|| arg0.getPropertyName().equals( TestAssertion.DISABLED_PROPERTY ) )
{
if( getAMFRequest().getResponse() != null )
{
assertResponse( new WsdlTestRunContext( this ) );
}
}
}
public Map<String, TestAssertion> getAssertions()
{
return assertionsSupport.getAssertions();
}
public String getDefaultAssertableContent()
{
return null;
}
public AssertionStatus getAssertionStatus()
{
return amfRequest.getAssertionStatus();
}
public ImageIcon getIcon()
{
return amfRequest.getIcon();
}
public Interface getInterface()
{
return null;
}
public TestAssertion moveAssertion( int ix, int offset )
{
PropertyChangeNotifier notifier = new PropertyChangeNotifier();
TestAssertion assertion = getAssertionAt( ix );
try
{
return assertionsSupport.moveAssertion( ix, offset );
}
finally
{
( ( WsdlMessageAssertion )assertion ).release();
notifier.notifyChange();
}
}
public void removeAssertion( TestAssertion assertion )
{
PropertyChangeNotifier notifier = new PropertyChangeNotifier();
try
{
assertionsSupport.removeAssertion( ( WsdlMessageAssertion )assertion );
}
finally
{
( ( WsdlMessageAssertion )assertion ).release();
notifier.notifyChange();
}
}
public void removeAssertionsListener( AssertionsListener listener )
{
assertionsSupport.removeAssertionsListener( listener );
}
public void assertResponse( SubmitContext context )
{
try
{
if( notifier == null )
notifier = new PropertyChangeNotifier();
AMFMessageExchange messageExchange = new AMFMessageExchange( this, getAMFRequest().getResponse() );
if( this != null )
{
// assert!
for( WsdlMessageAssertion assertion : assertionsSupport.getAssertionList() )
{
assertion.assertResponse( messageExchange, context );
}
}
notifier.notifyChange();
}
catch( Exception e )
{
e.printStackTrace();
}
}
public TestProperty addProperty( String name )
{
return propertyHolderSupport.addProperty( name );
}
public TestProperty removeProperty( String propertyName )
{
return propertyHolderSupport.removeProperty( propertyName );
}
public boolean renameProperty( String name, String newName )
{
return PropertyExpansionUtils.renameProperty( propertyHolderSupport.getProperty( name ), newName, getTestCase() ) != null;
}
public void addTestPropertyListener( TestPropertyListener listener )
{
propertyHolderSupport.addTestPropertyListener( listener );
}
public Map<String, TestProperty> getProperties()
{
return propertyHolderSupport.getProperties();
}
public TestProperty getProperty( String name )
{
return propertyHolderSupport.getProperty( name );
}
public TestProperty getPropertyAt( int index )
{
return propertyHolderSupport.getPropertyAt( index );
}
public int getPropertyCount()
{
return propertyHolderSupport.getPropertyCount();
}
public List<TestProperty> getPropertyList()
{
return propertyHolderSupport.getPropertyList();
}
public String[] getPropertyNames()
{
return propertyHolderSupport.getPropertyNames();
}
public String getPropertyValue( String name )
{
return propertyHolderSupport.getPropertyValue( name );
}
public void removeTestPropertyListener( TestPropertyListener listener )
{
propertyHolderSupport.removeTestPropertyListener( listener );
}
public boolean hasProperty( String name )
{
return propertyHolderSupport.hasProperty( name );
}
public void setPropertyValue( String name, String value )
{
propertyHolderSupport.setPropertyValue( name, value );
}
public void setPropertyValue( String name, Object value )
{
setPropertyValue( name, String.valueOf( value ) );
}
public void moveProperty( String propertyName, int targetIndex )
{
propertyHolderSupport.moveProperty( propertyName, targetIndex );
}
public AMFRequest getAMFRequest()
{
return amfRequest;
}
public void setResponse( AMFResponse response, SubmitContext context )
{
AMFResponse oldResponse = amfRequest.getResponse();
amfRequest.setResponse( response );
notifyPropertyChanged( RESPONSE_PROPERTY, oldResponse, response );
assertResponse( context );
}
public String getScript()
{
return amfRequestTestStepConfig.getScript() != null ? amfRequestTestStepConfig.getScript().getStringValue() : "";
}
public void setScript( String script )
{
String old = getScript();
scriptEngine.setScript( script );
if( amfRequestTestStepConfig.getScript() == null )
{
amfRequestTestStepConfig.addNewScript();
}
amfRequestTestStepConfig.getScript().setStringValue( script );
notifyPropertyChanged( "script", old, script );
}
public String getAmfCall()
{
return amfRequestTestStepConfig.getAmfCall();
}
public void setAmfCall( String amfCall )
{
String old = getAmfCall();
amfRequestTestStepConfig.setAmfCall( amfCall );
notifyPropertyChanged( "amfCall", old, amfCall );
}
public String getEndpoint()
{
return amfRequestTestStepConfig.getEndpoint();
}
public void setEndpoint( String endpoint )
{
String old = getEndpoint();
amfRequestTestStepConfig.setEndpoint( endpoint );
notifyPropertyChanged( "endpoint", old, endpoint );
}
public boolean initAmfRequest( SubmitContext submitContext )
{
amfRequest.setScriptEngine( scriptEngine );
amfRequest.setAmfCall( PropertyExpander.expandProperties( submitContext, getAmfCall() ) );
amfRequest.setEndpoint( PropertyExpander.expandProperties( submitContext, getEndpoint() ) );
amfRequest.setScript( getScript() );
amfRequest.setPropertyNames( getPropertyNames() );
amfRequest.setPropertyMap( ( HashMap<String, TestProperty> )getProperties() );
amfRequest.setHttpHeaders( getHttpHeaders() );
amfRequest.setAmfHeadersString( getAmfHeaders() );
return amfRequest.executeAmfScript( submitContext );
}
public void setHttpHeaders( StringToStringsMap httpHeaders )
{
StringToStringsMap old = getHttpHeaders();
getSettings().setString( HTTP_HEADERS_PROPERTY, httpHeaders.toXml() );
notifyPropertyChanged( HTTP_HEADERS_PROPERTY, old, httpHeaders );
}
public StringToStringsMap getHttpHeaders()
{
return StringToStringsMap.fromXml( getSettings().getString( HTTP_HEADERS_PROPERTY, null ) );
}
public void setAmfHeaders( StringToStringMap amfHeaders )
{
StringToStringMap old = getAmfHeaders();
getSettings().setString( AMF_HEADERS_PROPERTY, amfHeaders.toXml() );
notifyPropertyChanged( AMF_HEADERS_PROPERTY, old, amfHeaders );
}
public StringToStringMap getAmfHeaders()
{
return StringToStringMap.fromXml( getSettings().getString( AMF_HEADERS_PROPERTY, null ) );
}
public void resetConfigOnMove( TestStepConfig config )
{
super.resetConfigOnMove( config );
amfRequestTestStepConfig = ( AMFRequestTestStepConfig )config.getConfig().changeType(
AMFRequestTestStepConfig.type );
propertyHolderSupport.resetPropertiesConfig( amfRequestTestStepConfig.getProperties() );
// addResponseAsXmlVirtualProperty();
assertionsSupport.refresh();
}
public XmlBeansPropertiesTestPropertyHolder getPropertyHolderSupport()
{
return propertyHolderSupport;
}
public TestStep getTestStep()
{
return this;
}
public boolean isDiscardResponse()
{
return amfRequest.isDiscardResponse();
}
public void setDiscardResponse( boolean discardResponse )
{
amfRequest.setDiscardResponse( discardResponse );
}
public TestRequest getTestRequest()
{
return amfRequest;
}
}