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