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.teststeps.amf;
14  
15  import java.util.List;
16  import java.util.concurrent.Future;
17  
18  import com.eviware.soapui.SoapUI;
19  import com.eviware.soapui.config.TestCaseConfig;
20  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
21  import com.eviware.soapui.impl.wsdl.teststeps.AMFRequestTestStep;
22  import com.eviware.soapui.model.iface.Submit;
23  import com.eviware.soapui.model.iface.SubmitContext;
24  import com.eviware.soapui.model.iface.SubmitListener;
25  import com.eviware.soapui.support.StringUtils;
26  import com.eviware.soapui.support.UISupport;
27  
28  import flex.messaging.io.amf.client.exceptions.ClientStatusException;
29  import flex.messaging.io.amf.client.exceptions.ServerStatusException;
30  
31  public class AMFSubmit implements Submit, Runnable
32  {
33  	public static final String AMF_CONNECTION = "AMF_CONNECTION";
34  	private volatile Future<?> future;
35  	private SubmitContext context;
36  	private Status status;
37  	private SubmitListener[] listeners;
38  	private Exception error;
39  	private long timestamp;
40  	private final AMFRequest request;
41  	private AMFResponse response;
42  	private AMFCredentials credentials;
43  
44  	public AMFSubmit( AMFRequest request, SubmitContext submitContext, boolean async )
45  	{
46  		this.request = request;
47  		this.context = submitContext;
48  
49  		List<SubmitListener> regListeners = SoapUI.getListenerRegistry().getListeners( SubmitListener.class );
50  
51  		SubmitListener[] submitListeners = request.getSubmitListeners();
52  		this.listeners = new SubmitListener[submitListeners.length + regListeners.size()];
53  		for( int c = 0; c < submitListeners.length; c++ )
54  			this.listeners[c] = submitListeners[c];
55  
56  		for( int c = 0; c < regListeners.size(); c++ )
57  			this.listeners[submitListeners.length + c] = regListeners.get( c );
58  
59  		error = null;
60  		status = Status.INITIALIZED;
61  		timestamp = System.currentTimeMillis();
62  
63  		if( async )
64  			future = SoapUI.getThreadPool().submit( this );
65  		else
66  			run();
67  	}
68  
69  	public void cancel()
70  	{
71  		if( status == Status.CANCELED )
72  			return;
73  
74  		SoapUI.log.info( "Canceling request.." );
75  
76  		status = Status.CANCELED;
77  
78  		for( int i = 0; i < listeners.length; i++ )
79  		{
80  			try
81  			{
82  				listeners[i].afterSubmit( this, context );
83  			}
84  			catch( Throwable e )
85  			{
86  				SoapUI.logError( e );
87  			}
88  		}
89  	}
90  
91  	public Status waitUntilFinished()
92  	{
93  		if( future != null )
94  		{
95  			if( !future.isDone() )
96  			{
97  				try
98  				{
99  					future.get();
100 				}
101 				catch( Exception e )
102 				{
103 					SoapUI.logError( e );
104 				}
105 			}
106 		}
107 		else
108 			throw new RuntimeException( "cannot wait on null future" );
109 
110 		return getStatus();
111 	}
112 
113 	public void run()
114 	{
115 		try
116 		{
117 			for( int i = 0; i < listeners.length; i++ )
118 			{
119 				if( !listeners[i].beforeSubmit( this, context ) )
120 				{
121 					status = Status.CANCELED;
122 					SoapUI.log.error( "listener cancelled submit.." );
123 					return;
124 				}
125 			}
126 
127 			status = Status.RUNNING;
128 			Object responseContent = executeAmfCall( getRequest() );
129 			createResponse( responseContent );
130 
131 			if( status != Status.CANCELED && status != Status.ERROR )
132 			{
133 				status = Status.FINISHED;
134 			}
135 		}
136 		catch( Exception e )
137 		{
138 			UISupport.showErrorMessage( "There's been an error in executing query " + e.toString() );
139 			error = e;
140 		}
141 		finally
142 		{
143 
144 			if( status != Status.CANCELED )
145 			{
146 				for( int i = 0; i < listeners.length; i++ )
147 				{
148 					try
149 					{
150 						listeners[i].afterSubmit( this, context );
151 					}
152 					catch( Throwable e )
153 					{
154 						SoapUI.logError( e );
155 					}
156 				}
157 			}
158 		}
159 	}
160 
161 	protected void createResponse( Object responseContent )
162 	{
163 		try
164 		{
165 			response = new AMFResponse( request, context, responseContent );
166 			response.setTimestamp( timestamp );
167 			response.setTimeTaken( System.currentTimeMillis() - timestamp );
168 		}
169 		catch( Exception e )
170 		{
171 			SoapUI.logError( e );
172 		}
173 
174 	}
175 
176 	private Object executeAmfCall( AMFRequest amfRequest ) throws ClientStatusException, ServerStatusException
177 	{
178 		SoapUIAMFConnection amfConnection = null;
179 		try
180 		{
181 			amfConnection = getConnection( amfRequest );
182 			addAmfHeaders( amfRequest, amfConnection );
183 			addHttpHeaders( amfRequest, amfConnection );
184 			Object result = amfConnection.call( context, amfRequest.getAmfCall(), amfRequest.argumentsToArray() );
185 
186 			return result;
187 		}
188 		catch( Exception e )
189 		{
190 			SoapUI.logError( e );
191 			error = e;
192 			status = Status.ERROR;
193 		}
194 		finally
195 		{
196 			amfRequest.clearArguments();
197 			if( context.getModelItem() instanceof AMFRequestTestStep )
198 			{
199 				if( credentials != null && credentials.isLoggedIn() )
200 				{
201 					credentials.logout();
202 					credentials = null;
203 				}
204 				else
205 				{
206 					amfConnection.close();
207 				}
208 			}
209 		}
210 		return null;
211 
212 	}
213 
214 	private SoapUIAMFConnection getConnection( AMFRequest amfRequest ) throws Exception
215 	{
216 		SoapUIAMFConnection amfConnection = null;
217 		if( isAuthorisationEnabled( amfRequest ) && ( context.getModelItem() instanceof WsdlTestCase ) )
218 		{
219 			if( ( amfConnection = ( SoapUIAMFConnection )context.getProperty( AMF_CONNECTION ) ) != null )
220 			{
221 				return amfConnection;
222 			}
223 			else
224 			{
225 				throw new Exception( "amf session connection error! " );
226 			}
227 		}
228 		else if( isAuthorisationEnabled( amfRequest ) && ( context.getModelItem() instanceof AMFRequestTestStep ) )
229 		{
230 			String endpoint = context.expand( getTestCaseConfig( amfRequest ).getAmfEndpoint() );
231 			String username = context.expand( getTestCaseConfig( amfRequest ).getAmfLogin() );
232 			String password = context.expand( getTestCaseConfig( amfRequest ).getAmfPassword() );
233 
234 			if( StringUtils.hasContent( endpoint ) && StringUtils.hasContent( username ) )
235 			{
236 				credentials = new AMFCredentials( endpoint, username, password, context );
237 				amfConnection = credentials.login();
238 			}
239 			else
240 			{
241 				amfConnection = new SoapUIAMFConnection();
242 				amfConnection.connect( context.expand( amfRequest.getEndpoint() ) );
243 			}
244 
245 			context.setProperty( AMF_CONNECTION, amfConnection );
246 			return amfConnection;
247 		}
248 		else
249 		{
250 			amfConnection = new SoapUIAMFConnection();
251 			amfConnection.connect( context.expand( amfRequest.getEndpoint() ) );
252 			return amfConnection;
253 		}
254 	}
255 
256 	private boolean isAuthorisationEnabled( AMFRequest amfRequest )
257 	{
258 		return getTestCaseConfig( amfRequest ).getAmfAuthorisation();
259 	}
260 
261 	private TestCaseConfig getTestCaseConfig( AMFRequest amfRequest )
262 	{
263 		return amfRequest.getTestStep().getTestCase().getConfig();
264 	}
265 
266 	private void addHttpHeaders( AMFRequest amfRequest, SoapUIAMFConnection amfConnection )
267 	{
268 		if( amfRequest.getHttpHeaders() != null )
269 		{
270 			for( String key : amfRequest.getHttpHeaders().getKeys() )
271 			{
272 				amfConnection.addHttpRequestHeader( key, context.expand( amfRequest.getHttpHeaders().get( key ) ) );
273 			}
274 		}
275 	}
276 
277 	private void addAmfHeaders( AMFRequest amfRequest, SoapUIAMFConnection amfConnection )
278 	{
279 		if( amfRequest.getAmfHeaders() != null )
280 		{
281 			for( String key : amfRequest.getAmfHeaders().keySet() )
282 			{
283 				Object data = amfRequest.getAmfHeaders().get( key );
284 				if( data instanceof String )
285 					data = context.expand( ( String )data );
286 
287 				amfConnection.addAmfHeader( key, data );
288 			}
289 		}
290 	}
291 
292 	public Exception getError()
293 	{
294 		return error;
295 	}
296 
297 	public AMFRequest getRequest()
298 	{
299 		return request;
300 	}
301 
302 	public AMFResponse getResponse()
303 	{
304 		return response;
305 	}
306 
307 	public Status getStatus()
308 	{
309 		return status;
310 	}
311 
312 }