1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.dbcp2;
18
19 import java.sql.Connection;
20 import java.sql.ResultSet;
21 import java.sql.SQLException;
22 import java.sql.SQLWarning;
23 import java.sql.Statement;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Objects;
27
28
29
30
31
32
33
34
35
36
37
38
39 public class DelegatingStatement extends AbandonedTrace implements Statement {
40
41
42 private Statement statement;
43
44
45 private DelegatingConnection<?> connection;
46
47 private volatile boolean closed;
48
49
50
51
52
53
54
55
56
57
58 public DelegatingStatement(final DelegatingConnection<?> connection, final Statement statement) {
59 super(connection);
60 this.statement = statement;
61 this.connection = connection;
62 }
63
64
65
66
67
68
69
70
71 public void activate() throws SQLException {
72 if (statement instanceof DelegatingStatement) {
73 ((DelegatingStatement) statement).activate();
74 }
75 }
76
77 @Override
78 public void addBatch(final String sql) throws SQLException {
79 checkOpen();
80 try {
81 statement.addBatch(sql);
82 } catch (final SQLException e) {
83 handleException(e);
84 }
85 }
86
87 @Override
88 public void cancel() throws SQLException {
89 checkOpen();
90 try {
91 statement.cancel();
92 } catch (final SQLException e) {
93 handleException(e);
94 }
95 }
96
97
98
99
100
101
102 protected void checkOpen() throws SQLException {
103 if (isClosed()) {
104 throw new SQLException(this.getClass().getName() + " with address: \"" + toString() + "\" is closed.");
105 }
106 }
107
108 @Override
109 public void clearBatch() throws SQLException {
110 checkOpen();
111 try {
112 statement.clearBatch();
113 } catch (final SQLException e) {
114 handleException(e);
115 }
116 }
117
118 @Override
119 public void clearWarnings() throws SQLException {
120 checkOpen();
121 try {
122 statement.clearWarnings();
123 } catch (final SQLException e) {
124 handleException(e);
125 }
126 }
127
128
129
130
131 @Override
132 public void close() throws SQLException {
133 if (isClosed()) {
134 return;
135 }
136 final List<Exception> thrownList = new ArrayList<>();
137 try {
138 if (connection != null) {
139 connection.removeTrace(this);
140 connection = null;
141 }
142
143
144
145
146
147 final List<AbandonedTrace> traceList = getTrace();
148 if (traceList != null) {
149 traceList.forEach(trace -> trace.close(e -> {
150 if (connection != null) {
151
152 connection.handleExceptionNoThrow(e);
153 }
154 thrownList.add(e);
155 }));
156 clearTrace();
157 }
158 Utils.close(statement, e -> {
159 if (connection != null) {
160
161 connection.handleExceptionNoThrow(e);
162 }
163 thrownList.add(e);
164 });
165 } finally {
166 closed = true;
167 statement = null;
168 if (!thrownList.isEmpty()) {
169 throw new SQLExceptionList(thrownList);
170 }
171 }
172 }
173
174 @Override
175 public void closeOnCompletion() throws SQLException {
176 checkOpen();
177 try {
178 Jdbc41Bridge.closeOnCompletion(statement);
179 } catch (final SQLException e) {
180 handleException(e);
181 }
182 }
183
184 @Override
185 public boolean execute(final String sql) throws SQLException {
186 checkOpen();
187 setLastUsedInParent();
188 try {
189 return statement.execute(sql);
190 } catch (final SQLException e) {
191 handleException(e);
192 return false;
193 }
194 }
195
196 @Override
197 public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException {
198 checkOpen();
199 setLastUsedInParent();
200 try {
201 return statement.execute(sql, autoGeneratedKeys);
202 } catch (final SQLException e) {
203 handleException(e);
204 return false;
205 }
206 }
207
208 @Override
209 public boolean execute(final String sql, final int[] columnIndexes) throws SQLException {
210 checkOpen();
211 setLastUsedInParent();
212 try {
213 return statement.execute(sql, columnIndexes);
214 } catch (final SQLException e) {
215 handleException(e);
216 return false;
217 }
218 }
219
220 @Override
221 public boolean execute(final String sql, final String[] columnNames) throws SQLException {
222 checkOpen();
223 setLastUsedInParent();
224 try {
225 return statement.execute(sql, columnNames);
226 } catch (final SQLException e) {
227 handleException(e);
228 return false;
229 }
230 }
231
232 @Override
233 public int[] executeBatch() throws SQLException {
234 checkOpen();
235 setLastUsedInParent();
236 try {
237 return statement.executeBatch();
238 } catch (final SQLException e) {
239 handleException(e);
240 throw new AssertionError();
241 }
242 }
243
244
245
246
247 @Override
248 public long[] executeLargeBatch() throws SQLException {
249 checkOpen();
250 setLastUsedInParent();
251 try {
252 return statement.executeLargeBatch();
253 } catch (final SQLException e) {
254 handleException(e);
255 return null;
256 }
257 }
258
259
260
261
262 @Override
263 public long executeLargeUpdate(final String sql) throws SQLException {
264 checkOpen();
265 setLastUsedInParent();
266 try {
267 return statement.executeLargeUpdate(sql);
268 } catch (final SQLException e) {
269 handleException(e);
270 return 0;
271 }
272 }
273
274
275
276
277 @Override
278 public long executeLargeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
279 checkOpen();
280 setLastUsedInParent();
281 try {
282 return statement.executeLargeUpdate(sql, autoGeneratedKeys);
283 } catch (final SQLException e) {
284 handleException(e);
285 return 0;
286 }
287 }
288
289
290
291
292 @Override
293 public long executeLargeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
294 checkOpen();
295 setLastUsedInParent();
296 try {
297 return statement.executeLargeUpdate(sql, columnIndexes);
298 } catch (final SQLException e) {
299 handleException(e);
300 return 0;
301 }
302 }
303
304
305
306
307 @Override
308 public long executeLargeUpdate(final String sql, final String[] columnNames) throws SQLException {
309 checkOpen();
310 setLastUsedInParent();
311 try {
312 return statement.executeLargeUpdate(sql, columnNames);
313 } catch (final SQLException e) {
314 handleException(e);
315 return 0;
316 }
317 }
318
319 @SuppressWarnings("resource")
320 @Override
321 public ResultSet executeQuery(final String sql) throws SQLException {
322 checkOpen();
323 setLastUsedInParent();
324 try {
325 return DelegatingResultSet.wrapResultSet(this, statement.executeQuery(sql));
326 } catch (final SQLException e) {
327 handleException(e);
328 throw new AssertionError();
329 }
330 }
331
332 @Override
333 public int executeUpdate(final String sql) throws SQLException {
334 checkOpen();
335 setLastUsedInParent();
336 try {
337 return statement.executeUpdate(sql);
338 } catch (final SQLException e) {
339 handleException(e);
340 return 0;
341 }
342 }
343
344 @Override
345 public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
346 checkOpen();
347 setLastUsedInParent();
348 try {
349 return statement.executeUpdate(sql, autoGeneratedKeys);
350 } catch (final SQLException e) {
351 handleException(e);
352 return 0;
353 }
354 }
355
356 @Override
357 public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
358 checkOpen();
359 setLastUsedInParent();
360 try {
361 return statement.executeUpdate(sql, columnIndexes);
362 } catch (final SQLException e) {
363 handleException(e);
364 return 0;
365 }
366 }
367
368 @Override
369 public int executeUpdate(final String sql, final String[] columnNames) throws SQLException {
370 checkOpen();
371 setLastUsedInParent();
372 try {
373 return statement.executeUpdate(sql, columnNames);
374 } catch (final SQLException e) {
375 handleException(e);
376 return 0;
377 }
378 }
379
380 @Override
381 protected void finalize() throws Throwable {
382
383
384
385
386
387
388
389
390 close();
391 super.finalize();
392 }
393
394 @Override
395 public Connection getConnection() throws SQLException {
396 checkOpen();
397 return getConnectionInternal();
398 }
399
400
401
402
403
404
405 protected DelegatingConnection<?> getConnectionInternal() {
406 return connection;
407 }
408
409
410
411
412
413
414
415 public Statement getDelegate() {
416 return statement;
417 }
418
419 @Override
420 public int getFetchDirection() throws SQLException {
421 checkOpen();
422 try {
423 return statement.getFetchDirection();
424 } catch (final SQLException e) {
425 handleException(e);
426 return 0;
427 }
428 }
429
430 @Override
431 public int getFetchSize() throws SQLException {
432 checkOpen();
433 try {
434 return statement.getFetchSize();
435 } catch (final SQLException e) {
436 handleException(e);
437 return 0;
438 }
439 }
440
441 @SuppressWarnings("resource")
442 @Override
443 public ResultSet getGeneratedKeys() throws SQLException {
444 checkOpen();
445 try {
446 return DelegatingResultSet.wrapResultSet(this, statement.getGeneratedKeys());
447 } catch (final SQLException e) {
448 handleException(e);
449 throw new AssertionError();
450 }
451 }
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468 @SuppressWarnings("resource")
469 public Statement getInnermostDelegate() {
470 Statement stmt = statement;
471 while (stmt instanceof DelegatingStatement) {
472 stmt = ((DelegatingStatement) stmt).getDelegate();
473 if (this == stmt) {
474 return null;
475 }
476 }
477 return stmt;
478 }
479
480
481
482
483 @Override
484 public long getLargeMaxRows() throws SQLException {
485 checkOpen();
486 try {
487 return statement.getLargeMaxRows();
488 } catch (final SQLException e) {
489 handleException(e);
490 return 0;
491 }
492 }
493
494
495
496
497 @Override
498 public long getLargeUpdateCount() throws SQLException {
499 checkOpen();
500 try {
501 return statement.getLargeUpdateCount();
502 } catch (final SQLException e) {
503 handleException(e);
504 return 0;
505 }
506 }
507
508 @Override
509 public int getMaxFieldSize() throws SQLException {
510 checkOpen();
511 try {
512 return statement.getMaxFieldSize();
513 } catch (final SQLException e) {
514 handleException(e);
515 return 0;
516 }
517 }
518
519 @Override
520 public int getMaxRows() throws SQLException {
521 checkOpen();
522 try {
523 return statement.getMaxRows();
524 } catch (final SQLException e) {
525 handleException(e);
526 return 0;
527 }
528 }
529
530 @Override
531 public boolean getMoreResults() throws SQLException {
532 checkOpen();
533 try {
534 return statement.getMoreResults();
535 } catch (final SQLException e) {
536 handleException(e);
537 return false;
538 }
539 }
540
541 @Override
542 public boolean getMoreResults(final int current) throws SQLException {
543 checkOpen();
544 try {
545 return statement.getMoreResults(current);
546 } catch (final SQLException e) {
547 handleException(e);
548 return false;
549 }
550 }
551
552 @Override
553 public int getQueryTimeout() throws SQLException {
554 checkOpen();
555 try {
556 return statement.getQueryTimeout();
557 } catch (final SQLException e) {
558 handleException(e);
559 return 0;
560 }
561 }
562
563 @SuppressWarnings("resource")
564 @Override
565 public ResultSet getResultSet() throws SQLException {
566 checkOpen();
567 try {
568 return DelegatingResultSet.wrapResultSet(this, statement.getResultSet());
569 } catch (final SQLException e) {
570 handleException(e);
571 throw new AssertionError();
572 }
573 }
574
575 @Override
576 public int getResultSetConcurrency() throws SQLException {
577 checkOpen();
578 try {
579 return statement.getResultSetConcurrency();
580 } catch (final SQLException e) {
581 handleException(e);
582 return 0;
583 }
584 }
585
586 @Override
587 public int getResultSetHoldability() throws SQLException {
588 checkOpen();
589 try {
590 return statement.getResultSetHoldability();
591 } catch (final SQLException e) {
592 handleException(e);
593 return 0;
594 }
595 }
596
597 @Override
598 public int getResultSetType() throws SQLException {
599 checkOpen();
600 try {
601 return statement.getResultSetType();
602 } catch (final SQLException e) {
603 handleException(e);
604 return 0;
605 }
606 }
607
608 @Override
609 public int getUpdateCount() throws SQLException {
610 checkOpen();
611 try {
612 return statement.getUpdateCount();
613 } catch (final SQLException e) {
614 handleException(e);
615 return 0;
616 }
617 }
618
619 @Override
620 public SQLWarning getWarnings() throws SQLException {
621 checkOpen();
622 try {
623 return statement.getWarnings();
624 } catch (final SQLException e) {
625 handleException(e);
626 throw new AssertionError();
627 }
628 }
629
630
631
632
633
634
635
636 protected void handleException(final SQLException e) throws SQLException {
637 if (connection == null) {
638 throw e;
639 }
640 connection.handleException(e);
641 }
642
643
644
645
646 @Override
647 public boolean isClosed() throws SQLException {
648 return closed;
649 }
650
651
652
653
654
655
656 protected boolean isClosedInternal() {
657 return closed;
658 }
659
660 @Override
661 public boolean isCloseOnCompletion() throws SQLException {
662 checkOpen();
663 try {
664 return Jdbc41Bridge.isCloseOnCompletion(statement);
665 } catch (final SQLException e) {
666 handleException(e);
667 return false;
668 }
669 }
670
671 @Override
672 public boolean isPoolable() throws SQLException {
673 checkOpen();
674 try {
675 return statement.isPoolable();
676 } catch (final SQLException e) {
677 handleException(e);
678 return false;
679 }
680 }
681
682 @Override
683 public boolean isWrapperFor(final Class<?> iface) throws SQLException {
684 if (iface.isAssignableFrom(getClass()) || iface.isAssignableFrom(statement.getClass())) {
685 return true;
686 }
687 return statement.isWrapperFor(iface);
688 }
689
690
691
692
693
694
695
696
697 public void passivate() throws SQLException {
698 if (statement instanceof DelegatingStatement) {
699 ((DelegatingStatement) statement).passivate();
700 }
701 }
702
703
704
705
706
707
708 protected void setClosedInternal(final boolean closed) {
709 this.closed = closed;
710 }
711
712 @Override
713 public void setCursorName(final String name) throws SQLException {
714 checkOpen();
715 try {
716 statement.setCursorName(name);
717 } catch (final SQLException e) {
718 handleException(e);
719 }
720 }
721
722
723
724
725
726
727
728 public void setDelegate(final Statement statement) {
729 this.statement = statement;
730 }
731
732 @Override
733 public void setEscapeProcessing(final boolean enable) throws SQLException {
734 checkOpen();
735 try {
736 statement.setEscapeProcessing(enable);
737 } catch (final SQLException e) {
738 handleException(e);
739 }
740 }
741
742 @Override
743 public void setFetchDirection(final int direction) throws SQLException {
744 checkOpen();
745 try {
746 statement.setFetchDirection(direction);
747 } catch (final SQLException e) {
748 handleException(e);
749 }
750 }
751
752 @Override
753 public void setFetchSize(final int rows) throws SQLException {
754 checkOpen();
755 try {
756 statement.setFetchSize(rows);
757 } catch (final SQLException e) {
758 handleException(e);
759 }
760 }
761
762
763
764
765 @Override
766 public void setLargeMaxRows(final long max) throws SQLException {
767 checkOpen();
768 try {
769 statement.setLargeMaxRows(max);
770 } catch (final SQLException e) {
771 handleException(e);
772 }
773 }
774
775 private void setLastUsedInParent() {
776 if (connection != null) {
777 connection.setLastUsed();
778 }
779 }
780
781 @Override
782 public void setMaxFieldSize(final int max) throws SQLException {
783 checkOpen();
784 try {
785 statement.setMaxFieldSize(max);
786 } catch (final SQLException e) {
787 handleException(e);
788 }
789 }
790
791 @Override
792 public void setMaxRows(final int max) throws SQLException {
793 checkOpen();
794 try {
795 statement.setMaxRows(max);
796 } catch (final SQLException e) {
797 handleException(e);
798 }
799 }
800
801 @Override
802 public void setPoolable(final boolean poolable) throws SQLException {
803 checkOpen();
804 try {
805 statement.setPoolable(poolable);
806 } catch (final SQLException e) {
807 handleException(e);
808 }
809 }
810
811 @Override
812 public void setQueryTimeout(final int seconds) throws SQLException {
813 checkOpen();
814 try {
815 statement.setQueryTimeout(seconds);
816 } catch (final SQLException e) {
817 handleException(e);
818 }
819 }
820
821
822
823
824
825
826 @Override
827 public synchronized String toString() {
828 return Objects.toString(statement, "NULL");
829 }
830
831 @Override
832 public <T> T unwrap(final Class<T> iface) throws SQLException {
833 if (iface.isAssignableFrom(getClass())) {
834 return iface.cast(this);
835 }
836 if (iface.isAssignableFrom(statement.getClass())) {
837 return iface.cast(statement);
838 }
839 return statement.unwrap(iface);
840 }
841 }