/*
* 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.panels.teststeps.amf;
import java.util.List;
import java.util.concurrent.Future;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.TestCaseConfig;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.impl.wsdl.teststeps.AMFRequestTestStep;
import com.eviware.soapui.model.iface.Submit;
import com.eviware.soapui.model.iface.SubmitContext;
import com.eviware.soapui.model.iface.SubmitListener;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.types.StringToStringsMap;
import flex.messaging.io.amf.client.exceptions.ClientStatusException;
import flex.messaging.io.amf.client.exceptions.ServerStatusException;
public class AMFSubmit implements Submit, Runnable
{
public static final String AMF_CONNECTION = "AMF_CONNECTION";
private volatile Future<?> future;
private SubmitContext context;
private Status status;
private SubmitListener[] listeners;
private Exception error;
private long timestamp;
private final AMFRequest request;
private AMFResponse response;
private AMFCredentials credentials;
public AMFSubmit( AMFRequest request, SubmitContext submitContext, boolean async )
{
this.request = request;
this.context = submitContext;
List<SubmitListener> regListeners = SoapUI.getListenerRegistry().getListeners( SubmitListener.class );
SubmitListener[] submitListeners = request.getSubmitListeners();
this.listeners = new SubmitListener[submitListeners.length + regListeners.size()];
for( int c = 0; c < submitListeners.length; c++ )
this.listeners[c] = submitListeners[c];
for( int c = 0; c < regListeners.size(); c++ )
this.listeners[submitListeners.length + c] = regListeners.get( c );
error = null;
status = Status.INITIALIZED;
timestamp = System.currentTimeMillis();
if( async )
future = SoapUI.getThreadPool().submit( this );
else
run();
}
public void cancel()
{
if( status == Status.CANCELED )
return;
SoapUI.log.info( "Canceling request.." );
status = Status.CANCELED;
for( int i = 0; i < listeners.length; i++ )
{
try
{
listeners[i].afterSubmit( this, context );
}
catch( Throwable e )
{
SoapUI.logError( e );
}
}
}
public Status waitUntilFinished()
{
if( future != null )
{
if( !future.isDone() )
{
try
{
future.get();
}
catch( Exception e )
{
SoapUI.logError( e );
}
}
}
else
throw new RuntimeException( "cannot wait on null future" );
return getStatus();
}
public void run()
{
try
{
for( int i = 0; i < listeners.length; i++ )
{
if( !listeners[i].beforeSubmit( this, context ) )
{
status = Status.CANCELED;
SoapUI.log.error( "listener cancelled submit.." );
return;
}
}
status = Status.RUNNING;
Object responseContent = executeAmfCall( getRequest() );
createResponse( responseContent );
if( status != Status.CANCELED && status != Status.ERROR )
{
status = Status.FINISHED;
}
}
catch( Exception e )
{
UISupport.showErrorMessage( "There's been an error in executing query " + e.toString() );
error = e;
}
finally
{
if( status != Status.CANCELED )
{
for( int i = 0; i < listeners.length; i++ )
{
try
{
listeners[i].afterSubmit( this, context );
}
catch( Throwable e )
{
SoapUI.logError( e );
}
}
}
}
}
protected void createResponse( Object responseContent )
{
try
{
response = new AMFResponse( request, context, responseContent );
response.setTimestamp( timestamp );
response.setTimeTaken( System.currentTimeMillis() - timestamp );
}
catch( Exception e )
{
SoapUI.logError( e );
}
}
private Object executeAmfCall( AMFRequest amfRequest ) throws ClientStatusException, ServerStatusException
{
SoapUIAMFConnection amfConnection = null;
try
{
amfConnection = getConnection( amfRequest );
addAmfHeaders( amfRequest, amfConnection );
addHttpHeaders( amfRequest, amfConnection );
Object result = amfConnection.call( context, amfRequest.getAmfCall(), amfRequest.argumentsToArray() );
return result;
}
catch( Exception e )
{
SoapUI.logError( e );
error = e;
status = Status.ERROR;
}
finally
{
amfRequest.clearArguments();
if( context.getModelItem() instanceof AMFRequestTestStep )
{
if( credentials != null && credentials.isLoggedIn() )
{
credentials.logout();
credentials = null;
}
else
{
amfConnection.close();
}
}
}
return null;
}
private SoapUIAMFConnection getConnection( AMFRequest amfRequest ) throws Exception
{
SoapUIAMFConnection amfConnection = null;
if( isAuthorisationEnabled( amfRequest ) && ( context.getModelItem() instanceof WsdlTestCase ) )
{
if( ( amfConnection = ( SoapUIAMFConnection )context.getProperty( AMF_CONNECTION ) ) != null )
{
return amfConnection;
}
else
{
throw new Exception( "amf session connection error! " );
}
}
else if( isAuthorisationEnabled( amfRequest ) && ( context.getModelItem() instanceof AMFRequestTestStep ) )
{
String endpoint = context.expand( getTestCaseConfig( amfRequest ).getAmfEndpoint() );
String username = context.expand( getTestCaseConfig( amfRequest ).getAmfLogin() );
String password = context.expand( getTestCaseConfig( amfRequest ).getAmfPassword() );
if( StringUtils.hasContent( endpoint ) && StringUtils.hasContent( username ) )
{
credentials = new AMFCredentials( endpoint, username, password, context );
amfConnection = credentials.login();
}
else
{
amfConnection = new SoapUIAMFConnection();
amfConnection.connect( context.expand( amfRequest.getEndpoint() ) );
}
context.setProperty( AMF_CONNECTION, amfConnection );
return amfConnection;
}
else
{
amfConnection = new SoapUIAMFConnection();
amfConnection.connect( context.expand( amfRequest.getEndpoint() ) );
return amfConnection;
}
}
private boolean isAuthorisationEnabled( AMFRequest amfRequest )
{
return getTestCaseConfig( amfRequest ).getAmfAuthorisation();
}
private TestCaseConfig getTestCaseConfig( AMFRequest amfRequest )
{
return amfRequest.getTestStep().getTestCase().getConfig();
}
private void addHttpHeaders( AMFRequest amfRequest, SoapUIAMFConnection amfConnection )
{
StringToStringsMap httpHeaders = amfRequest.getHttpHeaders();
if( httpHeaders != null )
{
for( String key : httpHeaders.getKeys() )
{
for( String value : httpHeaders.get( key ) )
amfConnection.addHttpRequestHeader( key, context.expand( value ) );
}
}
}
private void addAmfHeaders( AMFRequest amfRequest, SoapUIAMFConnection amfConnection )
{
if( amfRequest.getAmfHeaders() != null )
{
for( String key : amfRequest.getAmfHeaders().keySet() )
{
Object data = amfRequest.getAmfHeaders().get( key );
if( data instanceof String )
data = context.expand( ( String )data );
amfConnection.addAmfHeader( key, data );
}
}
}
public Exception getError()
{
return error;
}
public AMFRequest getRequest()
{
return request;
}
public AMFResponse getResponse()
{
return response;
}
public Status getStatus()
{
return status;
}
}