1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.panels.teststeps;
14
15 import java.sql.CallableStatement;
16 import java.sql.Connection;
17 import java.sql.DriverManager;
18 import java.sql.PreparedStatement;
19 import java.sql.ResultSet;
20 import java.sql.SQLException;
21 import java.sql.SQLFeatureNotSupportedException;
22 import java.util.List;
23 import java.util.concurrent.Future;
24
25 import com.eviware.soapui.SoapUI;
26 import com.eviware.soapui.impl.wsdl.panels.teststeps.support.NamedParameterStatement;
27 import com.eviware.soapui.impl.wsdl.teststeps.JdbcRequestTestStep;
28 import com.eviware.soapui.model.iface.Request;
29 import com.eviware.soapui.model.iface.Submit;
30 import com.eviware.soapui.model.iface.SubmitContext;
31 import com.eviware.soapui.model.iface.SubmitListener;
32 import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
33 import com.eviware.soapui.model.testsuite.TestProperty;
34 import com.eviware.soapui.support.SoapUIException;
35 import com.eviware.soapui.support.StringUtils;
36 import com.eviware.soapui.support.UISupport;
37
38 public class JdbcSubmit implements Submit, Runnable
39 {
40 public static final String JDBC_ERROR = "JDBC_ERROR";
41 public static final String JDBC_TIMEOUT = "JDBC_TIMEOUT";
42 private volatile Future<?> future;
43 private SubmitContext context;
44 private Status status;
45 private SubmitListener[] listeners;
46 private Exception error;
47 private long timestamp;
48 protected ResultSet resultSet;
49 protected PreparedStatement statement;
50 private Connection connection;
51 private long timeTaken;
52 private final JdbcRequest request;
53 private JdbcResponse response;
54
55 public JdbcSubmit( JdbcRequest request, SubmitContext submitContext, boolean async )
56 {
57 this.request = request;
58 this.context = submitContext;
59
60 List<SubmitListener> regListeners = SoapUI.getListenerRegistry().getListeners( SubmitListener.class );
61
62 SubmitListener[] submitListeners = request.getSubmitListeners();
63 this.listeners = new SubmitListener[submitListeners.length + regListeners.size()];
64 for( int c = 0; c < submitListeners.length; c++ )
65 this.listeners[c] = submitListeners[c];
66
67 for( int c = 0; c < regListeners.size(); c++ )
68 this.listeners[submitListeners.length + c] = regListeners.get( c );
69
70 error = null;
71 status = Status.INITIALIZED;
72
73 if( async )
74 future = SoapUI.getThreadPool().submit( this );
75 else
76 run();
77 }
78
79 public void cancel()
80 {
81 if( status == Status.CANCELED )
82 return;
83
84 JdbcRequest.logger.info( "Canceling request.." );
85 if( status == Status.RUNNING )
86 {
87 cancelQuery();
88 }
89
90 status = Status.CANCELED;
91
92 for( int i = 0; i < listeners.length; i++ )
93 {
94 try
95 {
96 listeners[i].afterSubmit( this, context );
97 }
98 catch( Throwable e )
99 {
100 SoapUI.logError( e );
101 }
102 }
103 }
104
105 public Exception getError()
106 {
107 return error;
108 }
109
110 public Request getRequest()
111 {
112 return request;
113 }
114
115 public JdbcResponse getResponse()
116 {
117 return response;
118 }
119
120 public Status getStatus()
121 {
122 return status;
123 }
124
125 public Status waitUntilFinished()
126 {
127 if( future != null )
128 {
129 if( !future.isDone() )
130 {
131 try
132 {
133 future.get();
134 }
135 catch( Exception e )
136 {
137 SoapUI.logError( e );
138 }
139 }
140 }
141 else
142 throw new RuntimeException( "cannot wait on null future" );
143
144 return getStatus();
145 }
146
147 public void run()
148 {
149 try
150 {
151 for( int i = 0; i < listeners.length; i++ )
152 {
153 if( !listeners[i].beforeSubmit( this, context ) )
154 {
155 status = Status.CANCELED;
156 System.err.println( "listener cancelled submit.." );
157 return;
158 }
159 }
160
161 status = Status.RUNNING;
162 runQuery();
163
164 if( status != Status.CANCELED )
165 {
166 status = Status.FINISHED;
167 }
168 }
169 catch( Exception e )
170 {
171 SoapUI.logError( e );
172 error = e;
173 }
174 finally
175 {
176 if( status != Status.CANCELED )
177 {
178 for( int i = 0; i < listeners.length; i++ )
179 {
180 try
181 {
182 listeners[i].afterSubmit( this, context );
183 }
184 catch( Throwable e )
185 {
186 SoapUI.logError( e );
187 }
188 }
189 }
190 }
191 }
192
193 protected void runQuery() throws Exception
194 {
195 try
196 {
197 prepare();
198 load();
199 }
200 catch( SQLException e )
201 {
202 throw e;
203 }
204 createResponse();
205 }
206
207 public void cancelQuery()
208 {
209 try
210 {
211 if( statement != null )
212 statement.cancel();
213 }
214 catch( SQLFeatureNotSupportedException e )
215 {
216 UISupport.showErrorMessage( e );
217 }
218 catch( SQLException ex )
219 {
220 UISupport.showErrorMessage( ex );
221 }
222 }
223
224 protected void getDatabaseConnection() throws Exception, SQLException
225 {
226 String drvr = "";
227 String connStr = "";
228 String pass = "";
229
230 JdbcRequestTestStep testStep = request.getTestStep();
231
232 if( !StringUtils.isNullOrEmpty( testStep.getDriver() )
233 && !StringUtils.isNullOrEmpty( testStep.getConnectionString() ) )
234 {
235 drvr = PropertyExpander.expandProperties( context, testStep.getDriver() ).trim();
236 connStr = PropertyExpander.expandProperties( context, testStep.getConnectionString() ).trim();
237 pass = PropertyExpander.expandProperties( context, testStep.getPassword() ).trim();
238 }
239 else
240 {
241 UISupport.showErrorMessage( "Please supply connection settings for all DataSources" );
242 throw new SoapUIException( "Please supply connection settings" );
243 }
244 if( connStr.contains( JdbcRequestTestStep.PASS_TEMPLATE ) )
245 {
246 connStr = connStr.replaceFirst( JdbcRequestTestStep.PASS_TEMPLATE, pass );
247 }
248 try
249 {
250 DriverManager.getDriver( connStr );
251 }
252 catch( SQLException e )
253 {
254 try
255 {
256 Class.forName( drvr ).newInstance();
257 }
258 catch( Exception e1 )
259 {
260 throw new Exception( "Failed to init connection for drvr [" + drvr + "], connectionString ["
261 + testStep.getConnectionString() + "]" );
262 }
263 }
264
265 resultSet = null;
266 connection = DriverManager.getConnection( connStr );
267
268
269
270 }
271
272 protected void load() throws SQLException
273 {
274 try
275 {
276 JdbcRequestTestStep testStep = request.getTestStep();
277
278 if( testStep.isStoredProcedure() )
279 {
280 timestamp = System.currentTimeMillis();
281 statement.execute();
282 }
283 else
284 {
285 timestamp = System.currentTimeMillis();
286 statement.execute();
287 }
288 timeTaken = System.currentTimeMillis() - timestamp;
289 if( !StringUtils.isNullOrEmpty( request.getTimeout() ) && timeTaken > Long.parseLong( request.getTimeout() ) )
290 {
291 context.setProperty( JDBC_TIMEOUT, PropertyExpander.expandProperties( context, request.getTimeout() ) );
292 }
293 }
294 catch( SQLException e )
295 {
296 context.setProperty( JDBC_ERROR, e );
297 throw e;
298 }
299 finally
300 {
301 timeTaken = System.currentTimeMillis() - timestamp;
302 }
303 }
304
305 protected void prepare() throws Exception
306 {
307 JdbcRequestTestStep testStep = request.getTestStep();
308 getDatabaseConnection();
309 String sql;
310 List<TestProperty> props = testStep.getPropertyList();
311 if( testStep.isStoredProcedure() )
312 {
313 sql = PropertyExpander.expandProperties( context, testStep.getQuery() );
314
315 if( !sql.startsWith( "{call " ) && !sql.endsWith( "}" ) )
316 sql = "{call " + sql + "}";
317
318 }
319 else
320 {
321 sql = PropertyExpander.expandProperties( context, testStep.getQuery() );
322 }
323 NamedParameterStatement p = new NamedParameterStatement( connection, sql );
324 for( TestProperty testProperty : props )
325 {
326 String value = PropertyExpander.expandProperties( context, testProperty.getValue() );
327 if( !testProperty.getName().equals( "ResponseAsXML" ) )
328 {
329 p.setString( testProperty.getName(), value );
330 }
331 }
332 statement = p.getStatement();
333
334 try
335 {
336 if( !StringUtils.isNullOrEmpty( testStep.getQueryTimeout() ) )
337 {
338 String queryTimeout = PropertyExpander.expandProperties( testStep, testStep.getQueryTimeout() );
339 statement.setQueryTimeout( Integer.parseInt( queryTimeout ) );
340 }
341 }
342 catch( NumberFormatException e )
343 {
344 UISupport.showErrorMessage( "Problem setting timeout: " + e.getMessage() );
345 }
346
347 try
348 {
349 if( !StringUtils.isNullOrEmpty( testStep.getMaxRows() ) )
350 {
351 String maxRows = PropertyExpander.expandProperties( testStep, testStep.getMaxRows() );
352 statement.setMaxRows( Integer.parseInt( maxRows ) );
353 }
354 }
355 catch( NumberFormatException e )
356 {
357 UISupport.showErrorMessage( "Problem setting maxRows: " + e.getMessage() );
358 }
359 try
360 {
361 if( !StringUtils.isNullOrEmpty( testStep.getFetchSize() ) )
362 {
363 String fetchSize = PropertyExpander.expandProperties( testStep, testStep.getFetchSize() );
364 statement.setFetchSize( Integer.parseInt( fetchSize ) );
365 }
366 }
367 catch( NumberFormatException e )
368 {
369 UISupport.showErrorMessage( "Problem setting fetchSize: " + e.getMessage() );
370 }
371 }
372
373 protected String createResponse()
374 {
375 try
376 {
377 response = new JdbcResponse( request, statement );
378 response.setTimestamp( timestamp );
379 response.setTimeTaken( timeTaken );
380 }
381 catch( Exception e )
382 {
383 SoapUI.logError( e );
384 }
385 finally
386 {
387 try
388 {
389 if( connection != null )
390 connection.close();
391 if( statement != null )
392 statement.close();
393 if( resultSet != null )
394 resultSet.close();
395 }
396 catch( Exception e )
397 {
398 }
399 }
400 return null;
401 }
402 }