View Javadoc

1   /***
2    * WrappedStatement.java
3    *
4    * This file is part of the creme library.
5    * The creme library intends to ease the development effort of large
6    * applications by providing easy to use support classes.
7    *
8    * Copyright (C) 2002 Denis Bregeon
9    *
10   *
11   * This library is free software; you can redistribute it and/or
12   * modify it under the terms of the GNU Lesser General Public
13   * License as published by the Free Software Foundation; either
14   * version 2.1 of the License, or (at your option) any later version.
15   *
16   * This library is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19   * Lesser General Public License for more details.
20   *
21   * You should have received a copy of the GNU Lesser General Public
22   * License along with this library; if not, write to the Free Software
23   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24   *
25   * contact information: dbregeon@sourceforge.net
26   */
27  package org.jcreme.sql;
28  
29  import java.sql.BatchUpdateException;
30  import java.sql.Connection;
31  import java.sql.ResultSet;
32  import java.sql.SQLException;
33  import java.sql.SQLWarning;
34  import java.sql.Statement;
35  import java.util.Vector;
36  
37  /***
38   * This class enables to wrap an actual statement to provide a few extra
39   * services: tracing of the queries, handling of some exceptions (rollback, loss
40   * of connection). The ResultSets provided by this class are wrapped around the
41   * actual ResultSet.
42   * 
43   * @author $Author: dbregeon $
44   * @version $Revision: 1.1 $
45   */
46  public class WrappedStatement implements Statement {
47      /***
48       * The String displayed when no query has been assigned to the Statement
49       * yet.
50       */
51      protected static final String UNKNOWN_QUERY = "Query Not Known Yet";
52  
53      /***
54       * The underlying statement.
55       */
56      protected Statement realStatement = null;
57  
58      /***
59       * This vector enables to store the queries contained in a batch statement.
60       */
61      protected final Vector batchRequests = new Vector();
62  
63      /***
64       * The initial query assigned to the Statement.
65       */
66      protected String baseQuery = UNKNOWN_QUERY;
67  
68      /***
69       * The object that will handle the exceptions.
70       */
71      private SQLExceptionHandler exceptionHandler = null;
72  
73      /***
74       * The action that will be used by the exception handler in case of
75       * rollback.
76       */
77      private CremeAction rollBackAction = null;
78  
79      /***
80       * The action that will be used by the exception handler in case of loss of
81       * connection.
82       */
83      private CremeAction lossOfConnectionAction = null;
84  
85      /***
86       * Enables to wrap a Statement.
87       * 
88       * @param statement
89       *            the statement to wrap.
90       * @throws SQLException
91       *             if the statement is null.
92       */
93      public WrappedStatement(Statement statement) throws SQLException {
94          if (statement == null) {
95              throw new SQLException("Null is not a valid statement.");
96          }
97          setRealStatement(statement);
98      }
99  
100     /***
101      * This method should be used by subclasses to set the realStatement. It
102      * also sets the ExceptionHandler and the rollback and lossOfConnection
103      * actions.
104      * 
105      * @param statement
106      *            the statement to wrap.
107      * @throws SQLException
108      *             if the statement is null.
109      */
110     protected void setRealStatement(Statement statement) throws SQLException {
111         this.realStatement = statement;
112         if (this.realStatement == null) {
113             throw new SQLException("Can not allocate Statement.");
114         }
115         WrappedConnection conn = WrappedConnection
116                 .getInstance(this.realStatement.getConnection());
117         if (conn != null) {
118             conn.registerActiveStatement(this);
119         }
120         this.exceptionHandler = conn.getExceptionHandler();
121         this.rollBackAction = conn.getRollBackAction();
122         this.lossOfConnectionAction = conn.getLossOfConnectionAction();
123     }
124 
125     /***
126      * This method enables to set the base query of the statement.
127      * 
128      * @param sql
129      *            the sql query underlying the statement.
130      * @throws SQLException
131      *             if the query is null.
132      */
133     protected void setBaseQuery(String sql) throws SQLException {
134         if (sql == null) {
135             throw new SQLException("Null is not a valid query.");
136         }
137         this.baseQuery = sql;
138     }
139 
140     /***
141      * This method enables to generate an SQLException that contains the query
142      * of the statement in its message.
143      * 
144      * @param e
145      *            the original exception.
146      * @return an exception which has the query as message.
147      */
148     protected SQLException generateException(SQLException e) {
149         return generateException(this.baseQuery, e);
150     }
151 
152     /***
153      * This method enables to append a message to the original exception's
154      * message.
155      * 
156      * @param message
157      *            the message to append.
158      * @param e
159      *            the original exception.
160      * @return an exception with the appended message.
161      */
162     protected SQLException generateException(String message, SQLException e) {
163         message = message + ": \n" + e.getMessage();
164         SQLException exc = null;
165         if ((this.exceptionHandler != null)
166                 && (this.exceptionHandler.isDeadLock(e))) {
167             exc = generateDeadLockException(message, e);
168         } else if ((this.exceptionHandler != null)
169                 && (this.exceptionHandler.isLossOfConnection(e))) {
170             exc = generateConnectionLostException(message, e);
171         } else {
172             exc = generateNewException(message, e);
173         }
174         exc.setNextException(e);
175         return exc;
176     }
177 
178     /***
179      * This method generates a DeadLockException from an SQLException.
180      * 
181      * @param message
182      *            the message to append.
183      * @param e
184      *            the original exception.
185      * @return a DeadLockException with the given message.
186      */
187     protected DeadLockException generateDeadLockException(String message,
188             SQLException e) {
189         return new DeadLockException(message, e.getSQLState(), e.getErrorCode());
190     }
191 
192     /***
193      * This method generates a ConnectionLostException from an SQLException.
194      * 
195      * @param message
196      *            the message to append.
197      * @param e
198      *            the original exception.
199      * @return a ConnectionLostException with the given message.
200      */
201     protected ConnectionLostException generateConnectionLostException(
202             String message, SQLException e) {
203         return new ConnectionLostException(message, e.getSQLState(), e
204                 .getErrorCode());
205     }
206 
207     /***
208      * This method generates a new SQLException from an SQLException.
209      * 
210      * @param message
211      *            the message to append.
212      * @param e
213      *            the original exception.
214      * @return a new SQLException with the given message.
215      */
216     protected SQLException generateNewException(String message, SQLException e) {
217         return new SQLException(message, e.getSQLState(), e.getErrorCode());
218     }
219 
220     /***
221      * This method generates a BatchUpdateException from an SQLException.
222      * 
223      * @param message
224      *            the message to append.
225      * @param e
226      *            the original exception.
227      * @return a BatchUpdateException with the given message.
228      */
229     protected SQLException generateNewException(String message,
230             BatchUpdateException e) {
231         return new BatchUpdateException(message, e.getSQLState(), e
232                 .getErrorCode(), e.getUpdateCounts());
233     }
234 
235     /***
236      * This method enables to call upon an ExceptionHandler to manage the given
237      * exception. Both rollbacks and loss of connections are handled through
238      * this method.
239      * 
240      * @param e
241      *            exception to handle.
242      * @return the type of the exception as defined in the SQLExceptionHandler
243      *         interface.
244      */
245     protected int manageException(SQLException e) {
246         int result = 0;
247         if (this.exceptionHandler != null) {
248             result = this.exceptionHandler.handleException(e,
249                     this.rollBackAction, this.lossOfConnectionAction);
250         }
251         return result;
252     }
253 
254     /***
255      * This method enables to call upon an ExceptionHandler to manage the given
256      * exception. Both rollbacks and loss of connections are handled through
257      * this method. This method also enables to redo the action that caused the
258      * original exception.
259      * 
260      * @param e
261      *            exception to handle.
262      * @param redo
263      *            the action that caused the original exception.
264      * @return the type of the exception as defined in the SQLExceptionHandler
265      *         interface.
266      */
267     protected int manageException(SQLException e, CremeAction redo) {
268         int result = 0;
269         if (this.exceptionHandler != null) {
270             result = this.exceptionHandler.handleException(e,
271                     this.rollBackAction, this.lossOfConnectionAction, redo);
272         }
273         return result;
274     }
275 
276     /***
277      * @see Statement#executeQuery(java.lang.String)
278      */
279     public ResultSet executeQuery(String sql) throws SQLException {
280         try {
281             setBaseQuery(sql);
282             return new WrappedResultSet(this.realStatement
283                     .executeQuery(this.baseQuery), this, this.baseQuery);
284         } catch (SQLException e) {
285             CremeAction redo = null;
286             try {
287                 Class[] types = { java.lang.String.class };
288                 Object[] params = { this.baseQuery };
289                 redo = new CremeAction(getClass().getMethod("executeQuery",
290                         types));
291                 redo.setSubject(this);
292                 redo.setParameters(params);
293             } catch (NoSuchMethodException ex) {
294                 e.printStackTrace();
295             } catch (IllegalArgumentException ex) {
296                 e.printStackTrace();
297             }
298             manageException(e, redo);
299             if (redo != null && redo.isSuccessfull()) {
300                 return (ResultSet) redo.getResult();
301             }
302             throw generateException(e);
303         }
304     }
305 
306     /***
307      * @see Statement#executeUpdate(java.lang.String)
308      */
309     public int executeUpdate(String sql) throws SQLException {
310         try {
311             setBaseQuery(sql);
312             return this.realStatement.executeUpdate(this.baseQuery);
313         } catch (SQLException e) {
314             CremeAction redo = null;
315             try {
316                 Class[] types = { java.lang.String.class };
317                 Object[] params = { this.baseQuery };
318                 redo = new CremeAction(getClass().getMethod("executeUpdate",
319                         types));
320                 redo.setSubject(this);
321                 redo.setParameters(params);
322             } catch (NoSuchMethodException ex) {
323                 ex.printStackTrace();
324             } catch (IllegalArgumentException ex) {
325                 ex.printStackTrace();
326             }
327             manageException(e, redo);
328             if ((redo != null) && (redo.isSuccessfull())) {
329                 return ((Integer) redo.getResult()).intValue();
330             }
331             throw generateException(e);
332         }
333     }
334 
335     /***
336      * @see Statement#close()
337      */
338     public void close() throws SQLException {
339         try {
340             WrappedConnection conn = WrappedConnection
341                     .getInstance(this.realStatement.getConnection());
342             if (conn != null) {
343                 conn.unregisterActiveStatement(this);
344             }
345             if (!getConnection().isClosed()) {
346                 this.realStatement.close();
347             }
348         } catch (SQLException e) {
349             manageException(e);
350             throw generateException(e);
351         }
352     }
353 
354     /***
355      * @see Statement#getMaxFieldSize()
356      */
357     public int getMaxFieldSize() throws SQLException {
358         try {
359             return this.realStatement.getMaxFieldSize();
360         } catch (SQLException e) {
361             manageException(e);
362             throw generateException(e);
363         }
364     }
365 
366     /***
367      * @see Statement#setMaxFieldSize(int)
368      */
369     public void setMaxFieldSize(int max) throws SQLException {
370         try {
371             this.realStatement.setMaxFieldSize(max);
372         } catch (SQLException e) {
373             manageException(e);
374             throw generateException(e);
375         }
376     }
377 
378     /***
379      * @see Statement#getMaxRows()
380      */
381     public int getMaxRows() throws SQLException {
382         try {
383             return this.realStatement.getMaxRows();
384         } catch (SQLException e) {
385             manageException(e);
386             throw generateException(e);
387         }
388     }
389 
390     /***
391      * @see Statement#setMaxRows(int)
392      */
393     public void setMaxRows(int i) throws SQLException {
394         try {
395             this.realStatement.setMaxRows(i);
396         } catch (SQLException e) {
397             manageException(e);
398             throw generateException(e);
399         }
400     }
401 
402     /***
403      * @see Statement#setEscapeProcessing(boolean)
404      */
405     public void setEscapeProcessing(boolean enable) throws SQLException {
406         try {
407             this.realStatement.setEscapeProcessing(enable);
408         } catch (SQLException e) {
409             manageException(e);
410             throw generateException(e);
411         }
412     }
413 
414     /***
415      * @see Statement#getQueryTimeout()
416      */
417     public int getQueryTimeout() throws SQLException {
418         try {
419             return this.realStatement.getQueryTimeout();
420         } catch (SQLException e) {
421             manageException(e);
422             throw generateException(e);
423         }
424     }
425 
426     /***
427      * @see Statement#setQueryTimeout(int)
428      */
429     public void setQueryTimeout(int seconds) throws SQLException {
430         try {
431             this.realStatement.setQueryTimeout(seconds);
432         } catch (SQLException e) {
433             manageException(e);
434             throw generateException(e);
435         }
436     }
437 
438     /***
439      * @see Statement#cancel()
440      */
441     public void cancel() throws SQLException {
442         try {
443             this.realStatement.cancel();
444         } catch (SQLException e) {
445             manageException(e);
446             throw generateException(e);
447         }
448     }
449 
450     /***
451      * @see Statement#getWarnings()
452      */
453     public SQLWarning getWarnings() throws SQLException {
454         try {
455             return this.realStatement.getWarnings();
456         } catch (SQLException e) {
457             manageException(e);
458             throw generateException(e);
459         }
460     }
461 
462     /***
463      * @see Statement#clearWarnings()
464      */
465     public void clearWarnings() throws SQLException {
466         try {
467             this.realStatement.clearWarnings();
468         } catch (SQLException e) {
469             manageException(e);
470             throw generateException(e);
471         }
472     }
473 
474     /***
475      * @see Statement#setCursorName(java.lang.String)
476      */
477     public void setCursorName(String name) throws SQLException {
478         try {
479             this.realStatement.setCursorName(name);
480         } catch (SQLException e) {
481             manageException(e);
482             throw generateException(e);
483         }
484     }
485 
486     /***
487      * @see Statement#execute(java.lang.String)
488      */
489     public boolean execute(String sql) throws SQLException {
490         try {
491             setBaseQuery(sql);
492             return this.realStatement.execute(this.baseQuery);
493         } catch (SQLException e) {
494             CremeAction redo = null;
495             try {
496                 Class[] types = { java.lang.String.class };
497                 Object[] params = { this.baseQuery };
498                 redo = new CremeAction(getClass().getMethod("execute", types));
499                 redo.setSubject(this);
500                 redo.setParameters(params);
501             } catch (NoSuchMethodException ex) {
502                 ex.printStackTrace();
503             } catch (IllegalArgumentException ex) {
504                 ex.printStackTrace();
505             }
506             manageException(e, redo);
507             if ((redo != null) && (redo.isSuccessfull())) {
508                 return ((Boolean) redo.getResult()).booleanValue();
509             }
510             throw generateException(e);
511         }
512     }
513 
514     /***
515      * @see Statement#getResultSet()
516      */
517     public ResultSet getResultSet() throws SQLException {
518         try {
519             return new WrappedResultSet(this.realStatement.getResultSet(),
520                     this, this.baseQuery);
521         } catch (SQLException e) {
522             manageException(e);
523             throw generateException(e);
524         }
525     }
526 
527     /***
528      * @see Statement#getUpdateCount()
529      */
530     public int getUpdateCount() throws SQLException {
531         try {
532             return this.realStatement.getUpdateCount();
533         } catch (SQLException e) {
534             manageException(e);
535             throw generateException(e);
536         }
537     }
538 
539     /***
540      * @see Statement#getMoreResults()
541      */
542     public boolean getMoreResults() throws SQLException {
543         try {
544             return this.realStatement.getMoreResults();
545         } catch (SQLException e) {
546             manageException(e);
547             throw generateException(e);
548         }
549     }
550 
551     /***
552      * @see Statement#setFetchDirection(int)
553      */
554     public void setFetchDirection(int direction) throws SQLException {
555         try {
556             this.realStatement.setFetchDirection(direction);
557         } catch (SQLException e) {
558             manageException(e);
559             throw generateException(e);
560         }
561     }
562 
563     /***
564      * @see Statement#getFetchDirection()
565      */
566     public int getFetchDirection() throws SQLException {
567         try {
568             return this.realStatement.getFetchDirection();
569         } catch (SQLException e) {
570             manageException(e);
571             throw generateException(e);
572         }
573     }
574 
575     /***
576      * @see Statement#setFetchSize(int)
577      */
578     public void setFetchSize(int rows) throws SQLException {
579         try {
580             this.realStatement.setFetchSize(rows);
581         } catch (SQLException e) {
582             manageException(e);
583             throw generateException(e);
584         }
585     }
586 
587     /***
588      * @see Statement#getFetchSize()
589      */
590     public int getFetchSize() throws SQLException {
591         try {
592             return this.realStatement.getFetchSize();
593         } catch (SQLException e) {
594             manageException(e);
595             throw generateException(e);
596         }
597     }
598 
599     /***
600      * @see Statement#getResultSetConcurrency()
601      */
602     public int getResultSetConcurrency() throws SQLException {
603         try {
604             return this.realStatement.getResultSetConcurrency();
605         } catch (SQLException e) {
606             manageException(e);
607             throw generateException(e);
608         }
609     }
610 
611     /***
612      * @see Statement#getResultSetType()
613      */
614     public int getResultSetType() throws SQLException {
615         try {
616             return this.realStatement.getResultSetType();
617         } catch (SQLException e) {
618             manageException(e);
619             throw generateException(e);
620         }
621     }
622 
623     /***
624      * @see Statement#addBatch(java.lang.String)
625      */
626     public void addBatch(String sql) throws SQLException {
627         try {
628             setBaseQuery(sql);
629             this.realStatement.addBatch(this.baseQuery);
630             this.batchRequests.add(this.baseQuery);
631         } catch (SQLException e) {
632             manageException(e);
633             throw generateException(e);
634         }
635     }
636 
637     /***
638      * @see Statement#clearBatch()
639      */
640     public void clearBatch() throws SQLException {
641         try {
642             this.realStatement.clearBatch();
643             this.batchRequests.clear();
644         } catch (SQLException e) {
645             manageException(e);
646             throw generateException(e);
647         }
648     }
649 
650     /***
651      * @see Statement#executeBatch()
652      */
653     public int[] executeBatch() throws SQLException {
654         try {
655             return this.realStatement.executeBatch();
656         } catch (BatchUpdateException e) {
657             manageException(e);
658             int[] counts = e.getUpdateCounts();
659             for (int i = 0; i < counts.length && i < this.batchRequests.size(); i++) {
660                 if ((counts[i] == -1) || (counts[i] < -2)) {
661                     throw generateException(getBatchRequestAt(i), e);
662                 }
663             }
664             throw generateException(getBatchRequestAt(counts.length), e);
665         } catch (SQLException e) {
666             manageException(e);
667             throw generateException(e);
668         }
669     }
670 
671     /***
672      * This method gives access to the batch query at the given index. It should
673      * be used for trace purpose.
674      * 
675      * @param i
676      *            the index of the batch query to find.
677      * @return the batch query at index.
678      */
679     protected String getBatchRequestAt(int i) {
680         return (String) this.batchRequests.elementAt(i);
681     }
682 
683     /***
684      * @see Statement#getConnection()
685      */
686     public Connection getConnection() throws SQLException {
687         try {
688             return WrappedConnection.getInstance(this.realStatement
689                     .getConnection());
690         } catch (SQLException e) {
691             manageException(e);
692             throw generateException(e);
693         }
694     }
695 
696     /***
697      * @see Statement#getMoreResults(int)
698      */
699     public boolean getMoreResults(int current) throws SQLException {
700         try {
701             return this.realStatement.getMoreResults(current);
702         } catch (SQLException e) {
703             manageException(e);
704             throw generateException(e);
705         }
706     }
707 
708     /***
709      * @see Statement#getGeneratedKeys()
710      */
711     public ResultSet getGeneratedKeys() throws SQLException {
712         try {
713             return new WrappedResultSet(this.realStatement.getGeneratedKeys(),
714                     this.realStatement, this.baseQuery);
715         } catch (SQLException e) {
716             manageException(e);
717             throw generateException(e);
718         }
719     }
720 
721     /***
722      * @see Statement#executeUpdate(java.lang.String, int)
723      */
724     public int executeUpdate(String sql, int autoGeneratedKeys)
725             throws SQLException {
726         try {
727             setBaseQuery(sql);
728             return this.realStatement.executeUpdate(sql, autoGeneratedKeys);
729         } catch (SQLException e) {
730             CremeAction redo = null;
731             try {
732                 Class[] types = { java.lang.String.class, Integer.TYPE };
733                 Object[] params = { this.baseQuery,
734                         new Integer(autoGeneratedKeys) };
735                 redo = new CremeAction(getClass().getMethod("executeUpdate",
736                         types));
737                 redo.setSubject(this);
738                 redo.setParameters(params);
739             } catch (NoSuchMethodException ex) {
740                 ex.printStackTrace();
741             } catch (IllegalArgumentException ex) {
742                 ex.printStackTrace();
743             }
744             manageException(e, redo);
745             if ((redo != null) && (redo.isSuccessfull())) {
746                 return ((Integer) redo.getResult()).intValue();
747             }
748             throw generateException(e);
749         }
750     }
751 
752     /***
753      * @see Statement#executeUpdate(java.lang.String, int[])
754      */
755     public int executeUpdate(String sql, int[] columnIndexes)
756             throws SQLException {
757         try {
758             setBaseQuery(sql);
759             return this.realStatement.executeUpdate(sql, columnIndexes);
760         } catch (SQLException e) {
761             CremeAction redo = null;
762             try {
763                 Class[] types = { java.lang.String.class, int[].class };
764                 Object[] params = { this.baseQuery, columnIndexes };
765                 redo = new CremeAction(getClass().getMethod("executeUpdate",
766                         types));
767                 redo.setSubject(this);
768                 redo.setParameters(params);
769             } catch (NoSuchMethodException ex) {
770                 ex.printStackTrace();
771             } catch (IllegalArgumentException ex) {
772                 ex.printStackTrace();
773             }
774             manageException(e, redo);
775             if ((redo != null) && (redo.isSuccessfull())) {
776                 return ((Integer) redo.getResult()).intValue();
777             }
778             throw generateException(e);
779         }
780     }
781 
782     /***
783      * @see Statement#executeUpdate(java.lang.String, java.lang.String[])
784      */
785     public int executeUpdate(String sql, String[] columnNames)
786             throws SQLException {
787         try {
788             return this.realStatement.executeUpdate(sql, columnNames);
789         } catch (SQLException e) {
790             CremeAction redo = null;
791             try {
792                 Class[] types = { java.lang.String.class, String[].class };
793                 Object[] params = { this.baseQuery, columnNames };
794                 redo = new CremeAction(getClass().getMethod("executeUpdate",
795                         types));
796                 redo.setSubject(this);
797                 redo.setParameters(params);
798             } catch (NoSuchMethodException ex) {
799                 ex.printStackTrace();
800             } catch (IllegalArgumentException ex) {
801                 ex.printStackTrace();
802             }
803             manageException(e, redo);
804             if ((redo != null) && (redo.isSuccessfull())) {
805                 return ((Integer) redo.getResult()).intValue();
806             }
807             throw generateException(e);
808         }
809     }
810 
811     /***
812      * @see Statement#execute(java.lang.String, int)
813      */
814     public boolean execute(String sql, int autoGeneratedKeys)
815             throws SQLException {
816         try {
817             return this.realStatement.execute(sql, autoGeneratedKeys);
818         } catch (SQLException e) {
819             CremeAction redo = null;
820             try {
821                 Class[] types = { java.lang.String.class, Integer.TYPE };
822                 Object[] params = { this.baseQuery,
823                         new Integer(autoGeneratedKeys) };
824                 redo = new CremeAction(getClass().getMethod("executeUpdate",
825                         types));
826                 redo.setSubject(this);
827                 redo.setParameters(params);
828             } catch (NoSuchMethodException ex) {
829                 ex.printStackTrace();
830             } catch (IllegalArgumentException ex) {
831                 ex.printStackTrace();
832             }
833             manageException(e, redo);
834             if ((redo != null) && (redo.isSuccessfull())) {
835                 return ((Boolean) redo.getResult()).booleanValue();
836             }
837             throw generateException(e);
838         }
839     }
840 
841     /***
842      * @see Statement#execute(java.lang.String, int[])
843      */
844     public boolean execute(String sql, int[] columnIndexes) throws SQLException {
845         try {
846             return this.realStatement.execute(sql, columnIndexes);
847         } catch (SQLException e) {
848             CremeAction redo = null;
849             try {
850                 Class[] types = { java.lang.String.class, int[].class };
851                 Object[] params = { this.baseQuery, columnIndexes };
852                 redo = new CremeAction(getClass().getMethod("executeUpdate",
853                         types));
854                 redo.setSubject(this);
855                 redo.setParameters(params);
856             } catch (NoSuchMethodException ex) {
857                 ex.printStackTrace();
858             } catch (IllegalArgumentException ex) {
859                 ex.printStackTrace();
860             }
861             manageException(e, redo);
862             if ((redo != null) && (redo.isSuccessfull())) {
863                 return ((Boolean) redo.getResult()).booleanValue();
864             }
865             throw generateException(e);
866         }
867     }
868 
869     /***
870      * @see Statement#execute(java.lang.String, java.lang.String[])
871      */
872     public boolean execute(String sql, String[] columnNames)
873             throws SQLException {
874         try {
875             return this.realStatement.execute(sql, columnNames);
876         } catch (SQLException e) {
877             CremeAction redo = null;
878             try {
879                 Class[] types = { java.lang.String.class, String[].class };
880                 Object[] params = { this.baseQuery, columnNames };
881                 redo = new CremeAction(getClass().getMethod("executeUpdate",
882                         types));
883                 redo.setSubject(this);
884                 redo.setParameters(params);
885             } catch (NoSuchMethodException ex) {
886                 ex.printStackTrace();
887             } catch (IllegalArgumentException ex) {
888                 ex.printStackTrace();
889             }
890             manageException(e, redo);
891             if ((redo != null) && (redo.isSuccessfull())) {
892                 return ((Boolean) redo.getResult()).booleanValue();
893             }
894             throw generateException(e);
895         }
896     }
897 
898     /***
899      * @see Statement#getResultSetHoldability()
900      */
901     public int getResultSetHoldability() throws SQLException {
902         try {
903             return this.realStatement.getResultSetHoldability();
904         } catch (SQLException e) {
905             manageException(e);
906             throw generateException(e);
907         }
908     }
909 }