/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Cambridge Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.jdbc.container; import java.sql.Connection; import org.apache.commons.dbcp.ConnectionFactory; import org.apache.commons.dbcp.DriverManagerConnectionFactory; import org.apache.commons.dbcp.PoolableConnectionFactory; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericObjectPool; import org.openanzo.cache.ICacheProvider; import org.openanzo.cache.LRUCacheProvider; import org.openanzo.exceptions.AnzoException; import org.openanzo.exceptions.AnzoRuntimeException; import org.openanzo.exceptions.ExceptionConstants; import org.openanzo.exceptions.LogUtils; import org.openanzo.jdbc.layout.indexer.LiteralIndexer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Creates RDBQuadStores from a pool. * * @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>) * */ class RDBQuadStoreFactory implements PoolableObjectFactory { private static final Logger log = LoggerFactory.getLogger(RDBQuadStoreFactory.class); /** JDBC Connection Pool */ private PoolableConnectionFactory pcf; private GenericObjectPool connectionPool; /** RespositoryConnectionPool */ private final RDBQuadStorePool quadStorePool; /** ConnectionPool */ private final PoolableConnectionFactory connectionFactory; /** ReadOnly connections */ private final boolean write; /** Configuration data for the connections in this pool */ private final CoreDBConfiguration configuration; /** Shared cache provider for the connections in this pool */ private final ICacheProvider cacheProvider; /** Literal indexer for the stores in this pool */ private final LiteralIndexer literalIndexer; /** * Create new RDBQuadStoreFactory * * @param quadStorePool * Pool of jdbc connections * @param parentPool * Parent pool that is using this factory to create connections * @param literalIndexer * Literal indexer for the connections in this pool * @param write * is connection for writting data * @param maxActive * connections allowed * @param configuration * data for connections */ protected RDBQuadStoreFactory(RDBQuadStorePool quadStorePool, LiteralIndexer literalIndexer, boolean write, int maxActive, CoreDBConfiguration configuration) { this.quadStorePool = quadStorePool; this.write = write; this.configuration = configuration; this.cacheProvider = new LRUCacheProvider(); this.connectionFactory = initializeConnectionFactory(write, maxActive, configuration); this.literalIndexer = literalIndexer; } /** * Close the factory * * @throws Exception */ protected void close() throws Exception { connectionFactory.getPool().close(); } /** Activate RDBConnection from pool */ public void activateObject(Object obj) throws Exception { ((RDBQuadStore) obj).setReturned(false); } /** Destroy RDBConnection */ public void destroyObject(Object obj) throws Exception { closeConnection(((RDBQuadStore) obj)); } /** Make new RDBConnection */ public Object makeObject() throws Exception { Connection connection = (Connection) connectionFactory.makeObject(); connectionFactory.activateObject(connection); RDBQuadStore con = new RDBQuadStore(cacheProvider, literalIndexer, write, configuration, connection); //quadStorePool.registerResetListener(con); return con; } /** Put RDBConnection back in pool */ public void passivateObject(Object obj) throws Exception { cleanConnection(((IRDBQuadStore) obj)); ((RDBQuadStore) obj).setReturned(true); } /** Validate RDBConnection is still good */ public boolean validateObject(Object obj) { RDBQuadStore con = ((RDBQuadStore) obj); return !con.isClosed(); } private static void cleanConnection(IRDBQuadStore con) { try { con.abort(); } catch (AnzoException bre) { log.error(LogUtils.RDB_MARKER, "Error aborting jdbc connection", bre); } } private void closeConnection(RDBQuadStore con) { cleanConnection(con); con.close(); quadStorePool.allStores.remove(con); //quadStorePool.unregisterResetListener(con); } private PoolableConnectionFactory initializeConnectionFactory(boolean write, int maxActive, CoreDBConfiguration configuration) { // Will use in jndi // DataSource ds = (DataSource) ctx.lookup(RepositoryProperties.getDatabaseJndiName(properties)); try { Class.forName(configuration.getDriverClassName()); } catch (ClassNotFoundException e1) { throw new AnzoRuntimeException(ExceptionConstants.RDB.DRIVER_NAME, e1, configuration.getDriverClassName()); } ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(configuration.getJdbcUrl(), configuration.getUser(), configuration.getPassword()); connectionPool = new GenericObjectPool(); connectionPool.setMaxActive(maxActive); connectionPool.setMinIdle(1); connectionPool.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK); connectionPool.setMaxWait(30000); connectionPool.setMaxActive(maxActive); pcf = new PoolableConnectionFactory(connectionFactory, connectionPool, null, null, false, true); if ((!write && configuration.getSupportsIsolation())) pcf.setDefaultTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); return pcf; } }