001    /*
002     * $Id: StasiPreparedStatement.java,v 1.3 2014/05/17 06:55:25 oboehm Exp $
003     *
004     * Copyright (c) 2014 by Oliver Boehm
005     *
006     * Licensed under the Apache License, Version 2.0 (the "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *   http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     *
018     * (c)reated 05.04.2014 by oliver (ob@oasd.de)
019     */
020    
021    package patterntesting.runtime.monitor.db.internal;
022    
023    import java.io.*;
024    import java.math.BigDecimal;
025    import java.net.URL;
026    import java.sql.*;
027    import java.sql.Date;
028    import java.util.*;
029    
030    import org.apache.commons.lang.StringUtils;
031    import org.slf4j.*;
032    
033    import patterntesting.runtime.log.LogWatch;
034    import patterntesting.runtime.monitor.ProfileMonitor;
035    import patterntesting.runtime.monitor.db.SqlStatistic;
036    
037    /**
038     * A simple wrapper for {@link PreparedStatement} to be able to find resource
039     * problems while reading and writing to the database. It allows us also to
040     * measure times of SQL statements.
041     * <p>
042     * Why the name "Stasi..."? The Stasi was the official state security service of
043     * Eastern Germany which controls the people (like NSA in the U.S. or KGB in
044     * Russia, see also <a href="http://en.wikipedia.org/wiki/Stasi">Wikipedia</a>).
045     * The StasiPreparedStatement controls the embedded {@link PreparedStatement} -
046     * therefore the name.
047     * </p>
048     *
049     * @author oliver
050     * @version $Revision: 1.3 $
051     * @since 1.4.1 (05.04.2014)
052     */
053    public final class StasiPreparedStatement extends StasiStatement implements PreparedStatement {
054    
055        private static final Logger log = LoggerFactory.getLogger(StasiPreparedStatement.class);
056        private final LogWatch logWatch = new LogWatch();
057        private final PreparedStatement preparedStatement;
058    
059        private final String sqlTemplate;
060        private final Map<Integer, Object> parameters = new HashMap<Integer, Object>();
061    
062        /**
063         * Instantiates a new stasi prepared statement.
064         *
065         * @param statement the statement
066         * @param args the arguments for the creation of the
067         *            {@link PreparedStatement}
068         */
069        public StasiPreparedStatement(final PreparedStatement statement, final Object... args) {
070            super(statement);
071            this.preparedStatement = statement;
072            this.sqlTemplate = (String) args[0];
073        }
074    
075        /**
076         * Adds the batch.
077         *
078         * @throws SQLException the sQL exception
079         * @see java.sql.PreparedStatement#addBatch()
080         */
081        public void addBatch() throws SQLException {
082            this.preparedStatement.addBatch();
083            log.trace("Batch added.");
084        }
085    
086        /**
087         * Clear parameters.
088         *
089         * @throws SQLException the sQL exception
090         * @see java.sql.PreparedStatement#clearParameters()
091         */
092        public void clearParameters() throws SQLException {
093            this.preparedStatement.clearParameters();
094            this.parameters.clear();
095            log.trace("Parameters cleared.");
096        }
097    
098        /**
099         * Close.
100         *
101         * @throws SQLException the sQL exception
102         * @see java.sql.Statement#close()
103         */
104        public void close() throws SQLException {
105            this.getStatement().close();
106            log.debug("Statement for \"{}\" was closed after {}.", this.sqlTemplate, logWatch);
107        }
108    
109        /**
110         * Execute.
111         *
112         * @return true, if successful
113         * @throws SQLException the sQL exception
114         * @see java.sql.PreparedStatement#execute()
115         */
116        public boolean execute() throws SQLException {
117            ProfileMonitor mon = SqlStatistic.start(this.sqlTemplate);
118            try {
119                boolean ok = this.preparedStatement.execute();
120                logSQL(mon, ok);
121                return ok;
122            } catch (SQLException ex) {
123                throw enrichedSQLException(mon, ex);
124            }
125        }
126    
127        /**
128         * Execute query.
129         *
130         * @return the result set
131         * @throws SQLException the sQL exception
132         * @see java.sql.PreparedStatement#executeQuery()
133         */
134        public ResultSet executeQuery() throws SQLException {
135            ProfileMonitor mon = SqlStatistic.start(this.sqlTemplate);
136            try {
137                ResultSet rs = new StasiResultSet(this.preparedStatement.executeQuery());
138                this.logSQL(mon, rs);
139                return rs;
140            } catch (SQLException ex) {
141                throw enrichedSQLException(mon, ex);
142            }
143        }
144    
145        /**
146         * Execute update.
147         *
148         * @return the int
149         * @throws SQLException the sQL exception
150         * @see java.sql.PreparedStatement#executeUpdate()
151         */
152        public int executeUpdate() throws SQLException {
153            ProfileMonitor mon = SqlStatistic.start(this.sqlTemplate);
154            try {
155                int ret = this.preparedStatement.executeUpdate();
156                logSQL(mon, ret);
157                return ret;
158            } catch (SQLException ex) {
159                throw enrichedSQLException(mon, ex);
160            }
161        }
162    
163        private SQLException enrichedSQLException(final ProfileMonitor mon, final SQLException original) {
164            return enrichedSQLException(mon, this.resolveSQL(), original);
165        }
166    
167        /**
168         * Gets the meta data.
169         *
170         * @return the meta data
171         * @throws SQLException the sQL exception
172         * @see java.sql.PreparedStatement#getMetaData()
173         */
174        public ResultSetMetaData getMetaData() throws SQLException {
175            return this.preparedStatement.getMetaData();
176        }
177    
178        /**
179         * Gets the parameter meta data.
180         *
181         * @return the parameter meta data
182         * @throws SQLException the sQL exception
183         * @see java.sql.PreparedStatement#getParameterMetaData()
184         */
185        public ParameterMetaData getParameterMetaData() throws SQLException {
186            return this.preparedStatement.getParameterMetaData();
187        }
188    
189        /**
190         * Sets the array.
191         *
192         * @param arg0 the arg0
193         * @param arg1 the arg1
194         * @throws SQLException the sQL exception
195         * @see java.sql.PreparedStatement#setArray(int, java.sql.Array)
196         */
197        public void setArray(final int arg0, final Array arg1) throws SQLException {
198            this.preparedStatement.setArray(arg0, arg1);
199            this.parameters.put(arg0, arg1);
200        }
201    
202        /**
203         * Sets the ascii stream.
204         *
205         * @param arg0 the arg0
206         * @param arg1 the arg1
207         * @param arg2 the arg2
208         * @throws SQLException the sQL exception
209         * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream, int)
210         */
211        public void setAsciiStream(final int arg0, final InputStream arg1, final int arg2) throws SQLException {
212            this.preparedStatement.setAsciiStream(arg0, arg1, arg2);
213            this.parameters.put(arg0, arg1);
214        }
215    
216        /**
217         * Sets the ascii stream.
218         *
219         * @param arg0 the arg0
220         * @param arg1 the arg1
221         * @param arg2 the arg2
222         * @throws SQLException the sQL exception
223         * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream, long)
224         */
225        public void setAsciiStream(final int arg0, final InputStream arg1, final long arg2) throws SQLException {
226            this.preparedStatement.setAsciiStream(arg0, arg1, arg2);
227            this.parameters.put(arg0, arg1);
228        }
229    
230        /**
231         * Sets the ascii stream.
232         *
233         * @param arg0 the arg0
234         * @param arg1 the arg1
235         * @throws SQLException the sQL exception
236         * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream)
237         */
238        public void setAsciiStream(final int arg0, final InputStream arg1) throws SQLException {
239            this.preparedStatement.setAsciiStream(arg0, arg1);
240            this.parameters.put(arg0, arg1);
241        }
242    
243        /**
244         * Sets the big decimal.
245         *
246         * @param arg0 the arg0
247         * @param arg1 the arg1
248         * @throws SQLException the sQL exception
249         * @see java.sql.PreparedStatement#setBigDecimal(int, java.math.BigDecimal)
250         */
251        public void setBigDecimal(final int arg0, final BigDecimal arg1) throws SQLException {
252            this.preparedStatement.setBigDecimal(arg0, arg1);
253            this.parameters.put(arg0, arg1);
254        }
255    
256        /**
257         * Sets the binary stream.
258         *
259         * @param arg0 the arg0
260         * @param arg1 the arg1
261         * @param arg2 the arg2
262         * @throws SQLException the sQL exception
263         * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream, int)
264         */
265        public void setBinaryStream(final int arg0, final InputStream arg1, final int arg2) throws SQLException {
266            this.preparedStatement.setBinaryStream(arg0, arg1, arg2);
267            this.parameters.put(arg0, arg1);
268        }
269    
270        /**
271         * Sets the binary stream.
272         *
273         * @param arg0 the arg0
274         * @param arg1 the arg1
275         * @param arg2 the arg2
276         * @throws SQLException the sQL exception
277         * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream, long)
278         */
279        public void setBinaryStream(final int arg0, final InputStream arg1, final long arg2) throws SQLException {
280            this.preparedStatement.setBinaryStream(arg0, arg1, arg2);
281            this.parameters.put(arg0, arg1);
282        }
283    
284        /**
285         * Sets the binary stream.
286         *
287         * @param arg0 the arg0
288         * @param arg1 the arg1
289         * @throws SQLException the sQL exception
290         * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream)
291         */
292        public void setBinaryStream(final int arg0, final InputStream arg1) throws SQLException {
293            this.preparedStatement.setBinaryStream(arg0, arg1);
294            this.parameters.put(arg0, arg1);
295        }
296    
297        /**
298         * Sets the blob.
299         *
300         * @param arg0 the arg0
301         * @param arg1 the arg1
302         * @throws SQLException the sQL exception
303         * @see java.sql.PreparedStatement#setBlob(int, java.sql.Blob)
304         */
305        public void setBlob(final int arg0, final Blob arg1) throws SQLException {
306            this.preparedStatement.setBlob(arg0, arg1);
307            this.parameters.put(arg0, arg1);
308        }
309    
310        /**
311         * Sets the blob.
312         *
313         * @param arg0 the arg0
314         * @param arg1 the arg1
315         * @param arg2 the arg2
316         * @throws SQLException the sQL exception
317         * @see java.sql.PreparedStatement#setBlob(int, java.io.InputStream, long)
318         */
319        public void setBlob(final int arg0, final InputStream arg1, final long arg2) throws SQLException {
320            this.preparedStatement.setBlob(arg0, arg1, arg2);
321            this.parameters.put(arg0, arg1);
322        }
323    
324        /**
325         * Sets the blob.
326         *
327         * @param arg0 the arg0
328         * @param arg1 the arg1
329         * @throws SQLException the sQL exception
330         * @see java.sql.PreparedStatement#setBlob(int, java.io.InputStream)
331         */
332        public void setBlob(final int arg0, final InputStream arg1) throws SQLException {
333            this.preparedStatement.setBlob(arg0, arg1);
334            this.parameters.put(arg0, arg1);
335        }
336    
337        /**
338         * Sets the boolean.
339         *
340         * @param arg0 the arg0
341         * @param arg1 the arg1
342         * @throws SQLException the sQL exception
343         * @see java.sql.PreparedStatement#setBoolean(int, boolean)
344         */
345        public void setBoolean(final int arg0, final boolean arg1) throws SQLException {
346            this.preparedStatement.setBoolean(arg0, arg1);
347            this.parameters.put(arg0, arg1);
348        }
349    
350        /**
351         * Sets the byte.
352         *
353         * @param arg0 the arg0
354         * @param arg1 the arg1
355         * @throws SQLException the sQL exception
356         * @see java.sql.PreparedStatement#setByte(int, byte)
357         */
358        public void setByte(final int arg0, final byte arg1) throws SQLException {
359            this.preparedStatement.setByte(arg0, arg1);
360            this.parameters.put(arg0, arg1);
361        }
362    
363        /**
364         * Sets the bytes.
365         *
366         * @param arg0 the arg0
367         * @param arg1 the arg1
368         * @throws SQLException the sQL exception
369         * @see java.sql.PreparedStatement#setBytes(int, byte[])
370         */
371        public void setBytes(final int arg0, final byte[] arg1) throws SQLException {
372            this.preparedStatement.setBytes(arg0, arg1);
373            this.parameters.put(arg0, arg1);
374        }
375    
376        /**
377         * Sets the character stream.
378         *
379         * @param arg0 the arg0
380         * @param arg1 the arg1
381         * @param arg2 the arg2
382         * @throws SQLException the sQL exception
383         * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, int)
384         */
385        public void setCharacterStream(final int arg0, final Reader arg1, final int arg2) throws SQLException {
386            this.preparedStatement.setCharacterStream(arg0, arg1, arg2);
387            this.parameters.put(arg0, arg1);
388        }
389    
390        /**
391         * Sets the character stream.
392         *
393         * @param arg0 the arg0
394         * @param arg1 the arg1
395         * @param arg2 the arg2
396         * @throws SQLException the sQL exception
397         * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, long)
398         */
399        public void setCharacterStream(final int arg0, final Reader arg1, final long arg2) throws SQLException {
400            this.preparedStatement.setCharacterStream(arg0, arg1, arg2);
401            this.parameters.put(arg0, arg1);
402        }
403    
404        /**
405         * Sets the character stream.
406         *
407         * @param arg0 the arg0
408         * @param arg1 the arg1
409         * @throws SQLException the sQL exception
410         * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader)
411         */
412        public void setCharacterStream(final int arg0, final Reader arg1) throws SQLException {
413            this.preparedStatement.setCharacterStream(arg0, arg1);
414            this.parameters.put(arg0, arg1);
415        }
416    
417        /**
418         * Sets the clob.
419         *
420         * @param arg0 the arg0
421         * @param arg1 the arg1
422         * @throws SQLException the sQL exception
423         * @see java.sql.PreparedStatement#setClob(int, java.sql.Clob)
424         */
425        public void setClob(final int arg0, final Clob arg1) throws SQLException {
426            this.preparedStatement.setClob(arg0, arg1);
427            this.parameters.put(arg0, arg1);
428        }
429    
430        /**
431         * Sets the clob.
432         *
433         * @param arg0 the arg0
434         * @param arg1 the arg1
435         * @param arg2 the arg2
436         * @throws SQLException the sQL exception
437         * @see java.sql.PreparedStatement#setClob(int, java.io.Reader, long)
438         */
439        public void setClob(final int arg0, final Reader arg1, final long arg2) throws SQLException {
440            this.preparedStatement.setClob(arg0, arg1, arg2);
441            this.parameters.put(arg0, arg1);
442        }
443    
444        /**
445         * Sets the clob.
446         *
447         * @param arg0 the arg0
448         * @param arg1 the arg1
449         * @throws SQLException the sQL exception
450         * @see java.sql.PreparedStatement#setClob(int, java.io.Reader)
451         */
452        public void setClob(final int arg0, final Reader arg1) throws SQLException {
453            this.preparedStatement.setClob(arg0, arg1);
454            this.parameters.put(arg0, arg1);
455       }
456    
457        /**
458         * Sets the date.
459         *
460         * @param arg0 the arg0
461         * @param arg1 the arg1
462         * @param arg2 the arg2
463         * @throws SQLException the sQL exception
464         * @see java.sql.PreparedStatement#setDate(int, java.sql.Date, java.util.Calendar)
465         */
466        public void setDate(final int arg0, final Date arg1, final Calendar arg2) throws SQLException {
467            this.preparedStatement.setDate(arg0, arg1, arg2);
468            this.parameters.put(arg0, arg1);
469        }
470    
471        /**
472         * Sets the date.
473         *
474         * @param arg0 the arg0
475         * @param arg1 the arg1
476         * @throws SQLException the sQL exception
477         * @see java.sql.PreparedStatement#setDate(int, java.sql.Date)
478         */
479        public void setDate(final int arg0, final Date arg1) throws SQLException {
480            this.preparedStatement.setDate(arg0, arg1);
481            this.parameters.put(arg0, arg1);
482       }
483    
484        /**
485         * Sets the double.
486         *
487         * @param arg0 the arg0
488         * @param arg1 the arg1
489         * @throws SQLException the sQL exception
490         * @see java.sql.PreparedStatement#setDouble(int, double)
491         */
492        public void setDouble(final int arg0, final double arg1) throws SQLException {
493            this.preparedStatement.setDouble(arg0, arg1);
494            this.parameters.put(arg0, arg1);
495        }
496    
497        /**
498         * Sets the float.
499         *
500         * @param arg0 the arg0
501         * @param arg1 the arg1
502         * @throws SQLException the sQL exception
503         * @see java.sql.PreparedStatement#setFloat(int, float)
504         */
505        public void setFloat(final int arg0, final float arg1) throws SQLException {
506            this.preparedStatement.setFloat(arg0, arg1);
507            this.parameters.put(arg0, arg1);
508        }
509    
510        /**
511         * Sets the int.
512         *
513         * @param arg0 the arg0
514         * @param arg1 the arg1
515         * @throws SQLException the sQL exception
516         * @see java.sql.PreparedStatement#setInt(int, int)
517         */
518        public void setInt(final int arg0, final int arg1) throws SQLException {
519            this.preparedStatement.setInt(arg0, arg1);
520            this.parameters.put(arg0, arg1);
521        }
522    
523        /**
524         * Sets the long.
525         *
526         * @param arg0 the arg0
527         * @param arg1 the arg1
528         * @throws SQLException the sQL exception
529         * @see java.sql.PreparedStatement#setLong(int, long)
530         */
531        public void setLong(final int arg0, final long arg1) throws SQLException {
532            this.preparedStatement.setLong(arg0, arg1);
533            this.parameters.put(arg0, arg1);
534        }
535    
536        /**
537         * Sets the n character stream.
538         *
539         * @param arg0 the arg0
540         * @param arg1 the arg1
541         * @param arg2 the arg2
542         * @throws SQLException the sQL exception
543         * @see java.sql.PreparedStatement#setNCharacterStream(int, java.io.Reader, long)
544         */
545        public void setNCharacterStream(final int arg0, final Reader arg1, final long arg2) throws SQLException {
546            this.preparedStatement.setNCharacterStream(arg0, arg1, arg2);
547            this.parameters.put(arg0, arg1);
548        }
549    
550        /**
551         * Sets the n character stream.
552         *
553         * @param arg0 the arg0
554         * @param arg1 the arg1
555         * @throws SQLException the sQL exception
556         * @see java.sql.PreparedStatement#setNCharacterStream(int, java.io.Reader)
557         */
558        public void setNCharacterStream(final int arg0, final Reader arg1) throws SQLException {
559            this.preparedStatement.setNCharacterStream(arg0, arg1);
560            this.parameters.put(arg0, arg1);
561        }
562    
563        /**
564         * Sets the n clob.
565         *
566         * @param arg0 the arg0
567         * @param arg1 the arg1
568         * @throws SQLException the sQL exception
569         * @see java.sql.PreparedStatement#setNClob(int, java.sql.NClob)
570         */
571        public void setNClob(final int arg0, final NClob arg1) throws SQLException {
572            this.preparedStatement.setNClob(arg0, arg1);
573            this.parameters.put(arg0, arg1);
574        }
575    
576        /**
577         * Sets the n clob.
578         *
579         * @param arg0 the arg0
580         * @param arg1 the arg1
581         * @param arg2 the arg2
582         * @throws SQLException the sQL exception
583         * @see java.sql.PreparedStatement#setNClob(int, java.io.Reader, long)
584         */
585        public void setNClob(final int arg0, final Reader arg1, final long arg2) throws SQLException {
586            this.preparedStatement.setNClob(arg0, arg1, arg2);
587            this.parameters.put(arg0, arg1);
588        }
589    
590        /**
591         * Sets the n clob.
592         *
593         * @param arg0 the arg0
594         * @param arg1 the arg1
595         * @throws SQLException the sQL exception
596         * @see java.sql.PreparedStatement#setNClob(int, java.io.Reader)
597         */
598        public void setNClob(final int arg0, final Reader arg1) throws SQLException {
599            this.preparedStatement.setNClob(arg0, arg1);
600            this.parameters.put(arg0, arg1);
601        }
602    
603        /**
604         * Sets the n string.
605         *
606         * @param arg0 the arg0
607         * @param arg1 the arg1
608         * @throws SQLException the sQL exception
609         * @see java.sql.PreparedStatement#setNString(int, java.lang.String)
610         */
611        public void setNString(final int arg0, final String arg1) throws SQLException {
612            this.preparedStatement.setNString(arg0, arg1);
613            this.parameters.put(arg0, arg1);
614        }
615    
616        /**
617         * Sets the null.
618         *
619         * @param arg0 the arg0
620         * @param arg1 the arg1
621         * @param arg2 the arg2
622         * @throws SQLException the sQL exception
623         * @see java.sql.PreparedStatement#setNull(int, int, java.lang.String)
624         */
625        public void setNull(final int arg0, final int arg1, final String arg2) throws SQLException {
626            this.preparedStatement.setNull(arg0, arg1, arg2);
627            this.parameters.put(arg0, "'null'");
628        }
629    
630        /**
631         * Sets the null.
632         *
633         * @param arg0 the arg0
634         * @param arg1 the arg1
635         * @throws SQLException the sQL exception
636         * @see java.sql.PreparedStatement#setNull(int, int)
637         */
638        public void setNull(final int arg0, final int arg1) throws SQLException {
639            this.preparedStatement.setNull(arg0, arg1);
640            this.parameters.put(arg0, "'null'");
641        }
642    
643        /**
644         * Sets the object.
645         *
646         * @param arg0 the arg0
647         * @param arg1 the arg1
648         * @param arg2 the arg2
649         * @param arg3 the arg3
650         * @throws SQLException the sQL exception
651         * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int, int)
652         */
653        public void setObject(final int arg0, final Object arg1, final int arg2, final int arg3) throws SQLException {
654            this.preparedStatement.setObject(arg0, arg1, arg2, arg3);
655            this.parameters.put(arg0, arg1);
656        }
657    
658        /**
659         * Sets the object.
660         *
661         * @param arg0 the arg0
662         * @param arg1 the arg1
663         * @param arg2 the arg2
664         * @throws SQLException the sQL exception
665         * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int)
666         */
667        public void setObject(final int arg0, final Object arg1, final int arg2) throws SQLException {
668            this.preparedStatement.setObject(arg0, arg1, arg2);
669            this.parameters.put(arg0, arg1);
670        }
671    
672        /**
673         * Sets the object.
674         *
675         * @param arg0 the arg0
676         * @param arg1 the arg1
677         * @throws SQLException the sQL exception
678         * @see java.sql.PreparedStatement#setObject(int, java.lang.Object)
679         */
680        public void setObject(final int arg0, final Object arg1) throws SQLException {
681            this.preparedStatement.setObject(arg0, arg1);
682            this.parameters.put(arg0, arg1);
683        }
684    
685        /**
686         * Sets the ref.
687         *
688         * @param arg0 the arg0
689         * @param arg1 the arg1
690         * @throws SQLException the sQL exception
691         * @see java.sql.PreparedStatement#setRef(int, java.sql.Ref)
692         */
693        public void setRef(final int arg0, final Ref arg1) throws SQLException {
694            this.preparedStatement.setRef(arg0, arg1);
695            this.parameters.put(arg0, arg1);
696        }
697    
698        /**
699         * Sets the row id.
700         *
701         * @param arg0 the arg0
702         * @param arg1 the arg1
703         * @throws SQLException the sQL exception
704         * @see java.sql.PreparedStatement#setRowId(int, java.sql.RowId)
705         */
706        public void setRowId(final int arg0, final RowId arg1) throws SQLException {
707            this.preparedStatement.setRowId(arg0, arg1);
708            this.parameters.put(arg0, arg1);
709        }
710    
711        /**
712         * Sets the sqlxml.
713         *
714         * @param arg0 the arg0
715         * @param arg1 the arg1
716         * @throws SQLException the sQL exception
717         * @see java.sql.PreparedStatement#setSQLXML(int, java.sql.SQLXML)
718         */
719        public void setSQLXML(final int arg0, final SQLXML arg1) throws SQLException {
720            this.preparedStatement.setSQLXML(arg0, arg1);
721            this.parameters.put(arg0, arg1);
722        }
723    
724        /**
725         * Sets the short.
726         *
727         * @param arg0 the arg0
728         * @param arg1 the arg1
729         * @throws SQLException the sQL exception
730         * @see java.sql.PreparedStatement#setShort(int, short)
731         */
732        public void setShort(final int arg0, final short arg1) throws SQLException {
733            this.preparedStatement.setShort(arg0, arg1);
734            this.parameters.put(arg0, arg1);
735        }
736    
737        /**
738         * Sets the string.
739         *
740         * @param arg0 the arg0
741         * @param arg1 the arg1
742         * @throws SQLException the sQL exception
743         * @see java.sql.PreparedStatement#setString(int, java.lang.String)
744         */
745        public void setString(final int arg0, final String arg1) throws SQLException {
746            this.preparedStatement.setString(arg0, arg1);
747            this.parameters.put(arg0, "'" + arg1 + "'");
748        }
749    
750        /**
751         * Sets the time.
752         *
753         * @param arg0 the arg0
754         * @param arg1 the arg1
755         * @param arg2 the arg2
756         * @throws SQLException the sQL exception
757         * @see java.sql.PreparedStatement#setTime(int, java.sql.Time, java.util.Calendar)
758         */
759        public void setTime(final int arg0, final Time arg1, final Calendar arg2) throws SQLException {
760            this.preparedStatement.setTime(arg0, arg1, arg2);
761            this.parameters.put(arg0, arg1);
762        }
763    
764        /**
765         * Sets the time.
766         *
767         * @param arg0 the arg0
768         * @param arg1 the arg1
769         * @throws SQLException the sQL exception
770         * @see java.sql.PreparedStatement#setTime(int, java.sql.Time)
771         */
772        public void setTime(final int arg0, final Time arg1) throws SQLException {
773            this.preparedStatement.setTime(arg0, arg1);
774            this.parameters.put(arg0, arg1);
775       }
776    
777        /**
778         * Sets the timestamp.
779         *
780         * @param arg0 the arg0
781         * @param arg1 the arg1
782         * @param arg2 the arg2
783         * @throws SQLException the sQL exception
784         * @see java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp, java.util.Calendar)
785         */
786        public void setTimestamp(final int arg0, final Timestamp arg1, final Calendar arg2) throws SQLException {
787            this.preparedStatement.setTimestamp(arg0, arg1, arg2);
788            this.parameters.put(arg0, arg1);
789        }
790    
791        /**
792         * Sets the timestamp.
793         *
794         * @param arg0 the arg0
795         * @param arg1 the arg1
796         * @throws SQLException the sQL exception
797         * @see java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp)
798         */
799        public void setTimestamp(final int arg0, final Timestamp arg1) throws SQLException {
800            this.preparedStatement.setTimestamp(arg0, arg1);
801            this.parameters.put(arg0, arg1);
802       }
803    
804        /**
805         * Sets the url.
806         *
807         * @param arg0 the arg0
808         * @param arg1 the arg1
809         * @throws SQLException the sQL exception
810         * @see java.sql.PreparedStatement#setURL(int, java.net.URL)
811         */
812        public void setURL(final int arg0, final URL arg1) throws SQLException {
813            this.preparedStatement.setURL(arg0, arg1);
814        }
815    
816        /**
817         * Sets the unicode stream.
818         *
819         * @param arg0 the arg0
820         * @param arg1 the arg1
821         * @param arg2 the arg2
822         * @throws SQLException the sQL exception
823         */
824        @SuppressWarnings("deprecation")
825        public void setUnicodeStream(final int arg0, final InputStream arg1, final int arg2) throws SQLException {
826            this.preparedStatement.setUnicodeStream(arg0, arg1, arg2);
827        }
828    
829        /**
830         * We want to return the real SQL as string represenation.
831         *
832         * @return the string
833         * @see java.lang.Object#toString()
834         */
835        @Override
836        public String toString() {
837            return this.resolveSQL();
838        }
839    
840        private String resolveSQL() {
841            String[] elements = StringUtils.split(this.sqlTemplate + " ", '?');
842            StringBuffer buf = new StringBuffer(elements[0]);
843            for (int i = 1; i < elements.length; i++) {
844                buf.append(this.getSqlParameter(i));
845                buf.append(elements[i]);
846            }
847            return buf.toString().trim();
848        }
849    
850        private Object getSqlParameter(final int n) {
851            Object param = this.parameters.get(n);
852            if (param == null) {
853                return '?';
854            }
855            return param;
856        }
857    
858        private void logSQL(final ProfileMonitor mon, final Object ret) {
859            if (log.isDebugEnabled()) {
860                SqlStatistic.stop(mon, this.resolveSQL(), ret);
861            } else {
862                SqlStatistic.stop(mon, this.sqlTemplate, ret);
863            }
864        }
865    
866    }
867