001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.dbcp2; 019 020import java.sql.Array; 021import java.sql.Blob; 022import java.sql.CallableStatement; 023import java.sql.ClientInfoStatus; 024import java.sql.Clob; 025import java.sql.Connection; 026import java.sql.DatabaseMetaData; 027import java.sql.NClob; 028import java.sql.PreparedStatement; 029import java.sql.ResultSet; 030import java.sql.SQLClientInfoException; 031import java.sql.SQLException; 032import java.sql.SQLWarning; 033import java.sql.SQLXML; 034import java.sql.Savepoint; 035import java.sql.Statement; 036import java.sql.Struct; 037import java.util.Collections; 038import java.util.Iterator; 039import java.util.List; 040import java.util.Map; 041import java.util.Properties; 042import java.util.concurrent.Executor; 043 044/** 045 * A base delegating implementation of {@link Connection}. 046 * <p> 047 * All of the methods from the {@link Connection} interface 048 * simply check to see that the {@link Connection} is active, 049 * and call the corresponding method on the "delegate" 050 * provided in my constructor. 051 * <p> 052 * Extends AbandonedTrace to implement Connection tracking and 053 * logging of code which created the Connection. Tracking the 054 * Connection ensures that the AbandonedObjectPool can close 055 * this connection and recycle it if its pool of connections 056 * is nearing exhaustion and this connection's last usage is 057 * older than the removeAbandonedTimeout. 058 * 059 * @param <C> the Connection type 060 * 061 * @author Rodney Waldhoff 062 * @author Glenn L. Nielsen 063 * @author James House 064 * @author Dirk Verbeeck 065 * @version $Id: DelegatingConnection.java 1691861 2015-07-19 23:15:15Z psteitz $ 066 * @since 2.0 067 */ 068public class DelegatingConnection<C extends Connection> extends AbandonedTrace 069 implements Connection { 070 071 private static final Map<String, ClientInfoStatus> EMPTY_FAILED_PROPERTIES = 072 Collections.<String, ClientInfoStatus>emptyMap(); 073 074 /** My delegate {@link Connection}. */ 075 private volatile C _conn = null; 076 077 private volatile boolean _closed = false; 078 079 private boolean _cacheState = true; 080 private Boolean _autoCommitCached = null; 081 private Boolean _readOnlyCached = null; 082 private Integer defaultQueryTimeout = null; 083 084 /** 085 * Create a wrapper for the Connection which traces this 086 * Connection in the AbandonedObjectPool. 087 * 088 * @param c the {@link Connection} to delegate all calls to. 089 */ 090 public DelegatingConnection(C c) { 091 super(); 092 _conn = c; 093 } 094 095 096 /** 097 * Returns a string representation of the metadata associated with 098 * the innermost delegate connection. 099 */ 100 @Override 101 public String toString() { 102 String s = null; 103 104 Connection c = this.getInnermostDelegateInternal(); 105 if (c != null) { 106 try { 107 if (c.isClosed()) { 108 s = "connection is closed"; 109 } 110 else { 111 StringBuffer sb = new StringBuffer(); 112 sb.append(hashCode()); 113 DatabaseMetaData meta = c.getMetaData(); 114 if (meta != null) { 115 sb.append(", URL="); 116 sb.append(meta.getURL()); 117 sb.append(", UserName="); 118 sb.append(meta.getUserName()); 119 sb.append(", "); 120 sb.append(meta.getDriverName()); 121 s = sb.toString(); 122 } 123 } 124 } 125 catch (SQLException ex) { 126 // Ignore 127 } 128 } 129 130 if (s == null) { 131 s = super.toString(); 132 } 133 134 return s; 135 } 136 137 /** 138 * Returns my underlying {@link Connection}. 139 * @return my underlying {@link Connection}. 140 */ 141 public C getDelegate() { 142 return getDelegateInternal(); 143 } 144 145 protected final C getDelegateInternal() { 146 return _conn; 147 } 148 149 /** 150 * Compares innermost delegate to the given connection. 151 * 152 * @param c connection to compare innermost delegate with 153 * @return true if innermost delegate equals <code>c</code> 154 */ 155 public boolean innermostDelegateEquals(Connection c) { 156 Connection innerCon = getInnermostDelegateInternal(); 157 if (innerCon == null) { 158 return c == null; 159 } 160 return innerCon.equals(c); 161 } 162 163 164 /** 165 * If my underlying {@link Connection} is not a 166 * {@code DelegatingConnection}, returns it, 167 * otherwise recursively invokes this method on 168 * my delegate. 169 * <p> 170 * Hence this method will return the first 171 * delegate that is not a {@code DelegatingConnection}, 172 * or {@code null} when no non-{@code DelegatingConnection} 173 * delegate can be found by traversing this chain. 174 * <p> 175 * This method is useful when you may have nested 176 * {@code DelegatingConnection}s, and you want to make 177 * sure to obtain a "genuine" {@link Connection}. 178 */ 179 public Connection getInnermostDelegate() { 180 return getInnermostDelegateInternal(); 181 } 182 183 184 /** 185 * Although this method is public, it is part of the internal API and should 186 * not be used by clients. The signature of this method may change at any 187 * time including in ways that break backwards compatibility. 188 */ 189 public final Connection getInnermostDelegateInternal() { 190 Connection c = _conn; 191 while(c != null && c instanceof DelegatingConnection) { 192 c = ((DelegatingConnection<?>)c).getDelegateInternal(); 193 if(this == c) { 194 return null; 195 } 196 } 197 return c; 198 } 199 200 /** Sets my delegate. */ 201 public void setDelegate(C c) { 202 _conn = c; 203 } 204 205 /** 206 * Closes the underlying connection, and close any Statements that were not 207 * explicitly closed. Sub-classes that override this method must: 208 * <ol> 209 * <li>Call passivate()</li> 210 * <li>Call close (or the equivalent appropriate action) on the wrapped 211 * connection</li> 212 * <li>Set _closed to <code>false</code></li> 213 * </ol> 214 */ 215 @Override 216 public void close() throws SQLException { 217 if (!_closed) { 218 closeInternal(); 219 } 220 } 221 222 protected boolean isClosedInternal() { 223 return _closed; 224 } 225 226 protected void setClosedInternal(boolean closed) { 227 this._closed = closed; 228 } 229 230 protected final void closeInternal() throws SQLException { 231 try { 232 passivate(); 233 } finally { 234 if (_conn != null) { 235 try { 236 _conn.close(); 237 } finally { 238 _closed = true; 239 } 240 } else { 241 _closed = true; 242 } 243 } 244 } 245 246 protected void handleException(SQLException e) throws SQLException { 247 throw e; 248 } 249 250 private void initializeStatement(DelegatingStatement ds) throws SQLException { 251 if (defaultQueryTimeout != null && 252 defaultQueryTimeout.intValue() != ds.getQueryTimeout()) { 253 ds.setQueryTimeout(defaultQueryTimeout.intValue()); 254 } 255 } 256 257 @Override 258 public Statement createStatement() throws SQLException { 259 checkOpen(); 260 try { 261 DelegatingStatement ds = 262 new DelegatingStatement(this, _conn.createStatement()); 263 initializeStatement(ds); 264 return ds; 265 } 266 catch (SQLException e) { 267 handleException(e); 268 return null; 269 } 270 } 271 272 @Override 273 public Statement createStatement(int resultSetType, 274 int resultSetConcurrency) throws SQLException { 275 checkOpen(); 276 try { 277 DelegatingStatement ds = new DelegatingStatement( 278 this, _conn.createStatement(resultSetType,resultSetConcurrency)); 279 initializeStatement(ds); 280 return ds; 281 } 282 catch (SQLException e) { 283 handleException(e); 284 return null; 285 } 286 } 287 288 @Override 289 public PreparedStatement prepareStatement(String sql) throws SQLException { 290 checkOpen(); 291 try { 292 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 293 this, _conn.prepareStatement(sql)); 294 initializeStatement(dps); 295 return dps; 296 } 297 catch (SQLException e) { 298 handleException(e); 299 return null; 300 } 301 } 302 303 @Override 304 public PreparedStatement prepareStatement(String sql, 305 int resultSetType, 306 int resultSetConcurrency) throws SQLException { 307 checkOpen(); 308 try { 309 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 310 this, _conn.prepareStatement(sql,resultSetType,resultSetConcurrency)); 311 initializeStatement(dps); 312 return dps; 313 } 314 catch (SQLException e) { 315 handleException(e); 316 return null; 317 } 318 } 319 320 @Override 321 public CallableStatement prepareCall(String sql) throws SQLException { 322 checkOpen(); 323 try { 324 DelegatingCallableStatement dcs = 325 new DelegatingCallableStatement(this, _conn.prepareCall(sql)); 326 initializeStatement(dcs); 327 return dcs; 328 } 329 catch (SQLException e) { 330 handleException(e); 331 return null; 332 } 333 } 334 335 @Override 336 public CallableStatement prepareCall(String sql, 337 int resultSetType, 338 int resultSetConcurrency) throws SQLException { 339 checkOpen(); 340 try { 341 DelegatingCallableStatement dcs = new DelegatingCallableStatement( 342 this, _conn.prepareCall(sql, resultSetType,resultSetConcurrency)); 343 initializeStatement(dcs); 344 return dcs; 345 } 346 catch (SQLException e) { 347 handleException(e); 348 return null; 349 } 350 } 351 352 353 @Override 354 public void clearWarnings() throws SQLException { 355 checkOpen(); 356 try { 357 _conn.clearWarnings(); 358 } catch (SQLException e) { 359 handleException(e); 360 } 361 } 362 363 364 @Override 365 public void commit() throws SQLException { 366 checkOpen(); 367 try { 368 _conn.commit(); 369 } catch (SQLException e) { 370 handleException(e); 371 } 372 } 373 374 375 /** 376 * Returns the state caching flag. 377 * 378 * @return the state caching flag 379 */ 380 public boolean getCacheState() { 381 return _cacheState; 382 } 383 384 @Override 385 public boolean getAutoCommit() throws SQLException { 386 checkOpen(); 387 if (_cacheState && _autoCommitCached != null) { 388 return _autoCommitCached.booleanValue(); 389 } 390 try { 391 _autoCommitCached = Boolean.valueOf(_conn.getAutoCommit()); 392 return _autoCommitCached.booleanValue(); 393 } catch (SQLException e) { 394 handleException(e); 395 return false; 396 } 397 } 398 399 400 @Override 401 public String getCatalog() throws SQLException { 402 checkOpen(); 403 try { 404 return _conn.getCatalog(); 405 } catch (SQLException e) { 406 handleException(e); 407 return null; 408 } 409 } 410 411 412 @Override 413 public DatabaseMetaData getMetaData() throws SQLException { 414 checkOpen(); 415 try { 416 return new DelegatingDatabaseMetaData(this, _conn.getMetaData()); 417 } catch (SQLException e) { 418 handleException(e); 419 return null; 420 } 421 } 422 423 424 @Override 425 public int getTransactionIsolation() throws SQLException { 426 checkOpen(); 427 try { 428 return _conn.getTransactionIsolation(); 429 } catch (SQLException e) { 430 handleException(e); 431 return -1; 432 } 433 } 434 435 436 @Override 437 public Map<String,Class<?>> getTypeMap() throws SQLException { 438 checkOpen(); 439 try { 440 return _conn.getTypeMap(); 441 } catch (SQLException e) { 442 handleException(e); 443 return null; 444 } 445 } 446 447 448 @Override 449 public SQLWarning getWarnings() throws SQLException { 450 checkOpen(); 451 try { 452 return _conn.getWarnings(); 453 } catch (SQLException e) { 454 handleException(e); 455 return null; 456 } 457 } 458 459 460 @Override 461 public boolean isReadOnly() throws SQLException { 462 checkOpen(); 463 if (_cacheState && _readOnlyCached != null) { 464 return _readOnlyCached.booleanValue(); 465 } 466 try { 467 _readOnlyCached = Boolean.valueOf(_conn.isReadOnly()); 468 return _readOnlyCached.booleanValue(); 469 } catch (SQLException e) { 470 handleException(e); 471 return false; 472 } 473 } 474 475 476 @Override 477 public String nativeSQL(String sql) throws SQLException { 478 checkOpen(); 479 try { 480 return _conn.nativeSQL(sql); 481 } catch (SQLException e) { 482 handleException(e); 483 return null; 484 } 485 } 486 487 488 @Override 489 public void rollback() throws SQLException { 490 checkOpen(); 491 try { 492 _conn.rollback(); 493 } catch (SQLException e) { 494 handleException(e); 495 } 496 } 497 498 499 /** 500 * Obtain the default query timeout that will be used for {@link Statement}s 501 * created from this connection. <code>null</code> means that the driver 502 * default will be used. 503 */ 504 public Integer getDefaultQueryTimeout() { 505 return defaultQueryTimeout; 506 } 507 508 509 /** 510 * Set the default query timeout that will be used for {@link Statement}s 511 * created from this connection. <code>null</code> means that the driver 512 * default will be used. 513 */ 514 public void setDefaultQueryTimeout(Integer defaultQueryTimeout) { 515 this.defaultQueryTimeout = defaultQueryTimeout; 516 } 517 518 519 /** 520 * Sets the state caching flag. 521 * 522 * @param cacheState The new value for the state caching flag 523 */ 524 public void setCacheState(boolean cacheState) { 525 this._cacheState = cacheState; 526 } 527 528 /** 529 * Can be used to clear cached state when it is known that the underlying 530 * connection may have been accessed directly. 531 */ 532 public void clearCachedState() { 533 _autoCommitCached = null; 534 _readOnlyCached = null; 535 if (_conn instanceof DelegatingConnection) { 536 ((DelegatingConnection<?>)_conn).clearCachedState(); 537 } 538 } 539 540 @Override 541 public void setAutoCommit(boolean autoCommit) throws SQLException { 542 checkOpen(); 543 try { 544 _conn.setAutoCommit(autoCommit); 545 if (_cacheState) { 546 _autoCommitCached = Boolean.valueOf(autoCommit); 547 } 548 } catch (SQLException e) { 549 _autoCommitCached = null; 550 handleException(e); 551 } 552 } 553 554 @Override 555 public void setCatalog(String catalog) throws SQLException 556 { checkOpen(); try { _conn.setCatalog(catalog); } catch (SQLException e) { handleException(e); } } 557 558 @Override 559 public void setReadOnly(boolean readOnly) throws SQLException { 560 checkOpen(); 561 try { 562 _conn.setReadOnly(readOnly); 563 if (_cacheState) { 564 _readOnlyCached = Boolean.valueOf(readOnly); 565 } 566 } catch (SQLException e) { 567 _readOnlyCached = null; 568 handleException(e); 569 } 570 } 571 572 573 @Override 574 public void setTransactionIsolation(int level) throws SQLException { 575 checkOpen(); 576 try { 577 _conn.setTransactionIsolation(level); 578 } catch (SQLException e) { 579 handleException(e); 580 } 581 } 582 583 584 @Override 585 public void setTypeMap(Map<String,Class<?>> map) throws SQLException { 586 checkOpen(); 587 try { 588 _conn.setTypeMap(map); 589 } catch (SQLException e) { 590 handleException(e); 591 } 592 } 593 594 595 @Override 596 public boolean isClosed() throws SQLException { 597 return _closed || _conn.isClosed(); 598 } 599 600 protected void checkOpen() throws SQLException { 601 if(_closed) { 602 if (null != _conn) { 603 String label = ""; 604 try { 605 label = _conn.toString(); 606 } catch (Exception ex) { 607 // ignore, leave label empty 608 } 609 throw new SQLException 610 ("Connection " + label + " is closed."); 611 } 612 throw new SQLException 613 ("Connection is null."); 614 } 615 } 616 617 protected void activate() { 618 _closed = false; 619 setLastUsed(); 620 if(_conn instanceof DelegatingConnection) { 621 ((DelegatingConnection<?>)_conn).activate(); 622 } 623 } 624 625 protected void passivate() throws SQLException { 626 // The JDBC spec requires that a Connection close any open 627 // Statement's when it is closed. 628 // DBCP-288. Not all the traced objects will be statements 629 List<AbandonedTrace> traces = getTrace(); 630 if(traces != null && traces.size() > 0) { 631 Iterator<AbandonedTrace> traceIter = traces.iterator(); 632 while (traceIter.hasNext()) { 633 Object trace = traceIter.next(); 634 if (trace instanceof Statement) { 635 ((Statement) trace).close(); 636 } else if (trace instanceof ResultSet) { 637 // DBCP-265: Need to close the result sets that are 638 // generated via DatabaseMetaData 639 ((ResultSet) trace).close(); 640 } 641 } 642 clearTrace(); 643 } 644 setLastUsed(0); 645 } 646 647 648 @Override 649 public int getHoldability() throws SQLException { 650 checkOpen(); 651 try { 652 return _conn.getHoldability(); 653 } catch (SQLException e) { 654 handleException(e); 655 return 0; 656 } 657 } 658 659 660 @Override 661 public void setHoldability(int holdability) throws SQLException { 662 checkOpen(); 663 try { 664 _conn.setHoldability(holdability); 665 } catch (SQLException e) { 666 handleException(e); 667 } 668 } 669 670 671 @Override 672 public Savepoint setSavepoint() throws SQLException { 673 checkOpen(); 674 try { 675 return _conn.setSavepoint(); 676 } catch (SQLException e) { 677 handleException(e); 678 return null; 679 } 680 } 681 682 683 @Override 684 public Savepoint setSavepoint(String name) throws SQLException { 685 checkOpen(); 686 try { 687 return _conn.setSavepoint(name); 688 } catch (SQLException e) { 689 handleException(e); 690 return null; 691 } 692 } 693 694 695 @Override 696 public void rollback(Savepoint savepoint) throws SQLException { 697 checkOpen(); 698 try { 699 _conn.rollback(savepoint); 700 } catch (SQLException e) { 701 handleException(e); 702 } 703 } 704 705 706 @Override 707 public void releaseSavepoint(Savepoint savepoint) 708 throws SQLException { 709 checkOpen(); 710 try { 711 _conn.releaseSavepoint(savepoint); 712 } catch (SQLException e) { 713 handleException(e); 714 } 715 } 716 717 718 @Override 719 public Statement createStatement(int resultSetType, 720 int resultSetConcurrency, 721 int resultSetHoldability) throws SQLException { 722 checkOpen(); 723 try { 724 DelegatingStatement ds = new DelegatingStatement(this, 725 _conn.createStatement(resultSetType, resultSetConcurrency, 726 resultSetHoldability)); 727 initializeStatement(ds); 728 return ds; 729 } 730 catch (SQLException e) { 731 handleException(e); 732 return null; 733 } 734 } 735 736 @Override 737 public PreparedStatement prepareStatement(String sql, int resultSetType, 738 int resultSetConcurrency, 739 int resultSetHoldability) throws SQLException { 740 checkOpen(); 741 try { 742 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 743 this, _conn.prepareStatement(sql, resultSetType, 744 resultSetConcurrency, resultSetHoldability)); 745 initializeStatement(dps); 746 return dps; 747 } 748 catch (SQLException e) { 749 handleException(e); 750 return null; 751 } 752 } 753 754 @Override 755 public CallableStatement prepareCall(String sql, int resultSetType, 756 int resultSetConcurrency, 757 int resultSetHoldability) throws SQLException { 758 checkOpen(); 759 try { 760 DelegatingCallableStatement dcs = new DelegatingCallableStatement( 761 this, _conn.prepareCall(sql, resultSetType, 762 resultSetConcurrency, resultSetHoldability)); 763 initializeStatement(dcs); 764 return dcs; 765 } 766 catch (SQLException e) { 767 handleException(e); 768 return null; 769 } 770 } 771 772 @Override 773 public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { 774 checkOpen(); 775 try { 776 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 777 this, _conn.prepareStatement(sql, autoGeneratedKeys)); 778 initializeStatement(dps); 779 return dps; 780 } 781 catch (SQLException e) { 782 handleException(e); 783 return null; 784 } 785 } 786 787 @Override 788 public PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException { 789 checkOpen(); 790 try { 791 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 792 this, _conn.prepareStatement(sql, columnIndexes)); 793 initializeStatement(dps); 794 return dps; 795 } 796 catch (SQLException e) { 797 handleException(e); 798 return null; 799 } 800 } 801 802 @Override 803 public PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException { 804 checkOpen(); 805 try { 806 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 807 this, _conn.prepareStatement(sql, columnNames)); 808 initializeStatement(dps); 809 return dps; 810 } 811 catch (SQLException e) { 812 handleException(e); 813 return null; 814 } 815 } 816 817 818 @Override 819 public boolean isWrapperFor(Class<?> iface) throws SQLException { 820 if (iface.isAssignableFrom(getClass())) { 821 return true; 822 } else if (iface.isAssignableFrom(_conn.getClass())) { 823 return true; 824 } else { 825 return _conn.isWrapperFor(iface); 826 } 827 } 828 829 @Override 830 public <T> T unwrap(Class<T> iface) throws SQLException { 831 if (iface.isAssignableFrom(getClass())) { 832 return iface.cast(this); 833 } else if (iface.isAssignableFrom(_conn.getClass())) { 834 return iface.cast(_conn); 835 } else { 836 return _conn.unwrap(iface); 837 } 838 } 839 840 @Override 841 public Array createArrayOf(String typeName, Object[] elements) throws SQLException { 842 checkOpen(); 843 try { 844 return _conn.createArrayOf(typeName, elements); 845 } 846 catch (SQLException e) { 847 handleException(e); 848 return null; 849 } 850 } 851 852 @Override 853 public Blob createBlob() throws SQLException { 854 checkOpen(); 855 try { 856 return _conn.createBlob(); 857 } 858 catch (SQLException e) { 859 handleException(e); 860 return null; 861 } 862 } 863 864 @Override 865 public Clob createClob() throws SQLException { 866 checkOpen(); 867 try { 868 return _conn.createClob(); 869 } 870 catch (SQLException e) { 871 handleException(e); 872 return null; 873 } 874 } 875 876 @Override 877 public NClob createNClob() throws SQLException { 878 checkOpen(); 879 try { 880 return _conn.createNClob(); 881 } 882 catch (SQLException e) { 883 handleException(e); 884 return null; 885 } 886 } 887 888 @Override 889 public SQLXML createSQLXML() throws SQLException { 890 checkOpen(); 891 try { 892 return _conn.createSQLXML(); 893 } 894 catch (SQLException e) { 895 handleException(e); 896 return null; 897 } 898 } 899 900 @Override 901 public Struct createStruct(String typeName, Object[] attributes) throws SQLException { 902 checkOpen(); 903 try { 904 return _conn.createStruct(typeName, attributes); 905 } 906 catch (SQLException e) { 907 handleException(e); 908 return null; 909 } 910 } 911 912 @Override 913 public boolean isValid(int timeout) throws SQLException { 914 if (isClosed()) { 915 return false; 916 } 917 try { 918 return _conn.isValid(timeout); 919 } 920 catch (SQLException e) { 921 handleException(e); 922 return false; 923 } 924 } 925 926 @Override 927 public void setClientInfo(String name, String value) throws SQLClientInfoException { 928 try { 929 checkOpen(); 930 _conn.setClientInfo(name, value); 931 } 932 catch (SQLClientInfoException e) { 933 throw e; 934 } 935 catch (SQLException e) { 936 throw new SQLClientInfoException("Connection is closed.", EMPTY_FAILED_PROPERTIES, e); 937 } 938 } 939 940 @Override 941 public void setClientInfo(Properties properties) throws SQLClientInfoException { 942 try { 943 checkOpen(); 944 _conn.setClientInfo(properties); 945 } 946 catch (SQLClientInfoException e) { 947 throw e; 948 } 949 catch (SQLException e) { 950 throw new SQLClientInfoException("Connection is closed.", EMPTY_FAILED_PROPERTIES, e); 951 } 952 } 953 954 @Override 955 public Properties getClientInfo() throws SQLException { 956 checkOpen(); 957 try { 958 return _conn.getClientInfo(); 959 } 960 catch (SQLException e) { 961 handleException(e); 962 return null; 963 } 964 } 965 966 @Override 967 public String getClientInfo(String name) throws SQLException { 968 checkOpen(); 969 try { 970 return _conn.getClientInfo(name); 971 } 972 catch (SQLException e) { 973 handleException(e); 974 return null; 975 } 976 } 977 978 @Override 979 public void setSchema(String schema) throws SQLException { 980 checkOpen(); 981 try { 982 _conn.setSchema(schema); 983 } 984 catch (SQLException e) { 985 handleException(e); 986 } 987 } 988 989 @Override 990 public String getSchema() throws SQLException { 991 checkOpen(); 992 try { 993 return _conn.getSchema(); 994 } 995 catch (SQLException e) { 996 handleException(e); 997 return null; 998 } 999 } 1000 1001 @Override 1002 public void abort(Executor executor) throws SQLException { 1003 checkOpen(); 1004 try { 1005 _conn.abort(executor); 1006 } 1007 catch (SQLException e) { 1008 handleException(e); 1009 } 1010 } 1011 1012 @Override 1013 public void setNetworkTimeout(Executor executor, int milliseconds) 1014 throws SQLException { 1015 checkOpen(); 1016 try { 1017 _conn.setNetworkTimeout(executor, milliseconds); 1018 } 1019 catch (SQLException e) { 1020 handleException(e); 1021 } 1022 } 1023 1024 @Override 1025 public int getNetworkTimeout() throws SQLException { 1026 checkOpen(); 1027 try { 1028 return _conn.getNetworkTimeout(); 1029 } 1030 catch (SQLException e) { 1031 handleException(e); 1032 return 0; 1033 } 1034 } 1035}