package org.infinispan.test.fwk; import static org.testng.Assert.assertEquals; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.concurrent.atomic.AtomicInteger; import org.infinispan.persistence.jdbc.DatabaseType; import org.infinispan.persistence.jdbc.JdbcUtil; import org.infinispan.persistence.jdbc.configuration.AbstractJdbcStoreConfigurationBuilder; import org.infinispan.persistence.jdbc.configuration.ConnectionFactoryConfigurationBuilder; import org.infinispan.persistence.jdbc.configuration.TableManipulationConfigurationBuilder; import org.infinispan.persistence.jdbc.connectionfactory.ConnectionFactory; import org.infinispan.persistence.jdbc.connectionfactory.PooledConnectionFactory; import org.infinispan.persistence.jdbc.connectionfactory.SimpleConnectionFactory; import org.infinispan.persistence.jdbc.table.management.TableName; /** * Class that assures concurrent access to the in memory database. * * @author Mircea.Markus@jboss.com * @author Navin Surtani (<a href="mailto:nsurtani@redhat.com">nsurtani@redhat.com</a>) * @author Tristan Tarrant */ public class UnitTestDatabaseManager { private static AtomicInteger userIndex = new AtomicInteger(0); private static final String DB_TYPE = System.getProperty("infinispan.test.jdbc.db", "H2"); private static final String H2_DRIVER = org.h2.Driver.class.getName(); private static final String NON_EXISTENT_DRIVER = "non.existent.Driver"; private static final DatabaseType dt; static { String driver = ""; try { if (DB_TYPE.equalsIgnoreCase("mysql")) { driver = com.mysql.jdbc.Driver.class.getName(); dt = DatabaseType.MYSQL; } else { driver = H2_DRIVER; dt = DatabaseType.H2; } try { Class.forName(driver); } catch (ClassNotFoundException e) { driver = H2_DRIVER; Class.forName(H2_DRIVER); } } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static ConnectionFactoryConfigurationBuilder<?> configureUniqueConnectionFactory(AbstractJdbcStoreConfigurationBuilder<?, ?> store) { switch (dt) { case H2: return store .connectionPool() .driverClass(org.h2.Driver.class) .connectionUrl(String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1", extractTestName() + userIndex.incrementAndGet())) .username("sa"); case MYSQL: return store .simpleConnection() .driverClass(com.mysql.jdbc.Driver.class) .connectionUrl("jdbc:mysql://localhost/infinispan?user=ispn&password=ispn") .username("ispn") .password("ispn"); default: throw new RuntimeException("Cannot configure connection for database type "+dt); } } public static ConnectionFactoryConfigurationBuilder<?> configureSimpleConnectionFactory(AbstractJdbcStoreConfigurationBuilder<?, ?> store) { return store .simpleConnection() .driverClass(org.h2.Driver.class) .connectionUrl(String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1", extractTestName() + userIndex.incrementAndGet())) .username("sa"); } public static ConnectionFactoryConfigurationBuilder<?> configureBrokenConnectionFactory (AbstractJdbcStoreConfigurationBuilder<?, ?> storeBuilder) { return storeBuilder.connectionPool() .driverClass(NON_EXISTENT_DRIVER); } private static String extractTestName() { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); if (stack.length == 0) return null; for (int i = stack.length - 1; i > 0; i--) { StackTraceElement e = stack[i]; String className = e.getClassName(); if (className.indexOf("org.infinispan") != -1) return className.replace('.', '_') + "_" + e.getMethodName(); } return null; } public static void setDialect(AbstractJdbcStoreConfigurationBuilder builder) { builder.dialect(dt); } public static void buildTableManipulation(TableManipulationConfigurationBuilder<?, ?> table) { table .tableNamePrefix("ISPN_STRING") .idColumnName("ID_COLUMN") .idColumnType("VARCHAR(255)") .dataColumnName("DATA_COLUMN") .dataColumnType("BLOB") .timestampColumnName("TIMESTAMP_COLUMN") .timestampColumnType("BIGINT"); } /** * Counts the number of rows in the given table. */ public static int rowCount(ConnectionFactory connectionFactory, TableName tableName) { Connection conn = null; PreparedStatement statement = null; ResultSet resultSet = null; try { conn = connectionFactory.getConnection(); String sql = "SELECT count(*) FROM " + tableName; statement = conn.prepareStatement(sql); resultSet = statement.executeQuery(); resultSet.next(); return resultSet.getInt(1); } catch (Exception ex) { throw new RuntimeException(ex); } finally { JdbcUtil.safeClose(resultSet); JdbcUtil.safeClose(statement); connectionFactory.releaseConnection(conn); } } public static void verifyConnectionLeaks(ConnectionFactory connectionFactory) { if (connectionFactory instanceof PooledConnectionFactory) { PooledConnectionFactory pcf = (PooledConnectionFactory) connectionFactory; try { Thread.sleep(500); // C3P0 needs a little delay before reporting the correct number of connections. Bah! assertEquals(pcf.getNumBusyConnectionsAllUsers(), 0); } catch (Exception e) { throw new RuntimeException(e); } } else if (connectionFactory instanceof SimpleConnectionFactory) { SimpleConnectionFactory scf = (SimpleConnectionFactory) connectionFactory; assertEquals(scf.getConnectionCount(), 0); } } }