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 * http://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 */ 017 018package org.apache.commons.dbcp2.managed; 019 020import java.sql.Connection; 021 022import javax.management.ObjectName; 023 024import org.apache.commons.dbcp2.Constants; 025import org.apache.commons.dbcp2.DelegatingPreparedStatement; 026import org.apache.commons.dbcp2.PStmtKey; 027import org.apache.commons.dbcp2.PoolableConnection; 028import org.apache.commons.dbcp2.PoolableConnectionFactory; 029import org.apache.commons.dbcp2.PoolingConnection; 030import org.apache.commons.pool2.KeyedObjectPool; 031import org.apache.commons.pool2.PooledObject; 032import org.apache.commons.pool2.impl.GenericKeyedObjectPool; 033import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; 034import org.apache.commons.pool2.impl.DefaultPooledObject; 035 036/** 037 * A {@link PoolableConnectionFactory} that creates {@link PoolableManagedConnection}s. 038 * 039 * @since 2.0 040 */ 041public class PoolableManagedConnectionFactory extends PoolableConnectionFactory { 042 043 /** Transaction registry associated with connections created by this factory */ 044 private final TransactionRegistry transactionRegistry; 045 046 /** 047 * Creates a PoolableManagedConnectionFactory and attach it to a connection pool. 048 * 049 * @param connFactory 050 * XAConnectionFactory 051 * @param dataSourceJmxName 052 * The data source name. 053 */ 054 public PoolableManagedConnectionFactory(final XAConnectionFactory connFactory, final ObjectName dataSourceJmxName) { 055 super(connFactory, dataSourceJmxName); 056 this.transactionRegistry = connFactory.getTransactionRegistry(); 057 } 058 059 /** 060 * Uses the configured XAConnectionFactory to create a {@link PoolableManagedConnection}. Throws 061 * <code>IllegalStateException</code> if the connection factory returns null. Also initializes the connection using 062 * configured initialization SQL (if provided) and sets up a prepared statement pool associated with the 063 * PoolableManagedConnection if statement pooling is enabled. 064 */ 065 @Override 066 synchronized public PooledObject<PoolableConnection> makeObject() throws Exception { 067 Connection conn = getConnectionFactory().createConnection(); 068 if (conn == null) { 069 throw new IllegalStateException("Connection factory returned null from createConnection"); 070 } 071 initializeConnection(conn); 072 if (getPoolStatements()) { 073 conn = new PoolingConnection(conn); 074 final GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig(); 075 config.setMaxTotalPerKey(-1); 076 config.setBlockWhenExhausted(false); 077 config.setMaxWaitMillis(0); 078 config.setMaxIdlePerKey(1); 079 config.setMaxTotal(getMaxOpenPreparedStatements()); 080 final ObjectName dataSourceJmxName = getDataSourceJmxName(); 081 final long connIndex = getConnectionIndex().getAndIncrement(); 082 if (dataSourceJmxName != null) { 083 final StringBuilder base = new StringBuilder(dataSourceJmxName.toString()); 084 base.append(Constants.JMX_CONNECTION_BASE_EXT); 085 base.append(Long.toString(connIndex)); 086 config.setJmxNameBase(base.toString()); 087 config.setJmxNamePrefix(Constants.JMX_STATEMENT_POOL_PREFIX); 088 } else { 089 config.setJmxEnabled(false); 090 } 091 final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>( 092 (PoolingConnection) conn, config); 093 ((PoolingConnection) conn).setStatementPool(stmtPool); 094 ((PoolingConnection) conn).setCacheState(getCacheState()); 095 } 096 final PoolableManagedConnection pmc = new PoolableManagedConnection(transactionRegistry, conn, getPool(), 097 getDisconnectionSqlCodes(), isFastFailValidation()); 098 pmc.setCacheState(getCacheState()); 099 return new DefaultPooledObject<PoolableConnection>(pmc); 100 } 101}