001/*
002
003  Licensed to the Apache Software Foundation (ASF) under one or more
004  contributor license agreements.  See the NOTICE file distributed with
005  this work for additional information regarding copyright ownership.
006  The ASF licenses this file to You under the Apache License, Version 2.0
007  (the "License"); you may not use this file except in compliance with
008  the License.  You may obtain a copy of the License at
009
010      http://www.apache.org/licenses/LICENSE-2.0
011
012   Unless required by applicable law or agreed to in writing, software
013   distributed under the License is distributed on an "AS IS" BASIS,
014   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015   See the License for the specific language governing permissions and
016   limitations under the License.
017 */
018package org.apache.commons.dbcp2.managed;
019
020import java.sql.Connection;
021import java.sql.SQLException;
022import java.util.Objects;
023
024import org.apache.commons.dbcp2.PoolingDataSource;
025import org.apache.commons.pool2.ObjectPool;
026
027/**
028 * The ManagedDataSource is a PoolingDataSource that creates ManagedConnections.
029 *
030 * @param <C>
031 *            The kind of {@link Connection} to manage.
032 * @since 2.0
033 */
034public class ManagedDataSource<C extends Connection> extends PoolingDataSource<C> {
035    private TransactionRegistry transactionRegistry;
036
037    /**
038     * Creates a ManagedDataSource which obtains connections from the specified pool and manages them using the
039     * specified transaction registry. The TransactionRegistry must be the transaction registry obtained from the
040     * XAConnectionFactory used to create the connection pool. If not, an error will occur when attempting to use the
041     * connection in a global transaction because the XAResource object associated with the connection will be
042     * unavailable.
043     *
044     * @param pool
045     *            the connection pool
046     * @param transactionRegistry
047     *            the transaction registry obtained from the XAConnectionFactory used to create the connection pool
048     *            object factory
049     */
050    public ManagedDataSource(final ObjectPool<C> pool, final TransactionRegistry transactionRegistry) {
051        super(pool);
052        this.transactionRegistry = transactionRegistry;
053    }
054
055    @Override
056    public Connection getConnection() throws SQLException {
057        if (getPool() == null) {
058            throw new IllegalStateException("Pool has not been set");
059        }
060        if (transactionRegistry == null) {
061            throw new IllegalStateException("TransactionRegistry has not been set");
062        }
063
064        return new ManagedConnection<>(getPool(), transactionRegistry, isAccessToUnderlyingConnectionAllowed());
065    }
066
067    /**
068     * Gets the transaction registry.
069     *
070     * @return The transaction registry.
071     * @see #setTransactionRegistry(TransactionRegistry)
072     * @since 2.6.0
073     */
074    public TransactionRegistry getTransactionRegistry() {
075        return transactionRegistry;
076    }
077
078    /**
079     * Sets the transaction registry from the XAConnectionFactory used to create the pool. The transaction registry can
080     * only be set once using either a connector or this setter method.
081     *
082     * @param transactionRegistry
083     *            the transaction registry acquired from the XAConnectionFactory used to create the pool
084     */
085    public void setTransactionRegistry(final TransactionRegistry transactionRegistry) {
086        if (this.transactionRegistry != null) {
087            throw new IllegalStateException("TransactionRegistry already set");
088        }
089        Objects.requireNonNull(transactionRegistry, "transactionRegistry is null");
090
091        this.transactionRegistry = transactionRegistry;
092    }
093}