001: package com.mockrunner.mock.jdbc;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.InputStream;
005: import java.io.Reader;
006: import java.io.StringReader;
007: import java.math.BigDecimal;
008: import java.net.URL;
009: import java.sql.Array;
010: import java.sql.BatchUpdateException;
011: import java.sql.Blob;
012: import java.sql.Clob;
013: import java.sql.Connection;
014: import java.sql.Date; //import java.sql.NClob;
015: import java.sql.ParameterMetaData;
016: import java.sql.PreparedStatement;
017: import java.sql.Ref;
018: import java.sql.ResultSet;
019: import java.sql.ResultSetMetaData; //import java.sql.RowId;
020: import java.sql.SQLException; //import java.sql.SQLXML;
021: import java.sql.Time;
022: import java.sql.Timestamp;
023: import java.util.ArrayList;
024: import java.util.Calendar;
025: import java.util.Collections;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Map;
030:
031: import com.mockrunner.jdbc.AbstractParameterResultSetHandler;
032: import com.mockrunner.jdbc.ParameterUtil;
033: import com.mockrunner.util.common.ArrayUtil;
034: import com.mockrunner.util.common.StreamUtil;
035: import com.mockrunner.util.common.StringUtil;
036:
037: /**
038: * Mock implementation of <code>PreparedStatement</code>.
039: */
040: public class MockPreparedStatement extends MockStatement implements
041: PreparedStatement {
042: private AbstractParameterResultSetHandler resultSetHandler;
043: private Map paramObjects = new HashMap();
044: private List batchParameters = new ArrayList();
045: private String sql;
046: private MockParameterMetaData parameterMetaData;
047: private boolean returnGeneratedKeys = false;
048:
049: public MockPreparedStatement(Connection connection, String sql) {
050: this (connection, sql, false);
051: }
052:
053: public MockPreparedStatement(Connection connection, String sql,
054: boolean returnGeneratedKeys) {
055: super (connection);
056: this .sql = sql;
057: this .returnGeneratedKeys = returnGeneratedKeys;
058: prepareParameterMetaData();
059: }
060:
061: public MockPreparedStatement(Connection connection, String sql,
062: int resultSetType, int resultSetConcurrency) {
063: super (connection, resultSetType, resultSetConcurrency);
064: this .sql = sql;
065: prepareParameterMetaData();
066: }
067:
068: public MockPreparedStatement(Connection connection, String sql,
069: int resultSetType, int resultSetConcurrency,
070: int resultSetHoldability) {
071: super (connection, resultSetType, resultSetConcurrency,
072: resultSetHoldability);
073: this .sql = sql;
074: prepareParameterMetaData();
075: }
076:
077: public void setPreparedStatementResultSetHandler(
078: AbstractParameterResultSetHandler resultSetHandler) {
079: super .setResultSetHandler(resultSetHandler);
080: this .resultSetHandler = resultSetHandler;
081: }
082:
083: private void prepareParameterMetaData() {
084: int number = StringUtil.countMatches(sql, "?");
085: parameterMetaData = new MockParameterMetaData();
086: parameterMetaData.setParameterCount(number);
087: }
088:
089: public String getSQL() {
090: return sql;
091: }
092:
093: public Map getIndexedParameterMap() {
094: return Collections.unmodifiableMap(paramObjects);
095: }
096:
097: public Map getParameterMap() {
098: return getIndexedParameterMap();
099: }
100:
101: public Object getParameter(int index) {
102: return paramObjects.get(new Integer(index));
103: }
104:
105: public void setObject(int index, Object object) throws SQLException {
106: paramObjects.put(new Integer(index), object);
107: }
108:
109: public void setObject(int parameterIndex, Object object,
110: int targetSqlType, int scale) throws SQLException {
111: setObject(parameterIndex, object);
112: }
113:
114: public void setObject(int parameterIndex, Object object,
115: int targetSqlType) throws SQLException {
116: setObject(parameterIndex, object);
117: }
118:
119: public void addBatch() throws SQLException {
120: batchParameters.add(new HashMap(paramObjects));
121: }
122:
123: public void clearParameters() throws SQLException {
124: paramObjects.clear();
125: }
126:
127: public boolean execute() throws SQLException {
128: boolean callExecuteQuery = isQuery(getSQL());
129: if (callExecuteQuery) {
130: executeQuery();
131: } else {
132: executeUpdate();
133: }
134: return callExecuteQuery;
135: }
136:
137: public ResultSet executeQuery() throws SQLException {
138: return executeQuery(paramObjects);
139: }
140:
141: protected ResultSet executeQuery(Map params) throws SQLException {
142: SQLException exception = resultSetHandler.getSQLException(sql,
143: params);
144: if (null != exception) {
145: throw exception;
146: }
147: exception = resultSetHandler.getSQLException(sql);
148: if (null != exception) {
149: throw exception;
150: }
151: resultSetHandler.addParameterMapForExecutedStatement(getSQL(),
152: getParameterMapCopy(params));
153: if (resultSetHandler.hasMultipleResultSets(getSQL(), params)) {
154: MockResultSet[] results = resultSetHandler.getResultSets(
155: getSQL(), params);
156: if (null != results) {
157: resultSetHandler.addExecutedStatement(getSQL());
158: return cloneAndSetMultipleResultSets(results, params);
159: }
160: } else {
161: MockResultSet result = resultSetHandler.getResultSet(
162: getSQL(), params);
163: if (null != result) {
164: resultSetHandler.addExecutedStatement(getSQL());
165: return cloneAndSetSingleResultSet(result, params);
166: }
167: }
168: ResultSet super ResultSet = super .executeQuery(getSQL());
169: setGeneratedKeysResultSet(sql, params);
170: return super ResultSet;
171: }
172:
173: private MockResultSet cloneAndSetSingleResultSet(
174: MockResultSet result, Map params) {
175: result = cloneResultSet(result);
176: if (null != result) {
177: resultSetHandler.addReturnedResultSet(result);
178: }
179: setResultSets(new MockResultSet[] { result });
180: setGeneratedKeysResultSet(sql, params);
181: return result;
182: }
183:
184: private MockResultSet cloneAndSetMultipleResultSets(
185: MockResultSet[] results, Map params) {
186: results = cloneResultSets(results);
187: if (null != results) {
188: resultSetHandler.addReturnedResultSets(results);
189: }
190: setResultSets(results);
191: setGeneratedKeysResultSet(sql, params);
192: if (null != results && results.length > 0) {
193: return results[0];
194: }
195: return null;
196: }
197:
198: public int executeUpdate() throws SQLException {
199: return executeUpdate(paramObjects);
200: }
201:
202: protected int executeUpdate(Map params) throws SQLException {
203: SQLException exception = resultSetHandler.getSQLException(sql,
204: params);
205: if (null != exception) {
206: throw exception;
207: }
208: exception = resultSetHandler.getSQLException(sql);
209: if (null != exception) {
210: throw exception;
211: }
212: resultSetHandler.addParameterMapForExecutedStatement(getSQL(),
213: getParameterMapCopy(params));
214: if (resultSetHandler.hasMultipleUpdateCounts(getSQL(), params)) {
215: Integer[] updateCounts = resultSetHandler.getUpdateCounts(
216: getSQL(), params);
217: if (null != updateCounts) {
218: resultSetHandler.addExecutedStatement(getSQL());
219: return setMultipleUpdateCounts((int[]) ArrayUtil
220: .convertToPrimitiveArray(updateCounts), params);
221: }
222: } else {
223: Integer updateCount = resultSetHandler.getUpdateCount(
224: getSQL(), params);
225: if (null != updateCount) {
226: resultSetHandler.addExecutedStatement(getSQL());
227: return setSingleUpdateCount(updateCount.intValue(),
228: params);
229: }
230: }
231: int super UpdateCount = super .executeUpdate(getSQL());
232: setGeneratedKeysResultSet(sql, params);
233: return super UpdateCount;
234: }
235:
236: private int setSingleUpdateCount(int updateCount, Map params) {
237: setUpdateCounts(new int[] { updateCount });
238: setGeneratedKeysResultSet(sql, params);
239: return updateCount;
240: }
241:
242: private int setMultipleUpdateCounts(int[] updateCounts, Map params) {
243: setUpdateCounts(updateCounts);
244: setGeneratedKeysResultSet(sql, params);
245: if (null != updateCounts && updateCounts.length > 0) {
246: return updateCounts[0];
247: }
248: return 0;
249: }
250:
251: public int[] executeBatch() throws SQLException {
252: return executeBatch(this .batchParameters);
253: }
254:
255: protected int[] executeBatch(List batchParams) throws SQLException {
256: int[] results = new int[batchParams.size()];
257: SQLException exception = null;
258: for (int ii = 0; ii < results.length; ii++) {
259: if (isQuery(getSQL())) {
260: exception = prepareFailedResult(
261: results,
262: ii,
263: "SQL "
264: + getSQL()
265: + " in the list of batches returned a ResultSet.",
266: null);
267: } else {
268: try {
269: Map currentParameters = (Map) batchParams.get(ii);
270: results[ii] = executeUpdate(currentParameters);
271: } catch (SQLException exc) {
272: exception = prepareFailedResult(results, ii, null,
273: exc);
274: }
275: }
276: if (null != exception
277: && !resultSetHandler
278: .getContinueProcessingOnBatchFailure()) {
279: throw exception;
280: }
281: }
282: if (null != exception) {
283: throw new BatchUpdateException(exception.getMessage(),
284: exception.getSQLState(), exception.getErrorCode(),
285: results);
286: }
287: return results;
288: }
289:
290: private void setGeneratedKeysResultSet(String sql, Map params) {
291: MockResultSet generatedKeys = resultSetHandler
292: .getGeneratedKeys(sql, params);
293: if (returnGeneratedKeys) {
294: if (null != generatedKeys) {
295: setLastGeneratedKeysResultSet(generatedKeys);
296: } else {
297: setLastGeneratedKeysResultSet(determineGeneratedKeysResultSet(sql));
298: }
299: } else {
300: setLastGeneratedKeysResultSet(null);
301: }
302: }
303:
304: public ResultSetMetaData getMetaData() throws SQLException {
305: return new MockResultSetMetaData();
306: }
307:
308: public ParameterMetaData getParameterMetaData() throws SQLException {
309: return parameterMetaData;
310: }
311:
312: public void setArray(int parameterIndex, Array array)
313: throws SQLException {
314: setObject(parameterIndex, array);
315: }
316:
317: public void setAsciiStream(int parameterIndex, InputStream stream)
318: throws SQLException {
319: setBinaryStream(parameterIndex, stream);
320: }
321:
322: public void setAsciiStream(int parameterIndex, InputStream stream,
323: int length) throws SQLException {
324: setBinaryStream(parameterIndex, stream, length);
325: }
326:
327: public void setAsciiStream(int parameterIndex, InputStream stream,
328: long length) throws SQLException {
329: setBinaryStream(parameterIndex, stream, length);
330: }
331:
332: public void setBinaryStream(int parameterIndex, InputStream stream)
333: throws SQLException {
334: byte[] data = StreamUtil.getStreamAsByteArray(stream);
335: setObject(parameterIndex, new ByteArrayInputStream(data));
336: }
337:
338: public void setBinaryStream(int parameterIndex, InputStream stream,
339: int length) throws SQLException {
340: byte[] data = StreamUtil.getStreamAsByteArray(stream, length);
341: setObject(parameterIndex, new ByteArrayInputStream(data));
342: }
343:
344: public void setBinaryStream(int parameterIndex, InputStream stream,
345: long length) throws SQLException {
346: setBinaryStream(parameterIndex, stream, (int) length);
347: }
348:
349: public void setCharacterStream(int parameterIndex, Reader reader)
350: throws SQLException {
351: String data = StreamUtil.getReaderAsString(reader);
352: setObject(parameterIndex, new StringReader(data));
353: }
354:
355: public void setCharacterStream(int parameterIndex, Reader reader,
356: int length) throws SQLException {
357: String data = StreamUtil
358: .getReaderAsString(reader, (int) length);
359: setObject(parameterIndex, new StringReader(data));
360: }
361:
362: public void setCharacterStream(int parameterIndex, Reader reader,
363: long length) throws SQLException {
364: setCharacterStream(parameterIndex, reader, (int) length);
365: }
366:
367: public void setNCharacterStream(int parameterIndex, Reader reader)
368: throws SQLException {
369: setCharacterStream(parameterIndex, reader);
370: }
371:
372: public void setNCharacterStream(int parameterIndex, Reader reader,
373: long length) throws SQLException {
374: setCharacterStream(parameterIndex, reader, length);
375: }
376:
377: public void setBigDecimal(int parameterIndex, BigDecimal bigDecimal)
378: throws SQLException {
379: setObject(parameterIndex, bigDecimal);
380: }
381:
382: public void setBlob(int parameterIndex, Blob blob)
383: throws SQLException {
384: setObject(parameterIndex, blob);
385: }
386:
387: public void setBlob(int parameterIndex, InputStream inputStream)
388: throws SQLException {
389: byte[] data = StreamUtil.getStreamAsByteArray(inputStream);
390: setBlob(parameterIndex, new MockBlob(data));
391: }
392:
393: public void setBlob(int parameterIndex, InputStream inputStream,
394: long length) throws SQLException {
395: byte[] data = StreamUtil.getStreamAsByteArray(inputStream,
396: (int) length);
397: setBlob(parameterIndex, new MockBlob(data));
398: }
399:
400: public void setBoolean(int parameterIndex, boolean bool)
401: throws SQLException {
402: setObject(parameterIndex, new Boolean(bool));
403: }
404:
405: public void setByte(int parameterIndex, byte byteValue)
406: throws SQLException {
407: setObject(parameterIndex, new Byte(byteValue));
408: }
409:
410: public void setBytes(int parameterIndex, byte[] byteArray)
411: throws SQLException {
412: setObject(parameterIndex, byteArray);
413: }
414:
415: public void setClob(int parameterIndex, Clob clob)
416: throws SQLException {
417: setObject(parameterIndex, clob);
418: }
419:
420: public void setClob(int parameterIndex, Reader reader)
421: throws SQLException {
422: String data = StreamUtil.getReaderAsString(reader);
423: setClob(parameterIndex, new MockClob(data));
424: }
425:
426: public void setClob(int parameterIndex, Reader reader, long length)
427: throws SQLException {
428: String data = StreamUtil
429: .getReaderAsString(reader, (int) length);
430: setClob(parameterIndex, new MockClob(data));
431: }
432:
433: /*public void setNClob(int parameterIndex, NClob nClob) throws SQLException
434: {
435: setObject(parameterIndex, nClob);
436: }*/
437:
438: /*public void setNClob(int parameterIndex, Reader reader) throws SQLException
439: {
440: String data = StreamUtil.getReaderAsString(reader);
441: setNClob(parameterIndex, new MockNClob(data));
442: }*/
443:
444: /*public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException
445: {
446: String data = StreamUtil.getReaderAsString(reader, (int)length);
447: setNClob(parameterIndex, new MockNClob(data));
448: }*/
449:
450: /*public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException
451: {
452: setObject(parameterIndex, xmlObject);
453: }*/
454:
455: public void setDate(int parameterIndex, Date date, Calendar calendar)
456: throws SQLException {
457: setObject(parameterIndex, date);
458: }
459:
460: public void setDate(int parameterIndex, Date date)
461: throws SQLException {
462: setObject(parameterIndex, date);
463: }
464:
465: public void setDouble(int parameterIndex, double doubleValue)
466: throws SQLException {
467: setObject(parameterIndex, new Double(doubleValue));
468: }
469:
470: public void setFloat(int parameterIndex, float floatValue)
471: throws SQLException {
472: setObject(parameterIndex, new Float(floatValue));
473: }
474:
475: public void setInt(int parameterIndex, int intValue)
476: throws SQLException {
477: setObject(parameterIndex, new Integer(intValue));
478: }
479:
480: public void setLong(int parameterIndex, long longValue)
481: throws SQLException {
482: setObject(parameterIndex, new Long(longValue));
483: }
484:
485: public void setNull(int parameterIndex, int sqlType, String typeName)
486: throws SQLException {
487: setObject(parameterIndex, null);
488: }
489:
490: public void setNull(int parameterIndex, int sqlType)
491: throws SQLException {
492: setObject(parameterIndex, null);
493: }
494:
495: public void setRef(int parameterIndex, Ref ref) throws SQLException {
496: setObject(parameterIndex, ref);
497: }
498:
499: /*public void setRowId(int parameterIndex, RowId rowId) throws SQLException
500: {
501: setObject(parameterIndex, rowId);
502: }*/
503:
504: public void setShort(int parameterIndex, short shortValue)
505: throws SQLException {
506: setObject(parameterIndex, new Short(shortValue));
507: }
508:
509: public void setString(int parameterIndex, String string)
510: throws SQLException {
511: setObject(parameterIndex, string);
512: }
513:
514: public void setNString(int parameterIndex, String string)
515: throws SQLException {
516: setObject(parameterIndex, string);
517: }
518:
519: public void setTime(int parameterIndex, Time time, Calendar calendar)
520: throws SQLException {
521: setObject(parameterIndex, time);
522: }
523:
524: public void setTime(int parameterIndex, Time time)
525: throws SQLException {
526: setObject(parameterIndex, time);
527: }
528:
529: public void setTimestamp(int parameterIndex, Timestamp timeStamp,
530: Calendar cal) throws SQLException {
531: setObject(parameterIndex, timeStamp);
532: }
533:
534: public void setTimestamp(int parameterIndex, Timestamp timeStamp)
535: throws SQLException {
536: setObject(parameterIndex, timeStamp);
537: }
538:
539: public void setUnicodeStream(int parameterIndex,
540: InputStream stream, int length) throws SQLException {
541: setObject(parameterIndex, stream);
542: }
543:
544: public void setURL(int parameterIndex, URL url) throws SQLException {
545: setObject(parameterIndex, url);
546: }
547:
548: private Map getParameterMapCopy(Map actualParameters) {
549: Map copyParameters = new HashMap();
550: Iterator keys = actualParameters.keySet().iterator();
551: while (keys.hasNext()) {
552: Object key = keys.next();
553: Object actualParameter = actualParameters.get(key);
554: Object copyParameter = ParameterUtil
555: .copyParameter(actualParameter);
556: copyParameters.put(key, copyParameter);
557: }
558: return copyParameters;
559: }
560: }
|