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.CallableStatement; 021import java.sql.Connection; 022import java.sql.DatabaseMetaData; 023import java.sql.PreparedStatement; 024import java.sql.SQLException; 025import java.sql.SQLWarning; 026import java.sql.Statement; 027import java.util.Iterator; 028import java.util.List; 029import java.util.Map; 030import java.sql.ResultSet; 031import java.sql.Array; 032import java.sql.Blob; 033import java.sql.ClientInfoStatus; 034import java.sql.Clob; 035import java.sql.NClob; 036import java.sql.SQLClientInfoException; 037import java.sql.SQLXML; 038import java.sql.Savepoint; 039import java.sql.Struct; 040import java.util.Collections; 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 $Revision: 1572242 $ $Date: 2014-02-26 20:34:39 +0000 (Wed, 26 Feb 2014) $ 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 innnermost 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 * <tt>DelegatingConnection</tt>, 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 <tt>DelegatingConnection</tt>, 172 * or <tt>null</tt> when no non-<tt>DelegatingConnection</tt> 173 * delegate can be found by traversing this chain. 174 * <p> 175 * This method is useful when you may have nested 176 * <tt>DelegatingConnection</tt>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 try { 235 _conn.close(); 236 } finally { 237 _closed = true; 238 } 239 } 240 } 241 242 protected void handleException(SQLException e) throws SQLException { 243 throw e; 244 } 245 246 private void initializeStatement(DelegatingStatement ds) throws SQLException { 247 if (defaultQueryTimeout != null && 248 defaultQueryTimeout.intValue() != ds.getQueryTimeout()) { 249 ds.setQueryTimeout(defaultQueryTimeout.intValue()); 250 } 251 } 252 253 @Override 254 public Statement createStatement() throws SQLException { 255 checkOpen(); 256 try { 257 DelegatingStatement ds = 258 new DelegatingStatement(this, _conn.createStatement()); 259 initializeStatement(ds); 260 return ds; 261 } 262 catch (SQLException e) { 263 handleException(e); 264 return null; 265 } 266 } 267 268 @Override 269 public Statement createStatement(int resultSetType, 270 int resultSetConcurrency) throws SQLException { 271 checkOpen(); 272 try { 273 DelegatingStatement ds = new DelegatingStatement( 274 this, _conn.createStatement(resultSetType,resultSetConcurrency)); 275 initializeStatement(ds); 276 return ds; 277 } 278 catch (SQLException e) { 279 handleException(e); 280 return null; 281 } 282 } 283 284 @Override 285 public PreparedStatement prepareStatement(String sql) throws SQLException { 286 checkOpen(); 287 try { 288 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 289 this, _conn.prepareStatement(sql)); 290 initializeStatement(dps); 291 return dps; 292 } 293 catch (SQLException e) { 294 handleException(e); 295 return null; 296 } 297 } 298 299 @Override 300 public PreparedStatement prepareStatement(String sql, 301 int resultSetType, 302 int resultSetConcurrency) throws SQLException { 303 checkOpen(); 304 try { 305 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 306 this, _conn.prepareStatement(sql,resultSetType,resultSetConcurrency)); 307 initializeStatement(dps); 308 return dps; 309 } 310 catch (SQLException e) { 311 handleException(e); 312 return null; 313 } 314 } 315 316 @Override 317 public CallableStatement prepareCall(String sql) throws SQLException { 318 checkOpen(); 319 try { 320 DelegatingCallableStatement dcs = 321 new DelegatingCallableStatement(this, _conn.prepareCall(sql)); 322 initializeStatement(dcs); 323 return dcs; 324 } 325 catch (SQLException e) { 326 handleException(e); 327 return null; 328 } 329 } 330 331 @Override 332 public CallableStatement prepareCall(String sql, 333 int resultSetType, 334 int resultSetConcurrency) throws SQLException { 335 checkOpen(); 336 try { 337 DelegatingCallableStatement dcs = new DelegatingCallableStatement( 338 this, _conn.prepareCall(sql, resultSetType,resultSetConcurrency)); 339 initializeStatement(dcs); 340 return dcs; 341 } 342 catch (SQLException e) { 343 handleException(e); 344 return null; 345 } 346 } 347 348 349 @Override 350 public void clearWarnings() throws SQLException { 351 checkOpen(); 352 try { 353 _conn.clearWarnings(); 354 } catch (SQLException e) { 355 handleException(e); 356 } 357 } 358 359 360 @Override 361 public void commit() throws SQLException { 362 checkOpen(); 363 try { 364 _conn.commit(); 365 } catch (SQLException e) { 366 handleException(e); 367 } 368 } 369 370 371 /** 372 * Returns the state caching flag. 373 * 374 * @return the state caching flag 375 */ 376 public boolean getCacheState() { 377 return _cacheState; 378 } 379 380 @Override 381 public boolean getAutoCommit() throws SQLException { 382 checkOpen(); 383 if (_cacheState && _autoCommitCached != null) { 384 return _autoCommitCached.booleanValue(); 385 } 386 try { 387 _autoCommitCached = Boolean.valueOf(_conn.getAutoCommit()); 388 return _autoCommitCached.booleanValue(); 389 } catch (SQLException e) { 390 handleException(e); 391 return false; 392 } 393 } 394 395 396 @Override 397 public String getCatalog() throws SQLException { 398 checkOpen(); 399 try { 400 return _conn.getCatalog(); 401 } catch (SQLException e) { 402 handleException(e); 403 return null; 404 } 405 } 406 407 408 @Override 409 public DatabaseMetaData getMetaData() throws SQLException { 410 checkOpen(); 411 try { 412 return new DelegatingDatabaseMetaData(this, _conn.getMetaData()); 413 } catch (SQLException e) { 414 handleException(e); 415 return null; 416 } 417 } 418 419 420 @Override 421 public int getTransactionIsolation() throws SQLException { 422 checkOpen(); 423 try { 424 return _conn.getTransactionIsolation(); 425 } catch (SQLException e) { 426 handleException(e); 427 return -1; 428 } 429 } 430 431 432 @Override 433 public Map<String,Class<?>> getTypeMap() throws SQLException { 434 checkOpen(); 435 try { 436 return _conn.getTypeMap(); 437 } catch (SQLException e) { 438 handleException(e); 439 return null; 440 } 441 } 442 443 444 @Override 445 public SQLWarning getWarnings() throws SQLException { 446 checkOpen(); 447 try { 448 return _conn.getWarnings(); 449 } catch (SQLException e) { 450 handleException(e); 451 return null; 452 } 453 } 454 455 456 @Override 457 public boolean isReadOnly() throws SQLException { 458 checkOpen(); 459 if (_cacheState && _readOnlyCached != null) { 460 return _readOnlyCached.booleanValue(); 461 } 462 try { 463 _readOnlyCached = Boolean.valueOf(_conn.isReadOnly()); 464 return _readOnlyCached.booleanValue(); 465 } catch (SQLException e) { 466 handleException(e); 467 return false; 468 } 469 } 470 471 472 @Override 473 public String nativeSQL(String sql) throws SQLException { 474 checkOpen(); 475 try { 476 return _conn.nativeSQL(sql); 477 } catch (SQLException e) { 478 handleException(e); 479 return null; 480 } 481 } 482 483 484 @Override 485 public void rollback() throws SQLException { 486 checkOpen(); 487 try { 488 _conn.rollback(); 489 } catch (SQLException e) { 490 handleException(e); 491 } 492 } 493 494 495 /** 496 * Obtain the default query timeout that will be used for {@link Statement}s 497 * created from this connection. <code>null</code> means that the driver 498 * default will be used. 499 */ 500 public Integer getDefaultQueryTimeout() { 501 return defaultQueryTimeout; 502 } 503 504 505 /** 506 * Set the default query timeout that will be used for {@link Statement}s 507 * created from this connection. <code>null</code> means that the driver 508 * default will be used. 509 */ 510 public void setDefaultQueryTimeout(Integer defaultQueryTimeout) { 511 this.defaultQueryTimeout = defaultQueryTimeout; 512 } 513 514 515 /** 516 * Sets the state caching flag. 517 * 518 * @param cacheState The new value for the state caching flag 519 */ 520 public void setCacheState(boolean cacheState) { 521 this._cacheState = cacheState; 522 } 523 524 /** 525 * Can be used to clear cached state when it is known that the underlying 526 * connection may have been accessed directly. 527 */ 528 public void clearCachedState() { 529 _autoCommitCached = null; 530 _readOnlyCached = null; 531 if (_conn instanceof DelegatingConnection) { 532 ((DelegatingConnection<?>)_conn).clearCachedState(); 533 } 534 } 535 536 @Override 537 public void setAutoCommit(boolean autoCommit) throws SQLException { 538 checkOpen(); 539 try { 540 _conn.setAutoCommit(autoCommit); 541 if (_cacheState) { 542 _autoCommitCached = Boolean.valueOf(autoCommit); 543 } 544 } catch (SQLException e) { 545 _autoCommitCached = null; 546 handleException(e); 547 } 548 } 549 550 @Override 551 public void setCatalog(String catalog) throws SQLException 552 { checkOpen(); try { _conn.setCatalog(catalog); } catch (SQLException e) { handleException(e); } } 553 554 @Override 555 public void setReadOnly(boolean readOnly) throws SQLException { 556 checkOpen(); 557 try { 558 _conn.setReadOnly(readOnly); 559 if (_cacheState) { 560 _readOnlyCached = Boolean.valueOf(readOnly); 561 } 562 } catch (SQLException e) { 563 _readOnlyCached = null; 564 handleException(e); 565 } 566 } 567 568 569 @Override 570 public void setTransactionIsolation(int level) throws SQLException { 571 checkOpen(); 572 try { 573 _conn.setTransactionIsolation(level); 574 } catch (SQLException e) { 575 handleException(e); 576 } 577 } 578 579 580 @Override 581 public void setTypeMap(Map<String,Class<?>> map) throws SQLException { 582 checkOpen(); 583 try { 584 _conn.setTypeMap(map); 585 } catch (SQLException e) { 586 handleException(e); 587 } 588 } 589 590 591 @Override 592 public boolean isClosed() throws SQLException { 593 return _closed || _conn.isClosed(); 594 } 595 596 protected void checkOpen() throws SQLException { 597 if(_closed) { 598 if (null != _conn) { 599 String label = ""; 600 try { 601 label = _conn.toString(); 602 } catch (Exception ex) { 603 // ignore, leave label empty 604 } 605 throw new SQLException 606 ("Connection " + label + " is closed."); 607 } 608 throw new SQLException 609 ("Connection is null."); 610 } 611 } 612 613 protected void activate() { 614 _closed = false; 615 setLastUsed(); 616 if(_conn instanceof DelegatingConnection) { 617 ((DelegatingConnection<?>)_conn).activate(); 618 } 619 } 620 621 protected void passivate() throws SQLException { 622 // The JDBC spec requires that a Connection close any open 623 // Statement's when it is closed. 624 // DBCP-288. Not all the traced objects will be statements 625 List<AbandonedTrace> traces = getTrace(); 626 if(traces != null) { 627 Iterator<AbandonedTrace> traceIter = traces.iterator(); 628 while (traceIter.hasNext()) { 629 Object trace = traceIter.next(); 630 if (trace instanceof Statement) { 631 ((Statement) trace).close(); 632 } else if (trace instanceof ResultSet) { 633 // DBCP-265: Need to close the result sets that are 634 // generated via DatabaseMetaData 635 ((ResultSet) trace).close(); 636 } 637 } 638 clearTrace(); 639 } 640 setLastUsed(0); 641 } 642 643 644 @Override 645 public int getHoldability() throws SQLException { 646 checkOpen(); 647 try { 648 return _conn.getHoldability(); 649 } catch (SQLException e) { 650 handleException(e); 651 return 0; 652 } 653 } 654 655 656 @Override 657 public void setHoldability(int holdability) throws SQLException { 658 checkOpen(); 659 try { 660 _conn.setHoldability(holdability); 661 } catch (SQLException e) { 662 handleException(e); 663 } 664 } 665 666 667 @Override 668 public Savepoint setSavepoint() throws SQLException { 669 checkOpen(); 670 try { 671 return _conn.setSavepoint(); 672 } catch (SQLException e) { 673 handleException(e); 674 return null; 675 } 676 } 677 678 679 @Override 680 public Savepoint setSavepoint(String name) throws SQLException { 681 checkOpen(); 682 try { 683 return _conn.setSavepoint(name); 684 } catch (SQLException e) { 685 handleException(e); 686 return null; 687 } 688 } 689 690 691 @Override 692 public void rollback(Savepoint savepoint) throws SQLException { 693 checkOpen(); 694 try { 695 _conn.rollback(savepoint); 696 } catch (SQLException e) { 697 handleException(e); 698 } 699 } 700 701 702 @Override 703 public void releaseSavepoint(Savepoint savepoint) 704 throws SQLException { 705 checkOpen(); 706 try { 707 _conn.releaseSavepoint(savepoint); 708 } catch (SQLException e) { 709 handleException(e); 710 } 711 } 712 713 714 @Override 715 public Statement createStatement(int resultSetType, 716 int resultSetConcurrency, 717 int resultSetHoldability) throws SQLException { 718 checkOpen(); 719 try { 720 DelegatingStatement ds = new DelegatingStatement(this, 721 _conn.createStatement(resultSetType, resultSetConcurrency, 722 resultSetHoldability)); 723 initializeStatement(ds); 724 return ds; 725 } 726 catch (SQLException e) { 727 handleException(e); 728 return null; 729 } 730 } 731 732 @Override 733 public PreparedStatement prepareStatement(String sql, int resultSetType, 734 int resultSetConcurrency, 735 int resultSetHoldability) throws SQLException { 736 checkOpen(); 737 try { 738 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 739 this, _conn.prepareStatement(sql, resultSetType, 740 resultSetConcurrency, resultSetHoldability)); 741 initializeStatement(dps); 742 return dps; 743 } 744 catch (SQLException e) { 745 handleException(e); 746 return null; 747 } 748 } 749 750 @Override 751 public CallableStatement prepareCall(String sql, int resultSetType, 752 int resultSetConcurrency, 753 int resultSetHoldability) throws SQLException { 754 checkOpen(); 755 try { 756 DelegatingCallableStatement dcs = new DelegatingCallableStatement( 757 this, _conn.prepareCall(sql, resultSetType, 758 resultSetConcurrency, resultSetHoldability)); 759 initializeStatement(dcs); 760 return dcs; 761 } 762 catch (SQLException e) { 763 handleException(e); 764 return null; 765 } 766 } 767 768 @Override 769 public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { 770 checkOpen(); 771 try { 772 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 773 this, _conn.prepareStatement(sql, autoGeneratedKeys)); 774 initializeStatement(dps); 775 return dps; 776 } 777 catch (SQLException e) { 778 handleException(e); 779 return null; 780 } 781 } 782 783 @Override 784 public PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException { 785 checkOpen(); 786 try { 787 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 788 this, _conn.prepareStatement(sql, columnIndexes)); 789 initializeStatement(dps); 790 return dps; 791 } 792 catch (SQLException e) { 793 handleException(e); 794 return null; 795 } 796 } 797 798 @Override 799 public PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException { 800 checkOpen(); 801 try { 802 DelegatingPreparedStatement dps = new DelegatingPreparedStatement( 803 this, _conn.prepareStatement(sql, columnNames)); 804 initializeStatement(dps); 805 return dps; 806 } 807 catch (SQLException e) { 808 handleException(e); 809 return null; 810 } 811 } 812 813 814 @Override 815 public boolean isWrapperFor(Class<?> iface) throws SQLException { 816 if (iface.isAssignableFrom(getClass())) { 817 return true; 818 } else if (iface.isAssignableFrom(_conn.getClass())) { 819 return true; 820 } else { 821 return _conn.isWrapperFor(iface); 822 } 823 } 824 825 @Override 826 public <T> T unwrap(Class<T> iface) throws SQLException { 827 if (iface.isAssignableFrom(getClass())) { 828 return iface.cast(this); 829 } else if (iface.isAssignableFrom(_conn.getClass())) { 830 return iface.cast(_conn); 831 } else { 832 return _conn.unwrap(iface); 833 } 834 } 835 836 @Override 837 public Array createArrayOf(String typeName, Object[] elements) throws SQLException { 838 checkOpen(); 839 try { 840 return _conn.createArrayOf(typeName, elements); 841 } 842 catch (SQLException e) { 843 handleException(e); 844 return null; 845 } 846 } 847 848 @Override 849 public Blob createBlob() throws SQLException { 850 checkOpen(); 851 try { 852 return _conn.createBlob(); 853 } 854 catch (SQLException e) { 855 handleException(e); 856 return null; 857 } 858 } 859 860 @Override 861 public Clob createClob() throws SQLException { 862 checkOpen(); 863 try { 864 return _conn.createClob(); 865 } 866 catch (SQLException e) { 867 handleException(e); 868 return null; 869 } 870 } 871 872 @Override 873 public NClob createNClob() throws SQLException { 874 checkOpen(); 875 try { 876 return _conn.createNClob(); 877 } 878 catch (SQLException e) { 879 handleException(e); 880 return null; 881 } 882 } 883 884 @Override 885 public SQLXML createSQLXML() throws SQLException { 886 checkOpen(); 887 try { 888 return _conn.createSQLXML(); 889 } 890 catch (SQLException e) { 891 handleException(e); 892 return null; 893 } 894 } 895 896 @Override 897 public Struct createStruct(String typeName, Object[] attributes) throws SQLException { 898 checkOpen(); 899 try { 900 return _conn.createStruct(typeName, attributes); 901 } 902 catch (SQLException e) { 903 handleException(e); 904 return null; 905 } 906 } 907 908 @Override 909 public boolean isValid(int timeout) throws SQLException { 910 if (isClosed()) { 911 return false; 912 } 913 try { 914 return _conn.isValid(timeout); 915 } 916 catch (SQLException e) { 917 handleException(e); 918 return false; 919 } 920 } 921 922 @Override 923 public void setClientInfo(String name, String value) throws SQLClientInfoException { 924 try { 925 checkOpen(); 926 _conn.setClientInfo(name, value); 927 } 928 catch (SQLClientInfoException e) { 929 throw e; 930 } 931 catch (SQLException e) { 932 throw new SQLClientInfoException("Connection is closed.", EMPTY_FAILED_PROPERTIES, e); 933 } 934 } 935 936 @Override 937 public void setClientInfo(Properties properties) throws SQLClientInfoException { 938 try { 939 checkOpen(); 940 _conn.setClientInfo(properties); 941 } 942 catch (SQLClientInfoException e) { 943 throw e; 944 } 945 catch (SQLException e) { 946 throw new SQLClientInfoException("Connection is closed.", EMPTY_FAILED_PROPERTIES, e); 947 } 948 } 949 950 @Override 951 public Properties getClientInfo() throws SQLException { 952 checkOpen(); 953 try { 954 return _conn.getClientInfo(); 955 } 956 catch (SQLException e) { 957 handleException(e); 958 return null; 959 } 960 } 961 962 @Override 963 public String getClientInfo(String name) throws SQLException { 964 checkOpen(); 965 try { 966 return _conn.getClientInfo(name); 967 } 968 catch (SQLException e) { 969 handleException(e); 970 return null; 971 } 972 } 973 974 @Override 975 public void setSchema(String schema) throws SQLException { 976 checkOpen(); 977 try { 978 _conn.setSchema(schema); 979 } 980 catch (SQLException e) { 981 handleException(e); 982 } 983 } 984 985 @Override 986 public String getSchema() throws SQLException { 987 checkOpen(); 988 try { 989 return _conn.getSchema(); 990 } 991 catch (SQLException e) { 992 handleException(e); 993 return null; 994 } 995 } 996 997 @Override 998 public void abort(Executor executor) throws SQLException { 999 checkOpen(); 1000 try { 1001 _conn.abort(executor); 1002 } 1003 catch (SQLException e) { 1004 handleException(e); 1005 } 1006 } 1007 1008 @Override 1009 public void setNetworkTimeout(Executor executor, int milliseconds) 1010 throws SQLException { 1011 checkOpen(); 1012 try { 1013 _conn.setNetworkTimeout(executor, milliseconds); 1014 } 1015 catch (SQLException e) { 1016 handleException(e); 1017 } 1018 } 1019 1020 @Override 1021 public int getNetworkTimeout() throws SQLException { 1022 checkOpen(); 1023 try { 1024 return _conn.getNetworkTimeout(); 1025 } 1026 catch (SQLException e) { 1027 handleException(e); 1028 return 0; 1029 } 1030 } 1031}