1 package org.apache.ojb.broker.accesslayer; 2 3 17 18 import org.apache.commons.dbcp.AbandonedConfig; 19 import org.apache.commons.dbcp.AbandonedObjectPool; 20 import org.apache.commons.dbcp.DriverManagerConnectionFactory; 21 import org.apache.commons.dbcp.PoolableConnectionFactory; 22 import org.apache.commons.dbcp.PoolingDataSource; 23 import org.apache.commons.pool.KeyedObjectPoolFactory; 24 import org.apache.commons.pool.ObjectPool; 25 import org.apache.commons.pool.impl.GenericKeyedObjectPool; 26 import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory; 27 import org.apache.commons.pool.impl.GenericObjectPool; 28 import org.apache.ojb.broker.PBKey; 29 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor; 30 import org.apache.ojb.broker.util.ClassHelper; 31 import org.apache.ojb.broker.util.logging.Logger; 32 import org.apache.ojb.broker.util.logging.LoggerFactory; 33 import org.apache.ojb.broker.util.logging.LoggerWrapperPrintWriter; 34 35 import javax.sql.DataSource ; 36 import java.sql.Connection ; 37 import java.sql.SQLException ; 38 import java.util.Collection ; 39 import java.util.Collections ; 40 import java.util.HashMap ; 41 import java.util.Iterator ; 42 import java.util.Map ; 43 import java.util.Properties ; 44 45 56 public class ConnectionFactoryDBCPImpl extends ConnectionFactoryAbstractImpl 57 { 58 59 public static final String PARAM_NAME_UNWRAP_ALLOWED = "accessToUnderlyingConnectionAllowed"; 60 public static final String PARAM_NAME_POOL_STATEMENTS = "poolPreparedStatements"; 61 public static final String PARAM_NAME_STATEMENT_POOL_MAX_TOTAL = "maxOpenPreparedStatements"; 62 63 private Logger log = LoggerFactory.getLogger(ConnectionFactoryDBCPImpl.class); 64 65 66 private Map poolMap = Collections.synchronizedMap(new HashMap ()); 67 68 private Map dsMap = Collections.synchronizedMap(new HashMap ()); 69 70 private final Object poolSynch = new Object (); 71 72 public Connection checkOutJdbcConnection(JdbcConnectionDescriptor jcd) throws LookupException 73 { 74 final DataSource ds = getDataSource(jcd); 75 76 79 Connection conn; 80 try 81 { 82 conn = ds.getConnection(); 83 } 84 catch (SQLException e) 85 { 86 throw new LookupException("Could not get connection from DBCP DataSource", e); 87 } 88 return conn; 89 } 90 91 public void releaseJdbcConnection(JdbcConnectionDescriptor jcd, Connection con) 92 throws LookupException 93 { 94 try 95 { 96 con.close(); 98 } 99 catch (SQLException e) 100 { 101 log.warn("Connection close failed", e); 102 } 103 } 104 105 108 public void releaseAllResources() 109 { 110 super.releaseAllResources(); 111 synchronized (poolSynch) 112 { 113 if (!poolMap.isEmpty()) 114 { 115 Collection pools = poolMap.values(); 116 Iterator iterator = pools.iterator(); 117 ObjectPool op = null; 118 while (iterator.hasNext()) 119 { 120 try 121 { 122 op = (ObjectPool) iterator.next(); 123 op.close(); 124 } 125 catch (Exception e) 126 { 127 log.error("Exception occured while closing ObjectPool " + op, e); 128 } 129 } 130 poolMap.clear(); 131 } 132 dsMap.clear(); 133 } 134 } 135 136 144 protected DataSource getDataSource(JdbcConnectionDescriptor jcd) 145 throws LookupException 146 { 147 final PBKey key = jcd.getPBKey(); 148 DataSource ds = (DataSource) dsMap.get(key); 149 if (ds == null) 150 { 151 try 153 { 154 synchronized (poolSynch) 155 { 156 ObjectPool pool = setupPool(jcd); 158 poolMap.put(key, pool); 159 ds = wrapAsDataSource(jcd, pool); 161 dsMap.put(key, ds); 162 } 163 } 164 catch (Exception e) 165 { 166 log.error("Could not setup DBCP DataSource for " + jcd, e); 167 throw new LookupException(e); 168 } 169 } 170 return ds; 171 } 172 173 179 protected ObjectPool setupPool(JdbcConnectionDescriptor jcd) 180 { 181 log.info("Create new ObjectPool for DBCP connections:" + jcd); 182 183 try 184 { 185 ClassHelper.newInstance(jcd.getDriver()); 186 } 187 catch (InstantiationException e) 188 { 189 log.fatal("Unable to instantiate the driver class: " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!" , e); 190 } 191 catch (IllegalAccessException e) 192 { 193 log.fatal("IllegalAccessException while instantiating the driver class: " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!" , e); 194 } 195 catch (ClassNotFoundException e) 196 { 197 log.fatal("Could not find the driver class : " + jcd.getDriver() + " in ConnectionFactoryDBCImpl!" , e); 198 } 199 200 GenericObjectPool.Config conf = jcd.getConnectionPoolDescriptor().getObjectPoolConfig(); 202 203 AbandonedConfig ac = jcd.getConnectionPoolDescriptor().getAbandonedConfig(); 205 206 final ObjectPool connectionPool = createConnectionPool(conf, ac); 208 209 final org.apache.commons.dbcp.ConnectionFactory connectionFactory; 212 connectionFactory = createConnectionFactory(jcd); 213 214 KeyedObjectPoolFactory statementPoolFactory = createStatementPoolFactory(jcd); 216 217 final String validationQuery; 219 final boolean defaultAutoCommit; 220 final boolean defaultReadOnly = false; 221 validationQuery = jcd.getConnectionPoolDescriptor().getValidationQuery(); 222 defaultAutoCommit = (jcd.getUseAutoCommit() != JdbcConnectionDescriptor.AUTO_COMMIT_SET_FALSE); 223 224 final PoolableConnectionFactory poolableConnectionFactory; 230 poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, 231 connectionPool, 232 statementPoolFactory, 233 validationQuery, 234 defaultReadOnly, 235 defaultAutoCommit, 236 ac); 237 return poolableConnectionFactory.getPool(); 238 } 239 240 protected ObjectPool createConnectionPool(GenericObjectPool.Config config, 241 AbandonedConfig ac) 242 { 243 final GenericObjectPool connectionPool; 244 final boolean doRemoveAbandoned = ac != null && ac.getRemoveAbandoned(); 245 246 if (doRemoveAbandoned) { 247 connectionPool = new AbandonedObjectPool(null, ac); 248 } else { 249 connectionPool = new GenericObjectPool(); 250 } 251 connectionPool.setMaxActive(config.maxActive); 252 connectionPool.setMaxIdle(config.maxIdle); 253 connectionPool.setMinIdle(config.minIdle); 254 connectionPool.setMaxWait(config.maxWait); 255 connectionPool.setTestOnBorrow(config.testOnBorrow); 256 connectionPool.setTestOnReturn(config.testOnReturn); 257 connectionPool.setTimeBetweenEvictionRunsMillis(config.timeBetweenEvictionRunsMillis); 258 connectionPool.setNumTestsPerEvictionRun(config.numTestsPerEvictionRun); 259 connectionPool.setMinEvictableIdleTimeMillis(config.minEvictableIdleTimeMillis); 260 connectionPool.setTestWhileIdle(config.testWhileIdle); 261 return connectionPool; 262 } 263 264 protected KeyedObjectPoolFactory createStatementPoolFactory(JdbcConnectionDescriptor jcd) 265 { 266 final String platform = jcd.getDbms(); 267 if (platform.startsWith("Oracle9i")) 268 { 269 return null; 271 } 272 273 GenericKeyedObjectPoolFactory statementPoolFactory = null; 275 final Properties properties = jcd.getConnectionPoolDescriptor().getDbcpProperties(); 276 final String poolStmtParam = properties.getProperty(PARAM_NAME_POOL_STATEMENTS); 277 if (poolStmtParam != null && Boolean.valueOf(poolStmtParam).booleanValue()) 278 { 279 int maxOpenPreparedStatements = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL; 280 final String maxOpenPrepStmtString = properties.getProperty(PARAM_NAME_STATEMENT_POOL_MAX_TOTAL); 281 if (maxOpenPrepStmtString != null) 282 { 283 maxOpenPreparedStatements = Integer.parseInt(maxOpenPrepStmtString); 284 } 285 statementPoolFactory = new GenericKeyedObjectPoolFactory(null, 287 -1, GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL, 289 0, 1, maxOpenPreparedStatements); 292 } 293 return statementPoolFactory; 294 } 295 296 306 protected DataSource wrapAsDataSource(JdbcConnectionDescriptor jcd, 307 ObjectPool connectionPool) 308 { 309 final boolean allowConnectionUnwrap; 310 if (jcd == null) 311 { 312 allowConnectionUnwrap = false; 313 } 314 else 315 { 316 final Properties properties = jcd.getConnectionPoolDescriptor().getDbcpProperties(); 317 final String allowConnectionUnwrapParam; 318 allowConnectionUnwrapParam = properties.getProperty(PARAM_NAME_UNWRAP_ALLOWED); 319 allowConnectionUnwrap = allowConnectionUnwrapParam != null && 320 Boolean.valueOf(allowConnectionUnwrapParam).booleanValue(); 321 } 322 final PoolingDataSource dataSource; 323 dataSource = new PoolingDataSource(connectionPool); 324 dataSource.setAccessToUnderlyingConnectionAllowed(allowConnectionUnwrap); 325 326 if(jcd != null) 327 { 328 final AbandonedConfig ac = jcd.getConnectionPoolDescriptor().getAbandonedConfig(); 329 if (ac.getRemoveAbandoned() && ac.getLogAbandoned()) { 330 final LoggerWrapperPrintWriter loggerPiggyBack; 331 loggerPiggyBack = new LoggerWrapperPrintWriter(log, Logger.ERROR); 332 dataSource.setLogWriter(loggerPiggyBack); 333 } 334 } 335 return dataSource; 336 } 337 338 356 protected org.apache.commons.dbcp.ConnectionFactory createConnectionFactory(JdbcConnectionDescriptor jcd) 357 { 358 final ConPoolFactory result; 359 final Properties properties = getJdbcProperties(jcd); 360 result = new ConPoolFactory(jcd, properties); 361 return result; 362 } 363 364 366 371 protected ObjectPool createObjectPool(GenericObjectPool.Config config) 372 { 373 return createConnectionPool(config, null); 374 } 375 376 381 protected PoolingDataSource createPoolingDataSource(ObjectPool connectionPool) 382 { 383 return (PoolingDataSource) wrapAsDataSource(null, connectionPool); 387 } 388 389 391 395 401 class ConPoolFactory extends DriverManagerConnectionFactory 402 { 403 404 private final JdbcConnectionDescriptor jcd; 405 406 public ConPoolFactory(JdbcConnectionDescriptor jcd, Properties properties) 407 { 408 super(getDbURL(jcd), properties); 409 this.jcd = jcd; 410 } 411 412 public Connection createConnection() throws SQLException 413 { 414 final Connection conn = super.createConnection(); 415 if (conn != null) 416 { 417 try 418 { 419 initializeJdbcConnection(conn, jcd); 420 } 421 catch (LookupException e) 422 { 423 log.error("Platform dependent initialization of connection failed", e); 424 } 425 } 426 return conn; 427 } 428 429 } 430 431 } 432 | Popular Tags |