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