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