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;
18
19 import java.sql.CallableStatement;
20 import java.sql.Connection;
21 import java.sql.SQLException;
22
23 import org.apache.commons.pool2.KeyedObjectPool;
24
25 /**
26 * A {@link DelegatingCallableStatement} that cooperates with {@link PoolingConnection} to implement a pool of
27 * {@link CallableStatement}s.
28 * <p>
29 * The {@link #close} method returns this statement to its containing pool. (See {@link PoolingConnection}.)
30 *
31 * @see PoolingConnection
32 * @since 2.0
33 */
34 public class PoolableCallableStatement extends DelegatingCallableStatement {
35
36 /**
37 * The {@link KeyedObjectPool} from which this CallableStatement was obtained.
38 */
39 private final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pool;
40
41 /**
42 * Key for this statement in the containing {@link KeyedObjectPool}.
43 */
44 private final PStmtKey key;
45
46 /**
47 * Constructs a new instance.
48 *
49 * @param callableStatement
50 * the underlying {@link CallableStatement}
51 * @param key
52 * the key for this statement in the {@link KeyedObjectPool}
53 * @param pool
54 * the {@link KeyedObjectPool} from which this CallableStatement was obtained
55 * @param connection
56 * the {@link DelegatingConnection} that created this CallableStatement
57 */
58 public PoolableCallableStatement(final CallableStatement callableStatement, final PStmtKey key,
59 final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pool,
60 final DelegatingConnection<Connection> connection) {
61 super(connection, callableStatement);
62 this.pool = pool;
63 this.key = key;
64
65 // Remove from trace now because this statement will be
66 // added by the activate method.
67 removeThisTrace(connection);
68 }
69
70 /**
71 * Activates after retrieval from the pool. Adds a trace for this CallableStatement to the Connection that created
72 * it.
73 *
74 * @since 2.4.0 made public, was protected in 2.3.0.
75 */
76 @Override
77 public void activate() throws SQLException {
78 setClosedInternal(false);
79 AbandonedTrace.add(getConnectionInternal(), this);
80 super.activate();
81 }
82
83 /**
84 * Returns the CallableStatement to the pool. If {{@link #isClosed()}, this is a No-op.
85 */
86 @Override
87 public void close() throws SQLException {
88 // calling close twice should have no effect
89 if (!isClosed()) {
90 try {
91 pool.returnObject(key, this);
92 } catch (final SQLException | RuntimeException e) {
93 throw e;
94 } catch (final Exception e) {
95 throw new SQLException("Cannot close CallableStatement (return to pool failed)", e);
96 }
97 }
98 }
99
100 /**
101 * Passivates to prepare for return to the pool. Removes the trace associated with this CallableStatement from the
102 * Connection that created it. Also closes any associated ResultSets.
103 *
104 * @since 2.4.0 made public, was protected in 2.3.0.
105 */
106 @Override
107 public void passivate() throws SQLException {
108 prepareToReturn();
109 }
110
111 }