1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.dbcp2.cpdsadapter; 18 19 import java.sql.CallableStatement; 20 import java.sql.Connection; 21 import java.sql.PreparedStatement; 22 import java.sql.SQLException; 23 24 import org.apache.commons.dbcp2.DelegatingCallableStatement; 25 import org.apache.commons.dbcp2.DelegatingConnection; 26 import org.apache.commons.dbcp2.DelegatingPreparedStatement; 27 28 /** 29 * This class is the {@code Connection} that will be returned from 30 * {@code PooledConnectionImpl.getConnection()}. Most methods are wrappers around the JDBC 1.x 31 * {@code Connection}. A few exceptions include preparedStatement and close. In accordance with the JDBC 32 * specification this Connection cannot be used after closed() is called. Any further usage will result in an 33 * SQLException. 34 * <p> 35 * ConnectionImpl extends DelegatingConnection to enable access to the underlying connection. 36 * </p> 37 * 38 * @since 2.0 39 */ 40 final class ConnectionImpl extends DelegatingConnection<Connection> { 41 42 private final boolean accessToUnderlyingConnectionAllowed; 43 44 /** The object that instantiated this object */ 45 private final PooledConnectionImpl pooledConnection; 46 47 /** 48 * Creates a {@code ConnectionImpl}. 49 * 50 * @param pooledConnection 51 * The PooledConnection that is calling the ctor. 52 * @param connection 53 * The JDBC 1.x Connection to wrap. 54 * @param accessToUnderlyingConnectionAllowed 55 * if true, then access is allowed to the underlying connection 56 */ 57 ConnectionImpl(final PooledConnectionImpl pooledConnection, final Connection connection, 58 final boolean accessToUnderlyingConnectionAllowed) { 59 super(connection); 60 this.pooledConnection = pooledConnection; 61 this.accessToUnderlyingConnectionAllowed = accessToUnderlyingConnectionAllowed; 62 } 63 64 /** 65 * Marks the Connection as closed, and notifies the pool that the pooled connection is available. 66 * <p> 67 * In accordance with the JDBC specification this Connection cannot be used after closed() is called. Any further 68 * usage will result in an SQLException. 69 * </p> 70 * 71 * @throws SQLException 72 * The database connection couldn't be closed. 73 */ 74 @Override 75 public void close() throws SQLException { 76 if (!isClosedInternal()) { 77 try { 78 passivate(); 79 } finally { 80 setClosedInternal(true); 81 pooledConnection.notifyListeners(); 82 } 83 } 84 } 85 86 /** 87 * Gets the delegated connection, if allowed. 88 * 89 * @return the internal connection, or null if access is not allowed. 90 * @see #isAccessToUnderlyingConnectionAllowed() 91 */ 92 @Override 93 public Connection getDelegate() { 94 if (isAccessToUnderlyingConnectionAllowed()) { 95 return getDelegateInternal(); 96 } 97 return null; 98 } 99 100 /** 101 * Gets the innermost connection, if allowed. 102 * 103 * @return the innermost internal connection, or null if access is not allowed. 104 * @see #isAccessToUnderlyingConnectionAllowed() 105 */ 106 @Override 107 public Connection getInnermostDelegate() { 108 if (isAccessToUnderlyingConnectionAllowed()) { 109 return super.getInnermostDelegateInternal(); 110 } 111 return null; 112 } 113 114 /** 115 * Package-private for tests. 116 * 117 * @return the PooledConnectionImpl. 118 */ 119 PooledConnectionImpl getPooledConnectionImpl() { 120 return pooledConnection; 121 } 122 123 /** 124 * If false, getDelegate() and getInnermostDelegate() will return null. 125 * 126 * @return true if access is allowed to the underlying connection 127 * @see ConnectionImpl 128 */ 129 public boolean isAccessToUnderlyingConnectionAllowed() { 130 return accessToUnderlyingConnectionAllowed; 131 } 132 133 /** 134 * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may 135 * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. 136 * 137 * @param sql 138 * an SQL statement that may contain one or more '?' parameter placeholders. Typically, this statement is 139 * specified using JDBC call escape syntax. 140 * @return a default {@code CallableStatement} object containing the pre-compiled SQL statement. 141 * @throws SQLException 142 * Thrown if a database access error occurs or this method is called on a closed connection. 143 * @since 2.4.0 144 */ 145 @Override 146 public CallableStatement prepareCall(final String sql) throws SQLException { 147 checkOpen(); 148 try { 149 return new DelegatingCallableStatement(this, pooledConnection.prepareCall(sql)); 150 } catch (final SQLException e) { 151 handleException(e); // Does not return 152 return null; 153 } 154 } 155 156 /** 157 * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may 158 * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. 159 * 160 * @param sql 161 * a {@code String} object that is the SQL statement to be sent to the database; may contain on or 162 * more '?' parameters. 163 * @param resultSetType 164 * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, 165 * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. 166 * @param resultSetConcurrency 167 * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or 168 * {@code ResultSet.CONCUR_UPDATABLE}. 169 * @return a {@code CallableStatement} object containing the pre-compiled SQL statement that will produce 170 * {@code ResultSet} objects with the given type and concurrency. 171 * @throws SQLException 172 * Thrown if a database access error occurs, this method is called on a closed connection or the given 173 * parameters are not {@code ResultSet} constants indicating type and concurrency. 174 * @since 2.4.0 175 */ 176 @Override 177 public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) 178 throws SQLException { 179 checkOpen(); 180 try { 181 return new DelegatingCallableStatement(this, 182 pooledConnection.prepareCall(sql, resultSetType, resultSetConcurrency)); 183 } catch (final SQLException e) { 184 handleException(e); // Does not return 185 return null; 186 } 187 } 188 189 /** 190 * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may 191 * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. 192 * 193 * @param sql 194 * a {@code String} object that is the SQL statement to be sent to the database; may contain on or 195 * more '?' parameters. 196 * @param resultSetType 197 * one of the following {@code ResultSet} constants: {@code ResultSet.TYPE_FORWARD_ONLY}, 198 * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. 199 * @param resultSetConcurrency 200 * one of the following {@code ResultSet} constants: {@code ResultSet.CONCUR_READ_ONLY} or 201 * {@code ResultSet.CONCUR_UPDATABLE}. 202 * @param resultSetHoldability 203 * one of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} 204 * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. 205 * @return a new {@code CallableStatement} object, containing the pre-compiled SQL statement, that will 206 * generate {@code ResultSet} objects with the given type, concurrency, and holdability. 207 * @throws SQLException 208 * Thrown if a database access error occurs, this method is called on a closed connection or the given 209 * parameters are not {@code ResultSet} constants indicating type, concurrency, and holdability. 210 * @since 2.4.0 211 */ 212 @Override 213 public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, 214 final int resultSetHoldability) throws SQLException { 215 checkOpen(); 216 try { 217 return new DelegatingCallableStatement(this, 218 pooledConnection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); 219 } catch (final SQLException e) { 220 handleException(e); // Does not return 221 return null; 222 } 223 } 224 225 /** 226 * If pooling of {@code PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may 227 * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. 228 * 229 * @param sql 230 * SQL statement to be prepared 231 * @return the prepared statement 232 * @throws SQLException 233 * if this connection is closed or an error occurs in the wrapped connection. 234 */ 235 @Override 236 public PreparedStatement prepareStatement(final String sql) throws SQLException { 237 checkOpen(); 238 try { 239 return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql)); 240 } catch (final SQLException e) { 241 handleException(e); // Does not return 242 return null; 243 } 244 } 245 246 @Override 247 public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { 248 checkOpen(); 249 try { 250 return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, autoGeneratedKeys)); 251 } catch (final SQLException e) { 252 handleException(e); 253 return null; 254 } 255 } 256 257 // 258 // Methods for accessing the delegate connection 259 // 260 261 /** 262 * If pooling of {@code PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may 263 * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. 264 * 265 * @throws SQLException 266 * if this connection is closed or an error occurs in the wrapped connection. 267 */ 268 @Override 269 public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) 270 throws SQLException { 271 checkOpen(); 272 try { 273 return new DelegatingPreparedStatement(this, 274 pooledConnection.prepareStatement(sql, resultSetType, resultSetConcurrency)); 275 } catch (final SQLException e) { 276 handleException(e); 277 return null; 278 } 279 } 280 281 @Override 282 public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, 283 final int resultSetHoldability) throws SQLException { 284 checkOpen(); 285 try { 286 return new DelegatingPreparedStatement(this, 287 pooledConnection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); 288 } catch (final SQLException e) { 289 handleException(e); 290 return null; 291 } 292 } 293 294 @Override 295 public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { 296 checkOpen(); 297 try { 298 return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, columnIndexes)); 299 } catch (final SQLException e) { 300 handleException(e); 301 return null; 302 } 303 } 304 305 @Override 306 public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { 307 checkOpen(); 308 try { 309 return new DelegatingPreparedStatement(this, pooledConnection.prepareStatement(sql, columnNames)); 310 } catch (final SQLException e) { 311 handleException(e); 312 return null; 313 } 314 } 315 316 }