    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 *      https://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 */
    017package org.apache.commons.dbcp2;
    018
    019import java.sql.CallableStatement;
    020import java.sql.Connection;
    021import java.sql.SQLException;
    022
    023import org.apache.commons.pool2.KeyedObjectPool;
    024
    025/**
    026 * A {@link DelegatingCallableStatement} that cooperates with {@link PoolingConnection} to implement a pool of
    027 * {@link CallableStatement}s.
    028 * <p>
    029 * The {@link #close} method returns this statement to its containing pool. (See {@link PoolingConnection}.)
    030 *
    031 * @see PoolingConnection
    032 * @since 2.0
    033 */
    034public class PoolableCallableStatement extends DelegatingCallableStatement {
    035
    036    /**
    037     * The {@link KeyedObjectPool} from which this CallableStatement was obtained.
    038     */
    039    private final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pool;
    040
    041    /**
    042     * Key for this statement in the containing {@link KeyedObjectPool}.
    043     */
    044    private final PStmtKey key;
    045
    046    /**
    047     * Constructs a new instance.
    048     *
    049     * @param callableStatement
    050     *            the underlying {@link CallableStatement}
    051     * @param key
    052     *            the key for this statement in the {@link KeyedObjectPool}
    053     * @param pool
    054     *            the {@link KeyedObjectPool} from which this CallableStatement was obtained
    055     * @param connection
    056     *            the {@link DelegatingConnection} that created this CallableStatement
    057     */
    058    public PoolableCallableStatement(final CallableStatement callableStatement, final PStmtKey key,
    059            final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pool,
    060            final DelegatingConnection<Connection> connection) {
    061        super(connection, callableStatement);
    062        this.pool = pool;
    063        this.key = key;
    064
    065        // Remove from trace now because this statement will be
    066        // added by the activate method.
    067        removeThisTrace(connection);
    068    }
    069
    070    /**
    071     * Activates after retrieval from the pool. Adds a trace for this CallableStatement to the Connection that created
    072     * it.
    073     *
    074     * @since 2.4.0 made public, was protected in 2.3.0.
    075     */
    076    @Override
    077    public void activate() throws SQLException {
    078        setClosedInternal(false);
    079        add(getConnectionInternal(), this);
    080        super.activate();
    081    }
    082
    083    /**
    084     * Returns the CallableStatement to the pool. If {{@link #isClosed()}, this is a No-op.
    085     */
    086    @Override
    087    public void close() throws SQLException {
    088        // calling close twice should have no effect
    089        if (!isClosed()) {
    090            try {
    091                pool.returnObject(key, this);
    092            } catch (final SQLException | RuntimeException e) {
    093                throw e;
    094            } catch (final Exception e) {
    095                throw new SQLException("Cannot close CallableStatement (return to pool failed)", e);
    096            }
    097        }
    098    }
    099
    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}