001 package com.mockrunner.mock.jdbc; 002 003 import java.io.InputStream; 004 import java.io.Reader; 005 import java.math.BigDecimal; 006 import java.net.URL; 007 import java.sql.Array; 008 import java.sql.BatchUpdateException; 009 import java.sql.Blob; 010 import java.sql.Clob; 011 import java.sql.Connection; 012 import java.sql.Date; 013 import java.sql.ParameterMetaData; 014 import java.sql.PreparedStatement; 015 import java.sql.Ref; 016 import java.sql.ResultSet; 017 import java.sql.ResultSetMetaData; 018 import java.sql.SQLException; 019 import java.sql.Time; 020 import java.sql.Timestamp; 021 import java.util.ArrayList; 022 import java.util.Calendar; 023 import java.util.Collections; 024 import java.util.HashMap; 025 import java.util.Iterator; 026 import java.util.List; 027 import java.util.Map; 028 029 import com.mockrunner.jdbc.AbstractParameterResultSetHandler; 030 import com.mockrunner.jdbc.ParameterUtil; 031 import com.mockrunner.util.common.StringUtil; 032 033 /** 034 * Mock implementation of <code>PreparedStatement</code>. 035 */ 036 public class MockPreparedStatement extends MockStatement implements PreparedStatement 037 { 038 private AbstractParameterResultSetHandler resultSetHandler; 039 private Map paramObjects = new HashMap(); 040 private List batchParameters = new ArrayList(); 041 private String sql; 042 private MockParameterMetaData parameterMetaData; 043 044 public MockPreparedStatement(Connection connection, String sql) 045 { 046 super(connection); 047 this.sql = sql; 048 prepareParameterMetaData(); 049 } 050 051 public MockPreparedStatement(Connection connection, String sql, int resultSetType, int resultSetConcurrency) 052 { 053 super(connection, resultSetType, resultSetConcurrency); 054 this.sql = sql; 055 prepareParameterMetaData(); 056 } 057 058 public MockPreparedStatement(Connection connection, String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) 059 { 060 super(connection, resultSetType, resultSetConcurrency, resultSetHoldability); 061 this.sql = sql; 062 prepareParameterMetaData(); 063 } 064 065 public void setPreparedStatementResultSetHandler(AbstractParameterResultSetHandler resultSetHandler) 066 { 067 super.setResultSetHandler(resultSetHandler); 068 this.resultSetHandler = resultSetHandler; 069 } 070 071 private void prepareParameterMetaData() 072 { 073 int number = StringUtil.countMatches(sql, "?"); 074 parameterMetaData = new MockParameterMetaData(); 075 parameterMetaData.setParameterCount(number); 076 } 077 078 public String getSQL() 079 { 080 return sql; 081 } 082 083 public Map getIndexedParameterMap() 084 { 085 return Collections.unmodifiableMap(paramObjects); 086 } 087 088 public Map getParameterMap() 089 { 090 return getIndexedParameterMap(); 091 } 092 093 public Object getParameter(int index) 094 { 095 return paramObjects.get(new Integer(index)); 096 } 097 098 public void setObject(int index, Object object) throws SQLException 099 { 100 paramObjects.put(new Integer(index), object); 101 } 102 103 public void setObject(int parameterIndex, Object object, int targetSqlType, int scale) throws SQLException 104 { 105 setObject(parameterIndex, object); 106 } 107 108 public void setObject(int parameterIndex, Object object, int targetSqlType) throws SQLException 109 { 110 setObject(parameterIndex, object); 111 } 112 113 public void addBatch() throws SQLException 114 { 115 batchParameters.add(new HashMap(paramObjects)); 116 } 117 118 public void clearParameters() throws SQLException 119 { 120 paramObjects.clear(); 121 } 122 123 public boolean execute() throws SQLException 124 { 125 boolean callExecuteQuery = isQuery(getSQL()); 126 if(callExecuteQuery) 127 { 128 executeQuery(); 129 } 130 else 131 { 132 executeUpdate(); 133 } 134 return callExecuteQuery; 135 } 136 137 public ResultSet executeQuery() throws SQLException 138 { 139 return executeQuery(paramObjects); 140 } 141 142 protected ResultSet executeQuery(Map params) throws SQLException 143 { 144 if(resultSetHandler.getThrowsSQLException(getSQL(), params)) 145 { 146 throw new SQLException("Statement " + getSQL() + " was specified to throw an exception"); 147 } 148 if(resultSetHandler.getThrowsSQLException(getSQL())) 149 { 150 throw new SQLException("Statement " + getSQL() + " was specified to throw an exception"); 151 } 152 MockResultSet result = resultSetHandler.getResultSet(getSQL(), params); 153 resultSetHandler.addParameterMapForExecutedStatement(getSQL(), getParameterMapCopy(params)); 154 if(null != result) 155 { 156 resultSetHandler.addExecutedStatement(getSQL()); 157 result = cloneResultSet(result); 158 resultSetHandler.addReturnedResultSet(result); 159 setNextResultSet(result); 160 return result; 161 } 162 return super.executeQuery(getSQL()); 163 } 164 165 public int executeUpdate() throws SQLException 166 { 167 return executeUpdate(paramObjects); 168 } 169 170 protected int executeUpdate(Map params) throws SQLException 171 { 172 if(resultSetHandler.getThrowsSQLException(getSQL(), params)) 173 { 174 throw new SQLException("Statement " + getSQL() + " was specified to throw an exception"); 175 } 176 if(resultSetHandler.getThrowsSQLException(getSQL())) 177 { 178 throw new SQLException("Statement " + getSQL() + " was specified to throw an exception"); 179 } 180 Integer updateCount = resultSetHandler.getUpdateCount(getSQL(), params); 181 resultSetHandler.addParameterMapForExecutedStatement(getSQL(), getParameterMapCopy(params)); 182 if(null != updateCount) 183 { 184 resultSetHandler.addExecutedStatement(getSQL()); 185 int updateCountInt = updateCount.intValue(); 186 setNextUpdateCount(updateCountInt); 187 return updateCountInt; 188 } 189 return super.executeUpdate(getSQL()); 190 } 191 192 public int[] executeBatch() throws SQLException 193 { 194 return executeBatch(this.batchParameters); 195 } 196 197 protected int[] executeBatch(List batchParams) throws SQLException 198 { 199 int[] results = new int[batchParams.size()]; 200 if(isQuery(getSQL())) 201 { 202 throw new BatchUpdateException("SQL " + getSQL() + " returned a ResultSet.", null); 203 } 204 for(int ii = 0; ii < results.length; ii++) 205 { 206 Map currentParameters = (Map)batchParams.get(ii); 207 results[ii] = executeUpdate(currentParameters); 208 } 209 return results; 210 } 211 212 public ResultSetMetaData getMetaData() throws SQLException 213 { 214 return new MockResultSetMetaData(); 215 } 216 217 public ParameterMetaData getParameterMetaData() throws SQLException 218 { 219 return parameterMetaData; 220 } 221 222 public void setArray(int parameterIndex, Array array) throws SQLException 223 { 224 setObject(parameterIndex, array); 225 } 226 227 public void setAsciiStream(int parameterIndex, InputStream stream, int length) throws SQLException 228 { 229 setObject(parameterIndex, stream); 230 } 231 232 public void setBigDecimal(int parameterIndex, BigDecimal bigDecimal) throws SQLException 233 { 234 setObject(parameterIndex, bigDecimal); 235 } 236 237 public void setBinaryStream(int parameterIndex, InputStream stream, int length) throws SQLException 238 { 239 setObject(parameterIndex, stream); 240 } 241 242 public void setBlob(int parameterIndex, Blob blob) throws SQLException 243 { 244 setObject(parameterIndex, blob); 245 } 246 247 public void setBoolean(int parameterIndex, boolean bool) throws SQLException 248 { 249 setObject(parameterIndex, new Boolean(bool)); 250 } 251 252 public void setByte(int parameterIndex, byte byteValue) throws SQLException 253 { 254 setObject(parameterIndex, new Byte(byteValue)); 255 } 256 257 public void setBytes(int parameterIndex, byte[] byteArray) throws SQLException 258 { 259 setObject(parameterIndex, byteArray); 260 } 261 262 public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException 263 { 264 setObject(parameterIndex, reader); 265 } 266 267 public void setClob(int parameterIndex, Clob clob) throws SQLException 268 { 269 setObject(parameterIndex, clob); 270 } 271 272 public void setDate(int parameterIndex, Date date, Calendar calendar) throws SQLException 273 { 274 setObject(parameterIndex, date); 275 } 276 277 public void setDate(int parameterIndex, Date date) throws SQLException 278 { 279 setObject(parameterIndex, date); 280 } 281 282 public void setDouble(int parameterIndex, double doubleValue) throws SQLException 283 { 284 setObject(parameterIndex, new Double(doubleValue)); 285 } 286 287 public void setFloat(int parameterIndex, float floatValue) throws SQLException 288 { 289 setObject(parameterIndex, new Float(floatValue)); 290 } 291 292 public void setInt(int parameterIndex, int intValue) throws SQLException 293 { 294 setObject(parameterIndex, new Integer(intValue)); 295 } 296 297 public void setLong(int parameterIndex, long longValue) throws SQLException 298 { 299 setObject(parameterIndex, new Long(longValue)); 300 } 301 302 public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException 303 { 304 setObject(parameterIndex, null); 305 } 306 307 public void setNull(int parameterIndex, int sqlType) throws SQLException 308 { 309 setObject(parameterIndex, null); 310 } 311 312 public void setRef(int parameterIndex, Ref ref) throws SQLException 313 { 314 setObject(parameterIndex, ref); 315 } 316 317 public void setShort(int parameterIndex, short shortValue) throws SQLException 318 { 319 setObject(parameterIndex, new Short(shortValue)); 320 } 321 322 public void setString(int parameterIndex, String string) throws SQLException 323 { 324 setObject(parameterIndex, string); 325 } 326 327 public void setTime(int parameterIndex, Time time, Calendar calendar) throws SQLException 328 { 329 setObject(parameterIndex, time); 330 } 331 332 public void setTime(int parameterIndex, Time time) throws SQLException 333 { 334 setObject(parameterIndex, time); 335 } 336 337 public void setTimestamp(int parameterIndex, Timestamp timeStamp, Calendar cal) throws SQLException 338 { 339 setObject(parameterIndex, timeStamp); 340 } 341 342 public void setTimestamp(int parameterIndex, Timestamp timeStamp) throws SQLException 343 { 344 setObject(parameterIndex, timeStamp); 345 } 346 347 public void setUnicodeStream(int parameterIndex, InputStream stream, int length) throws SQLException 348 { 349 setObject(parameterIndex, stream); 350 } 351 352 public void setURL(int parameterIndex, URL url) throws SQLException 353 { 354 setObject(parameterIndex, url); 355 } 356 357 private Map getParameterMapCopy(Map actualParameters) 358 { 359 Map copyParameters = new HashMap(); 360 Iterator keys = actualParameters.keySet().iterator(); 361 while(keys.hasNext()) 362 { 363 Object key = keys.next(); 364 Object actualParameter = actualParameters.get(key); 365 Object copyParameter = ParameterUtil.copyParameter(actualParameter); 366 copyParameters.put(key, copyParameter); 367 } 368 return copyParameters; 369 } 370 }