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 }