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