001: /*
002: * Craftsman Spy.
003: * Copyright (C) 2005 Sébastien LECACHEUR
004: *
005: * This program is free software; you can redistribute it and/or modify
006: * it under the terms of the GNU General Public License as published by
007: * the Free Software Foundation; either version 2 of the License, or
008: * (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: */
019: package craftsman.spy;
020:
021: import java.io.InputStream;
022: import java.io.Reader;
023: import java.math.BigDecimal;
024: import java.net.URL;
025: import java.sql.Array;
026: import java.sql.Blob;
027: import java.sql.CallableStatement;
028: import java.sql.Clob;
029: import java.sql.Connection;
030: import java.sql.Date;
031: import java.sql.Ref;
032: import java.sql.SQLException;
033: import java.sql.Time;
034: import java.sql.Timestamp;
035: import java.sql.Types;
036: import java.util.ArrayList;
037: import java.util.Calendar;
038: import java.util.HashMap;
039: import java.util.Map;
040:
041: /**
042: * The classe used to execute SQL stored procedures.
043: *
044: * @author Sébastien LECACHEUR
045: */
046: public class SpyCallableStatement extends SpyPreparedStatement
047: implements CallableStatement {
048: /**
049: * The real JDBC callable statement instance.
050: */
051: private CallableStatement real = null;
052:
053: /**
054: * Indicates if the output parameters were already logged.
055: */
056: private boolean outputParametersLogged = false;
057:
058: /**
059: * The list of all the output parameters type.
060: */
061: private ArrayList outputParametersIndex = null;
062:
063: /**
064: * The list of all the output parameters name.
065: */
066: private HashMap outputParametersName = null;
067:
068: /**
069: * Constructs a new Spy JDBC callable statement.
070: * @param c Connection The used connection.
071: * @param cstm CallableStatement The real JDBC callable statement.
072: * @param sql String The callable SQL.
073: */
074: protected SpyCallableStatement(Connection c,
075: CallableStatement cstm, String sql) {
076: super (c, cstm, sql);
077: real = cstm;
078:
079: // Initialize capacity with the number of '?' in sql string
080: outputParametersIndex = new ArrayList(
081: getEstimatedParametersCount() + 1);
082: for (int i = 0; i < getEstimatedParametersCount() + 1; i++)
083: outputParametersIndex.add(i, null);
084: outputParametersName = new HashMap(
085: getEstimatedParametersCount() + 1);
086: }
087:
088: /**
089: * Registers the given output parameter.
090: *
091: * @param paramIndex int The index position of the parameter.
092: * @param type int The type of the parameter.
093: */
094: private void registerOutputParameter(int paramIndex, int type) {
095: if (outputParametersIndex.size() <= paramIndex) {
096: outputParametersIndex.ensureCapacity(paramIndex + 1);
097: for (int i = outputParametersIndex.size(); i < paramIndex; i++)
098: outputParametersIndex.add(i, null);
099: outputParametersIndex.add(paramIndex, new Integer(type));
100: } else {
101: outputParametersIndex.set(paramIndex, new Integer(type));
102: }
103: }
104:
105: /**
106: * Registers the given output parameter.
107: *
108: * @param paramName String The name of the parameter.
109: * @param type int The type of the parameter.
110: */
111: private void registerOutputParameter(String paramName, int type) {
112: outputParametersName.put(paramName, new Integer(type));
113: }
114:
115: /**
116: * @see SpyPreparedStatement#clearParameters()
117: */
118: public void clearParameters() throws SQLException {
119: outputParametersIndex.clear();
120: outputParametersName.clear();
121: super .clearParameters();
122: }
123:
124: /**
125: * Logs all the output parameters.
126: */
127: private void logOutputParameters() {
128: //TODO add input parameter
129: //TODO add output parameter registrered by name
130: /*
131: * Cannot use {@link PreparedStatement#getParameterMetaData()} because some
132: * JDBC drivers don't implement this method.
133: */
134: if (outputParametersLogged == false) {
135: StringBuffer displayableSql = new StringBuffer(preparedSql
136: .length());
137:
138: if (outputParametersIndex != null
139: && outputParametersName != null) {
140: int i = 1, limit = 0, base = 0;
141: while ((limit = preparedSql.indexOf('?', limit)) != -1) {
142: displayableSql.append(preparedSql.substring(base,
143: limit));
144: if (outputParametersIndex.get(i) != null) {
145: switch (((Integer) outputParametersIndex.get(i))
146: .intValue()) {
147: case Types.ARRAY:
148: case Types.BLOB:
149: case Types.CHAR:
150: case Types.CLOB:
151: case Types.DATALINK:
152: case Types.DATE:
153: case Types.JAVA_OBJECT:
154: case Types.LONGVARBINARY:
155: case Types.LONGVARCHAR:
156: case Types.REF:
157: case Types.TIME:
158: case Types.TIMESTAMP:
159: case Types.VARBINARY:
160: case Types.VARCHAR:
161: displayableSql.append("'");
162: try {
163: displayableSql
164: .append(real.getString(i));
165: } catch (SQLException e) {
166: if (log.isErrorEnabled())
167: log
168: .error(
169: getId()
170: + ":"
171: + "unable to retrieve output parameter",
172: e);
173: }
174: displayableSql.append("'");
175: break;
176: default:
177: try {
178: displayableSql
179: .append(real.getString(i));
180: } catch (SQLException e) {
181: if (log.isErrorEnabled())
182: log
183: .error(
184: getId()
185: + ":"
186: + "unable to retrieve output parameter",
187: e);
188: }
189: break;
190: }
191: } else {
192: displayableSql.append("?");
193: }
194: i++;
195: limit++;
196: base = limit;
197: }
198:
199: if (base < preparedSql.length()) {
200: displayableSql.append(preparedSql.substring(base));
201: }
202: }
203:
204: log.info(getId() + ":" + displayableSql.toString());
205: outputParametersLogged = true;
206: }
207: }
208:
209: /**
210: * @see CallableStatement#wasNull()
211: */
212: public boolean wasNull() throws SQLException {
213: return real.wasNull();
214: }
215:
216: /**
217: * @see CallableStatement#getByte(int)
218: */
219: public byte getByte(int parameterIndex) throws SQLException {
220: logOutputParameters();
221: return real.getByte(parameterIndex);
222: }
223:
224: /**
225: * @see CallableStatement#getDouble(int)
226: */
227: public double getDouble(int parameterIndex) throws SQLException {
228: logOutputParameters();
229: return real.getDouble(parameterIndex);
230: }
231:
232: /**
233: * @see CallableStatement#getFloat(int)
234: */
235: public float getFloat(int parameterIndex) throws SQLException {
236: logOutputParameters();
237: return real.getFloat(parameterIndex);
238: }
239:
240: /**
241: * @see CallableStatement#getInt(int)
242: */
243: public int getInt(int parameterIndex) throws SQLException {
244: logOutputParameters();
245: return real.getInt(parameterIndex);
246: }
247:
248: /**
249: * @see CallableStatement#getLong(int)
250: */
251: public long getLong(int parameterIndex) throws SQLException {
252: logOutputParameters();
253: return real.getLong(parameterIndex);
254: }
255:
256: /**
257: * @see CallableStatement#getShort(int)
258: */
259: public short getShort(int parameterIndex) throws SQLException {
260: logOutputParameters();
261: return real.getShort(parameterIndex);
262: }
263:
264: /**
265: * @see CallableStatement#getBoolean(int)
266: */
267: public boolean getBoolean(int parameterIndex) throws SQLException {
268: logOutputParameters();
269: return real.getBoolean(parameterIndex);
270: }
271:
272: /**
273: * @see CallableStatement#getBytes(int)
274: */
275: public byte[] getBytes(int parameterIndex) throws SQLException {
276: logOutputParameters();
277: return real.getBytes(parameterIndex);
278: }
279:
280: /**
281: * @see CallableStatement#registerOutParameter(int, int)
282: */
283: public void registerOutParameter(int parameterIndex, int sqlType)
284: throws SQLException {
285: registerOutputParameter(parameterIndex, sqlType);
286: real.registerOutParameter(parameterIndex, sqlType);
287: }
288:
289: /**
290: * @see CallableStatement#registerOutParameter(int, int, int)
291: */
292: public void registerOutParameter(int parameterIndex, int sqlType,
293: int scale) throws SQLException {
294: registerOutputParameter(parameterIndex, sqlType);
295: real.registerOutParameter(parameterIndex, sqlType, scale);
296: }
297:
298: /**
299: * @see CallableStatement#getObject(int)
300: */
301: public Object getObject(int parameterIndex) throws SQLException {
302: logOutputParameters();
303: return real.getObject(parameterIndex);
304: }
305:
306: /**
307: * @see CallableStatement#getString(int)
308: */
309: public String getString(int parameterIndex) throws SQLException {
310: logOutputParameters();
311: return real.getString(parameterIndex);
312: }
313:
314: /**
315: * @see CallableStatement#registerOutParameter(int, int, String)
316: */
317: public void registerOutParameter(int paramIndex, int sqlType,
318: String typeName) throws SQLException {
319: registerOutputParameter(paramIndex, sqlType);
320: real.registerOutParameter(paramIndex, sqlType, typeName);
321: }
322:
323: /**
324: * @see CallableStatement#getByte(String)
325: */
326: public byte getByte(String parameterName) throws SQLException {
327: logOutputParameters();
328: return real.getByte(parameterName);
329: }
330:
331: /**
332: * @see CallableStatement#getDouble(String)
333: */
334: public double getDouble(String parameterName) throws SQLException {
335: logOutputParameters();
336: return real.getDouble(parameterName);
337: }
338:
339: /**
340: * @see CallableStatement#getFloat(String)
341: */
342: public float getFloat(String parameterName) throws SQLException {
343: logOutputParameters();
344: return real.getFloat(parameterName);
345: }
346:
347: /**
348: * @see CallableStatement#getInt(String)
349: */
350: public int getInt(String parameterName) throws SQLException {
351: logOutputParameters();
352: return real.getInt(parameterName);
353: }
354:
355: /**
356: * @see CallableStatement#getLong(String)
357: */
358: public long getLong(String parameterName) throws SQLException {
359: logOutputParameters();
360: return real.getLong(parameterName);
361: }
362:
363: /**
364: * @see CallableStatement#getShort(String)
365: */
366: public short getShort(String parameterName) throws SQLException {
367: logOutputParameters();
368: return real.getShort(parameterName);
369: }
370:
371: /**
372: * @see CallableStatement#getBoolean(String)
373: */
374: public boolean getBoolean(String parameterName) throws SQLException {
375: logOutputParameters();
376: return real.getBoolean(parameterName);
377: }
378:
379: /**
380: * @see CallableStatement#getBytes(String)
381: */
382: public byte[] getBytes(String parameterName) throws SQLException {
383: logOutputParameters();
384: return real.getBytes(parameterName);
385: }
386:
387: /**
388: * @see CallableStatement#setByte(String, byte)
389: */
390: public void setByte(String parameterName, byte x)
391: throws SQLException {
392: real.setByte(parameterName, x);
393: }
394:
395: /**
396: * @see CallableStatement#setDouble(String, double)
397: */
398: public void setDouble(String parameterName, double x)
399: throws SQLException {
400: real.setDouble(parameterName, x);
401: }
402:
403: /**
404: * @see CallableStatement#setFloat(String, float)
405: */
406: public void setFloat(String parameterName, float x)
407: throws SQLException {
408: real.setFloat(parameterName, x);
409: }
410:
411: /**
412: * @see CallableStatement#registerOutParameter(String, int)
413: */
414: public void registerOutParameter(String parameterName, int sqlType)
415: throws SQLException {
416: registerOutputParameter(parameterName, sqlType);
417: real.registerOutParameter(parameterName, sqlType);
418: }
419:
420: /**
421: * @see CallableStatement#setInt(String, int)
422: */
423: public void setInt(String parameterName, int x) throws SQLException {
424: real.setInt(parameterName, x);
425: }
426:
427: /**
428: * @see CallableStatement#setNull(String, int)
429: */
430: public void setNull(String parameterName, int sqlType)
431: throws SQLException {
432: real.setNull(parameterName, sqlType);
433: }
434:
435: /**
436: * @see CallableStatement#registerOutParameter(String, int, int)
437: */
438: public void registerOutParameter(String parameterName, int sqlType,
439: int scale) throws SQLException {
440: registerOutputParameter(parameterName, sqlType);
441: real.registerOutParameter(parameterName, sqlType, scale);
442: }
443:
444: /**
445: * @see CallableStatement#setLong(String, long)
446: */
447: public void setLong(String parameterName, long x)
448: throws SQLException {
449: real.setLong(parameterName, x);
450: }
451:
452: /**
453: * @see CallableStatement#setShort(String, short)
454: */
455: public void setShort(String parameterName, short x)
456: throws SQLException {
457: real.setShort(parameterName, x);
458: }
459:
460: /**
461: * @see CallableStatement#setBoolean(String, boolean)
462: */
463: public void setBoolean(String parameterName, boolean x)
464: throws SQLException {
465: real.setBoolean(parameterName, x);
466: }
467:
468: /**
469: * @see CallableStatement#setBytes(String, byte[])
470: */
471: public void setBytes(String parameterName, byte[] x)
472: throws SQLException {
473: real.setBytes(parameterName, x);
474: }
475:
476: /**
477: * @see CallableStatement#getBigDecimal(int)
478: */
479: public BigDecimal getBigDecimal(int parameterIndex)
480: throws SQLException {
481: logOutputParameters();
482: return real.getBigDecimal(parameterIndex);
483: }
484:
485: /**
486: * @see CallableStatement#getBigDecimal(int, int)
487: */
488: public BigDecimal getBigDecimal(int parameterIndex, int scale)
489: throws SQLException {
490: logOutputParameters();
491: return real.getBigDecimal(parameterIndex, scale);
492: }
493:
494: /**
495: * @see CallableStatement#getURL(int)
496: */
497: public URL getURL(int parameterIndex) throws SQLException {
498: logOutputParameters();
499: return real.getURL(parameterIndex);
500: }
501:
502: /**
503: * @see CallableStatement#getArray(int)
504: */
505: public Array getArray(int i) throws SQLException {
506: logOutputParameters();
507: return real.getArray(i);
508: }
509:
510: /**
511: * @see CallableStatement#getBlob(int)
512: */
513: public Blob getBlob(int i) throws SQLException {
514: logOutputParameters();
515: return real.getBlob(i);
516: }
517:
518: /**
519: * @see CallableStatement#getClob(int)
520: */
521: public Clob getClob(int i) throws SQLException {
522: logOutputParameters();
523: return real.getClob(i);
524: }
525:
526: /**
527: * @see CallableStatement#getDate(int)
528: */
529: public Date getDate(int parameterIndex) throws SQLException {
530: logOutputParameters();
531: return real.getDate(parameterIndex);
532: }
533:
534: /**
535: * @see CallableStatement#getRef(int)
536: */
537: public Ref getRef(int i) throws SQLException {
538: logOutputParameters();
539: return real.getRef(i);
540: }
541:
542: /**
543: * @see CallableStatement#getTime(int)
544: */
545: public Time getTime(int parameterIndex) throws SQLException {
546: logOutputParameters();
547: return real.getTime(parameterIndex);
548: }
549:
550: /**
551: * @see CallableStatement#getTimestamp(int)
552: */
553: public Timestamp getTimestamp(int parameterIndex)
554: throws SQLException {
555: logOutputParameters();
556: return real.getTimestamp(parameterIndex);
557: }
558:
559: /**
560: * @see CallableStatement#setAsciiStream(String, java.io.InputStream, int)
561: */
562: public void setAsciiStream(String parameterName, InputStream x,
563: int length) throws SQLException {
564: real.setAsciiStream(parameterName, x, length);
565: }
566:
567: /**
568: * @see CallableStatement#setBinaryStream(String, java.io.InputStream, int)
569: */
570: public void setBinaryStream(String parameterName, InputStream x,
571: int length) throws SQLException {
572: real.setBinaryStream(parameterName, x, length);
573: }
574:
575: /**
576: * @see CallableStatement#setCharacterStream(String, java.io.Reader, int)
577: */
578: public void setCharacterStream(String parameterName, Reader reader,
579: int length) throws SQLException {
580: real.setCharacterStream(parameterName, reader, length);
581: }
582:
583: /**
584: * @see CallableStatement#getObject(String)
585: */
586: public Object getObject(String parameterName) throws SQLException {
587: logOutputParameters();
588: return real.getObject(parameterName);
589: }
590:
591: /**
592: * @see CallableStatement#setObject(String, Object)
593: */
594: public void setObject(String parameterName, Object x)
595: throws SQLException {
596: real.setObject(parameterName, x);
597: }
598:
599: /**
600: * @see CallableStatement#setObject(String, Object, int)
601: */
602: public void setObject(String parameterName, Object x,
603: int targetSqlType) throws SQLException {
604: real.setObject(parameterName, x, targetSqlType);
605: }
606:
607: /**
608: * @see CallableStatement#setObject(String, Object, int, int)
609: */
610: public void setObject(String parameterName, Object x,
611: int targetSqlType, int scale) throws SQLException {
612: real.setObject(parameterName, x, targetSqlType, scale);
613: }
614:
615: /**
616: * @see CallableStatement#getObject(int, Map)
617: */
618: public Object getObject(int i, Map map) throws SQLException {
619: logOutputParameters();
620: return real.getObject(i, map);
621: }
622:
623: /**
624: * @see CallableStatement#getString(String)
625: */
626: public String getString(String parameterName) throws SQLException {
627: logOutputParameters();
628: return real.getString(parameterName);
629: }
630:
631: /**
632: * @see CallableStatement#registerOutParameter(String, int, String)
633: */
634: public void registerOutParameter(String parameterName, int sqlType,
635: String typeName) throws SQLException {
636: registerOutputParameter(parameterName, sqlType);
637: real.registerOutParameter(parameterName, sqlType, typeName);
638: }
639:
640: /**
641: * @see CallableStatement#setNull(String, int, String)
642: */
643: public void setNull(String parameterName, int sqlType,
644: String typeName) throws SQLException {
645: real.setNull(parameterName, sqlType, typeName);
646: }
647:
648: /**
649: * @see CallableStatement#setString(String, String)
650: */
651: public void setString(String parameterName, String x)
652: throws SQLException {
653: real.setString(parameterName, x);
654: }
655:
656: /**
657: * @see CallableStatement#getBigDecimal(String)
658: */
659: public BigDecimal getBigDecimal(String parameterName)
660: throws SQLException {
661: logOutputParameters();
662: return real.getBigDecimal(parameterName);
663: }
664:
665: /**
666: * @see CallableStatement#setBigDecimal(String, BigDecimal)
667: */
668: public void setBigDecimal(String parameterName, BigDecimal x)
669: throws SQLException {
670: real.setBigDecimal(parameterName, x);
671: }
672:
673: /**
674: * @see CallableStatement#getURL(String)
675: */
676: public URL getURL(String parameterName) throws SQLException {
677: logOutputParameters();
678: return real.getURL(parameterName);
679: }
680:
681: /**
682: * @see CallableStatement#setURL(String, java.net.URL)
683: */
684: public void setURL(String parameterName, URL val)
685: throws SQLException {
686: real.setURL(parameterName, val);
687: }
688:
689: /**
690: * @see CallableStatement#getArray(String)
691: */
692: public Array getArray(String parameterName) throws SQLException {
693: logOutputParameters();
694: return real.getArray(parameterName);
695: }
696:
697: /**
698: * @see CallableStatement#getBlob(String)
699: */
700: public Blob getBlob(String parameterName) throws SQLException {
701: logOutputParameters();
702: return real.getBlob(parameterName);
703: }
704:
705: /**
706: * @see CallableStatement#getClob(String)
707: */
708: public Clob getClob(String parameterName) throws SQLException {
709: logOutputParameters();
710: return real.getClob(parameterName);
711: }
712:
713: /**
714: * @see CallableStatement#getDate(String)
715: */
716: public Date getDate(String parameterName) throws SQLException {
717: logOutputParameters();
718: return real.getDate(parameterName);
719: }
720:
721: /**
722: * @see CallableStatement#setDate(String, Date)
723: */
724: public void setDate(String parameterName, Date x)
725: throws SQLException {
726: real.setDate(parameterName, x);
727: }
728:
729: /**
730: * @see CallableStatement#getDate(int, Calendar)
731: */
732: public Date getDate(int parameterIndex, Calendar cal)
733: throws SQLException {
734: logOutputParameters();
735: return real.getDate(parameterIndex, cal);
736: }
737:
738: /**
739: * @see CallableStatement#getRef(String)
740: */
741: public Ref getRef(String parameterName) throws SQLException {
742: logOutputParameters();
743: return real.getRef(parameterName);
744: }
745:
746: /**
747: * @see CallableStatement#getTime(String)
748: */
749: public Time getTime(String parameterName) throws SQLException {
750: logOutputParameters();
751: return real.getTime(parameterName);
752: }
753:
754: /**
755: * @see CallableStatement#setTime(String, Time)
756: */
757: public void setTime(String parameterName, Time x)
758: throws SQLException {
759: real.setTime(parameterName, x);
760: }
761:
762: /**
763: * @see CallableStatement#getTime(int, Calendar)
764: */
765: public Time getTime(int parameterIndex, Calendar cal)
766: throws SQLException {
767: logOutputParameters();
768: return real.getTime(parameterIndex, cal);
769: }
770:
771: /**
772: * @see CallableStatement#getTimestamp(String)
773: */
774: public Timestamp getTimestamp(String parameterName)
775: throws SQLException {
776: logOutputParameters();
777: return real.getTimestamp(parameterName);
778: }
779:
780: /**
781: * @see CallableStatement#setTimestamp(String, Timestamp)
782: */
783: public void setTimestamp(String parameterName, Timestamp x)
784: throws SQLException {
785: real.setTimestamp(parameterName, x);
786: }
787:
788: /**
789: * @see CallableStatement#getTimestamp(int, Calendar)
790: */
791: public Timestamp getTimestamp(int parameterIndex, Calendar cal)
792: throws SQLException {
793: logOutputParameters();
794: return real.getTimestamp(parameterIndex, cal);
795: }
796:
797: /**
798: * @see CallableStatement#getObject(String, Map)
799: */
800: public Object getObject(String parameterName, Map map)
801: throws SQLException {
802: logOutputParameters();
803: return real.getObject(parameterName, map);
804: }
805:
806: /**
807: * @see CallableStatement#getDate(String, Calendar)
808: */
809: public Date getDate(String parameterName, Calendar cal)
810: throws SQLException {
811: logOutputParameters();
812: return real.getDate(parameterName, cal);
813: }
814:
815: /**
816: * @see CallableStatement#getTime(String, Calendar)
817: */
818: public Time getTime(String parameterName, Calendar cal)
819: throws SQLException {
820: logOutputParameters();
821: return real.getTime(parameterName, cal);
822: }
823:
824: /**
825: * @see CallableStatement#getTimestamp(String, Calendar)
826: */
827: public Timestamp getTimestamp(String parameterName, Calendar cal)
828: throws SQLException {
829: logOutputParameters();
830: return real.getTimestamp(parameterName, cal);
831: }
832:
833: /**
834: * @see CallableStatement#setDate(String, Date, Calendar)
835: */
836: public void setDate(String parameterName, Date x, Calendar cal)
837: throws SQLException {
838: real.setDate(parameterName, x, cal);
839: }
840:
841: /**
842: * @see CallableStatement#setTime(String, Time, Calendar)
843: */
844: public void setTime(String parameterName, Time x, Calendar cal)
845: throws SQLException {
846: real.setTime(parameterName, x, cal);
847: }
848:
849: /**
850: * @see CallableStatement#setTimestamp(String, Timestamp, Calendar)
851: */
852: public void setTimestamp(String parameterName, Timestamp x,
853: Calendar cal) throws SQLException {
854: real.setTimestamp(parameterName, x, cal);
855: }
856: }
|