ha-jdbc-2.0.16+rc1/0000775000175000017500000000000011674455606013451 5ustar moellermoellerha-jdbc-2.0.16+rc1/build.xml0000644000175000017500000002666611151703034015265 0ustar moellermoeller ha-jdbc-2.0.16+rc1/test/0000775000175000017500000000000011674455606014430 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/ha-jdbc-test-datasource-cluster.xml0000644000175000017500000000327711151703043023212 0ustar moellermoeller datasource1 net.sf.hajdbc.sql.MockInitialContextFactory datasource2 net.sf.hajdbc.sql.MockInitialContextFactory ha-jdbc-2.0.16+rc1/test/ha-jdbc-test-xa-datasource-cluster.xml0000644000175000017500000000115211217564673023627 0ustar moellermoeller datasource1 net.sf.hajdbc.sql.MockInitialContextFactory datasource2 net.sf.hajdbc.sql.MockInitialContextFactory ha-jdbc-2.0.16+rc1/test/testng.xml0000644000175000017500000000076411151703043016440 0ustar moellermoeller ha-jdbc-2.0.16+rc1/test/ha-jdbc-test-database-cluster.xml0000644000175000017500000000314411151703044022616 0ustar moellermoeller net.sf.hajdbc.sql.MockDriver jdbc:mock:database1 net.sf.hajdbc.sql.MockDriver jdbc:mock:database2 ha-jdbc-2.0.16+rc1/test/net/0000755000175000017500000000000011151703044015172 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/net/sf/0000755000175000017500000000000011151703044015602 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/0000755000175000017500000000000011674455606017037 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/0000755000175000017500000000000011674455606017636 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestDataSource.java0000644000175000017500000002325011151703044023353 0ustar moellermoeller/** * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.SQLException; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @SuppressWarnings({ "unchecked", "nls" }) @Test public class TestDataSource implements javax.sql.DataSource { private DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); private Balancer balancer = EasyMock.createStrictMock(Balancer.class); private javax.sql.DataSource dataSource1 = EasyMock.createStrictMock(javax.sql.DataSource.class); private javax.sql.DataSource dataSource2 = EasyMock.createStrictMock(javax.sql.DataSource.class); private LockManager lockManager = EasyMock.createStrictMock(LockManager.class); private Lock lock = EasyMock.createStrictMock(Lock.class); private Database database1 = new MockDataSourceDatabase("1", this.dataSource1); private Database database2 = new MockDataSourceDatabase("2", this.dataSource2); private Set databaseSet; private ExecutorService executor = Executors.newSingleThreadExecutor(); private javax.sql.DataSource dataSource; @BeforeClass void init() { Map map = new TreeMap(); map.put(this.database1, this.dataSource1); map.put(this.database2, this.dataSource2); this.databaseSet = map.keySet(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); this.replay(); this.dataSource = ProxyFactory.createProxy(javax.sql.DataSource.class, new DataSourceInvocationHandler(this.cluster)); this.verify(); this.reset(); } private Object[] objects() { return new Object[] { this.cluster, this.balancer, this.dataSource1, this.dataSource2, this.lockManager, this.lock }; } void replay() { EasyMock.replay(this.objects()); } void verify() { EasyMock.verify(this.objects()); } @AfterMethod void reset() { EasyMock.reset(this.objects()); } public void testGetConnection() throws SQLException { Connection connection1 = EasyMock.createStrictMock(Connection.class); Connection connection2 = EasyMock.createStrictMock(Connection.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getLockManager()).andReturn(this.lockManager); EasyMock.expect(this.lockManager.readLock(LockManager.GLOBAL)).andReturn(this.lock); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.dataSource1.getConnection()).andReturn(connection1); EasyMock.expect(this.dataSource2.getConnection()).andReturn(connection2); this.replay(); Connection result = this.getConnection(); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == connection1; assert proxy.getObject(this.database2) == connection2; } /** * @see javax.sql.DataSource#getConnection() */ @Override public Connection getConnection() throws SQLException { return this.dataSource.getConnection(); } @DataProvider(name = "string-string") Object[][] connectProvider() { return new Object[][] { new Object[] { "", "" } }; } @Test(dataProvider = "string-string") public void testGetConnection(String user, String password) throws SQLException { Connection connection1 = EasyMock.createStrictMock(Connection.class); Connection connection2 = EasyMock.createStrictMock(Connection.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getLockManager()).andReturn(this.lockManager); EasyMock.expect(this.lockManager.readLock(LockManager.GLOBAL)).andReturn(this.lock); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.dataSource1.getConnection(user, password)).andReturn(connection1); EasyMock.expect(this.dataSource2.getConnection(user, password)).andReturn(connection2); this.replay(); Connection result = this.getConnection(user, password); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == connection1; assert proxy.getObject(this.database2) == connection2; } /** * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) */ @Override public Connection getConnection(String user, String password) throws SQLException { return this.dataSource.getConnection(user, password); } public void testGetLogWriter() { PrintWriter writer = new PrintWriter(System.out); EasyMock.expect(this.cluster.isActive()).andReturn(true); try { EasyMock.expect(this.dataSource1.getLogWriter()).andReturn(writer); this.replay(); PrintWriter result = this.getLogWriter(); this.verify(); assert result == writer; } catch (SQLException e) { assert false : e; } } /** * @see javax.sql.CommonDataSource#getLogWriter() */ @Override public PrintWriter getLogWriter() throws SQLException { return this.dataSource.getLogWriter(); } public void testGetLoginTimeout() { int timeout = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); try { EasyMock.expect(this.dataSource1.getLoginTimeout()).andReturn(timeout); this.replay(); int result = this.getLoginTimeout(); this.verify(); assert result == timeout; } catch (SQLException e) { assert false : e; } } /** * @see javax.sql.CommonDataSource#getLoginTimeout() */ @Test public int getLoginTimeout() throws SQLException { return this.dataSource.getLoginTimeout(); } @DataProvider(name = "writer") Object[][] writerProvider() { return new Object[][] { new Object[] { new PrintWriter(new StringWriter()) } }; } /** * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter) */ @Test(dataProvider = "writer") public void setLogWriter(PrintWriter writer) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.dataSource1.setLogWriter(writer); this.dataSource2.setLogWriter(writer); this.replay(); this.dataSource.setLogWriter(writer); this.verify(); } @DataProvider(name = "int") Object[][] timeoutProvider() { return new Object[][] { new Object[] { 0 } }; } /** * @see javax.sql.CommonDataSource#setLoginTimeout(int) */ @Test(dataProvider = "int") public void setLoginTimeout(int timeout) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.dataSource1.setLoginTimeout(timeout); this.dataSource2.setLoginTimeout(timeout); this.replay(); this.dataSource.setLoginTimeout(timeout); this.verify(); } public void testIsWrapperFor() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.dataSource1.isWrapperFor(Object.class)).andReturn(true); this.replay(); boolean result = this.isWrapperFor(Object.class); this.verify(); assert result; } /** * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ @Override public boolean isWrapperFor(Class targetClass) throws SQLException { return this.dataSource.isWrapperFor(targetClass); } public void testUnwrap() throws SQLException { try { Object object = Object.class.newInstance(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.dataSource1.unwrap(Object.class)).andReturn(object); this.replay(); Object result = this.unwrap(Object.class); this.verify(); assert result == object; } catch (InstantiationException e) { assert false : e; } catch (IllegalAccessException e) { assert false : e; } } /** * @see java.sql.Wrapper#unwrap(java.lang.Class) */ @Override public T unwrap(Class targetClass) throws SQLException { return this.dataSource.unwrap(targetClass); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/AbstractTestPreparedStatement.java0000644000175000017500000012731711217530453026452 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.ByteArrayInputStream; import java.io.CharArrayReader; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.lang.reflect.Proxy; import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URL; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Date; import java.sql.NClob; import java.sql.ParameterMetaData; import java.sql.PreparedStatement; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.Map; import java.util.TreeMap; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Unit test for {@link PreparedStatement} * @author Paul Ferraro */ @Test @SuppressWarnings({ "unchecked", "nls" }) public abstract class AbstractTestPreparedStatement extends AbstractTestStatement implements java.sql.PreparedStatement { protected String sql = "sql"; protected Blob blob1 = EasyMock.createMock(Blob.class); protected Blob blob2 = EasyMock.createMock(Blob.class); protected Clob clob1 = EasyMock.createMock(Clob.class); protected Clob clob2 = EasyMock.createMock(Clob.class); protected NClob nClob1 = EasyMock.createMock(NClob.class); protected NClob nClob2 = EasyMock.createMock(NClob.class); /** * @see net.sf.hajdbc.sql.AbstractTestStatement#recordConstructor() */ @Override protected void recordConstructor() throws SQLException { this.parent.addChild(EasyMock.isA(PreparedStatementInvocationHandler.class)); this.expectIdentifiers(this.sql, null, null); this.expectSelectForUpdateCheck(this.sql, false); } /** * @see java.sql.PreparedStatement#addBatch() */ @Test public void addBatch() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.addBatch(); this.statement2.addBatch(); this.replay(); this.statement.addBatch(); this.verify(); } /** * @see java.sql.PreparedStatement#clearParameters() */ @Test public void clearParameters() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); this.statement1.addBatch(); this.statement2.addBatch(); this.replay(); this.statement.addBatch(); } public void testExecute() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute()).andReturn(true); EasyMock.expect(this.statement2.execute()).andReturn(true); this.replay(); boolean result = this.execute(); this.verify(); assert result; } /** * @see java.sql.PreparedStatement#execute() */ @Override public boolean execute() throws SQLException { return this.statement.execute(); } public void testExecuteQuery() throws SQLException { ResultSet resultSet = EasyMock.createMock(ResultSet.class); EasyMock.expect(this.cluster.isActive()).andReturn(true).times(2); // Read-only EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_READ_ONLY); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.statement2.executeQuery()).andReturn(resultSet); this.balancer.afterInvocation(this.database2); this.replay(); ResultSet results = this.executeQuery(); this.verify(); assert results == resultSet; this.reset(); EasyMock.makeThreadSafe(this.statement1, true); EasyMock.makeThreadSafe(this.statement2, true); ResultSet resultSet1 = EasyMock.createMock(ResultSet.class); ResultSet resultSet2 = EasyMock.createMock(ResultSet.class); EasyMock.expect(this.cluster.isActive()).andReturn(true).times(2); // Updatable EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_UPDATABLE); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeQuery()).andReturn(resultSet1); EasyMock.expect(this.statement2.executeQuery()).andReturn(resultSet2); this.replay(); results = this.executeQuery(); this.verify(); assert Proxy.isProxyClass(results.getClass()); assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database1) == resultSet1; assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database2) == resultSet2; } /** * @see java.sql.PreparedStatement#executeQuery() */ @Override public ResultSet executeQuery() throws SQLException { return this.statement.executeQuery(); } public void testExecuteUpdate() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate()).andReturn(1); EasyMock.expect(this.statement2.executeUpdate()).andReturn(1); this.replay(); int result = this.executeUpdate(); this.verify(); assert result == 1; } /** * @see java.sql.PreparedStatement#executeUpdate() */ @Override public int executeUpdate() throws SQLException { return this.statement.executeUpdate(); } public void testGetMetaData() throws SQLException { ResultSetMetaData metaData = EasyMock.createMock(ResultSetMetaData.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.statement2.getMetaData()).andReturn(metaData); this.balancer.afterInvocation(this.database2); this.replay(); ResultSetMetaData result = this.getMetaData(); this.verify(); assert result == metaData; } /** * @see java.sql.PreparedStatement#getMetaData() */ @Override public ResultSetMetaData getMetaData() throws SQLException { return this.statement.getMetaData(); } public void testGetParameterMetaData() throws SQLException { ParameterMetaData metaData = EasyMock.createMock(ParameterMetaData.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.statement2.getParameterMetaData()).andReturn(metaData); this.balancer.afterInvocation(this.database2); this.replay(); ParameterMetaData result = this.getParameterMetaData(); this.verify(); assert result == metaData; } /** * @see java.sql.PreparedStatement#getParameterMetaData() */ @Override public ParameterMetaData getParameterMetaData() throws SQLException { return this.statement.getParameterMetaData(); } @DataProvider(name = "int-array") Object[][] intArrayProvider() { return new Object[][] { new Object[] { 1, EasyMock.createMock(Array.class) } }; } /** * @see java.sql.PreparedStatement#setArray(int, java.sql.Array) */ @Test(dataProvider = "int-array") public void setArray(int index, Array array) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setArray(index, array); this.statement2.setArray(index, array); this.replay(); this.statement.setArray(index, array); this.verify(); } @DataProvider(name = "int-inputStream-int") Object[][] intInputStreamIntProvider() { return new Object[][] { new Object[] { 1, new ByteArrayInputStream(new byte[0]), 0 } }; } /** * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream, int) */ @Test(dataProvider = "int-inputStream-int") public void setAsciiStream(int index, InputStream inputStream, int length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(inputStream)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setAsciiStream(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setAsciiStream(index, input2, length); this.replay(); this.statement.setAsciiStream(index, inputStream, length); this.verify(); } @DataProvider(name = "int-bigDecimal") Object[][] intBigDecimalProvider() { return new Object[][] { new Object[] { 1, new BigDecimal(10) } }; } /** * @see java.sql.PreparedStatement#setBigDecimal(int, java.math.BigDecimal) */ @Test(dataProvider = "int-bigDecimal") public void setBigDecimal(int index, BigDecimal value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setBigDecimal(index, value); this.statement2.setBigDecimal(index, value); this.replay(); this.statement.setBigDecimal(index, value); this.verify(); } /** * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream, int) */ @Test(dataProvider = "int-inputStream-int") public void setBinaryStream(int index, InputStream inputStream, int length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(inputStream)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setBinaryStream(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setBinaryStream(index, input2, length); this.replay(); this.statement.setBinaryStream(index, inputStream, length); this.verify(); } @DataProvider(name = "int-blob") Object[][] intBlobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.blob1); map.put(this.database2, this.blob2); Blob blob = ProxyFactory.createProxy(Blob.class, new BlobInvocationHandler(null, this.handler, null, map)); return new Object[][] { new Object[] { 1, new MockBlob() }, new Object[] { 1, blob } }; } /** * @see java.sql.PreparedStatement#setBlob(int, java.sql.Blob) */ @Test(dataProvider = "int-blob") public void setBlob(int index, Blob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.statement1.setBlob(index, this.blob1); this.statement2.setBlob(index, this.blob2); } else { this.statement1.setBlob(EasyMock.eq(index), EasyMock.isA(SerialBlob.class)); this.statement2.setBlob(EasyMock.eq(index), EasyMock.isA(SerialBlob.class)); } this.replay(); this.statement.setBlob(index, value); this.verify(); } @DataProvider(name = "int-boolean") Object[][] intBooleanProvider() { return new Object[][] { new Object[] { 1, true } }; } /** * @see java.sql.PreparedStatement#setBoolean(int, boolean) */ @Test(dataProvider = "int-boolean") public void setBoolean(int index, boolean value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setBoolean(index, value); this.statement2.setBoolean(index, value); this.replay(); this.statement.setBoolean(index, value); this.verify(); } @DataProvider(name = "int-byte") Object[][] intByteProvider() { return new Object[][] { new Object[] { 1, Integer.valueOf(1).byteValue() } }; } /** * @see java.sql.PreparedStatement#setByte(int, byte) */ @Test(dataProvider = "int-byte") public void setByte(int index, byte value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setByte(index, value); this.statement2.setByte(index, value); this.replay(); this.statement.setByte(index, value); this.verify(); } @DataProvider(name = "int-bytes") Object[][] intBytesProvider() { return new Object[][] { new Object[] { 1, new byte[0] } }; } /** * @see java.sql.PreparedStatement#setBytes(int, byte[]) */ @Test(dataProvider = "int-bytes") public void setBytes(int index, byte[] value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setBytes(index, value); this.statement2.setBytes(index, value); this.replay(); this.statement.setBytes(index, value); this.verify(); } @DataProvider(name = "int-reader-int") Object[][] intReaderIntProvider() { return new Object[][] { new Object[] { 1, new CharArrayReader(new char[0]), 0 } }; } /** * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, int) */ @Test(dataProvider = "int-reader-int") public void setCharacterStream(int index, Reader reader, int length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(reader)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setCharacterStream(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setCharacterStream(index, reader2, length); this.replay(); this.statement.setCharacterStream(index, reader, length); this.verify(); } @DataProvider(name = "int-clob") Object[][] intClobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.clob1); map.put(this.database2, this.clob2); Clob clob = ProxyFactory.createProxy(Clob.class, new ClobInvocationHandler(null, this.handler, null, map)); return new Object[][] { new Object[] { 1, new MockClob() }, new Object[] { 1, clob } }; } /** * @see java.sql.PreparedStatement#setClob(int, java.sql.Clob) */ @Test(dataProvider = "int-clob") public void setClob(int index, Clob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.statement1.setClob(index, this.clob1); this.statement2.setClob(index, this.clob2); } else { this.statement1.setClob(EasyMock.eq(index), EasyMock.isA(SerialClob.class)); this.statement2.setClob(EasyMock.eq(index), EasyMock.isA(SerialClob.class)); } this.replay(); this.statement.setClob(index, value); this.verify(); } @DataProvider(name = "int-date") Object[][] intDateProvider() { return new Object[][] { new Object[] { 1, new Date(System.currentTimeMillis()) } }; } /** * @see java.sql.PreparedStatement#setDate(int, java.sql.Date) */ @Test(dataProvider = "int-date") public void setDate(int index, Date date) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setDate(index, date); this.statement2.setDate(index, date); this.replay(); this.statement.setDate(index, date); this.verify(); } @DataProvider(name = "int-date-calendar") Object[][] intDateCalendarProvider() { return new Object[][] { new Object[] { 1, new Date(System.currentTimeMillis()), Calendar.getInstance() } }; } /** * @see java.sql.PreparedStatement#setDate(int, java.sql.Date, java.util.Calendar) */ @Test(dataProvider = "int-date-calendar") public void setDate(int index, Date date, Calendar calendar) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setDate(index, date, calendar); this.statement2.setDate(index, date, calendar); this.replay(); this.statement.setDate(index, date, calendar); this.verify(); } @DataProvider(name = "int-double") Object[][] intDoubleProvider() { return new Object[][] { new Object[] { 1, 1.0 } }; } /** * @see java.sql.PreparedStatement#setDouble(int, double) */ @Test(dataProvider = "int-double") public void setDouble(int index, double value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setDouble(index, value); this.statement2.setDouble(index, value); this.replay(); this.statement.setDouble(index, value); this.verify(); } @DataProvider(name = "int-float") Object[][] intFloatProvider() { return new Object[][] { new Object[] { 1, 1.0f } }; } /** * @see java.sql.PreparedStatement#setFloat(int, float) */ @Test(dataProvider = "int-float") public void setFloat(int index, float value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setFloat(index, value); this.statement2.setFloat(index, value); this.replay(); this.statement.setFloat(index, value); this.verify(); } @DataProvider(name = "int-int") Object[][] intIntProvider() { return new Object[][] { new Object[] { 1, 1 } }; } /** * @see java.sql.PreparedStatement#setInt(int, int) */ @Test(dataProvider = "int-int") public void setInt(int index, int value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setInt(index, value); this.statement2.setInt(index, value); this.replay(); this.statement.setInt(index, value); this.verify(); } @DataProvider(name = "int-long") Object[][] intLongProvider() { return new Object[][] { new Object[] { 1, 1L } }; } /** * @see java.sql.PreparedStatement#setLong(int, long) */ @Test(dataProvider = "int-long") public void setLong(int index, long value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setLong(index, value); this.statement2.setLong(index, value); this.replay(); this.statement.setLong(index, value); this.verify(); } /** * @see java.sql.PreparedStatement#setNull(int, int) */ @Test(dataProvider = "int-int") public void setNull(int index, int sqlType) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setNull(index, sqlType); this.statement2.setNull(index, sqlType); this.replay(); this.statement.setNull(index, sqlType); this.verify(); } @DataProvider(name = "int-int-string") Object[][] intIntStringProvider() { return new Object[][] { new Object[] { 1, 1, "" } }; } /** * @see java.sql.PreparedStatement#setNull(int, int, java.lang.String) */ @Test(dataProvider = "int-int-string") public void setNull(int index, int sqlType, String typeName) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setNull(index, sqlType, typeName); this.statement2.setNull(index, sqlType, typeName); this.replay(); this.statement.setNull(index, sqlType, typeName); this.verify(); } @DataProvider(name = "int-object") Object[][] intObjectProvider() { return new Object[][] { new Object[] { 1, new Object() } }; } /** * @see java.sql.PreparedStatement#setObject(int, java.lang.Object) */ @Test(dataProvider = "int-object") public void setObject(int index, Object value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setObject(index, value); this.statement2.setObject(index, value); this.replay(); this.statement.setObject(index, value); this.verify(); } @DataProvider(name = "int-object-int") Object[][] intObjectIntProvider() { return new Object[][] { new Object[] { 1, new Object(), 1 } }; } /** * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int) */ @Test(dataProvider = "int-object-int") public void setObject(int index, Object value, int targetSqlType) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setObject(index, value, targetSqlType); this.statement2.setObject(index, value, targetSqlType); this.replay(); this.statement.setObject(index, value, targetSqlType); this.verify(); } @DataProvider(name = "int-object-int-int") Object[][] intObjectIntIntProvider() { return new Object[][] { new Object[] { 1, new Object(), 1, 1 } }; } /** * @see java.sql.PreparedStatement#setObject(int, java.lang.Object, int, int) */ @Test(dataProvider = "int-object-int-int") public void setObject(int index, Object value, int targetSqlType, int scale) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setObject(index, value, targetSqlType, scale); this.statement2.setObject(index, value, targetSqlType, scale); this.replay(); this.statement.setObject(index, value, targetSqlType, scale); this.verify(); } @DataProvider(name = "int-ref") Object[][] intRefProvider() { return new Object[][] { new Object[] { 1, EasyMock.createMock(Ref.class) } }; } /** * @see java.sql.PreparedStatement#setRef(int, java.sql.Ref) */ @Test(dataProvider = "int-ref") public void setRef(int index, Ref value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setRef(index, value); this.statement2.setRef(index, value); this.replay(); this.statement.setRef(index, value); this.verify(); } @DataProvider(name = "int-short") Object[][] intShortProvider() { return new Object[][] { new Object[] { 1, Integer.valueOf(1).shortValue() } }; } /** * @see java.sql.PreparedStatement#setShort(int, short) */ @Test(dataProvider = "int-short") public void setShort(int index, short value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setShort(index, value); this.statement2.setShort(index, value); this.replay(); this.statement.setShort(index, value); this.verify(); } @DataProvider(name = "int-string") Object[][] intStringProvider() { return new Object[][] { new Object[] { 1, "" } }; } /** * @see java.sql.PreparedStatement#setString(int, java.lang.String) */ @Test(dataProvider = "int-string") public void setString(int index, String value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setString(index, value); this.statement2.setString(index, value); this.replay(); this.statement.setString(index, value); this.verify(); } @DataProvider(name = "int-time") Object[][] intTimeProvider() { return new Object[][] { new Object[] { 1, new Time(System.currentTimeMillis()) } }; } /** * @see java.sql.PreparedStatement#setTime(int, java.sql.Time) */ @Test(dataProvider = "int-time") public void setTime(int index, Time value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setTime(index, value); this.statement2.setTime(index, value); this.replay(); this.statement.setTime(index, value); this.verify(); } @DataProvider(name = "int-time-calendar") Object[][] intTimeCalendarProvider() { return new Object[][] { new Object[] { 1, new Time(System.currentTimeMillis()), Calendar.getInstance() } }; } /** * @see java.sql.PreparedStatement#setTime(int, java.sql.Time, java.util.Calendar) */ @Test(dataProvider = "int-time-calendar") public void setTime(int index, Time value, Calendar calendar) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setTime(index, value, calendar); this.statement2.setTime(index, value, calendar); this.replay(); this.statement.setTime(index, value, calendar); this.verify(); } @DataProvider(name = "int-timestamp") Object[][] intTimestampProvider() { return new Object[][] { new Object[] { 1, new Timestamp(System.currentTimeMillis()) } }; } /** * @see java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp) */ @Test(dataProvider = "int-timestamp") public void setTimestamp(int index, Timestamp value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setTimestamp(index, value); this.statement2.setTimestamp(index, value); this.replay(); this.statement.setTimestamp(index, value); this.verify(); } @DataProvider(name = "int-timestamp-calendar") Object[][] intTimestampCalendarProvider() { return new Object[][] { new Object[] { 1, new Timestamp(System.currentTimeMillis()), Calendar.getInstance() } }; } /** * @see java.sql.PreparedStatement#setTimestamp(int, java.sql.Timestamp, java.util.Calendar) */ @Test(dataProvider = "int-timestamp-calendar") public void setTimestamp(int index, Timestamp value, Calendar calendar) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setTimestamp(index, value, calendar); this.statement2.setTimestamp(index, value, calendar); this.replay(); this.statement.setTimestamp(index, value, calendar); this.verify(); } /** * @see java.sql.PreparedStatement#setUnicodeStream(int, java.io.InputStream, int) */ @SuppressWarnings("deprecation") @Test(dataProvider = "int-inputStream-int") @Deprecated public void setUnicodeStream(int index, InputStream inputStream, int length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(inputStream)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setUnicodeStream(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setUnicodeStream(index, input2, length); this.replay(); this.statement.setUnicodeStream(index, inputStream, length); this.verify(); } @DataProvider(name = "int-url") Object[][] intURLProvider() throws MalformedURLException { return new Object[][] { new Object[] { 1, new URL("http://ha-jdbc.sf.net") } }; } /** * @see java.sql.PreparedStatement#setURL(int, java.net.URL) */ @Test(dataProvider = "int-url") public void setURL(int index, URL value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setURL(index, value); this.statement2.setURL(index, value); this.replay(); this.statement.setURL(index, value); this.verify(); } @DataProvider(name = "int-inputStream") Object[][] intInputStreamProvider() { return new Object[][] { new Object[] { 1, new ByteArrayInputStream(new byte[0]) } }; } /** * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream) */ @Test(dataProvider = "int-inputStream") public void setAsciiStream(int index, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setAsciiStream(index, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setAsciiStream(index, input2); this.replay(); this.statement.setAsciiStream(index, value); this.verify(); } @DataProvider(name = "int-inputStream-long") Object[][] intInputStreamLongProvider() { return new Object[][] { new Object[] { 1, new ByteArrayInputStream(new byte[0]), 1L } }; } /** * @see java.sql.PreparedStatement#setAsciiStream(int, java.io.InputStream, long) */ @Test(dataProvider = "int-inputStream-long") public void setAsciiStream(int index, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setAsciiStream(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setAsciiStream(index, input2, length); this.replay(); this.statement.setAsciiStream(index, value, length); this.verify(); } /** * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream) */ @Test(dataProvider = "int-inputStream") public void setBinaryStream(int index, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setBinaryStream(index, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setBinaryStream(index, input2); this.replay(); this.statement.setBinaryStream(index, value); this.verify(); } /** * @see java.sql.PreparedStatement#setBinaryStream(int, java.io.InputStream, long) */ @Test(dataProvider = "int-inputStream-long") public void setBinaryStream(int index, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setBinaryStream(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setBinaryStream(index, input2, length); this.replay(); this.statement.setBinaryStream(index, value, length); this.verify(); } /** * @see java.sql.PreparedStatement#setBlob(int, java.io.InputStream) */ @Test(dataProvider = "int-inputStream") public void setBlob(int index, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setBlob(index, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setBlob(index, input2); this.replay(); this.statement.setBlob(index, value); this.verify(); } /** * @see java.sql.PreparedStatement#setBlob(int, java.io.InputStream, long) */ @Test(dataProvider = "int-inputStream-long") public void setBlob(int index, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setBlob(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setBlob(index, input2, length); this.replay(); this.statement.setBlob(index, value, length); this.verify(); } /** * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader) */ @Test(dataProvider = "int-reader") public void setCharacterStream(int index, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setCharacterStream(index, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setCharacterStream(index, reader2); this.replay(); this.statement.setCharacterStream(index, value); this.verify(); } @DataProvider(name = "int-reader-long") Object[][] intReaderLongProvider() { return new Object[][] { new Object[] { 1, new StringReader(""), 1L } }; } /** * @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, long) */ @Test(dataProvider = "int-reader-long") public void setCharacterStream(int index, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setCharacterStream(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setCharacterStream(index, reader2, length); this.replay(); this.statement.setCharacterStream(index, value, length); this.verify(); } @DataProvider(name = "int-reader") Object[][] intReaderProvider() { return new Object[][] { new Object[] { 1, new StringReader("") } }; } /** * @see java.sql.PreparedStatement#setClob(int, java.io.Reader) */ @Test(dataProvider = "int-reader") public void setClob(int index, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setClob(index, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setClob(index, reader2); this.replay(); this.statement.setClob(index, value); this.verify(); } /** * @see java.sql.PreparedStatement#setClob(int, java.io.Reader, long) */ @Test(dataProvider = "int-reader-long") public void setClob(int index, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setClob(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setClob(index, reader2, length); this.replay(); this.statement.setClob(index, value, length); this.verify(); } /** * @see java.sql.PreparedStatement#setNCharacterStream(int, java.io.Reader) */ @Test(dataProvider = "int-reader") public void setNCharacterStream(int index, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setNCharacterStream(index, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setNCharacterStream(index, reader2); this.replay(); this.statement.setNCharacterStream(index, value); this.verify(); } /** * @see java.sql.PreparedStatement#setNCharacterStream(int, java.io.Reader, long) */ @Test(dataProvider = "int-reader-long") public void setNCharacterStream(int index, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setNCharacterStream(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setNCharacterStream(index, reader2, length); this.replay(); this.statement.setNCharacterStream(index, value, length); this.verify(); } @DataProvider(name = "int-nclob") Object[][] intNClobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.nClob1); map.put(this.database2, this.nClob2); NClob nClob = ProxyFactory.createProxy(NClob.class, new ClobInvocationHandler(null, this.handler, null, map)); return new Object[][] { new Object[] { 1, new MockClob() }, new Object[] { 1, nClob } }; } /** * @see java.sql.PreparedStatement#setNClob(int, java.sql.NClob) */ @Test(dataProvider = "int-nclob") public void setNClob(int index, NClob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.statement1.setNClob(index, this.nClob1); this.statement2.setNClob(index, this.nClob2); } else { this.statement1.setNClob(EasyMock.eq(index), EasyMock.isA(NClob.class)); this.statement2.setNClob(EasyMock.eq(index), EasyMock.isA(NClob.class)); } this.replay(); this.statement.setNClob(index, value); this.verify(); } /** * @see java.sql.PreparedStatement#setNClob(int, java.io.Reader) */ @Test(dataProvider = "int-reader") public void setNClob(int index, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setNClob(index, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setNClob(index, reader2); this.replay(); this.statement.setNClob(index, value); this.verify(); } /** * @see java.sql.PreparedStatement#setNClob(int, java.io.Reader, long) */ @Test(dataProvider = "int-reader-long") public void setNClob(int index, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setNClob(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setNClob(index, reader2, length); this.replay(); this.statement.setNClob(index, value, length); this.verify(); } /** * @see java.sql.PreparedStatement#setNString(int, java.lang.String) */ @Test(dataProvider = "int-string") public void setNString(int index, String value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setNString(index, value); this.statement2.setNString(index, value); this.replay(); this.statement.setNString(index, value); this.verify(); } @DataProvider(name = "int-rowId") Object[][] intRowIdProvider() { return new Object[][] { new Object[] { 1, EasyMock.createMock(RowId.class) } }; } /** * @see java.sql.PreparedStatement#setRowId(int, java.sql.RowId) */ @Test(dataProvider = "int-rowId") public void setRowId(int index, RowId value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setRowId(index, value); this.statement2.setRowId(index, value); this.replay(); this.statement.setRowId(index, value); this.verify(); } @DataProvider(name = "int-xml") Object[][] intSQLXMLProvider() { return new Object[][] { new Object[] { 1, EasyMock.createMock(SQLXML.class) } }; } /** * @see java.sql.PreparedStatement#setSQLXML(int, java.sql.SQLXML) */ @Test(dataProvider = "int-xml") public void setSQLXML(int index, SQLXML value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setSQLXML(index, value); this.statement2.setSQLXML(index, value); this.replay(); this.statement.setSQLXML(index, value); this.verify(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestDataSourceFactory.java0000644000175000017500000001153611151703043024706 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Proxy; import java.sql.Driver; import java.sql.SQLException; import java.util.Hashtable; import java.util.Properties; import java.util.prefs.Preferences; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Name; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; import javax.sql.DataSource; import net.sf.hajdbc.local.LocalStateManager; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Unit test for {@link DataSourceFactory}. * * @author Paul Ferraro * @since 1.1 */ @SuppressWarnings("nls") public class TestDataSourceFactory implements ObjectFactory { private DataSourceFactory factory = new DataSourceFactory(); private Context context; @BeforeClass protected void setUp() throws Exception { Preferences.userNodeForPackage(LocalStateManager.class).put("test-datasource-cluster", "datasource1,datasource2"); Properties properties = new Properties(); properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, MockInitialContextFactory.class.getName()); this.context = new InitialContext(properties); Reference reference = new Reference(DataSourceFactory.class.toString(), MockDataSourceFactory.class.getName(), null); this.context.bind("datasource1", reference); this.context.bind("datasource2", reference); this.context.bind("datasource", new DataSourceReference("test-datasource-cluster")); } @AfterClass protected void tearDown() throws Exception { this.context.unbind("datasource"); this.context.unbind("datasource1"); this.context.unbind("datasource2"); Preferences.userNodeForPackage(LocalStateManager.class).remove("test-datasource-cluster"); } @DataProvider(name = "factory") Object[][] objectInstanceProvider() { return new Object[][] { new Object[] { null, null, null, null }, new Object[] { new Object(), null, null, null }, new Object[] { new Reference(DataSource.class.getName(), new StringRefAddr("cluster", "test-datasource-cluster")), null, null, null }, new Object[] { new Reference(DataSource.class.getName(), new StringRefAddr("cluster", null)), null, null, null }, new Object[] { new Reference(Driver.class.getName(), new StringRefAddr("cluster", "test-datasource-cluster")), null, null, null }, new Object[] { new Reference(DataSource.class.getName()), null, null, null }, new Object[] { new Reference(DataSource.class.getName(), new StringRefAddr("cluster", "invalid-cluster")), null, null, null } }; } /** * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable) */ @Test(dataProvider = "factory") public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) { try { Object result = this.factory.getObjectInstance(obj, name, nameCtx, environment); if ((obj == null) || !Reference.class.isInstance(obj)) { assert result == null; return result; } Reference reference = (Reference) obj; if (!reference.getClassName().equals(DataSource.class.getName())) { assert result == null; return result; } RefAddr addr = reference.get("cluster"); if ((addr == null) || (addr.getContent() == null)) { assert result == null; return result; } String id = (String) addr.getContent(); if ((id == null) || !id.equals("test-datasource-cluster")) { assert result == null; } else { assert result != null; assert Proxy.isProxyClass(result.getClass()) : result.getClass().getName(); } return result; } catch (SQLException e) { assert ((Reference) obj).get("cluster").getContent().equals("invalid-cluster"); return null; } catch (Exception e) { assert false : e; return null; } } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/MockDriver.java0000644000175000017500000000414611151703044022531 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverPropertyInfo; import java.util.Properties; /** * Mock driver that creates mock connections * @author Paul Ferraro * @since 1.1 */ @SuppressWarnings("nls") public class MockDriver implements Driver { private Connection connection; public MockDriver(Connection connection) { this.connection = connection; } /** * @see java.sql.Driver#connect(java.lang.String, java.util.Properties) */ public Connection connect(String url, Properties properties) { return this.connection; } /** * @see java.sql.Driver#acceptsURL(java.lang.String) */ public boolean acceptsURL(String url) { return url.startsWith("jdbc:mock:"); } /** * @see java.sql.Driver#getPropertyInfo(java.lang.String, java.util.Properties) */ public DriverPropertyInfo[] getPropertyInfo(String url, Properties properties) { return new DriverPropertyInfo[0]; } /** * @see java.sql.Driver#getMajorVersion() */ public int getMajorVersion() { return 0; } /** * @see java.sql.Driver#getMinorVersion() */ public int getMinorVersion() { return 0; } /** * @see java.sql.Driver#jdbcCompliant() */ public boolean jdbcCompliant() { return false; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestResultSet.java0000644000175000017500000037775011216573075023307 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.ByteArrayInputStream; import java.io.CharArrayReader; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.lang.reflect.Proxy; import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URL; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Connection; import java.sql.Date; import java.sql.NClob; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.MockDatabase; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.easymock.IAnswer; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /*** * @author Paul Ferraro * @since 1.0 */ @Test @SuppressWarnings({ "unchecked", "nls" }) public class TestResultSet implements ResultSet { private Connection connection = EasyMock.createStrictMock(Connection.class); private TransactionContext transactionContext = EasyMock.createStrictMock(TransactionContext.class); private Balancer balancer = EasyMock.createStrictMock(Balancer.class); private DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); private FileSupport fileSupport = EasyMock.createStrictMock(FileSupport.class); private Lock writeLock1 = EasyMock.createStrictMock(Lock.class); private Lock writeLock2 = EasyMock.createStrictMock(Lock.class); private LockManager lockManager = EasyMock.createStrictMock(LockManager.class); private Dialect dialect = EasyMock.createStrictMock(Dialect.class); private DatabaseMetaDataCache metaData = EasyMock.createStrictMock(DatabaseMetaDataCache.class); private DatabaseProperties databaseProperties = EasyMock.createStrictMock(DatabaseProperties.class); private TableProperties tableProperties = EasyMock.createStrictMock(TableProperties.class); private ColumnProperties columnProperties = EasyMock.createStrictMock(ColumnProperties.class); private ResultSet resultSet1 = EasyMock.createStrictMock(ResultSet.class); private ResultSet resultSet2 = EasyMock.createStrictMock(ResultSet.class); private SQLProxy parent = EasyMock.createStrictMock(SQLProxy.class); private SQLProxy root = EasyMock.createStrictMock(SQLProxy.class); private Blob blob1 = EasyMock.createMock(Blob.class); private Blob blob2 = EasyMock.createMock(Blob.class); private Clob clob1 = EasyMock.createMock(Clob.class); private Clob clob2 = EasyMock.createMock(Clob.class); private NClob nClob1 = EasyMock.createMock(NClob.class); private NClob nClob2 = EasyMock.createMock(NClob.class); private Database database1 = new MockDatabase("1"); private Database database2 = new MockDatabase("2"); private Set databaseSet; private ExecutorService executor = Executors.newSingleThreadExecutor(); private Statement statement = EasyMock.createMock(Statement.class); private ResultSet resultSet; private ResultSetInvocationHandler handler; private IAnswer anwser = new IAnswer() { @Override public InvocationStrategy answer() throws Throwable { return (InvocationStrategy) EasyMock.getCurrentArguments()[0]; } }; @BeforeClass void init() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.resultSet1); map.put(this.database2, this.resultSet2); this.databaseSet = map.keySet(); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(ResultSetInvocationHandler.class)); this.replay(); this.handler = new ResultSetInvocationHandler(this.statement, this.parent, EasyMock.createMock(Invoker.class), map, this.transactionContext, this.fileSupport); this.resultSet = ProxyFactory.createProxy(ResultSet.class, this.handler); this.verify(); this.reset(); } private Object[] objects() { return new Object[] { this.cluster, this.balancer, this.resultSet1, this.resultSet2, this.fileSupport, this.writeLock1, this.writeLock2, this.lockManager, this.parent, this.root, this.dialect, this.metaData, this.databaseProperties, this.tableProperties, this.columnProperties, this.connection, this.transactionContext, this.statement }; } void replay() { EasyMock.replay(this.objects()); } void verify() { EasyMock.verify(this.objects()); } @AfterMethod void reset() { EasyMock.reset(this.objects()); } @DataProvider(name = "int") Object[][] intProvider() { return new Object[][] { new Object[] { 1 } }; } public void testAbsolute() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.absolute(1)).andReturn(true); EasyMock.expect(this.resultSet2.absolute(1)).andReturn(true); this.replay(); boolean valid = this.absolute(1); this.verify(); assert valid; } /** * @see java.sql.ResultSet#absolute(int) */ @Override public boolean absolute(int row) throws SQLException { return this.resultSet.absolute(row); } /** * @see java.sql.ResultSet#afterLast() */ @Override public void afterLast() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.afterLast(); this.resultSet2.afterLast(); this.replay(); this.resultSet.afterLast(); this.verify(); } /** * @see java.sql.ResultSet#beforeFirst() */ @Override public void beforeFirst() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.beforeFirst(); this.resultSet2.beforeFirst(); this.replay(); this.resultSet.beforeFirst(); this.verify(); } /** * @see java.sql.ResultSet#cancelRowUpdates() */ @Override public void cancelRowUpdates() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.cancelRowUpdates(); this.resultSet2.cancelRowUpdates(); this.replay(); this.resultSet.cancelRowUpdates(); this.verify(); } /** * @see java.sql.ResultSet#clearWarnings() */ @Override public void clearWarnings() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.clearWarnings(); this.resultSet2.clearWarnings(); this.replay(); this.resultSet.clearWarnings(); this.verify(); } /** * @see java.sql.ResultSet#close() */ @Override public void close() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.close(); this.resultSet2.close(); this.parent.removeChild(this.handler); this.replay(); this.resultSet.close(); this.verify(); } /** * @see java.sql.ResultSet#deleteRow() */ @Override public void deleteRow() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement.getConnection()).andReturn(this.connection); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resultSet1.deleteRow(); this.resultSet2.deleteRow(); this.replay(); this.resultSet.deleteRow(); this.verify(); } @DataProvider(name = "string") Object[][] stringProvider() { return new Object[][] { new Object[] { "" } }; } @Test(dataProvider = "string") public void testFindColumn(String name) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.findColumn(name)).andReturn(1); this.replay(); int result = this.findColumn(name); this.verify(); assert result == 1 : result; } /** * @see java.sql.ResultSet#findColumn(java.lang.String) */ @Override public int findColumn(String name) throws SQLException { return this.resultSet.findColumn(name); } public void testFirst() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.first()).andReturn(true); EasyMock.expect(this.resultSet2.first()).andReturn(true); this.replay(); boolean result = this.first(); this.verify(); assert result; } /** * @see java.sql.ResultSet#first() */ @Override public boolean first() throws SQLException { return this.resultSet.first(); } @Test(dataProvider = "int") public void testGetArray(int index) throws SQLException { Array array = EasyMock.createMock(Array.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getArray(index)).andReturn(array); this.replay(); Array result = this.getArray(index); this.verify(); assert array == result; } /** * @see java.sql.ResultSet#getArray(int) */ @Override public Array getArray(int index) throws SQLException { return this.resultSet.getArray(index); } @Test(dataProvider = "string") public void testGetArray(String name) throws SQLException { Array array = EasyMock.createMock(Array.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getArray(name)).andReturn(array); this.replay(); Array result = this.getArray(name); this.verify(); assert array == result; } /** * @see java.sql.ResultSet#getArray(java.lang.String) */ @Override public Array getArray(String name) throws SQLException { return this.resultSet.getArray(name); } @Test(dataProvider = "int") public void testGetAsciiStream(int index) throws SQLException { InputStream inputStream = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getAsciiStream(index)).andReturn(inputStream); this.replay(); InputStream result = this.getAsciiStream(index); this.verify(); assert inputStream == result; } /** * @see java.sql.ResultSet#getAsciiStream(int) */ @Override public InputStream getAsciiStream(int index) throws SQLException { return this.resultSet.getAsciiStream(index); } @Test(dataProvider = "string") public void testGetAsciiStream(String name) throws SQLException { InputStream inputStream = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getAsciiStream(name)).andReturn(inputStream); this.replay(); InputStream result = this.getAsciiStream(name); this.verify(); assert inputStream == result; } /** * @see java.sql.ResultSet#getAsciiStream(java.lang.String) */ @Override public InputStream getAsciiStream(String name) throws SQLException { return this.resultSet.getAsciiStream(name); } @Test(dataProvider = "int") public void testGetBigDecimal(int index) throws SQLException { BigDecimal decimal = new BigDecimal(1.0); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBigDecimal(index)).andReturn(decimal); this.replay(); BigDecimal result = this.getBigDecimal(index); this.verify(); assert decimal == result; } /** * @see java.sql.ResultSet#getBigDecimal(int) */ @Override public BigDecimal getBigDecimal(int index) throws SQLException { return this.resultSet.getBigDecimal(index); } @Test(dataProvider = "string") public void testGetBigDecimal(String name) throws SQLException { BigDecimal decimal = new BigDecimal(1.0); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBigDecimal(name)).andReturn(decimal); this.replay(); BigDecimal result = this.getBigDecimal(name); this.verify(); assert decimal == result; } /** * @see java.sql.ResultSet#getBigDecimal(java.lang.String) */ @Override public BigDecimal getBigDecimal(String name) throws SQLException { return this.resultSet.getBigDecimal(name); } @DataProvider(name = "int-int") Object[][] intIntProvider() { return new Object[][] { new Object[] { 1, 1 } }; } @SuppressWarnings("deprecation") @Test(dataProvider = "int-int") public void testGetBigDecimal(int index, int scale) throws SQLException { BigDecimal decimal = new BigDecimal(1.0); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBigDecimal(index, scale)).andReturn(decimal); this.replay(); BigDecimal result = this.getBigDecimal(index, scale); this.verify(); assert decimal == result; } /** * @see java.sql.ResultSet#getBigDecimal(int, int) */ @Deprecated @Override public BigDecimal getBigDecimal(int index, int scale) throws SQLException { return this.resultSet.getBigDecimal(index, scale); } @DataProvider(name = "string-int") Object[][] stringIntProvider() { return new Object[][] { new Object[] { "", 1 } }; } @SuppressWarnings("deprecation") @Test(dataProvider = "string-int") public void testGetBigDecimal(String name, int scale) throws SQLException { BigDecimal decimal = new BigDecimal(1.0); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBigDecimal(name, scale)).andReturn(decimal); this.replay(); BigDecimal result = this.getBigDecimal(name, scale); this.verify(); assert decimal == result; } /** * @see java.sql.ResultSet#getBigDecimal(java.lang.String, int) */ @Deprecated @Override public BigDecimal getBigDecimal(String name, int scale) throws SQLException { return this.resultSet.getBigDecimal(name, scale); } @Test(dataProvider = "int") public void testGetBinaryStream(int index) throws SQLException { InputStream inputStream = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBinaryStream(index)).andReturn(inputStream); this.replay(); InputStream result = this.getBinaryStream(index); this.verify(); assert inputStream == result; } /** * @see java.sql.ResultSet#getBinaryStream(int) */ @Override public InputStream getBinaryStream(int index) throws SQLException { return this.resultSet.getBinaryStream(index); } @Test(dataProvider = "string") public void testGetBinaryStream(String name) throws SQLException { InputStream inputStream = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBinaryStream(name)).andReturn(inputStream); this.replay(); InputStream result = this.getBinaryStream(name); this.verify(); assert inputStream == result; } /** * @see java.sql.ResultSet#getBinaryStream(java.lang.String) */ @Override public InputStream getBinaryStream(String name) throws SQLException { return this.resultSet.getBinaryStream(name); } @Test(dataProvider = "int") public void testGetBlob(int index) throws SQLException { Blob blob1 = EasyMock.createMock(Blob.class); Blob blob2 = EasyMock.createMock(Blob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.resultSet1.getBlob(index)).andReturn(blob1); EasyMock.expect(this.resultSet2.getBlob(index)).andReturn(blob2); this.replay(); Blob result = this.getBlob(index); this.verify(); assert Proxy.isProxyClass(result.getClass()); BlobInvocationHandler handler = BlobInvocationHandler.class.cast(Proxy.getInvocationHandler(result)); assert handler.getObject(this.database1) == blob1; assert handler.getObject(this.database2) == blob2; } /** * @see java.sql.ResultSet#getBlob(int) */ @Override public Blob getBlob(int index) throws SQLException { return this.resultSet.getBlob(index); } @Test(dataProvider = "string") public void testGetBlob(String name) throws SQLException { Blob blob1 = EasyMock.createMock(Blob.class); Blob blob2 = EasyMock.createMock(Blob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.resultSet1.getBlob(name)).andReturn(blob1); EasyMock.expect(this.resultSet2.getBlob(name)).andReturn(blob2); this.replay(); Blob result = this.getBlob(name); this.verify(); assert Proxy.isProxyClass(result.getClass()); BlobInvocationHandler handler = BlobInvocationHandler.class.cast(Proxy.getInvocationHandler(result)); assert handler.getObject(this.database1) == blob1; assert handler.getObject(this.database2) == blob2; } /** * @see java.sql.ResultSet#getBlob(java.lang.String) */ @Override public Blob getBlob(String name) throws SQLException { return this.resultSet.getBlob(name); } @Test(dataProvider = "int") public void testGetBoolean(int index) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBoolean(index)).andReturn(true); this.replay(); boolean result = this.getBoolean(index); this.verify(); assert result; } /** * @see java.sql.ResultSet#getBoolean(int) */ @Override public boolean getBoolean(int index) throws SQLException { return this.resultSet.getBoolean(index); } @Test(dataProvider = "string") public void testGetBoolean(String name) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBoolean(name)).andReturn(true); this.replay(); boolean result = this.getBoolean(name); this.verify(); assert result; } /** * @see java.sql.ResultSet#getBoolean(java.lang.String) */ @Override public boolean getBoolean(String name) throws SQLException { return this.resultSet.getBoolean(name); } @Test(dataProvider = "int") public void testGetByte(int index) throws SQLException { byte b = Integer.valueOf(1).byteValue(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getByte(index)).andReturn(b); this.replay(); byte result = this.getByte(index); this.verify(); assert b == result; } /** * @see java.sql.ResultSet#getByte(int) */ @Override public byte getByte(int index) throws SQLException { return this.resultSet.getByte(index); } @Test(dataProvider = "string") public void testGetByte(String name) throws SQLException { byte b = Integer.valueOf(1).byteValue(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getByte(name)).andReturn(b); this.replay(); byte result = this.getByte(name); this.verify(); assert b == result; } /** * @see java.sql.ResultSet#getByte(java.lang.String) */ @Override public byte getByte(String name) throws SQLException { return this.resultSet.getByte(name); } @Test(dataProvider = "int") public void testGetBytes(int index) throws SQLException { byte[] bytes = new byte[0]; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBytes(index)).andReturn(bytes); this.replay(); byte[] result = this.getBytes(index); this.verify(); assert bytes == result; } /** * @see java.sql.ResultSet#getBytes(int) */ @Override public byte[] getBytes(int index) throws SQLException { return this.resultSet.getBytes(index); } @Test(dataProvider = "string") public void testGetBytes(String name) throws SQLException { byte[] bytes = new byte[0]; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getBytes(name)).andReturn(bytes); this.replay(); byte[] result = this.getBytes(name); this.verify(); assert bytes == result; } /** * @see java.sql.ResultSet#getBytes(java.lang.String) */ @Override public byte[] getBytes(String name) throws SQLException { return this.resultSet.getBytes(name); } @Test(dataProvider = "int") public void testGetCharacterStream(int index) throws SQLException { Reader reader = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getCharacterStream(index)).andReturn(reader); this.replay(); Reader result = this.getCharacterStream(index); this.verify(); assert result == reader; } /** * @see java.sql.ResultSet#getCharacterStream(int) */ @Override public Reader getCharacterStream(int index) throws SQLException { return this.resultSet.getCharacterStream(index); } @Test(dataProvider = "string") public void testGetCharacterStream(String name) throws SQLException { Reader reader = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getCharacterStream(name)).andReturn(reader); this.replay(); Reader result = this.getCharacterStream(name); this.verify(); assert result == reader; } /** * @see java.sql.ResultSet#getCharacterStream(java.lang.String) */ @Override public Reader getCharacterStream(String name) throws SQLException { return this.resultSet.getCharacterStream(name); } @Test(dataProvider = "int") public void testGetClob(int index) throws SQLException { Clob clob1 = EasyMock.createMock(Clob.class); Clob clob2 = EasyMock.createMock(Clob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.resultSet1.getClob(index)).andReturn(clob1); EasyMock.expect(this.resultSet2.getClob(index)).andReturn(clob2); this.replay(); Clob result = this.getClob(index); this.verify(); assert Proxy.isProxyClass(result.getClass()); ClobInvocationHandler handler = ClobInvocationHandler.class.cast(Proxy.getInvocationHandler(result)); assert handler.getObject(this.database1) == clob1; assert handler.getObject(this.database2) == clob2; } /** * @see java.sql.ResultSet#getClob(int) */ @Override public Clob getClob(int index) throws SQLException { return this.resultSet.getClob(index); } @Test(dataProvider = "string") public void testGetClob(String name) throws SQLException { Clob clob1 = EasyMock.createMock(Clob.class); Clob clob2 = EasyMock.createMock(Clob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.resultSet1.getClob(name)).andReturn(clob1); EasyMock.expect(this.resultSet2.getClob(name)).andReturn(clob2); this.replay(); Clob result = this.getClob(name); this.verify(); assert Proxy.isProxyClass(result.getClass()); ClobInvocationHandler handler = ClobInvocationHandler.class.cast(Proxy.getInvocationHandler(result)); assert handler.getObject(this.database1) == clob1; assert handler.getObject(this.database2) == clob2; } /** * @see java.sql.ResultSet#getClob(java.lang.String) */ @Override public Clob getClob(String name) throws SQLException { return this.resultSet.getClob(name); } public void testGetConcurrency() throws SQLException { int concurrency = java.sql.ResultSet.CONCUR_READ_ONLY; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getConcurrency()).andReturn(concurrency); this.replay(); int result = this.getConcurrency(); this.verify(); assert result == concurrency; } /** * @see java.sql.ResultSet#getConcurrency() */ @Test public int getConcurrency() throws SQLException { return this.resultSet.getConcurrency(); } public void testGetCursorName() throws SQLException { String cursor = "cursor"; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getCursorName()).andReturn(cursor); this.replay(); String result = this.getCursorName(); this.verify(); assert result == cursor; } /** * @see java.sql.ResultSet#getCursorName() */ @Override public String getCursorName() throws SQLException { return this.resultSet.getCursorName(); } @Test(dataProvider = "int") public void testGetDate(int index) throws SQLException { Date date = new Date(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getDate(index)).andReturn(date); this.replay(); Date result = this.getDate(index); this.verify(); assert result == date; } /** * @see java.sql.ResultSet#getDate(int) */ @Override public Date getDate(int index) throws SQLException { return this.resultSet.getDate(index); } @Test(dataProvider = "string") public void testGetDate(String name) throws SQLException { Date date = new Date(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getDate(name)).andReturn(date); this.replay(); Date result = this.getDate(name); this.verify(); assert result == date; } /** * @see java.sql.ResultSet#getDate(java.lang.String) */ @Override public Date getDate(String name) throws SQLException { return this.resultSet.getDate(name); } @DataProvider(name = "int-calendar") Object[][] intCalendarProvider() { return new Object[][] { new Object[] { 1, Calendar.getInstance() } }; } @Test(dataProvider = "int-calendar") public void testGetDate(int index, Calendar calendar) throws SQLException { Date date = new Date(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getDate(index, calendar)).andReturn(date); this.replay(); Date result = this.resultSet.getDate(index, calendar); this.verify(); assert result == date; } /** * @see java.sql.ResultSet#getDate(int, java.util.Calendar) */ @Override public Date getDate(int index, Calendar calendar) throws SQLException { return this.resultSet.getDate(index, calendar); } @DataProvider(name = "string-calendar") Object[][] stringCalendarProvider() { return new Object[][] { new Object[] { "", Calendar.getInstance() } }; } @Test(dataProvider = "string-calendar") public void testGetDate(String name, Calendar calendar) throws SQLException { Date date = new Date(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getDate(name, calendar)).andReturn(date); this.replay(); Date result = this.getDate(name, calendar); this.verify(); assert result == date; } /** * @see java.sql.ResultSet#getDate(java.lang.String, java.util.Calendar) */ @Override public Date getDate(String name, Calendar calendar) throws SQLException { return this.resultSet.getDate(name, calendar); } @Test(dataProvider = "int") public void testGetDouble(int index) throws SQLException { double d = 1.0; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getDouble(index)).andReturn(d); this.replay(); double result = this.resultSet.getDouble(index); this.verify(); assert result == d; } /** * @see java.sql.ResultSet#getDouble(int) */ @Override public double getDouble(int index) throws SQLException { return this.resultSet.getDouble(index); } @Test(dataProvider = "string") public void testGetDouble(String name) throws SQLException { double d = 1.0; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getDouble(name)).andReturn(d); this.replay(); double result = this.resultSet.getDouble(name); this.verify(); assert result == d; } /** * @see java.sql.ResultSet#getDouble(java.lang.String) */ @Override public double getDouble(String name) throws SQLException { return this.resultSet.getDouble(name); } public void testGetFetchDirection() throws SQLException { int direction = java.sql.ResultSet.FETCH_FORWARD; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getFetchDirection()).andReturn(direction); this.replay(); int result = this.getFetchDirection(); this.verify(); assert result == direction; } /** * @see java.sql.ResultSet#getFetchDirection() */ @Override public int getFetchDirection() throws SQLException { return this.resultSet.getFetchDirection(); } public void testGetFetchSize() throws SQLException { int size = 10; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getFetchSize()).andReturn(size); this.replay(); int result = this.getFetchSize(); this.verify(); assert result == size; } /** * @see java.sql.ResultSet#getFetchSize() */ @Override public int getFetchSize() throws SQLException { return this.resultSet.getFetchSize(); } @Test(dataProvider = "int") public void testGetFloat(int index) throws SQLException { float f = 1.0F; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getFloat(index)).andReturn(f); this.replay(); float result = this.getFloat(index); this.verify(); assert result == f; } /** * @see java.sql.ResultSet#getFloat(int) */ @Override public float getFloat(int index) throws SQLException { return this.resultSet.getFloat(index); } @Test(dataProvider = "string") public void testGetFloat(String name) throws SQLException { float f = 1.0F; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getFloat(name)).andReturn(f); this.replay(); float result = this.getFloat(name); this.verify(); assert result == f; } /** * @see java.sql.ResultSet#getFloat(java.lang.String) */ @Override public float getFloat(String name) throws SQLException { return this.resultSet.getFloat(name); } @Test(dataProvider = "int") public void testGetInt(int index) throws SQLException { int i = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getInt(index)).andReturn(i); this.replay(); int result = this.getInt(index); this.verify(); assert result == i; } /** * @see java.sql.ResultSet#getInt(int) */ @Override public int getInt(int index) throws SQLException { return this.resultSet.getInt(index); } @Test(dataProvider = "string") public void testGetInt(String name) throws SQLException { int i = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getInt(name)).andReturn(i); this.replay(); int result = this.getInt(name); this.verify(); assert result == i; } /** * @see java.sql.ResultSet#getInt(java.lang.String) */ @Override public int getInt(String name) throws SQLException { return this.resultSet.getInt(name); } @Test(dataProvider = "int") public void testGetLong(int index) throws SQLException { long l = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getLong(index)).andReturn(l); this.replay(); long result = this.getLong(index); this.verify(); assert result == l; } /** * @see java.sql.ResultSet#getLong(int) */ @Override public long getLong(int index) throws SQLException { return this.resultSet.getLong(index); } @Test(dataProvider = "string") public void testGetLong(String name) throws SQLException { long l = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getLong(name)).andReturn(l); this.replay(); long result = this.getLong(name); this.verify(); assert result == l; } /** * @see java.sql.ResultSet#getLong(java.lang.String) */ @Override public long getLong(String name) throws SQLException { return this.resultSet.getLong(name); } public void testGetMetaData() throws SQLException { ResultSetMetaData metaData = EasyMock.createMock(ResultSetMetaData.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getMetaData()).andReturn(metaData); this.replay(); ResultSetMetaData result = this.getMetaData(); this.verify(); assert result == metaData; } /** * @see java.sql.ResultSet#getMetaData() */ public ResultSetMetaData getMetaData() throws SQLException { return this.resultSet.getMetaData(); } @Test(dataProvider = "int") public void testGetObject(int index) throws SQLException { Object object = new Object(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getObject(index)).andReturn(object); this.replay(); Object result = this.getObject(index); this.verify(); assert result == object; } /** * @see java.sql.ResultSet#getObject(int) */ @Override public Object getObject(int index) throws SQLException { return this.resultSet.getObject(index); } @Test(dataProvider = "string") public void testGetObject(String name) throws SQLException { Object object = new Object(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getObject(name)).andReturn(object); this.replay(); Object result = this.getObject(name); this.verify(); assert result == object; } /** * @see java.sql.ResultSet#getObject(java.lang.String) */ @Override public Object getObject(String name) throws SQLException { return this.resultSet.getObject(name); } @DataProvider(name = "int-map") Object[][] intMapProvider() { return new Object[][] { new Object[] { 1, Collections.EMPTY_MAP } }; } @Test(dataProvider = "int-map") public void testGetObject(int index, Map> map) throws SQLException { Object object = new Object(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getObject(index, map)).andReturn(object); this.replay(); Object result = this.getObject(index, map); this.verify(); assert result == object; } /** * @see java.sql.ResultSet#getObject(int, java.util.Map) */ @Override public Object getObject(int index, Map> map) throws SQLException { return this.resultSet.getObject(index, map); } @DataProvider(name = "string-map") Object[][] stringMapProvider() { return new Object[][] { new Object[] { "", Collections.EMPTY_MAP } }; } @Test(dataProvider = "string-map") public void testGetObject(String name, Map> map) throws SQLException { Object object = new Object(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getObject(name, map)).andReturn(object); this.replay(); Object result = this.getObject(name, map); this.verify(); assert result == object; } /** * @see java.sql.ResultSet#getObject(java.lang.String, java.util.Map) */ @Override public Object getObject(String name, Map> map) throws SQLException { return this.resultSet.getObject(name, map); } @Test(dataProvider = "int") public void testGetRef(int index) throws SQLException { Ref ref = EasyMock.createMock(Ref.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getRef(index)).andReturn(ref); this.replay(); Ref result = this.getRef(index); this.verify(); assert result == ref; } /** * @see java.sql.ResultSet#getRef(int) */ @Override public Ref getRef(int index) throws SQLException { return this.resultSet.getRef(index); } @Test(dataProvider = "string") public void testRef(String name) throws SQLException { Ref ref = EasyMock.createMock(Ref.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getRef(name)).andReturn(ref); this.replay(); Ref result = this.getRef(name); this.verify(); assert result == ref; } /** * @see java.sql.ResultSet#getRef(java.lang.String) */ @Override public Ref getRef(String name) throws SQLException { return this.resultSet.getRef(name); } public void testGetRow() throws SQLException { int row = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getRow()).andReturn(row); this.replay(); int result = this.getRow(); this.verify(); assert result == row; } /** * @see java.sql.ResultSet#getRow() */ @Override public int getRow() throws SQLException { return this.resultSet.getRow(); } @Test(dataProvider = "int") public void testGetShort(int index) throws SQLException { short s = Integer.valueOf(1).shortValue(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getShort(index)).andReturn(s); this.replay(); short result = this.getShort(index); this.verify(); assert result == s; } /** * @see java.sql.ResultSet#getShort(int) */ @Override public short getShort(int index) throws SQLException { return this.resultSet.getShort(index); } @Test(dataProvider = "string") public void testGetShort(String name) throws SQLException { short s = Integer.valueOf(1).shortValue(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getShort(name)).andReturn(s); this.replay(); short result = this.getShort(name); this.verify(); assert result == s; } /** * @see java.sql.ResultSet#getShort(java.lang.String) */ @Override public short getShort(String name) throws SQLException { return this.resultSet.getShort(name); } public void testGetStatement() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.replay(); Statement result = this.getStatement(); this.verify(); assert result == this.statement; } /** * @see java.sql.ResultSet#getStatement() */ @Override public Statement getStatement() throws SQLException { return this.resultSet.getStatement(); } @Test(dataProvider = "int") public void testGetString(int index) throws SQLException { String string = ""; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getString(index)).andReturn(string); this.replay(); String result = this.getString(index); this.verify(); assert result == string; } /** * @see java.sql.ResultSet#getString(int) */ @Override public String getString(int index) throws SQLException { return this.resultSet.getString(index); } @Test(dataProvider = "string") public void testGetString(String name) throws SQLException { String string = ""; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getString(name)).andReturn(string); this.replay(); String result = this.getString(name); this.verify(); assert result == string; } /** * @see java.sql.ResultSet#getString(java.lang.String) */ @Override public String getString(String name) throws SQLException { return this.resultSet.getString(name); } @Test(dataProvider = "int") public void testGetTime(int index) throws SQLException { Time time = new Time(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getTime(index)).andReturn(time); this.replay(); Time result = this.getTime(index); this.verify(); assert result == time; } /** * @see java.sql.ResultSet#getTime(int) */ @Override public Time getTime(int index) throws SQLException { return this.resultSet.getTime(index); } @Test(dataProvider = "string") public void testGetTime(String name) throws SQLException { Time time = new Time(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getTime(name)).andReturn(time); this.replay(); Time result = this.getTime(name); this.verify(); assert result == time; } /** * @see java.sql.ResultSet#getTime(java.lang.String) */ @Override public Time getTime(String name) throws SQLException { return this.resultSet.getTime(name); } @Test(dataProvider = "int-calendar") public void testGetTime(int index, Calendar calendar) throws SQLException { Time time = new Time(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getTime(index, calendar)).andReturn(time); this.replay(); Time result = this.getTime(index, calendar); this.verify(); assert result == time; } /** * @see java.sql.ResultSet#getTime(int, java.util.Calendar) */ @Override public Time getTime(int index, Calendar calendar) throws SQLException { return this.resultSet.getTime(index, calendar); } @Test(dataProvider = "string-calendar") public void testGetTime(String name, Calendar calendar) throws SQLException { Time time = new Time(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getTime(name, calendar)).andReturn(time); this.replay(); Time result = this.getTime(name, calendar); this.verify(); assert result == time; } /** * @see java.sql.ResultSet#getTime(java.lang.String, java.util.Calendar) */ @Override public Time getTime(String name, Calendar calendar) throws SQLException { return this.resultSet.getTime(name, calendar); } @Test(dataProvider = "int") public void testGetTimestamp(int index) throws SQLException { Timestamp timestamp = new Timestamp(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getTimestamp(index)).andReturn(timestamp); this.replay(); Timestamp result = this.getTimestamp(index); this.verify(); assert result == timestamp; } /** * @see java.sql.ResultSet#getTimestamp(int) */ @Override public Timestamp getTimestamp(int index) throws SQLException { return this.resultSet.getTimestamp(index); } @Test(dataProvider = "string") public void testGetTimestamp(String name) throws SQLException { Timestamp timestamp = new Timestamp(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getTimestamp(name)).andReturn(timestamp); this.replay(); Timestamp result = this.getTimestamp(name); this.verify(); assert result == timestamp; } /** * @see java.sql.ResultSet#getTimestamp(java.lang.String) */ @Override public Timestamp getTimestamp(String name) throws SQLException { return this.resultSet.getTimestamp(name); } @Test(dataProvider = "int-calendar") public void testGetTimestamp(int index, Calendar calendar) throws SQLException { Timestamp timestamp = new Timestamp(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getTimestamp(index, calendar)).andReturn(timestamp); this.replay(); Timestamp result = this.getTimestamp(index, calendar); this.verify(); assert result == timestamp; } /** * @see java.sql.ResultSet#getTimestamp(int, java.util.Calendar) */ @Override public Timestamp getTimestamp(int index, Calendar calendar) throws SQLException { return this.resultSet.getTimestamp(index, calendar); } @Test(dataProvider = "string-calendar") public void testGetTimestamp(String name, Calendar calendar) throws SQLException { Timestamp timestamp = new Timestamp(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getTimestamp(name, calendar)).andReturn(timestamp); this.replay(); Timestamp result = this.getTimestamp(name, calendar); this.verify(); assert result == timestamp; } /** * @see java.sql.ResultSet#getTimestamp(java.lang.String, java.util.Calendar) */ @Override public Timestamp getTimestamp(String name, Calendar calendar) throws SQLException { return this.resultSet.getTimestamp(name, calendar); } public void testGetType() throws SQLException { int type = java.sql.ResultSet.TYPE_FORWARD_ONLY; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getType()).andReturn(type); this.replay(); int result = this.getType(); this.verify(); assert result == type; } /** * @see java.sql.ResultSet#getType() */ @Override public int getType() throws SQLException { return this.resultSet.getType(); } @Test(dataProvider = "int") public void testGetURL(int index) throws SQLException { try { URL url = new URL("http://ha-jdbc.sf.net"); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getURL(index)).andReturn(url); this.replay(); URL result = this.getURL(index); this.verify(); assert result == url; } catch (MalformedURLException e) { assert false : e; } } /** * @see java.sql.ResultSet#getURL(int) */ @Override public URL getURL(int index) throws SQLException { return this.resultSet.getURL(index); } @Test(dataProvider = "string") public void testGetURL(String name) throws SQLException { try { URL url = new URL("http://ha-jdbc.sf.net"); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getURL(name)).andReturn(url); this.replay(); URL result = this.getURL(name); this.verify(); assert result == url; } catch (MalformedURLException e) { assert false : e; } } /** * @see java.sql.ResultSet#getURL(java.lang.String) */ @Override public URL getURL(String name) throws SQLException { return this.resultSet.getURL(name); } @SuppressWarnings("deprecation") @Test(dataProvider = "int") public void testGetUnicodeStream(int index) throws SQLException { InputStream inputStream = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getUnicodeStream(index)).andReturn(inputStream); this.replay(); InputStream result = this.getUnicodeStream(index); this.verify(); assert result == inputStream; } /** * @see java.sql.ResultSet#getUnicodeStream(int) */ @Deprecated public InputStream getUnicodeStream(int index) throws SQLException { return this.resultSet.getUnicodeStream(index); } @SuppressWarnings("deprecation") @Test(dataProvider = "string") public void testGetUnicodeStream(String name) throws SQLException { InputStream inputStream = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getUnicodeStream(name)).andReturn(inputStream); this.replay(); InputStream result = this.getUnicodeStream(name); this.verify(); assert result == inputStream; } /** * @see java.sql.ResultSet#getUnicodeStream(java.lang.String) */ @Deprecated public InputStream getUnicodeStream(String name) throws SQLException { return this.resultSet.getUnicodeStream(name); } public void testGetWarnings() throws SQLException { SQLWarning warning = new SQLWarning(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getWarnings()).andReturn(warning); this.replay(); SQLWarning result = this.getWarnings(); this.verify(); assert result == warning; } /** * @see java.sql.ResultSet#getWarnings() */ public SQLWarning getWarnings() throws SQLException { return this.resultSet.getWarnings(); } /** * @see java.sql.ResultSet#insertRow() */ public void insertRow() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement.getConnection()).andReturn(this.connection); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resultSet1.insertRow(); this.resultSet2.insertRow(); this.replay(); this.resultSet.insertRow(); this.verify(); } public void testIsAfterLast() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.isAfterLast()).andReturn(true); this.replay(); boolean result = this.isAfterLast(); this.verify(); assert result; } /** * @see java.sql.ResultSet#isAfterLast() */ public boolean isAfterLast() throws SQLException { return this.resultSet.isAfterLast(); } public void testIsBeforeFirst() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.isBeforeFirst()).andReturn(true); this.replay(); boolean result = this.isBeforeFirst(); this.verify(); assert result; } /** * @see java.sql.ResultSet#isBeforeFirst() */ public boolean isBeforeFirst() throws SQLException { return this.resultSet.isBeforeFirst(); } public void testIsFirst() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.isFirst()).andReturn(true); this.replay(); boolean result = this.isFirst(); this.verify(); assert result; } /** * @see java.sql.ResultSet#isFirst() */ @Test public boolean isFirst() throws SQLException { return this.resultSet.isFirst(); } public void testIsLast() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.isLast()).andReturn(true); this.replay(); boolean result = this.isLast(); this.verify(); assert result; } /** * @see java.sql.ResultSet#isLast() */ @Test public boolean isLast() throws SQLException { return this.resultSet.isLast(); } public void testLast() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.last()).andReturn(true); EasyMock.expect(this.resultSet2.last()).andReturn(true); this.replay(); boolean result = this.resultSet.last(); this.verify(); assert result; } /** * @see java.sql.ResultSet#last() */ public boolean last() throws SQLException { return this.resultSet.last(); } /** * @see java.sql.ResultSet#moveToCurrentRow() */ @Test public void moveToCurrentRow() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.moveToCurrentRow(); this.resultSet2.moveToCurrentRow(); this.replay(); this.resultSet.moveToCurrentRow(); this.verify(); } /** * @see java.sql.ResultSet#moveToInsertRow() */ @Test public void moveToInsertRow() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.moveToInsertRow(); this.resultSet2.moveToInsertRow(); this.replay(); this.resultSet.moveToInsertRow(); this.verify(); } public void testNext() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.next()).andReturn(true); EasyMock.expect(this.resultSet2.next()).andReturn(true); this.replay(); boolean result = this.next(); this.verify(); assert result; } /** * @see java.sql.ResultSet#next() */ public boolean next() throws SQLException { return this.resultSet.next(); } public void testPrevious() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.previous()).andReturn(true); EasyMock.expect(this.resultSet2.previous()).andReturn(true); this.replay(); boolean result = this.previous(); this.verify(); assert result; } /** * @see java.sql.ResultSet#previous() */ public boolean previous() throws SQLException { return this.resultSet.previous(); } /** * @see java.sql.ResultSet#refreshRow() */ @Test public void refreshRow() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resultSet1.refreshRow(); this.resultSet2.refreshRow(); this.replay(); this.resultSet.refreshRow(); this.verify(); } @Test(dataProvider = "int") public void testRelative(int rows) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.relative(rows)).andReturn(true); EasyMock.expect(this.resultSet2.relative(rows)).andReturn(true); this.replay(); boolean result = this.resultSet.relative(rows); this.verify(); assert result; } /** * @see java.sql.ResultSet#relative(int) */ @Override public boolean relative(int rows) throws SQLException { return this.resultSet.relative(rows); } public void testRowDeleted() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.rowDeleted()).andReturn(true); this.replay(); boolean result = this.rowDeleted(); this.verify(); assert result; } /** * @see java.sql.ResultSet#rowDeleted() */ @Override public boolean rowDeleted() throws SQLException { return this.resultSet.rowDeleted(); } public void testRowInserted() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.rowInserted()).andReturn(true); this.replay(); boolean result = this.rowInserted(); this.verify(); assert result; } /** * @see java.sql.ResultSet#rowInserted() */ @Override public boolean rowInserted() throws SQLException { return this.resultSet.rowInserted(); } public void testRowUpdated() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.rowUpdated()).andReturn(true); this.replay(); boolean result = this.rowUpdated(); this.verify(); assert result; } /** * @see java.sql.ResultSet#rowUpdated() */ @Override public boolean rowUpdated() throws SQLException { return this.resultSet.rowUpdated(); } /** * @see java.sql.ResultSet#setFetchDirection(int) */ @Test(dataProvider = "int") public void setFetchDirection(int direction) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.setFetchDirection(direction); this.resultSet2.setFetchDirection(direction); this.replay(); this.resultSet.setFetchDirection(direction); this.verify(); } /** * @see java.sql.ResultSet#setFetchSize(int) */ @Test(dataProvider = "int") public void setFetchSize(int rows) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.setFetchSize(rows); this.resultSet2.setFetchSize(rows); this.replay(); this.resultSet.setFetchSize(rows); this.verify(); } @DataProvider(name = "int-array") Object[][] intArrayProvider() { return new Object[][] { new Object[] { 1, EasyMock.createMock(Array.class) } }; } /** * @see java.sql.ResultSet#updateArray(int, java.sql.Array) */ @Test(dataProvider = "int-array") public void updateArray(int index, Array value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateArray(index, value); this.resultSet2.updateArray(index, value); this.replay(); this.resultSet.updateArray(index, value); this.verify(); } @DataProvider(name = "string-array") Object[][] stringArrayProvider() { return new Object[][] { new Object[] { "", EasyMock.createMock(Array.class) } }; } /** * @see java.sql.ResultSet#updateArray(java.lang.String, java.sql.Array) */ @Test(dataProvider = "string-array") public void updateArray(String name, Array value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateArray(name, value); this.resultSet2.updateArray(name, value); this.replay(); this.resultSet.updateArray(name, value); this.verify(); } @DataProvider(name = "int-inputStream-int") Object[][] intInputStreamIntProvider() { return new Object[][] { new Object[] { 1, new ByteArrayInputStream(new byte[0]), 1 } }; } /** * @see java.sql.ResultSet#updateAsciiStream(int, java.io.InputStream, int) */ @Test(dataProvider = "int-inputStream-int") public void updateAsciiStream(int index, InputStream value, int length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateAsciiStream(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateAsciiStream(index, input2, length); this.replay(); this.resultSet.updateAsciiStream(index, value, length); this.verify(); } @DataProvider(name = "string-inputStream-int") Object[][] stringInputStreamIntProvider() { return new Object[][] { new Object[] { "", new ByteArrayInputStream(new byte[0]), 1 } }; } /** * @see java.sql.ResultSet#updateAsciiStream(java.lang.String, java.io.InputStream, int) */ @Test(dataProvider = "string-inputStream-int") public void updateAsciiStream(String name, InputStream value, int length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateAsciiStream(name, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateAsciiStream(name, input2, length); this.replay(); this.resultSet.updateAsciiStream(name, value, length); this.verify(); } @DataProvider(name = "int-bigDecimal") Object[][] intBigDecimalProvider() { return new Object[][] { new Object[] { 1, new BigDecimal(1.0) } }; } /** * @see java.sql.ResultSet#updateBigDecimal(int, java.math.BigDecimal) */ @Test(dataProvider = "int-bigDecimal") public void updateBigDecimal(int index, BigDecimal value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateBigDecimal(index, value); this.resultSet2.updateBigDecimal(index, value); this.replay(); this.resultSet.updateBigDecimal(index, value); this.verify(); } @DataProvider(name = "string-bigDecimal") Object[][] stringBigDecimalProvider() { return new Object[][] { new Object[] { "", new BigDecimal(1.0) } }; } /** * @see java.sql.ResultSet#updateBigDecimal(java.lang.String, java.math.BigDecimal) */ @Test(dataProvider = "string-bigDecimal") public void updateBigDecimal(String name, BigDecimal value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateBigDecimal(name, value); this.resultSet2.updateBigDecimal(name, value); this.replay(); this.resultSet.updateBigDecimal(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateBinaryStream(int, java.io.InputStream, int) */ @Test(dataProvider = "int-inputStream-int") public void updateBinaryStream(int index, InputStream value, int length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBinaryStream(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBinaryStream(index, input2, length); this.replay(); this.resultSet.updateBinaryStream(index, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateBinaryStream(java.lang.String, java.io.InputStream, int) */ @Test(dataProvider = "string-inputStream-int") public void updateBinaryStream(String name, InputStream value, int length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBinaryStream(name, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBinaryStream(name, input2, length); this.replay(); this.resultSet.updateBinaryStream(name, value, length); this.verify(); } @DataProvider(name = "int-blob") Object[][] intBlobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.blob1); map.put(this.database2, this.blob2); Blob blob = ProxyFactory.createProxy(Blob.class, new BlobInvocationHandler(null, this.handler, null, map)); return new Object[][] { new Object[] { 1, new MockBlob() }, new Object[] { 1, blob } }; } /** * @see java.sql.ResultSet#updateBlob(int, java.sql.Blob) */ @Test(dataProvider = "int-blob") public void updateBlob(int index, Blob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.resultSet1.updateBlob(index, this.blob1); this.resultSet2.updateBlob(index, this.blob2); } else { this.resultSet1.updateBlob(EasyMock.eq(index), EasyMock.isA(SerialBlob.class)); this.resultSet2.updateBlob(EasyMock.eq(index), EasyMock.isA(SerialBlob.class)); } this.replay(); this.resultSet.updateBlob(index, value); this.verify(); } @DataProvider(name = "string-blob") Object[][] stringBlobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.blob1); map.put(this.database2, this.blob2); Blob blob = ProxyFactory.createProxy(Blob.class, new BlobInvocationHandler(null, this.handler, null, map)); return new Object[][] { new Object[] { "", new MockBlob() }, new Object[] { "", blob } }; } /** * @see java.sql.ResultSet#updateBlob(java.lang.String, java.sql.Blob) */ @Test(dataProvider = "string-blob") public void updateBlob(String name, Blob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.resultSet1.updateBlob(name, this.blob1); this.resultSet2.updateBlob(name, this.blob2); } else { this.resultSet1.updateBlob(EasyMock.eq(name), EasyMock.isA(SerialBlob.class)); this.resultSet2.updateBlob(EasyMock.eq(name), EasyMock.isA(SerialBlob.class)); } this.replay(); this.resultSet.updateBlob(name, value); this.verify(); } @DataProvider(name = "int-boolean") Object[][] intBooleanProvider() { return new Object[][] { new Object[] { 1, true } }; } /** * @see java.sql.ResultSet#updateBoolean(int, boolean) */ @Test(dataProvider = "int-boolean") public void updateBoolean(int index, boolean value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateBoolean(index, value); this.resultSet2.updateBoolean(index, value); this.replay(); this.resultSet.updateBoolean(index, value); this.verify(); } @DataProvider(name = "string-boolean") Object[][] stringBooleanProvider() { return new Object[][] { new Object[] { "", true } }; } /** * @see java.sql.ResultSet#updateBoolean(java.lang.String, boolean) */ @Test(dataProvider = "string-boolean") public void updateBoolean(String name, boolean value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateBoolean(name, value); this.resultSet2.updateBoolean(name, value); this.replay(); this.resultSet.updateBoolean(name, value); this.verify(); } @DataProvider(name = "int-byte") Object[][] intByteProvider() { return new Object[][] { new Object[] { 1, Integer.valueOf(1).byteValue() } }; } /** * @see java.sql.ResultSet#updateByte(int, byte) */ @Test(dataProvider = "int-byte") public void updateByte(int index, byte value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateByte(index, value); this.resultSet2.updateByte(index, value); this.replay(); this.resultSet.updateByte(index, value); this.verify(); } @DataProvider(name = "string-byte") Object[][] stringByteProvider() { return new Object[][] { new Object[] { "", Integer.valueOf(1).byteValue() } }; } /** * @see java.sql.ResultSet#updateByte(java.lang.String, byte) */ @Test(dataProvider = "string-byte") public void updateByte(String name, byte value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateByte(name, value); this.resultSet2.updateByte(name, value); this.replay(); this.resultSet.updateByte(name, value); this.verify(); } @DataProvider(name = "int-bytes") Object[][] intBytesProvider() { return new Object[][] { new Object[] { 1, new byte[0] } }; } /** * @see java.sql.ResultSet#updateBytes(int, byte[]) */ @Test(dataProvider = "int-bytes") public void updateBytes(int index, byte[] value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateBytes(index, value); this.resultSet2.updateBytes(index, value); this.replay(); this.resultSet.updateBytes(index, value); this.verify(); } @DataProvider(name = "string-bytes") Object[][] stringBytesProvider() { return new Object[][] { new Object[] { "", new byte[0] } }; } /** * @see java.sql.ResultSet#updateBytes(java.lang.String, byte[]) */ @Test(dataProvider = "string-bytes") public void updateBytes(String name, byte[] value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateBytes(name, value); this.resultSet2.updateBytes(name, value); this.replay(); this.resultSet.updateBytes(name, value); this.verify(); } @DataProvider(name = "int-reader-int") Object[][] intReaderIntProvider() { return new Object[][] { new Object[] { 1, new CharArrayReader(new char[0]), 0 } }; } /** * @see java.sql.ResultSet#updateCharacterStream(int, java.io.Reader, int) */ @Test(dataProvider = "int-reader-int") public void updateCharacterStream(int index, Reader value, int length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateCharacterStream(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateCharacterStream(index, reader2, length); this.replay(); this.resultSet.updateCharacterStream(index, value, length); this.verify(); } @DataProvider(name = "string-reader-int") Object[][] stringReaderIntProvider() { return new Object[][] { new Object[] { "", new CharArrayReader(new char[0]), 0 } }; } /** * @see java.sql.ResultSet#updateCharacterStream(java.lang.String, java.io.Reader, int) */ @Test(dataProvider = "string-reader-int") public void updateCharacterStream(String name, Reader value, int length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateCharacterStream(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateCharacterStream(name, reader2, length); this.replay(); this.resultSet.updateCharacterStream(name, value, length); this.verify(); } @DataProvider(name = "int-clob") Object[][] intClobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.clob1); map.put(this.database2, this.clob2); Clob clob = ProxyFactory.createProxy(Clob.class, new ClobInvocationHandler(null, this.handler, null, map)); return new Object[][] { new Object[] { 1, new MockClob() }, new Object[] { 1, clob } }; } /** * @see java.sql.ResultSet#updateClob(int, java.sql.Clob) */ @Test(dataProvider = "int-clob") public void updateClob(int index, Clob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.resultSet1.updateClob(index, this.clob1); this.resultSet2.updateClob(index, this.clob2); } else { this.resultSet1.updateClob(EasyMock.eq(index), EasyMock.isA(SerialClob.class)); this.resultSet2.updateClob(EasyMock.eq(index), EasyMock.isA(SerialClob.class)); } this.replay(); this.resultSet.updateClob(index, value); this.verify(); } @DataProvider(name = "string-clob") Object[][] stringClobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.clob1); map.put(this.database2, this.clob2); Clob clob = ProxyFactory.createProxy(Clob.class, new ClobInvocationHandler(null, this.handler, null, map)); return new Object[][] { new Object[] { "", new MockClob() }, new Object[] { "", clob } }; } /** * @see java.sql.ResultSet#updateClob(java.lang.String, java.sql.Clob) */ @Test(dataProvider = "string-clob") public void updateClob(String name, Clob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.resultSet1.updateClob(name, this.clob1); this.resultSet2.updateClob(name, this.clob2); } else { this.resultSet1.updateClob(EasyMock.eq(name), EasyMock.isA(SerialClob.class)); this.resultSet2.updateClob(EasyMock.eq(name), EasyMock.isA(SerialClob.class)); } this.replay(); this.resultSet.updateClob(name, value); this.verify(); } @DataProvider(name = "int-date") Object[][] intDateProvider() { return new Object[][] { new Object[] { 1, new Date(System.currentTimeMillis()) } }; } /** * @see java.sql.ResultSet#updateDate(int, java.sql.Date) */ @Test(dataProvider = "int-date") public void updateDate(int index, Date value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateDate(index, value); this.resultSet2.updateDate(index, value); this.replay(); this.resultSet.updateDate(index, value); this.verify(); } @DataProvider(name = "string-date") Object[][] stringDateProvider() { return new Object[][] { new Object[] { "", new Date(System.currentTimeMillis()) } }; } /** * @see java.sql.ResultSet#updateDate(java.lang.String, java.sql.Date) */ @Test(dataProvider = "string-date") public void updateDate(String name, Date value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateDate(name, value); this.resultSet2.updateDate(name, value); this.replay(); this.resultSet.updateDate(name, value); this.verify(); } @DataProvider(name = "int-double") Object[][] intDoubleProvider() { return new Object[][] { new Object[] { 1, 1.0 } }; } /** * @see java.sql.ResultSet#updateDouble(int, double) */ @Test(dataProvider = "int-double") public void updateDouble(int index, double value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateDouble(index, value); this.resultSet2.updateDouble(index, value); this.replay(); this.resultSet.updateDouble(index, value); this.verify(); } @DataProvider(name = "string-double") Object[][] stringDoubleProvider() { return new Object[][] { new Object[] { "", 1.0 } }; } /** * @see java.sql.ResultSet#updateDouble(java.lang.String, double) */ @Test(dataProvider = "string-double") public void updateDouble(String name, double value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateDouble(name, value); this.resultSet2.updateDouble(name, value); this.replay(); this.resultSet.updateDouble(name, value); this.verify(); } @DataProvider(name = "int-float") Object[][] intFloatProvider() { return new Object[][] { new Object[] { 1, 1.0F } }; } /** * @see java.sql.ResultSet#updateFloat(int, float) */ @Test(dataProvider = "int-float") public void updateFloat(int index, float value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateFloat(index, value); this.resultSet2.updateFloat(index, value); this.replay(); this.resultSet.updateFloat(index, value); this.verify(); } @DataProvider(name = "string-float") Object[][] stringFloatProvider() { return new Object[][] { new Object[] { "", 1.0F } }; } /** * @see java.sql.ResultSet#updateFloat(java.lang.String, float) */ @Test(dataProvider = "string-float") public void updateFloat(String name, float value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateFloat(name, value); this.resultSet2.updateFloat(name, value); this.replay(); this.resultSet.updateFloat(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateInt(int, int) */ @Test(dataProvider = "int-int") public void updateInt(int index, int value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateInt(index, value); this.resultSet2.updateInt(index, value); this.replay(); this.resultSet.updateInt(index, value); this.verify(); } /** * @see java.sql.ResultSet#updateInt(java.lang.String, int) */ @Test(dataProvider = "string-int") public void updateInt(String name, int value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateInt(name, value); this.resultSet2.updateInt(name, value); this.replay(); this.resultSet.updateInt(name, value); this.verify(); } @DataProvider(name = "int-long") Object[][] intLongProvider() { return new Object[][] { new Object[] { 1, 1L } }; } /** * @see java.sql.ResultSet#updateLong(int, long) */ @Test(dataProvider = "int-long") public void updateLong(int index, long value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateLong(index, value); this.resultSet2.updateLong(index, value); this.replay(); this.resultSet.updateLong(index, value); this.verify(); } @DataProvider(name = "string-long") Object[][] stringLongProvider() { return new Object[][] { new Object[] { "", 1L } }; } /** * @see java.sql.ResultSet#updateLong(java.lang.String, long) */ @Test(dataProvider = "string-long") public void updateLong(String name, long value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateLong(name, value); this.resultSet2.updateLong(name, value); this.replay(); this.resultSet.updateLong(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateNull(int) */ @Test(dataProvider = "int") public void updateNull(int index) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateNull(index); this.resultSet2.updateNull(index); this.replay(); this.resultSet.updateNull(index); this.verify(); } /** * @see java.sql.ResultSet#updateNull(java.lang.String) */ @Test(dataProvider = "string") public void updateNull(String name) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateNull(name); this.resultSet2.updateNull(name); this.replay(); this.resultSet.updateNull(name); this.verify(); } @DataProvider(name = "int-object") Object[][] intObjectProvider() { return new Object[][] { new Object[] { 1, new Object() } }; } /** * @see java.sql.ResultSet#updateObject(int, java.lang.Object) */ @Test(dataProvider = "int-object") public void updateObject(int index, Object value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateObject(index, value); this.resultSet2.updateObject(index, value); this.replay(); this.resultSet.updateObject(index, value); this.verify(); } @DataProvider(name = "string-object") Object[][] stringObjectProvider() { return new Object[][] { new Object[] { "", new Object() } }; } /** * @see java.sql.ResultSet#updateObject(java.lang.String, java.lang.Object) */ @Test(dataProvider = "string-object") public void updateObject(String name, Object value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateObject(name, value); this.resultSet2.updateObject(name, value); this.replay(); this.resultSet.updateObject(name, value); this.verify(); } @DataProvider(name = "int-object-int") Object[][] intObjectIntProvider() { return new Object[][] { new Object[] { 1, new Object(), 1 } }; } /** * @see java.sql.ResultSet#updateObject(int, java.lang.Object, int) */ @Test(dataProvider = "int-object-int") public void updateObject(int index, Object value, int scale) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateObject(index, value, scale); this.resultSet2.updateObject(index, value, scale); this.replay(); this.resultSet.updateObject(index, value, scale); this.verify(); } @DataProvider(name = "string-object-int") Object[][] stringObjectIntProvider() { return new Object[][] { new Object[] { "", new Object(), 1 } }; } /** * @see java.sql.ResultSet#updateObject(java.lang.String, java.lang.Object, int) */ @Test(dataProvider = "string-object-int") public void updateObject(String name, Object value, int scale) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateObject(name, value, scale); this.resultSet2.updateObject(name, value, scale); this.replay(); this.resultSet.updateObject(name, value, scale); this.verify(); } @DataProvider(name = "int-ref") Object[][] intRefProvider() { return new Object[][] { new Object[] { 1, EasyMock.createMock(Ref.class) } }; } /** * @see java.sql.ResultSet#updateRef(int, java.sql.Ref) */ @Test(dataProvider = "int-ref") public void updateRef(int index, Ref value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateRef(index, value); this.resultSet2.updateRef(index, value); this.replay(); this.resultSet.updateRef(index, value); this.verify(); } @DataProvider(name = "string-ref") Object[][] stringRefProvider() { return new Object[][] { new Object[] { "", EasyMock.createMock(Ref.class) } }; } /** * @see java.sql.ResultSet#updateRef(java.lang.String, java.sql.Ref) */ @Test(dataProvider = "string-ref") public void updateRef(String name, Ref value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateRef(name, value); this.resultSet2.updateRef(name, value); this.replay(); this.resultSet.updateRef(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateRow() */ @Test public void updateRow() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement.getConnection()).andReturn(this.connection); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resultSet1.updateRow(); this.resultSet2.updateRow(); this.replay(); this.resultSet.updateRow(); this.verify(); } @DataProvider(name = "int-short") Object[][] intShortProvider() { return new Object[][] { new Object[] { 1, Integer.valueOf(1).shortValue() } }; } /** * @see java.sql.ResultSet#updateShort(int, short) */ @Test(dataProvider = "int-short") public void updateShort(int index, short value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateShort(index, value); this.resultSet2.updateShort(index, value); this.replay(); this.resultSet.updateShort(index, value); this.verify(); } @DataProvider(name = "string-short") Object[][] stringShortProvider() { return new Object[][] { new Object[] { "", Integer.valueOf(1).shortValue() } }; } /** * @see java.sql.ResultSet#updateShort(java.lang.String, short) */ @Test(dataProvider = "string-short") public void updateShort(String name, short value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateShort(name, value); this.resultSet2.updateShort(name, value); this.replay(); this.resultSet.updateShort(name, value); this.verify(); } @DataProvider(name = "int-string") Object[][] intStringProvider() { return new Object[][] { new Object[] { 1, "" } }; } /** * @see java.sql.ResultSet#updateString(int, java.lang.String) */ @Test(dataProvider = "int-string") public void updateString(int index, String value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateString(index, value); this.resultSet2.updateString(index, value); this.replay(); this.resultSet.updateString(index, value); this.verify(); } @DataProvider(name = "string-string") Object[][] stringStringProvider() { return new Object[][] { new Object[] { "", "" } }; } /** * @see java.sql.ResultSet#updateString(java.lang.String, java.lang.String) */ @Test(dataProvider = "string-string") public void updateString(String name, String value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateString(name, value); this.resultSet2.updateString(name, value); this.replay(); this.resultSet.updateString(name, value); this.verify(); } @DataProvider(name = "int-time") Object[][] intTimeProvider() { return new Object[][] { new Object[] { 1, new Time(System.currentTimeMillis()) } }; } /** * @see java.sql.ResultSet#updateTime(int, java.sql.Time) */ @Test(dataProvider = "int-time") public void updateTime(int index, Time value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateTime(index, value); this.resultSet2.updateTime(index, value); this.replay(); this.resultSet.updateTime(index, value); this.verify(); } @DataProvider(name = "string-time") Object[][] stringTimeProvider() { return new Object[][] { new Object[] { "", new Time(System.currentTimeMillis()) } }; } /** * @see java.sql.ResultSet#updateTime(java.lang.String, java.sql.Time) */ @Test(dataProvider = "string-time") public void updateTime(String name, Time value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateTime(name, value); this.resultSet2.updateTime(name, value); this.replay(); this.resultSet.updateTime(name, value); this.verify(); } @DataProvider(name = "int-timestamp") Object[][] intTimestampProvider() { return new Object[][] { new Object[] { 1, new Timestamp(System.currentTimeMillis()) } }; } /** * @see java.sql.ResultSet#updateTimestamp(int, java.sql.Timestamp) */ @Test(dataProvider = "int-timestamp") public void updateTimestamp(int index, Timestamp value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateTimestamp(index, value); this.resultSet2.updateTimestamp(index, value); this.replay(); this.resultSet.updateTimestamp(index, value); this.verify(); } @DataProvider(name = "string-timestamp") Object[][] stringTimestampProvider() { return new Object[][] { new Object[] { "", new Timestamp(System.currentTimeMillis()) } }; } /** * @see java.sql.ResultSet#updateTimestamp(java.lang.String, java.sql.Timestamp) */ @Test(dataProvider = "string-timestamp") public void updateTimestamp(String name, Timestamp value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateTimestamp(name, value); this.resultSet2.updateTimestamp(name, value); this.replay(); this.resultSet.updateTimestamp(name, value); this.verify(); } public void testWasNull() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.wasNull()).andReturn(true); this.replay(); boolean result = this.wasNull(); this.verify(); assert result; } /** * @see java.sql.ResultSet#wasNull() */ @Override public boolean wasNull() throws SQLException { return this.resultSet.wasNull(); } public void testGetHoldability() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getHoldability()).andReturn(1); this.replay(); int result = this.getHoldability(); this.verify(); assert result == 1 : result; } /** * @see java.sql.ResultSet#getHoldability() */ @Override public int getHoldability() throws SQLException { return this.resultSet.getHoldability(); } @Test(dataProvider = "int") public void testGetNCharacterStream(int index) throws SQLException { Reader reader = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getNCharacterStream(index)).andReturn(reader); this.replay(); Reader result = this.getNCharacterStream(index); this.verify(); assert result == reader; } /** * @see java.sql.ResultSet#getNCharacterStream(int) */ @Override public Reader getNCharacterStream(int index) throws SQLException { return this.resultSet.getNCharacterStream(index); } @Test(dataProvider = "string") public void testGetNCharacterStream(String name) throws SQLException { Reader reader = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getNCharacterStream(name)).andReturn(reader); this.replay(); Reader result = this.getNCharacterStream(name); this.verify(); assert result == reader; } /** * @see java.sql.ResultSet#getNCharacterStream(java.lang.String) */ @Override public Reader getNCharacterStream(String name) throws SQLException { return this.resultSet.getNCharacterStream(name); } @Test(dataProvider = "int") public void testGetNClob(int index) throws SQLException { NClob clob1 = EasyMock.createMock(NClob.class); NClob clob2 = EasyMock.createMock(NClob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.resultSet1.getNClob(index)).andReturn(clob1); EasyMock.expect(this.resultSet2.getNClob(index)).andReturn(clob2); this.replay(); NClob result = this.getNClob(index); this.verify(); assert Proxy.isProxyClass(result.getClass()); ClobInvocationHandler handler = ClobInvocationHandler.class.cast(Proxy.getInvocationHandler(result)); assert handler.getObject(this.database1) == clob1; assert handler.getObject(this.database2) == clob2; } /** * @see java.sql.ResultSet#getNClob(int) */ public NClob getNClob(int index) throws SQLException { return this.resultSet.getNClob(index); } @Test(dataProvider = "string") public void testGetNClob(String name) throws SQLException { NClob clob1 = EasyMock.createMock(NClob.class); NClob clob2 = EasyMock.createMock(NClob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.resultSet1.getNClob(name)).andReturn(clob1); EasyMock.expect(this.resultSet2.getNClob(name)).andReturn(clob2); this.replay(); NClob result = this.getNClob(name); this.verify(); assert Proxy.isProxyClass(result.getClass()); ClobInvocationHandler handler = ClobInvocationHandler.class.cast(Proxy.getInvocationHandler(result)); assert handler.getObject(this.database1) == clob1; assert handler.getObject(this.database2) == clob2; } /** * @see java.sql.ResultSet#getNClob(java.lang.String) */ public NClob getNClob(String name) throws SQLException { return this.resultSet.getNClob(name); } @Test(dataProvider = "int") public void testGetNString(int index) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getNString(index)).andReturn(""); this.replay(); String result = this.getNString(index); this.verify(); assert result.equals("") : result; } /** * @see java.sql.ResultSet#getNString(int) */ @Override public String getNString(int index) throws SQLException { return this.resultSet.getNString(index); } @Test(dataProvider = "string") public void testGetNString(String name) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getNString(name)).andReturn(""); this.replay(); String result = this.getNString(name); this.verify(); assert result.equals("") : result; } /** * @see java.sql.ResultSet#getNString(java.lang.String) */ @Override public String getNString(String name) throws SQLException { return this.resultSet.getNString(name); } @Test(dataProvider = "int") public void testGetRowId(int index) throws SQLException { RowId rowId = EasyMock.createMock(RowId.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getRowId(index)).andReturn(rowId); this.replay(); RowId result = this.getRowId(index); this.verify(); assert result == rowId; } /** * @see java.sql.ResultSet#getRowId(int) */ @Override public RowId getRowId(int index) throws SQLException { return this.resultSet.getRowId(index); } @Test(dataProvider = "string") public void testGetRowId(String name) throws SQLException { RowId rowId = EasyMock.createMock(RowId.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getRowId(name)).andReturn(rowId); this.replay(); RowId result = this.getRowId(name); this.verify(); assert result == rowId; } /** * @see java.sql.ResultSet#getRowId(java.lang.String) */ @Override public RowId getRowId(String name) throws SQLException { return this.resultSet.getRowId(name); } @Test(dataProvider = "int") public void testGetSQLXML(int index) throws SQLException { SQLXML xml = EasyMock.createMock(SQLXML.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getSQLXML(index)).andReturn(xml); this.replay(); SQLXML result = this.getSQLXML(index); this.verify(); assert result == xml; } /** * @see java.sql.ResultSet#getSQLXML(int) */ @Override public SQLXML getSQLXML(int index) throws SQLException { return this.resultSet.getSQLXML(index); } @Test(dataProvider = "string") public void testGetSQLXML(String name) throws SQLException { SQLXML xml = EasyMock.createMock(SQLXML.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.getSQLXML(name)).andReturn(xml); this.replay(); SQLXML result = this.getSQLXML(name); this.verify(); assert result == xml; } /** * @see java.sql.ResultSet#getSQLXML(java.lang.String) */ @Override public SQLXML getSQLXML(String name) throws SQLException { return this.resultSet.getSQLXML(name); } public void testIsClosed() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.isClosed()).andReturn(true); this.replay(); boolean result = this.isClosed(); this.verify(); assert result; } /** * @see java.sql.ResultSet#isClosed() */ @Override public boolean isClosed() throws SQLException { return this.resultSet.isClosed(); } @DataProvider(name = "int-inputStream") Object[][] intInputStreamProvider() { return new Object[][] { new Object[] { 1, new ByteArrayInputStream(new byte[0]) } }; } /** * @see java.sql.ResultSet#updateAsciiStream(int, java.io.InputStream) */ @Test(dataProvider = "int-inputStream") public void updateAsciiStream(int index, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateAsciiStream(index, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateAsciiStream(index, input2); this.replay(); this.resultSet.updateAsciiStream(index, value); this.verify(); } @DataProvider(name = "string-inputStream") Object[][] stringInputStreamProvider() { return new Object[][] { new Object[] { "", new ByteArrayInputStream(new byte[0]) } }; } /** * @see java.sql.ResultSet#updateAsciiStream(java.lang.String, java.io.InputStream) */ @Test(dataProvider = "string-inputStream") public void updateAsciiStream(String name, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateAsciiStream(name, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateAsciiStream(name, input2); this.replay(); this.resultSet.updateAsciiStream(name, value); this.verify(); } @DataProvider(name = "int-inputStream-long") Object[][] intInputStreamLongProvider() { return new Object[][] { new Object[] { 1, new ByteArrayInputStream(new byte[0]), 1L } }; } /** * @see java.sql.ResultSet#updateAsciiStream(int, java.io.InputStream, long) */ @Test(dataProvider = "int-inputStream-long") public void updateAsciiStream(int index, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateAsciiStream(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateAsciiStream(index, input2, length); this.replay(); this.resultSet.updateAsciiStream(index, value, length); this.verify(); } @DataProvider(name = "string-inputStream-long") Object[][] stringInputStreamLongProvider() { return new Object[][] { new Object[] { "", new ByteArrayInputStream(new byte[0]), 1L } }; } /** * @see java.sql.ResultSet#updateAsciiStream(java.lang.String, java.io.InputStream, long) */ @Test(dataProvider = "string-inputStream-long") public void updateAsciiStream(String name, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateAsciiStream(name, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateAsciiStream(name, input2, length); this.replay(); this.resultSet.updateAsciiStream(name, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateBinaryStream(int, java.io.InputStream) */ @Test(dataProvider = "int-inputStream") public void updateBinaryStream(int index, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBinaryStream(index, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBinaryStream(index, input2); this.replay(); this.resultSet.updateBinaryStream(index, value); this.verify(); } /** * @see java.sql.ResultSet#updateBinaryStream(java.lang.String, java.io.InputStream) */ @Test(dataProvider = "string-inputStream") public void updateBinaryStream(String name, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBinaryStream(name, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBinaryStream(name, input2); this.replay(); this.resultSet.updateBinaryStream(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateBinaryStream(int, java.io.InputStream, long) */ @Test(dataProvider = "int-inputStream-long") public void updateBinaryStream(int index, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBinaryStream(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBinaryStream(index, input2, length); this.replay(); this.resultSet.updateBinaryStream(index, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateBinaryStream(java.lang.String, java.io.InputStream, long) */ @Test(dataProvider = "string-inputStream-long") public void updateBinaryStream(String name, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBinaryStream(name, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBinaryStream(name, input2, length); this.replay(); this.resultSet.updateBinaryStream(name, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateBlob(int, java.io.InputStream) */ @Test(dataProvider = "int-inputStream") public void updateBlob(int index, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBlob(index, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBlob(index, input2); this.replay(); this.resultSet.updateBlob(index, value); this.verify(); } /** * @see java.sql.ResultSet#updateBlob(java.lang.String, java.io.InputStream) */ @Test(dataProvider = "string-inputStream") public void updateBlob(String name, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBlob(name, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBlob(name, input2); this.replay(); this.resultSet.updateBlob(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateBlob(int, java.io.InputStream, long) */ @Test(dataProvider = "int-inputStream-long") public void updateBlob(int index, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBlob(index, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBlob(index, input2, length); this.replay(); this.resultSet.updateBlob(index, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateBlob(java.lang.String, java.io.InputStream, long) */ @Test(dataProvider = "string-inputStream-long") public void updateBlob(String name, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.resultSet1.updateBlob(name, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.resultSet2.updateBlob(name, input2, length); this.replay(); this.resultSet.updateBlob(name, value, length); this.verify(); } @DataProvider(name = "int-reader") Object[][] intReaderProvider() { return new Object[][] { new Object[] { 1, new StringReader("") } }; } /** * @see java.sql.ResultSet#updateCharacterStream(int, java.io.Reader) */ @Test(dataProvider = "int-reader") public void updateCharacterStream(int index, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateCharacterStream(index, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateCharacterStream(index, reader2); this.replay(); this.resultSet.updateCharacterStream(index, value); this.verify(); } @DataProvider(name = "string-reader") Object[][] stringReaderProvider() { return new Object[][] { new Object[] { "", new StringReader("") } }; } /** * @see java.sql.ResultSet#updateCharacterStream(java.lang.String, java.io.Reader) */ @Test(dataProvider = "string-reader") public void updateCharacterStream(String name, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateCharacterStream(name, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateCharacterStream(name, reader2); this.replay(); this.resultSet.updateCharacterStream(name, value); this.verify(); } @DataProvider(name = "int-reader-long") Object[][] intReaderLongProvider() { return new Object[][] { new Object[] { 1, new StringReader(""), 1L } }; } /** * @see java.sql.ResultSet#updateCharacterStream(int, java.io.Reader, long) */ @Test(dataProvider = "int-reader-long") public void updateCharacterStream(int index, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateCharacterStream(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateCharacterStream(index, reader2, length); this.replay(); this.resultSet.updateCharacterStream(index, value, length); this.verify(); } @DataProvider(name = "string-reader-long") Object[][] stringReaderLongProvider() { return new Object[][] { new Object[] { "", new StringReader(""), 1L } }; } /** * @see java.sql.ResultSet#updateCharacterStream(java.lang.String, java.io.Reader, long) */ @Test(dataProvider = "string-reader-long") public void updateCharacterStream(String name, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateCharacterStream(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateCharacterStream(name, reader2, length); this.replay(); this.resultSet.updateCharacterStream(name, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateClob(int, java.io.Reader) */ @Test(dataProvider = "int-reader") public void updateClob(int index, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateClob(index, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateClob(index, reader2); this.replay(); this.resultSet.updateClob(index, value); this.verify(); } /** * @see java.sql.ResultSet#updateClob(java.lang.String, java.io.Reader) */ @Test(dataProvider = "string-reader") public void updateClob(String name, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateClob(name, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateClob(name, reader2); this.replay(); this.resultSet.updateClob(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateClob(int, java.io.Reader, long) */ @Test(dataProvider = "int-reader-long") public void updateClob(int index, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateClob(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateClob(index, reader2, length); this.replay(); this.resultSet.updateClob(index, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateClob(java.lang.String, java.io.Reader, long) */ @Test(dataProvider = "string-reader-long") public void updateClob(String name, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateClob(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateClob(name, reader2, length); this.replay(); this.resultSet.updateClob(name, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateNCharacterStream(int, java.io.Reader) */ @Test(dataProvider = "int-reader") public void updateNCharacterStream(int index, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateNCharacterStream(index, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateNCharacterStream(index, reader2); this.replay(); this.resultSet.updateNCharacterStream(index, value); this.verify(); } /** * @see java.sql.ResultSet#updateNCharacterStream(java.lang.String, java.io.Reader) */ @Test(dataProvider = "string-reader") public void updateNCharacterStream(String name, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateNCharacterStream(name, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateNCharacterStream(name, reader2); this.replay(); this.resultSet.updateNCharacterStream(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateNCharacterStream(int, java.io.Reader, long) */ @Test(dataProvider = "int-reader-long") public void updateNCharacterStream(int index, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateNCharacterStream(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateNCharacterStream(index, reader2, length); this.replay(); this.resultSet.updateNCharacterStream(index, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateNCharacterStream(java.lang.String, java.io.Reader, long) */ @Test(dataProvider = "string-reader-long") public void updateNCharacterStream(String name, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateNCharacterStream(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateNCharacterStream(name, reader2, length); this.replay(); this.resultSet.updateNCharacterStream(name, value, length); this.verify(); } @DataProvider(name = "int-nclob") Object[][] intNClobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.nClob1); map.put(this.database2, this.nClob2); NClob clob = ProxyFactory.createProxy(NClob.class, new ClobInvocationHandler(null, this.handler, null, map)); return new Object[][] { new Object[] { 1, new MockClob() }, new Object[] { 1, clob } }; } /** * @see java.sql.ResultSet#updateNClob(int, java.sql.NClob) */ @Test(dataProvider = "int-nclob") public void updateNClob(int index, NClob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.resultSet1.updateNClob(index, this.nClob1); this.resultSet2.updateNClob(index, this.nClob2); } else { this.resultSet1.updateNClob(EasyMock.eq(index), EasyMock.isA(NClob.class)); this.resultSet2.updateNClob(EasyMock.eq(index), EasyMock.isA(NClob.class)); } this.replay(); this.resultSet.updateNClob(index, value); this.verify(); } @DataProvider(name = "string-nclob") Object[][] stringNClobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.nClob1); map.put(this.database2, this.nClob2); this.replay(); NClob clob = ProxyFactory.createProxy(NClob.class, new ClobInvocationHandler(null, this.handler, null, map)); this.verify(); this.reset(); return new Object[][] { new Object[] { "", new MockClob() }, new Object[] { "", clob } }; } /** * @see java.sql.ResultSet#updateNClob(java.lang.String, java.sql.NClob) */ @Test(dataProvider = "string-nclob") public void updateNClob(String name, NClob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.resultSet1.updateNClob(name, this.nClob1); this.resultSet2.updateNClob(name, this.nClob2); } else { this.resultSet1.updateNClob(EasyMock.eq(name), EasyMock.isA(NClob.class)); this.resultSet2.updateNClob(EasyMock.eq(name), EasyMock.isA(NClob.class)); } this.replay(); this.resultSet.updateNClob(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateNClob(int, java.io.Reader) */ @Test(dataProvider = "int-reader") public void updateNClob(int index, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateNClob(index, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateNClob(index, reader2); this.replay(); this.resultSet.updateNClob(index, value); this.verify(); } /** * @see java.sql.ResultSet#updateNClob(java.lang.String, java.io.Reader) */ @Test(dataProvider = "string-reader") public void updateNClob(String name, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateNClob(name, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateNClob(name, reader2); this.replay(); this.resultSet.updateNClob(name, value); this.verify(); } /** * @see java.sql.ResultSet#updateNClob(int, java.io.Reader, long) */ @Test(dataProvider = "int-reader-long") public void updateNClob(int index, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateNClob(index, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateNClob(index, reader2, length); this.replay(); this.resultSet.updateNClob(index, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateNClob(java.lang.String, java.io.Reader, long) */ @Test(dataProvider = "string-reader-long") public void updateNClob(String name, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new StringReader(""); Reader reader2 = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.resultSet1.updateNClob(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.resultSet2.updateNClob(name, reader2, length); this.replay(); this.resultSet.updateNClob(name, value, length); this.verify(); } /** * @see java.sql.ResultSet#updateNString(int, java.lang.String) */ @Test(dataProvider = "int-string") public void updateNString(int index, String value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateNString(index, value); this.resultSet2.updateNString(index, value); this.replay(); this.resultSet.updateNString(index, value); this.verify(); } /** * @see java.sql.ResultSet#updateNString(java.lang.String, java.lang.String) */ @Test(dataProvider = "string-string") public void updateNString(String name, String value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateNString(name, value); this.resultSet2.updateNString(name, value); this.replay(); this.resultSet.updateNString(name, value); this.verify(); } @DataProvider(name = "int-rowid") Object[][] intRowIdProvider() { return new Object[][] { new Object[] { 1, EasyMock.createMock(RowId.class) } }; } /** * @see java.sql.ResultSet#updateRowId(int, java.sql.RowId) */ @Test(dataProvider = "int-rowid") public void updateRowId(int index, RowId value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateRowId(index, value); this.resultSet2.updateRowId(index, value); this.replay(); this.resultSet.updateRowId(index, value); this.verify(); } @DataProvider(name = "string-rowid") Object[][] stringRowIdProvider() { return new Object[][] { new Object[] { "", EasyMock.createMock(RowId.class) } }; } /** * @see java.sql.ResultSet#updateRowId(java.lang.String, java.sql.RowId) */ @Test(dataProvider = "string-rowid") public void updateRowId(String name, RowId value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateRowId(name, value); this.resultSet2.updateRowId(name, value); this.replay(); this.resultSet.updateRowId(name, value); this.verify(); } @DataProvider(name = "int-xml") Object[][] intSQLXMLProvider() { return new Object[][] { new Object[] { 1, EasyMock.createMock(SQLXML.class) } }; } /** * @see java.sql.ResultSet#updateSQLXML(int, java.sql.SQLXML) */ @Test(dataProvider = "int-xml") public void updateSQLXML(int index, SQLXML value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateSQLXML(index, value); this.resultSet2.updateSQLXML(index, value); this.replay(); this.resultSet.updateSQLXML(index, value); this.verify(); } @DataProvider(name = "string-xml") Object[][] stringSQLXMLProvider() { return new Object[][] { new Object[] { "", EasyMock.createMock(SQLXML.class) } }; } /** * @see java.sql.ResultSet#updateSQLXML(java.lang.String, java.sql.SQLXML) */ @Test(dataProvider = "string-xml") public void updateSQLXML(String name, SQLXML value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.resultSet1.updateSQLXML(name, value); this.resultSet2.updateSQLXML(name, value); this.replay(); this.resultSet.updateSQLXML(name, value); this.verify(); } public void testIsWrapperFor() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.isWrapperFor(Object.class)).andReturn(true); this.replay(); boolean result = this.isWrapperFor(Object.class); assert result; } /** * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ @Override public boolean isWrapperFor(Class targetClass) throws SQLException { return this.resultSet.isWrapperFor(targetClass); } public void testUnwrap() throws SQLException { Object object = new Object(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resultSet1.unwrap(Object.class)).andReturn(object); this.replay(); Object result = this.unwrap(Object.class); assert result == object; } /** * @see java.sql.Wrapper#unwrap(java.lang.Class) */ @Override public T unwrap(Class targetClass) throws SQLException { return this.resultSet.unwrap(targetClass); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/MockCommonDataSource.java0000644000175000017500000000325011151703043024473 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.PrintWriter; import java.sql.SQLException; import javax.sql.CommonDataSource; /** * @author Paul Ferraro * */ public abstract class MockCommonDataSource implements CommonDataSource { /** * @see javax.sql.CommonDataSource#getLogWriter() */ @Override public PrintWriter getLogWriter() throws SQLException { return null; } /** * @see javax.sql.CommonDataSource#getLoginTimeout() */ @Override public int getLoginTimeout() throws SQLException { return 0; } /** * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter) */ @Override public void setLogWriter(PrintWriter arg0) throws SQLException { } /** * @see javax.sql.CommonDataSource#setLoginTimeout(int) */ @Override public void setLoginTimeout(int arg0) throws SQLException { } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestDataSourceDatabase.java0000644000175000017500000000551211151703043025000 0ustar moellermoeller/** * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.SQLException; import javax.naming.spi.ObjectFactory; import javax.sql.DataSource; import org.easymock.EasyMock; import org.testng.annotations.Test; /** * Unit test for {@link DataSourceDatabase}. * @author Paul Ferraro * @since 1.1 */ @Test @SuppressWarnings("nls") public class TestDataSourceDatabase extends TestCommonDataSourceDatabase { public TestDataSourceDatabase() { super(DataSource.class); } /** * @see net.sf.hajdbc.sql.TestDatabase#createDatabase(java.lang.String) */ @Override protected DataSourceDatabase createDatabase(String id) { DataSourceDatabase database = new DataSourceDatabase(); database.setId(id); return database; } /** * @see net.sf.hajdbc.sql.TestCommonDataSourceDatabase#mockDataSourceClass() */ @Override protected Class mockDataSourceClass() { return MockDataSource.class; } /** * @see net.sf.hajdbc.sql.TestCommonDataSourceDatabase#objectFactoryClass() */ @Override protected Class objectFactoryClass() { return MockDataSourceFactory.class; } @Override public void testConnect() throws SQLException { DataSource dataSource = EasyMock.createStrictMock(DataSource.class); Connection connection = EasyMock.createMock(Connection.class); EasyMock.expect(dataSource.getConnection()).andReturn(connection); EasyMock.replay(dataSource); Connection result = this.connect(dataSource); EasyMock.verify(dataSource); assert result == connection : result.getClass().getName(); EasyMock.reset(dataSource); this.database.setUser("user"); this.database.setPassword("password"); EasyMock.expect(dataSource.getConnection("user", "password")).andReturn(connection); EasyMock.replay(dataSource); result = this.connect(dataSource); EasyMock.verify(dataSource); assert result == connection : result.getClass().getName(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/MockInitialContextFactory.java0000644000175000017500000001722311151703043025563 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import javax.naming.Binding; import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameClassPair; import javax.naming.NameNotFoundException; import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.Referenceable; import javax.naming.spi.InitialContextFactory; import javax.naming.spi.ObjectFactory; /** * Mock initial context factory that creates mock contexts. * * @author Paul Ferraro * @since 1.1 */ public class MockInitialContextFactory implements InitialContextFactory { private static ThreadLocal threadLocal = new ThreadLocal() { /** * @see java.lang.ThreadLocal#initialValue() */ @Override protected Context initialValue() { return new MockContext(); } }; /** * @see javax.naming.spi.InitialContextFactory#getInitialContext(java.util.Hashtable) */ public Context getInitialContext(Hashtable environment) { return threadLocal.get(); } /** * @author Paul Ferraro * @since 1.1 */ public static class MockContext implements Context { private Map referenceMap = new HashMap(); /** * @see javax.naming.Context#lookup(javax.naming.Name) */ public Object lookup(Name name) throws NamingException { return this.lookup(name.toString()); } /** * @see javax.naming.Context#lookup(java.lang.String) */ public Object lookup(String name) throws NamingException { Reference reference = this.referenceMap.get(name); if (reference == null) { throw new NameNotFoundException(name); } try { ObjectFactory factory = (ObjectFactory) Thread.currentThread().getContextClassLoader().loadClass(reference.getFactoryClassName()).newInstance(); return factory.getObjectInstance(reference, new CompositeName(name), this, null); } catch (Exception e) { NamingException exception = new NamingException(); exception.setRootCause(e); exception.initCause(e); throw exception; } } /** * @see javax.naming.Context#bind(javax.naming.Name, java.lang.Object) */ public void bind(Name name, Object object) throws NamingException { this.bind(name.toString(), object); } /** * @see javax.naming.Context#bind(java.lang.String, java.lang.Object) */ public void bind(String name, Object object) throws NamingException { Reference reference = null; if (Reference.class.isInstance(object)) { reference = (Reference) object; } else if (Referenceable.class.isInstance(object)) { reference = ((Referenceable) object).getReference(); } else { throw new NamingException("Must extend javax.naming.Reference or implement javax.naming.Referenceable"); //$NON-NLS-1$ } this.referenceMap.put(name, reference); } /** * @see javax.naming.Context#rebind(javax.naming.Name, java.lang.Object) */ public void rebind(Name name, Object object) throws NamingException { this.rebind(name.toString(), object); } /** * @see javax.naming.Context#rebind(java.lang.String, java.lang.Object) */ public void rebind(String name, Object object) throws NamingException { this.bind(name, object); } /** * @see javax.naming.Context#unbind(javax.naming.Name) */ public void unbind(Name name) { this.unbind(name.toString()); } /** * @see javax.naming.Context#unbind(java.lang.String) */ public void unbind(String name) { this.referenceMap.remove(name); } /** * @see javax.naming.Context#rename(javax.naming.Name, javax.naming.Name) */ public void rename(Name oldName, Name newName) { this.rename(oldName.toString(), newName.toString()); } /** * @see javax.naming.Context#rename(java.lang.String, java.lang.String) */ public void rename(String oldName, String newName) { this.referenceMap.put(newName, this.referenceMap.remove(oldName)); } /** * @see javax.naming.Context#list(javax.naming.Name) */ public NamingEnumeration list(Name name) { return null; } /** * @see javax.naming.Context#list(java.lang.String) */ public NamingEnumeration list(String name) { return null; } /** * @see javax.naming.Context#listBindings(javax.naming.Name) */ public NamingEnumeration listBindings(Name name) { return null; } /** * @see javax.naming.Context#listBindings(java.lang.String) */ public NamingEnumeration listBindings(String name) { return null; } /** * @see javax.naming.Context#destroySubcontext(javax.naming.Name) */ public void destroySubcontext(Name name) { } /** * @see javax.naming.Context#destroySubcontext(java.lang.String) */ public void destroySubcontext(String name) { } /** * @see javax.naming.Context#createSubcontext(javax.naming.Name) */ public Context createSubcontext(Name name) { return null; } /** * @see javax.naming.Context#createSubcontext(java.lang.String) */ public Context createSubcontext(String name) { return null; } /** * @see javax.naming.Context#lookupLink(javax.naming.Name) */ public Object lookupLink(Name name) { return null; } /** * @see javax.naming.Context#lookupLink(java.lang.String) */ public Object lookupLink(String name) { return null; } /** * @see javax.naming.Context#getNameParser(javax.naming.Name) */ public NameParser getNameParser(Name name) { return null; } /** * @see javax.naming.Context#getNameParser(java.lang.String) */ public NameParser getNameParser(String name) { return null; } /** * @see javax.naming.Context#composeName(javax.naming.Name, javax.naming.Name) */ public Name composeName(Name arg0, Name arg1) { return null; } /** * @see javax.naming.Context#composeName(java.lang.String, java.lang.String) */ public String composeName(String arg0, String arg1) { return null; } /** * @see javax.naming.Context#addToEnvironment(java.lang.String, java.lang.Object) */ public Object addToEnvironment(String arg0, Object arg1) { return null; } /** * @see javax.naming.Context#removeFromEnvironment(java.lang.String) */ public Object removeFromEnvironment(String arg0) { return null; } /** * @see javax.naming.Context#getEnvironment() */ public Hashtable getEnvironment() { return null; } /** * @see javax.naming.Context#close() */ public void close() { this.referenceMap.clear(); } /** * @see javax.naming.Context#getNameInNamespace() */ public String getNameInNamespace() { return null; } } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestCommonDataSourceDatabase.java0000644000175000017500000001030311151703043026143 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import javax.management.DynamicMBean; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.spi.ObjectFactory; import javax.sql.CommonDataSource; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ public abstract class TestCommonDataSourceDatabase, D extends CommonDataSource> extends TestDatabase implements InactiveDataSourceDatabaseMBean { private Class dataSourceClass; protected TestCommonDataSourceDatabase(Class dataSourceClass) { this.dataSourceClass = dataSourceClass; } @Test @Override public void testCreateConnectionFactory() { // Test JNDI-based DataSource this.database.setName("test"); this.database.setProperty(Context.INITIAL_CONTEXT_FACTORY, MockInitialContextFactory.class.getName()); try { Reference reference = new Reference(this.dataSourceClass.getName(), this.objectFactoryClass().getName(), null); Context context = new InitialContext(this.database.getProperties()); context.rebind("test", reference); } catch (NamingException e) { assert false : e; } D dataSource = this.createConnectionFactory(); assert dataSource.getClass().equals(this.mockDataSourceClass()) : dataSource.getClass(); this.database.getProperties().clear(); // Test explicit DataSource creation this.database.setName(this.mockDataSourceClass().getName()); dataSource = this.createConnectionFactory(); assert dataSource.getClass().equals(this.mockDataSourceClass()) : dataSource.getClass(); } protected abstract Class objectFactoryClass(); protected abstract Class mockDataSourceClass(); @Test @Override public void testGetActiveMBean() { DynamicMBean mbean = this.getActiveMBean(); String className = mbean.getMBeanInfo().getClassName(); try { assert ActiveDataSourceDatabaseMBean.class.isAssignableFrom(Class.forName(className)) : className; } catch (ClassNotFoundException e) { assert false : e; } } @Test @Override public void testGetInactiveMBean() { DynamicMBean mbean = this.getInactiveMBean(); String className = mbean.getMBeanInfo().getClassName(); try { assert InactiveDataSourceDatabaseMBean.class.isAssignableFrom(Class.forName(className)) : className; } catch (ClassNotFoundException e) { assert false : e; } } @Test public void testGetName() { String name = this.getName(); assert name == null : name; this.database.setName("name"); name = this.database.getName(); assert name.equals("name") : name; } /** * @see net.sf.hajdbc.sql.ActiveDataSourceDatabaseMBean#getName() */ @Override public final String getName() { return this.database.getName(); } @Test(dataProvider = "string") @Override public final void setName(String name) { this.database.setName(name); String value = this.database.getName(); assert value.equals(name) : value; this.database.clean(); this.database.setName(name); value = this.database.getName(); assert value.equals(name) : value; assert !this.database.isDirty(); this.database.setName(null); assert this.database.isDirty(); value = this.database.getName(); assert value == null : value; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestDatabase.java0000644000175000017500000002740411151703043023031 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import javax.management.DynamicMBean; import net.sf.hajdbc.Database; import org.easymock.EasyMock; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings({ "unchecked", "nls" }) public abstract class TestDatabase, U> implements Database { protected T database; @BeforeMethod() public void init() { this.database = this.createDatabase("1"); } protected abstract T createDatabase(String id); @Test public void testCompareTo() { Database database = EasyMock.createStrictMock(Database.class); EasyMock.expect(database.getId()).andReturn("0"); EasyMock.replay(database); int result = this.compareTo(database); EasyMock.verify(database); assert result > 0 : result; EasyMock.reset(database); EasyMock.expect(database.getId()).andReturn("2"); EasyMock.replay(database); result = this.compareTo(database); EasyMock.verify(database); assert result < 0 : result; EasyMock.reset(database); EasyMock.expect(database.getId()).andReturn("1"); EasyMock.replay(database); result = this.compareTo(database); EasyMock.verify(database); assert result == 0 : result; } /** * @see java.lang.Comparable#compareTo(java.lang.Object) */ @Override public int compareTo(Database database) { return this.database.compareTo(database); } @Test public void testHashCode() { int hashCode = this.database.hashCode(); int expected = this.database.getId().hashCode(); assert hashCode == expected : hashCode; } @Test public void testToString() { String string = this.database.toString(); assert string.equals("1") : string; } /** * @see net.sf.hajdbc.Database#clean() */ @Test public void clean() { this.database.clean(); assert !this.database.isDirty(); this.database.setWeight(1); this.database.clean(); assert !this.database.isDirty(); } @Test public void testIsDirty() { boolean dirty = this.isDirty(); assert dirty; this.database.clean(); dirty = this.isDirty(); assert !dirty; } /** * @see net.sf.hajdbc.Database#isDirty() */ @Override public boolean isDirty() { return this.database.isDirty(); } @DataProvider(name = "string") protected Object[][] stringProvider() { return new Object[][] { new Object[] { "test" } }; } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#removeProperty(java.lang.String) */ @Test(dataProvider = "string") public void removeProperty(String name) { this.database.setProperty(name, "value"); String value = this.database.getProperties().getProperty(name); assert value.equals("value") : value; this.database.clean(); this.database.removeProperty(name); value = this.database.getProperties().getProperty(name); assert value == null; assert this.database.isDirty(); this.database.clean(); this.database.removeProperty(name); assert !this.database.isDirty(); } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setPassword(java.lang.String) */ @Test(dataProvider = "string") public void setPassword(String password) { this.database.setPassword(password); String value = this.database.getPassword(); assert value.equals(password) : value; this.database.clean(); this.database.setPassword(password); value = this.database.getPassword(); assert value.equals(password); assert !this.database.isDirty(); this.database.setPassword(null); assert this.database.isDirty(); value = this.database.getPassword(); assert value == null : value; } @DataProvider(name = "property") protected Object[][] propertyProvider() { return new Object[][] { new Object[] { "name", "value" }, new Object[] { "name", null }, new Object[] { null, "value" }, new Object[] { null, null } }; } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setProperty(java.lang.String, java.lang.String) */ @Test(dataProvider = "property") public void setProperty(String name, String value) { this.database.clean(); boolean accepted = (name != null) && (value != null); try { this.database.setProperty(name, value); assert accepted; String propertyValue = this.database.getProperties().getProperty(name); assert propertyValue.equals(value) : propertyValue; this.database.clean(); this.database.setProperty(name, value); propertyValue = this.database.getProperties().getProperty(name); assert propertyValue.equals(value) : propertyValue; assert !this.database.isDirty(); this.database.setProperty(name, ""); assert this.database.isDirty(); propertyValue = this.database.getProperties().getProperty(name); assert propertyValue.equals("") : propertyValue; } catch (IllegalArgumentException e) { assert !accepted; assert !this.database.isDirty(); } } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setUser(java.lang.String) */ @Test(dataProvider = "string") public void setUser(String user) { this.database.setUser(user); String value = this.database.getUser(); assert value.equals(user) : value; this.database.clean(); this.database.setUser(user); value = this.database.getUser(); assert value.equals(user); assert !this.database.isDirty(); this.database.setUser(null); assert this.database.isDirty(); value = this.database.getUser(); assert value == null : value; } @DataProvider(name = "int") protected Object[][] intProvider() { return new Object[][] { new Object[] { 1 } }; } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setWeight(int) */ @Test(dataProvider = "int") public void setWeight(int weight) { this.database.setWeight(weight); int value = this.database.getWeight(); assert value == weight : value; this.database.clean(); this.database.setWeight(weight); value = this.database.getWeight(); assert value == weight : value; assert !this.database.isDirty(); this.database.setWeight(0); assert this.database.isDirty(); value = this.database.getWeight(); assert value == 0 : value; this.database.clean(); try { this.database.setWeight(-1); assert false; } catch (IllegalArgumentException e) { assert true; } assert !this.database.isDirty(); } @DataProvider(name = "boolean") protected Object[][] booleanProvider() { return new Object[][] { new Object[] { true } }; } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setLocal(boolean) */ @Test(dataProvider = "boolean") public void setLocal(boolean local) { this.database.setLocal(local); boolean value = this.database.isLocal(); assert value == local : value; this.database.clean(); this.database.setLocal(local); value = this.database.isLocal(); assert value == local : value; assert !this.database.isDirty(); this.database.setLocal(false); assert this.database.isDirty(); value = this.database.isLocal(); assert !value; this.database.clean(); } @Test public void testGetId() { String id = this.getId(); assert id.equals("1") : id; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getId() */ @Override public String getId() { return this.database.getId(); } @Test public void testGetPassword() { String password = this.getPassword(); assert password == null : password; this.database.setPassword("password"); password = this.getPassword(); assert password.equals("password") : password; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getPassword() */ @Override public String getPassword() { return this.database.getPassword(); } @Test public void testGetProperties() { Properties properties = this.getProperties(); assert properties.isEmpty() : properties; this.database.setProperty("name", "value"); properties = this.getProperties(); assert properties.size() == 1 : properties.size(); String value = properties.getProperty("name"); assert value.equals("value") : value; this.database.removeProperty("name"); properties = this.getProperties(); assert properties.isEmpty(); } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getProperties() */ @Override public Properties getProperties() { return this.database.getProperties(); } @Test public void testGetUser() { String user = this.getUser(); assert user == null : user; this.database.setUser("user"); user = this.getUser(); assert user.equals("user") : user; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getUser() */ @Override public String getUser() { return this.database.getUser(); } @Test public void testGetWeight() { int weight = this.getWeight(); assert weight == 1 : weight; this.database.setWeight(0); weight = this.getWeight(); assert weight == 0 : weight; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getWeight() */ @Override public int getWeight() { return this.database.getWeight(); } @Test public void testIsLocal() { boolean local = this.isLocal(); assert !local; this.database.setLocal(true); local = this.isLocal(); assert local; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#isLocal() */ @Override public boolean isLocal() { return this.database.isLocal(); } public abstract void testConnect() throws SQLException; /** * @see net.sf.hajdbc.Database#connect(java.lang.Object) */ @Override public Connection connect(U connectionFactory) throws SQLException { return this.database.connect(connectionFactory); } public abstract void testCreateConnectionFactory(); /** * @see net.sf.hajdbc.Database#createConnectionFactory() */ @Override public U createConnectionFactory() { return this.database.createConnectionFactory(); } public abstract void testGetActiveMBean(); /** * @see net.sf.hajdbc.Database#getActiveMBean() */ @Override public DynamicMBean getActiveMBean() { return this.database.getActiveMBean(); } public abstract void testGetInactiveMBean(); /** * @see net.sf.hajdbc.Database#getInactiveMBean() */ @Override public DynamicMBean getInactiveMBean() { return this.database.getInactiveMBean(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/MockDataSourceDatabase.java0000644000175000017500000000360311151703043024751 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.SQLException; import javax.management.DynamicMBean; import javax.sql.DataSource; /** * @author Paul Ferraro */ public class MockDataSourceDatabase extends AbstractDatabase { private DataSource dataSource; public MockDataSourceDatabase(String id, DataSource dataSource) { this.setId(id); this.clean(); this.dataSource = dataSource; } /** * @see net.sf.hajdbc.Database#connect(java.lang.Object) */ @Override public Connection connect(DataSource dataSource) throws SQLException { return dataSource.getConnection(); } /** * @see net.sf.hajdbc.Database#createConnectionFactory() */ @Override public DataSource createConnectionFactory() { return this.dataSource; } /** * @see net.sf.hajdbc.Database#getActiveMBean() */ @Override public DynamicMBean getActiveMBean() { return null; } /** * @see net.sf.hajdbc.Database#getInactiveMBean() */ @Override public DynamicMBean getInactiveMBean() { return null; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestSavepoint.java0000644000175000017500000000723411151703043023274 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.SQLException; import java.sql.Savepoint; import java.util.Map; import java.util.TreeMap; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.MockDatabase; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test @SuppressWarnings({ "unchecked", "nls" }) public class TestSavepoint implements Savepoint { private DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); private Savepoint savepoint1 = EasyMock.createStrictMock(java.sql.Savepoint.class); private Savepoint savepoint2 = EasyMock.createStrictMock(java.sql.Savepoint.class); private SQLProxy parent = EasyMock.createStrictMock(SQLProxy.class); private Database database1 = new MockDatabase("1"); private Database database2 = new MockDatabase("2"); private Savepoint savepoint; @BeforeClass void init() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.savepoint1); map.put(this.database2, this.savepoint2); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(SavepointInvocationHandler.class)); this.replay(); this.savepoint = ProxyFactory.createProxy(Savepoint.class, new SavepointInvocationHandler(null, this.parent, EasyMock.createMock(Invoker.class), map)); this.verify(); this.reset(); } private Object[] objects() { return new Object[] { this.cluster, this.savepoint1, this.savepoint2, this.parent }; } void replay() { EasyMock.replay(this.objects()); } void verify() { EasyMock.verify(this.objects()); } @AfterMethod void reset() { EasyMock.reset(this.objects()); } public void testGetSavepointId() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.savepoint1.getSavepointId()).andReturn(1); this.replay(); int result = this.getSavepointId(); this.verify(); assert result == 1; } /** * @see java.sql.Savepoint#getSavepointId() */ @Override public int getSavepointId() throws SQLException { return this.savepoint.getSavepointId(); } public void testGetSavepointName() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.savepoint1.getSavepointName()).andReturn(""); this.replay(); String result = this.getSavepointName(); this.verify(); assert result.equals(""); } /** * @see java.sql.Savepoint#getSavepointName() */ @Override public String getSavepointName() throws SQLException { return this.savepoint.getSavepointName(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestBlob.java0000644000175000017500000003335411216572312022211 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.sql.Blob; import java.sql.SQLException; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.MockDatabase; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test @SuppressWarnings({ "unchecked", "nls" }) public class TestBlob implements Blob { private Balancer balancer = EasyMock.createStrictMock(Balancer.class); private DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); private Lock readLock = EasyMock.createStrictMock(Lock.class); private Lock writeLock1 = EasyMock.createStrictMock(Lock.class); private Lock writeLock2 = EasyMock.createStrictMock(Lock.class); private LockManager lockManager = EasyMock.createStrictMock(LockManager.class); private Blob blob1 = EasyMock.createStrictMock(java.sql.Blob.class); private Blob blob2 = EasyMock.createStrictMock(java.sql.Blob.class); private SQLProxy parent = EasyMock.createStrictMock(SQLProxy.class); private SQLProxy root = EasyMock.createStrictMock(SQLProxy.class); private Database database1 = new MockDatabase("1"); private Database database2 = new MockDatabase("2"); private Set databaseSet; private ExecutorService executor = Executors.newSingleThreadExecutor(); private Blob blob; private BlobInvocationHandler handler; @BeforeClass void init() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.blob1); map.put(this.database2, this.blob2); this.databaseSet = map.keySet(); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(BlobInvocationHandler.class)); this.replay(); this.handler = new BlobInvocationHandler(new Object(), this.parent, EasyMock.createMock(Invoker.class), map); this.blob = ProxyFactory.createProxy(Blob.class, this.handler); this.verify(); this.reset(); } private Object[] objects() { return new Object[] { this.cluster, this.balancer, this.blob1, this.blob2, this.readLock, this.writeLock1, this.writeLock2, this.lockManager, this.parent, this.root }; } void replay() { EasyMock.replay(this.objects()); } void verify() { EasyMock.verify(this.objects()); } @AfterMethod void reset() { EasyMock.reset(this.objects()); } /** * @see java.sql.Blob#free() */ @Override public void free() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.parent.removeChild(this.handler); this.blob1.free(); this.blob2.free(); this.replay(); this.blob.free(); this.verify(); } public void testGetBinaryStream() throws SQLException { InputStream input = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.blob2.getBinaryStream()).andReturn(input); this.balancer.afterInvocation(this.database2); this.replay(); InputStream result = this.getBinaryStream(); this.verify(); assert result == input; } /** * @see java.sql.Blob#getBinaryStream() */ @Override public InputStream getBinaryStream() throws SQLException { return this.blob.getBinaryStream(); } @DataProvider(name = "long-long") Object[][] longLongProvider() { return new Object[][] { new Object[] { 1L, 1L } }; } @Test(dataProvider = "long-long") public void testGetBinaryStream(long position, long length) throws SQLException { InputStream input = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.blob2.getBinaryStream(position, length)).andReturn(input); this.balancer.afterInvocation(this.database2); this.replay(); InputStream result = this.getBinaryStream(position, length); this.verify(); assert result == input; } /** * @see java.sql.Blob#getBinaryStream(long, long) */ @Override public InputStream getBinaryStream(long position, long length) throws SQLException { return this.blob.getBinaryStream(position, length); } @DataProvider(name = "long-int") Object[][] longIntProvider() { return new Object[][] { new Object[] { 1L, 1 } }; } @Test(dataProvider = "long-int") public void testGetBytes(long position, int length) throws SQLException { byte[] bytes = new byte[0]; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.blob2.getBytes(position, length)).andReturn(bytes); this.balancer.afterInvocation(this.database2); this.replay(); byte[] result = this.getBytes(position, length); this.verify(); assert result == bytes; } /** * @see java.sql.Blob#getBytes(long, int) */ @Override public byte[] getBytes(long position, int length) throws SQLException { return this.blob.getBytes(position, length); } public void testGetLength() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.blob2.length()).andReturn(1L); this.balancer.afterInvocation(this.database2); this.replay(); long result = this.length(); this.verify(); assert result == 1L; } /** * @see java.sql.Blob#length() */ @Override public long length() throws SQLException { return this.blob.length(); } @DataProvider(name = "bytes-long") Object[][] bytesLongProvider() { return new Object[][] { new Object[] { new byte[0], 1L } }; } @Test(dataProvider = "bytes-long") public void testPosition(byte[] pattern, long start) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.blob2.position(pattern, start)).andReturn(1L); this.balancer.afterInvocation(this.database2); this.replay(); long result = this.position(pattern, start); this.verify(); assert result == 1L; } /** * @see java.sql.Blob#position(byte[], long) */ @Override public long position(byte[] pattern, long start) throws SQLException { return this.blob.position(pattern, start); } @DataProvider(name = "blob-long") Object[][] blobLongProvider() { return new Object[][] { new Object[] { EasyMock.createMock(Blob.class), 1L } }; } @Test(dataProvider = "blob-long") public void testPosition(Blob pattern, long start) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.blob2.position(pattern, start)).andReturn(1L); this.balancer.afterInvocation(this.database2); this.replay(); long result = this.position(pattern, start); this.verify(); assert result == 1L; } /** * @see java.sql.Blob#position(java.sql.Blob, long) */ @Override public long position(Blob pattern, long start) throws SQLException { return this.blob.position(pattern, start); } @DataProvider(name = "long") Object[][] longProvider() { return new Object[][] { new Object[] { 1L } }; } @Test(dataProvider = "long") public void testSetBinaryStream(long position) throws SQLException { OutputStream output1 = new ByteArrayOutputStream(); OutputStream output2 = new ByteArrayOutputStream(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.blob1.setBinaryStream(position)).andReturn(output1); EasyMock.expect(this.blob2.setBinaryStream(position)).andReturn(output2); this.replay(); OutputStream result = this.setBinaryStream(position); this.verify(); assert result == output1; } /** * @see java.sql.Blob#setBinaryStream(long) */ @Override public OutputStream setBinaryStream(long position) throws SQLException { return this.blob.setBinaryStream(position); } @DataProvider(name = "long-bytes") Object[][] longBytesProvider() { return new Object[][] { new Object[] { 1L, new byte[0] } }; } @Test(dataProvider = "long-bytes") public void testSetBytes(long position, byte[] bytes) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.blob1.setBytes(position, bytes)).andReturn(1); EasyMock.expect(this.blob2.setBytes(position, bytes)).andReturn(1); this.replay(); int result = this.setBytes(position, bytes); this.verify(); assert result == 1; } /** * @see java.sql.Blob#setBytes(long, byte[]) */ @Override public int setBytes(long position, byte[] bytes) throws SQLException { return this.blob.setBytes(position, bytes); } @DataProvider(name = "long-bytes-int-int") Object[][] longBytesIntIntProvider() { return new Object[][] { new Object[] { 1L, new byte[0], 1, 1 } }; } @Test(dataProvider = "long-bytes-int-int") public void testSetBytes(long position, byte[] bytes, int offset, int length) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.blob1.setBytes(position, bytes, offset, length)).andReturn(1); EasyMock.expect(this.blob2.setBytes(position, bytes, offset, length)).andReturn(1); this.replay(); int result = this.setBytes(position, bytes, offset, length); this.verify(); assert result == 1; } /** * @see java.sql.Blob#setBytes(long, byte[], int, int) */ @Override public int setBytes(long position, byte[] bytes, int offset, int length) throws SQLException { return this.blob.setBytes(position, bytes, offset, length); } /** * @see java.sql.Blob#truncate(long) */ @Test(dataProvider = "long") public void truncate(long position) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.blob1.truncate(position); this.blob2.truncate(position); this.replay(); this.blob.truncate(position); this.verify(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/MockBlob.java0000644000175000017500000000440511151703043022151 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.InputStream; import java.io.OutputStream; import java.sql.Blob; /** * @author Paul Ferraro * */ public class MockBlob implements Blob { /** * @see java.sql.Blob#free() */ public void free() { } /** * @see java.sql.Blob#getBinaryStream() */ public InputStream getBinaryStream() { return null; } /** * @see java.sql.Blob#getBinaryStream(long, long) */ public InputStream getBinaryStream(long arg0, long arg1) { return null; } /** * @see java.sql.Blob#getBytes(long, int) */ public byte[] getBytes(long arg0, int arg1) { return null; } /** * @see java.sql.Blob#length() */ public long length() { return 0; } /** * @see java.sql.Blob#position(byte[], long) */ public long position(byte[] arg0, long arg1) { return 0; } /** * @see java.sql.Blob#position(java.sql.Blob, long) */ public long position(Blob arg0, long arg1) { return 0; } /** * @see java.sql.Blob#setBinaryStream(long) */ public OutputStream setBinaryStream(long arg0) { return null; } /** * @see java.sql.Blob#setBytes(long, byte[]) */ public int setBytes(long arg0, byte[] arg1) { return 0; } /** * @see java.sql.Blob#setBytes(long, byte[], int, int) */ public int setBytes(long arg0, byte[] arg1, int arg2, int arg3) { return 0; } /** * @see java.sql.Blob#truncate(long) */ public void truncate(long arg0) { } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/AbstractTestStatement.java0000644000175000017500000024470311151703043024760 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Statement; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.MockDatabase; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.easymock.IAnswer; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings({ "unchecked", "nls" }) public abstract class AbstractTestStatement implements java.sql.Statement { protected TransactionContext transactionContext = EasyMock.createStrictMock(TransactionContext.class); protected Balancer balancer = EasyMock.createStrictMock(Balancer.class); protected DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); protected FileSupport fileSupport = EasyMock.createStrictMock(FileSupport.class); protected Lock sequenceLock = EasyMock.createStrictMock(Lock.class); protected Lock tableLock = EasyMock.createStrictMock(Lock.class); protected LockManager lockManager = EasyMock.createStrictMock(LockManager.class); protected Dialect dialect = EasyMock.createStrictMock(Dialect.class); protected DatabaseMetaDataCache metaData = EasyMock.createStrictMock(DatabaseMetaDataCache.class); protected DatabaseProperties databaseProperties = EasyMock.createStrictMock(DatabaseProperties.class); protected TableProperties tableProperties = EasyMock.createStrictMock(TableProperties.class); protected ColumnProperties columnProperties = EasyMock.createStrictMock(ColumnProperties.class); protected Connection connection = EasyMock.createStrictMock(Connection.class); protected S statement1 = EasyMock.createStrictMock(this.getStatementClass()); protected S statement2 = EasyMock.createStrictMock(this.getStatementClass()); protected SQLProxy parent = EasyMock.createStrictMock(SQLProxy.class); protected SQLProxy root = EasyMock.createStrictMock(SQLProxy.class); protected Database database1 = new MockDatabase("1"); protected Database database2 = new MockDatabase("2"); protected Set databaseSet; protected ExecutorService executor = Executors.newSingleThreadExecutor(); protected S statement; protected AbstractStatementInvocationHandler handler; protected IAnswer anwser = new IAnswer() { @Override public InvocationStrategy answer() throws Throwable { return (InvocationStrategy) EasyMock.getCurrentArguments()[0]; } }; protected abstract Class getStatementClass(); protected abstract AbstractStatementInvocationHandler getInvocationHandler(Map map) throws Exception; @BeforeClass void init() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.statement1); map.put(this.database2, this.statement2); this.databaseSet = map.keySet(); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.recordConstructor(); this.replay(); this.handler = this.getInvocationHandler(map); this.statement = ProxyFactory.createProxy(this.getStatementClass(), this.handler); this.verify(); this.reset(); } protected void recordConstructor() throws SQLException { this.parent.addChild(EasyMock.isA(StatementInvocationHandler.class)); } private Object[] objects() { return new Object[] { this.cluster, this.balancer, this.connection, this.statement1, this.statement2, this.fileSupport, this.sequenceLock, this.tableLock, this.lockManager, this.parent, this.root, this.dialect, this.metaData, this.databaseProperties, this.tableProperties, this.columnProperties, this.transactionContext }; } void replay() { EasyMock.replay(this.objects()); } void verify() { EasyMock.verify(this.objects()); } @AfterMethod void reset() { EasyMock.reset(this.objects()); } @DataProvider(name = "string") Object[][] stringProvider() { return new Object[][] { new Object[] { "sql" } }; } /** * @see java.sql.Statement#addBatch(java.lang.String) */ @Test(dataProvider = "string") public void addBatch(String sql) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.statement1.addBatch(sql); this.statement2.addBatch(sql); this.replay(); this.statement.addBatch(sql); this.verify(); } /** * @see java.sql.Statement#cancel() */ @Test public void cancel() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.statement1.cancel(); this.statement2.cancel(); this.replay(); this.statement.cancel(); this.verify(); } /** * @see java.sql.Statement#clearBatch() */ @Test public void clearBatch() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.clearBatch(); this.statement2.clearBatch(); this.replay(); this.statement.clearBatch(); this.verify(); } /** * @see java.sql.Statement#clearWarnings() */ @Test public void clearWarnings() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.clearWarnings(); this.statement2.clearWarnings(); this.replay(); this.statement.clearWarnings(); this.verify(); } /** * @see java.sql.Statement#close() */ @Test public void close() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.close(); this.statement2.close(); this.fileSupport.close(); this.parent.removeChild(this.handler); this.replay(); this.statement.close(); this.verify(); } @Test(dataProvider = "string") public void testExecute(String sql) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql)).andReturn(true); EasyMock.expect(this.statement2.execute(sql)).andReturn(true); this.replay(); boolean result = this.execute(sql); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql)).andReturn(true); EasyMock.expect(this.statement2.execute(sql)).andReturn(true); this.sequenceLock.unlock(); this.replay(); result = this.execute(sql); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql)).andReturn(true); EasyMock.expect(this.statement2.execute(sql)).andReturn(true); this.tableLock.unlock(); this.replay(); result = this.execute(sql); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql)).andReturn(true); EasyMock.expect(this.statement2.execute(sql)).andReturn(true); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); result = this.execute(sql); this.verify(); assert result; } /** * @see java.sql.Statement#execute(java.lang.String) */ @Override public boolean execute(String sql) throws SQLException { return this.statement.execute(sql); } @DataProvider(name = "string-int") Object[][] stringIntProvider() { return new Object[][] { new Object[] { "sql", java.sql.Statement.NO_GENERATED_KEYS }, new Object[] { "sql", java.sql.Statement.RETURN_GENERATED_KEYS }, }; } @Test(dataProvider = "string-int") public void testExecute(String sql, int autoGeneratedKeys) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, autoGeneratedKeys)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, autoGeneratedKeys)).andReturn(true); this.replay(); boolean result = this.execute(sql, autoGeneratedKeys); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, autoGeneratedKeys)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, autoGeneratedKeys)).andReturn(true); this.sequenceLock.unlock(); this.replay(); result = this.execute(sql, autoGeneratedKeys); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, autoGeneratedKeys)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, autoGeneratedKeys)).andReturn(true); this.tableLock.unlock(); this.replay(); result = this.execute(sql, autoGeneratedKeys); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, autoGeneratedKeys)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, autoGeneratedKeys)).andReturn(true); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); result = this.execute(sql, autoGeneratedKeys); this.verify(); assert result; } /** * @see java.sql.Statement#execute(java.lang.String, int) */ @Override public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { return this.statement.execute(sql, autoGeneratedKeys); } @DataProvider(name = "string-ints") Object[][] stringIntsProvider() { return new Object[][] { new Object[] { "sql", new int[] { 1 } } }; } @Test(dataProvider = "string-ints") public void testExecute(String sql, int[] columnIndexes) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, columnIndexes)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, columnIndexes)).andReturn(true); this.replay(); boolean result = this.execute(sql, columnIndexes); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, columnIndexes)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, columnIndexes)).andReturn(true); this.sequenceLock.unlock(); this.replay(); result = this.execute(sql, columnIndexes); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, columnIndexes)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, columnIndexes)).andReturn(true); this.tableLock.unlock(); this.replay(); result = this.execute(sql, columnIndexes); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, columnIndexes)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, columnIndexes)).andReturn(true); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); result = this.execute(sql, columnIndexes); this.verify(); assert result; } /** * @see java.sql.Statement#execute(java.lang.String, int[]) */ @Override public boolean execute(String sql, int[] columnIndexes) throws SQLException { return this.statement.execute(sql, columnIndexes); } @DataProvider(name = "string-strings") Object[][] stringStringsProvider() { return new Object[][] { new Object[] { "sql", new String[] { "name" } } }; } @Test(dataProvider = "string-strings") public void testExecute(String sql, String[] columnNames) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, columnNames)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, columnNames)).andReturn(true); this.replay(); boolean result = this.execute(sql, columnNames); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, columnNames)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, columnNames)).andReturn(true); this.sequenceLock.unlock(); this.replay(); result = this.execute(sql, columnNames); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, columnNames)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, columnNames)).andReturn(true); this.tableLock.unlock(); this.replay(); result = this.execute(sql, columnNames); this.verify(); assert result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.execute(sql, columnNames)).andReturn(true); EasyMock.expect(this.statement2.execute(sql, columnNames)).andReturn(true); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); result = this.execute(sql, columnNames); this.verify(); assert result; } /** * @see java.sql.Statement#execute(java.lang.String, java.lang.String[]) */ @Override public boolean execute(String sql, String[] columnNames) throws SQLException { return this.statement.execute(sql, columnNames); } public void testExecuteBatch() throws SQLException { int[] array = new int[0]; this.addBatch("sql"); this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers("sql", null, null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeBatch()).andReturn(array); EasyMock.expect(this.statement2.executeBatch()).andReturn(array); this.replay(); int[] result = this.executeBatch(); this.verify(); assert result == array; this.reset(); this.addBatch("sql"); this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers("sql", "sequence", null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeBatch()).andReturn(array); EasyMock.expect(this.statement2.executeBatch()).andReturn(array); this.sequenceLock.unlock(); this.replay(); result = this.executeBatch(); this.verify(); assert result == array; this.reset(); this.addBatch("sql"); this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers("sql", null, "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeBatch()).andReturn(array); EasyMock.expect(this.statement2.executeBatch()).andReturn(array); this.tableLock.unlock(); this.replay(); result = this.executeBatch(); this.verify(); assert result == array; this.reset(); this.addBatch("sql"); this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers("sql", "sequence", "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeBatch()).andReturn(array); EasyMock.expect(this.statement2.executeBatch()).andReturn(array); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); result = this.executeBatch(); this.verify(); assert result == array; this.reset(); } /** * @see java.sql.Statement#executeBatch() */ @Override public int[] executeBatch() throws SQLException { return this.statement.executeBatch(); } @Test(dataProvider = "string") public void testExecuteQuery(String sql) throws SQLException { ResultSet resultSet1 = EasyMock.createMock(ResultSet.class); ResultSet resultSet2 = EasyMock.createMock(ResultSet.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.isActive()).andReturn(true); // Read-only result set EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_READ_ONLY); this.expectSelectForUpdateCheck(sql, false); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.statement2.executeQuery(sql)).andReturn(resultSet2); this.balancer.afterInvocation(this.database2); this.replay(); ResultSet results = this.executeQuery(sql); this.verify(); assert Proxy.isProxyClass(results.getClass()); assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database2) == resultSet2; this.reset(); EasyMock.makeThreadSafe(this.statement1, true); EasyMock.makeThreadSafe(this.statement2, true); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.isActive()).andReturn(true); // Updatable result set EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_UPDATABLE); this.expectSelectForUpdateCheck(sql, false); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeQuery(sql)).andReturn(resultSet1); EasyMock.expect(this.statement2.executeQuery(sql)).andReturn(resultSet2); this.replay(); results = this.executeQuery(sql); this.verify(); assert Proxy.isProxyClass(results.getClass()); assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database1) == resultSet1; assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database2) == resultSet2; this.reset(); EasyMock.makeThreadSafe(this.statement1, true); EasyMock.makeThreadSafe(this.statement2, true); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_READ_ONLY); // Select-for-update this.expectSelectForUpdateCheck(sql, true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeQuery(sql)).andReturn(resultSet1); EasyMock.expect(this.statement2.executeQuery(sql)).andReturn(resultSet2); this.replay(); results = this.executeQuery(sql); this.verify(); assert Proxy.isProxyClass(results.getClass()); assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database1) == resultSet1; assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database2) == resultSet2; this.reset(); EasyMock.makeThreadSafe(this.statement1, true); EasyMock.makeThreadSafe(this.statement2, true); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", null); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_READ_ONLY); this.expectSelectForUpdateCheck(sql, false); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeQuery(sql)).andReturn(resultSet1); EasyMock.expect(this.statement2.executeQuery(sql)).andReturn(resultSet2); this.sequenceLock.unlock(); this.replay(); results = this.executeQuery(sql); this.verify(); assert Proxy.isProxyClass(results.getClass()); assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database1) == resultSet1; assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database2) == resultSet2; this.reset(); EasyMock.makeThreadSafe(this.statement1, true); EasyMock.makeThreadSafe(this.statement2, true); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, "table"); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_READ_ONLY); this.expectSelectForUpdateCheck(sql, false); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeQuery(sql)).andReturn(resultSet1); EasyMock.expect(this.statement2.executeQuery(sql)).andReturn(resultSet2); this.tableLock.unlock(); this.replay(); results = this.executeQuery(sql); this.verify(); assert Proxy.isProxyClass(results.getClass()); assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database1) == resultSet1; assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database2) == resultSet2; this.reset(); EasyMock.makeThreadSafe(this.statement1, true); EasyMock.makeThreadSafe(this.statement2, true); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", "table"); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_READ_ONLY); this.expectSelectForUpdateCheck(sql, false); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeQuery(sql)).andReturn(resultSet1); EasyMock.expect(this.statement2.executeQuery(sql)).andReturn(resultSet2); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); results = this.executeQuery(sql); this.verify(); assert Proxy.isProxyClass(results.getClass()); assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database1) == resultSet1; assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database2) == resultSet2; } /** * @see java.sql.Statement#executeQuery(java.lang.String) */ @Override public ResultSet executeQuery(String sql) throws SQLException { return this.statement.executeQuery(sql); } @Test(dataProvider = "string") public void testExecuteUpdate(String sql) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql)).andReturn(1); this.replay(); int result = this.executeUpdate(sql); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql)).andReturn(1); this.sequenceLock.unlock(); this.replay(); result = this.executeUpdate(sql); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql)).andReturn(1); this.tableLock.unlock(); this.replay(); result = this.executeUpdate(sql); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql)).andReturn(1); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); result = this.executeUpdate(sql); this.verify(); assert result == 1 : result; } /** * @see java.sql.Statement#executeUpdate(java.lang.String) */ @Override public int executeUpdate(String sql) throws SQLException { return this.statement.executeUpdate(sql); } @Test(dataProvider = "string-int") public void testExecuteUpdate(String sql, int autoGeneratedKeys) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, autoGeneratedKeys)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, autoGeneratedKeys)).andReturn(1); this.replay(); int result = this.executeUpdate(sql, autoGeneratedKeys); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, autoGeneratedKeys)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, autoGeneratedKeys)).andReturn(1); this.sequenceLock.unlock(); this.replay(); result = this.executeUpdate(sql, autoGeneratedKeys); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, autoGeneratedKeys)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, autoGeneratedKeys)).andReturn(1); this.tableLock.unlock(); this.replay(); result = this.executeUpdate(sql, autoGeneratedKeys); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, autoGeneratedKeys)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, autoGeneratedKeys)).andReturn(1); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); result = this.executeUpdate(sql, autoGeneratedKeys); this.verify(); assert result == 1 : result; } /** * @see java.sql.Statement#executeUpdate(java.lang.String, int) */ @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { return this.statement.executeUpdate(sql, autoGeneratedKeys); } @Test(dataProvider = "string-ints") public void testExecuteUpdate(String sql, int[] columnIndexes) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, columnIndexes)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, columnIndexes)).andReturn(1); this.replay(); int result = this.executeUpdate(sql, columnIndexes); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, columnIndexes)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, columnIndexes)).andReturn(1); this.sequenceLock.unlock(); this.replay(); result = this.executeUpdate(sql, columnIndexes); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, columnIndexes)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, columnIndexes)).andReturn(1); this.tableLock.unlock(); this.replay(); result = this.executeUpdate(sql, columnIndexes); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, columnIndexes)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, columnIndexes)).andReturn(1); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); result = this.executeUpdate(sql, columnIndexes); this.verify(); assert result == 1 : result; } /** * @see java.sql.Statement#executeUpdate(java.lang.String, int[]) */ @Override public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { return this.statement.executeUpdate(sql, columnIndexes); } @Test(dataProvider = "string-strings") public void testExecuteUpdate(String sql, String[] columnNames) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, columnNames)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, columnNames)).andReturn(1); this.replay(); int result = this.executeUpdate(sql, columnNames); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", null); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, columnNames)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, columnNames)).andReturn(1); this.sequenceLock.unlock(); this.replay(); result = this.executeUpdate(sql, columnNames); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, null, "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, columnNames)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, columnNames)).andReturn(1); this.tableLock.unlock(); this.replay(); result = this.executeUpdate(sql, columnNames); this.verify(); assert result == 1 : result; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true); this.expectIdentifiers(sql, "sequence", "table"); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.start(EasyMock.isA(InvocationStrategy.class), EasyMock.same(this.connection))).andAnswer(this.anwser); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); this.sequenceLock.lock(); this.tableLock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.executeUpdate(sql, columnNames)).andReturn(1); EasyMock.expect(this.statement2.executeUpdate(sql, columnNames)).andReturn(1); this.sequenceLock.unlock(); this.tableLock.unlock(); this.replay(); result = this.executeUpdate(sql, columnNames); this.verify(); assert result == 1 : result; } /** * @see java.sql.Statement#executeUpdate(java.lang.String, java.lang.String[]) */ @Override public int executeUpdate(String sql, String[] columnNames) throws SQLException { return this.statement.executeUpdate(sql, columnNames); } public void testGetConnection() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.replay(); java.sql.Connection connection = this.getConnection(); this.verify(); assert connection == this.connection; } /** * @see java.sql.Statement#getConnection() */ @Override public java.sql.Connection getConnection() throws SQLException { return this.statement.getConnection(); } public void testGetFetchDirection() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getFetchDirection()).andReturn(ResultSet.FETCH_FORWARD); this.replay(); int result = this.getFetchDirection(); this.verify(); assert result == ResultSet.FETCH_FORWARD : result; } /** * @see java.sql.Statement#getFetchDirection() */ @Override public int getFetchDirection() throws SQLException { return this.statement.getFetchDirection(); } public void testGetFetchSize() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getFetchDirection()).andReturn(1); this.replay(); int result = this.getFetchDirection(); this.verify(); assert result == 1 : result; } /** * @see java.sql.Statement#getFetchSize() */ @Override public int getFetchSize() throws SQLException { return this.statement.getFetchSize(); } public void testGetGeneratedKeys() throws SQLException { ResultSet resultSet = EasyMock.createMock(ResultSet.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getGeneratedKeys()).andReturn(resultSet); this.replay(); ResultSet results = this.getGeneratedKeys(); this.verify(); assert results == resultSet : results; } /** * @see java.sql.Statement#getGeneratedKeys() */ @Override public ResultSet getGeneratedKeys() throws SQLException { return this.statement.getGeneratedKeys(); } public void testGetMaxFieldSize() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getMaxFieldSize()).andReturn(1); this.replay(); int result = this.getMaxFieldSize(); this.verify(); assert result == 1 : result; } /** * @see java.sql.Statement#getMaxFieldSize() */ @Override public int getMaxFieldSize() throws SQLException { return this.statement.getMaxFieldSize(); } public void testGetMaxRows() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getMaxRows()).andReturn(1); this.replay(); int result = this.getMaxRows(); this.verify(); assert result == 1 : result; } /** * @see java.sql.Statement#getMaxRows() */ @Override public int getMaxRows() throws SQLException { return this.statement.getMaxRows(); } public void testGetMoreResults() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.getMoreResults()).andReturn(true); EasyMock.expect(this.statement2.getMoreResults()).andReturn(true); this.replay(); boolean more = this.getMoreResults(); this.verify(); assert more; } /** * @see java.sql.Statement#getMoreResults() */ @Override public boolean getMoreResults() throws SQLException { return this.statement.getMoreResults(); } @DataProvider(name = "current") Object[][] currentProvider() { return new Object[][] { new Object[] { Statement.KEEP_CURRENT_RESULT }, new Object[] { Statement.CLOSE_ALL_RESULTS } }; } @Test(dataProvider = "current") public void testGetMoreResults(int current) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (current == Statement.KEEP_CURRENT_RESULT) { EasyMock.expect(this.statement1.getMoreResults(current)).andReturn(true); EasyMock.expect(this.statement2.getMoreResults(current)).andReturn(true); } else { EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.getMoreResults(current)).andReturn(true); EasyMock.expect(this.statement2.getMoreResults(current)).andReturn(true); } this.replay(); boolean more = this.getMoreResults(current); this.verify(); assert more; } /** * @see java.sql.Statement#getMoreResults(int) */ @Override public boolean getMoreResults(int current) throws SQLException { return this.statement.getMoreResults(current); } public void testGetQueryTimeout() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getQueryTimeout()).andReturn(1); this.replay(); int result = this.getQueryTimeout(); this.verify(); assert result == 1 : result; } /** * @see java.sql.Statement#getQueryTimeout() */ @Override public int getQueryTimeout() throws SQLException { return this.statement.getQueryTimeout(); } public void testGetResultSet() throws SQLException { ResultSet resultSet1 = EasyMock.createMock(ResultSet.class); ResultSet resultSet2 = EasyMock.createMock(ResultSet.class); EasyMock.expect(this.cluster.isActive()).andReturn(true).times(2); // Read-only EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_READ_ONLY); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.statement2.getResultSet()).andReturn(resultSet2); this.balancer.afterInvocation(this.database2); this.replay(); ResultSet results = this.getResultSet(); this.verify(); assert Proxy.isProxyClass(results.getClass()); assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database2) == resultSet2; this.reset(); EasyMock.expect(this.cluster.isActive()).andReturn(true).times(2); // Updatable EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_UPDATABLE); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.statement1.getResultSet()).andReturn(resultSet1); EasyMock.expect(this.statement2.getResultSet()).andReturn(resultSet2); this.replay(); results = this.getResultSet(); this.verify(); assert Proxy.isProxyClass(results.getClass()); assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database1) == resultSet1; assert SQLProxy.class.cast(Proxy.getInvocationHandler(results)).getObject(this.database2) == resultSet2; } /** * @see java.sql.Statement#getResultSet() */ @Override public ResultSet getResultSet() throws SQLException { return this.statement.getResultSet(); } public void testGetResultSetConcurrency() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getResultSetConcurrency()).andReturn(ResultSet.CONCUR_READ_ONLY); this.replay(); int result = this.statement.getResultSetConcurrency(); this.verify(); assert result == ResultSet.CONCUR_READ_ONLY : result; } /** * @see java.sql.Statement#getResultSetConcurrency() */ @Override public int getResultSetConcurrency() throws SQLException { return this.statement.getResultSetConcurrency(); } public void testGetResultSetHoldability() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getResultSetHoldability()).andReturn(ResultSet.CLOSE_CURSORS_AT_COMMIT); this.replay(); int result = this.getResultSetHoldability(); this.verify(); assert result == ResultSet.CLOSE_CURSORS_AT_COMMIT : result; } /** * @see java.sql.Statement#getResultSetHoldability() */ @Override public int getResultSetHoldability() throws SQLException { return this.statement.getResultSetHoldability(); } public void testGetResultType() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getResultSetType()).andReturn(ResultSet.TYPE_FORWARD_ONLY); this.replay(); int result = this.getResultSetType(); this.verify(); assert result == ResultSet.TYPE_FORWARD_ONLY : result; } /** * @see java.sql.Statement#getResultSetType() */ @Override public int getResultSetType() throws SQLException { return this.statement.getResultSetType(); } public void testGetUpdateCount() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getUpdateCount()).andReturn(1); this.replay(); int result = this.getUpdateCount(); this.verify(); assert result == 1 : result; } /** * @see java.sql.Statement#getUpdateCount() */ @Override public int getUpdateCount() throws SQLException { return this.statement.getUpdateCount(); } public void testGetWarnings() throws SQLException { SQLWarning warning = new SQLWarning(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getWarnings()).andReturn(warning); this.replay(); SQLWarning result = this.getWarnings(); this.verify(); assert result == warning : result; } /** * @see java.sql.Statement#getWarnings() */ @Override public SQLWarning getWarnings() throws SQLException { return this.statement.getWarnings(); } /** * @see java.sql.Statement#setCursorName(java.lang.String) */ @Test(dataProvider = "string") public void setCursorName(String name) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setCursorName(name); this.statement2.setCursorName(name); this.replay(); this.statement.setCursorName(name); this.verify(); } @DataProvider(name = "boolean") Object[][] booleanProvider() { return new Object[][] { new Object[] { true } }; } /** * @see java.sql.Statement#setEscapeProcessing(boolean) */ @Test(dataProvider = "boolean") public void setEscapeProcessing(boolean enable) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setEscapeProcessing(enable); this.statement2.setEscapeProcessing(enable); this.replay(); this.statement.setEscapeProcessing(enable); this.verify(); } @DataProvider(name = "direction") Object[][] directionProvider() { return new Object[][] { new Object[] { ResultSet.FETCH_FORWARD } }; } /** * @see java.sql.Statement#setFetchDirection(int) */ @Test(dataProvider = "direction") public void setFetchDirection(int direction) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setFetchDirection(direction); this.statement2.setFetchDirection(direction); this.replay(); this.statement.setFetchDirection(direction); this.verify(); } @DataProvider(name = "int") Object[][] intProvider() { return new Object[][] { new Object[] { 1 } }; } /** * @see java.sql.Statement#setFetchSize(int) */ @Test(dataProvider = "int") public void setFetchSize(int rows) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setFetchSize(rows); this.statement2.setFetchSize(rows); this.replay(); this.statement.setFetchSize(rows); this.verify(); } /** * @see java.sql.Statement#setMaxFieldSize(int) */ @Test(dataProvider = "int") public void setMaxFieldSize(int max) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setMaxFieldSize(max); this.statement2.setMaxFieldSize(max); this.replay(); this.statement.setMaxFieldSize(max); this.verify(); } /** * @see java.sql.Statement#setMaxRows(int) */ @Test(dataProvider = "int") public void setMaxRows(int max) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setMaxRows(max); this.statement2.setMaxRows(max); this.replay(); this.statement.setMaxRows(max); this.verify(); } /** * @see java.sql.Statement#setQueryTimeout(int) */ @Test(dataProvider = "int") public void setQueryTimeout(int seconds) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setQueryTimeout(seconds); this.statement2.setQueryTimeout(seconds); this.replay(); this.statement.setQueryTimeout(seconds); this.verify(); } public void testIsClosed() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.isClosed()).andReturn(true); this.replay(); boolean result = this.isClosed(); assert result; } /** * @see java.sql.Statement#isClosed() */ @Override public boolean isClosed() throws SQLException { return this.statement.isClosed(); } public void testIsPoolable() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.isPoolable()).andReturn(true); this.replay(); boolean result = this.isPoolable(); assert result; } /** * @see java.sql.Statement#isPoolable() */ @Override public boolean isPoolable() throws SQLException { return this.statement.isPoolable(); } /** * @see java.sql.Statement#setPoolable(boolean) */ @Test(dataProvider = "boolean") public void setPoolable(boolean poolable) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setPoolable(poolable); this.statement2.setPoolable(poolable); this.replay(); this.statement.setPoolable(poolable); } @DataProvider(name = "class") Object[][] classProvider() { return new Object[][] { new Object[] { Object.class } }; } public void testIsWrapperFor() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.isWrapperFor(Statement.class)).andReturn(true); this.replay(); boolean result = this.isWrapperFor(Statement.class); assert result; } /** * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ @Override public boolean isWrapperFor(Class targetClass) throws SQLException { return this.statement.isWrapperFor(targetClass); } public void testUnwrap() throws SQLException { Statement statement = EasyMock.createMock(Statement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.unwrap(Statement.class)).andReturn(statement); this.replay(); Statement result = this.statement.unwrap(Statement.class); assert result == statement; } /** * @see java.sql.Wrapper#unwrap(java.lang.Class) */ @Override public T unwrap(Class targetClass) throws SQLException { return this.statement.unwrap(targetClass); } protected void expectIdentifiers(String sql, String sequence, String table) throws SQLException { EasyMock.expect(this.cluster.isSequenceDetectionEnabled()).andReturn(true); EasyMock.expect(this.cluster.getDialect()).andReturn(this.dialect); EasyMock.expect(this.dialect.parseSequence(sql)).andReturn(sequence); EasyMock.expect(this.cluster.isIdentityColumnDetectionEnabled()).andReturn(true); EasyMock.expect(this.cluster.getDialect()).andReturn(this.dialect); EasyMock.expect(this.dialect.parseInsertTable(sql)).andReturn(table); if (table != null) { EasyMock.expect(this.cluster.getDatabaseMetaDataCache()).andReturn(this.metaData); EasyMock.expect(this.metaData.getDatabaseProperties(EasyMock.same(this.connection))).andReturn(this.databaseProperties); EasyMock.expect(this.databaseProperties.findTable(table)).andReturn(this.tableProperties); EasyMock.expect(this.tableProperties.getIdentityColumns()).andReturn(Collections.singleton("column")); EasyMock.expect(this.tableProperties.getName()).andReturn(table); } if ((sequence != null) || (table != null)) { EasyMock.expect(this.cluster.getLockManager()).andReturn(this.lockManager); if (sequence != null) { EasyMock.expect(this.lockManager.writeLock(sequence)).andReturn(this.sequenceLock); } if (table != null) { EasyMock.expect(this.lockManager.writeLock(table)).andReturn(this.tableLock); } } } protected void expectSelectForUpdateCheck(String sql, boolean isSelectForUpdate) throws SQLException { EasyMock.expect(this.cluster.getDatabaseMetaDataCache()).andReturn(this.metaData); EasyMock.expect(this.metaData.getDatabaseProperties(this.connection)).andReturn(this.databaseProperties); EasyMock.expect(this.databaseProperties.supportsSelectForUpdate()).andReturn(true); EasyMock.expect(this.cluster.getDialect()).andReturn(this.dialect); EasyMock.expect(this.dialect.isSelectForUpdate(sql)).andReturn(isSelectForUpdate); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestCallableStatement.java0000644000175000017500000022512111217530507024713 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.ByteArrayInputStream; import java.io.CharArrayReader; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.lang.reflect.Proxy; import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URL; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Date; import java.sql.NClob; import java.sql.Ref; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; import java.util.Collections; import java.util.Map; import java.util.TreeMap; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Unit test for {@link CallableStatement}. * * @author Paul Ferraro * @since 1.1 */ @Test @SuppressWarnings({ "unchecked", "nls" }) public class TestCallableStatement extends AbstractTestPreparedStatement implements java.sql.CallableStatement { @Override protected Class getStatementClass() { return java.sql.CallableStatement.class; } @Override protected AbstractStatementInvocationHandler getInvocationHandler(Map map) throws Exception { return new CallableStatementInvocationHandler(this.connection, this.parent, EasyMock.createMock(Invoker.class), map, this.transactionContext, this.fileSupport); } /** * @see net.sf.hajdbc.sql.AbstractTestStatement#recordConstructor() */ @Override protected void recordConstructor() throws SQLException { this.parent.addChild(EasyMock.isA(CallableStatementInvocationHandler.class)); } @Test(dataProvider = "int") public void testGetArray(int index) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); Array array = EasyMock.createMock(Array.class); EasyMock.expect(this.statement1.getArray(index)).andReturn(array); this.replay(); Array value = this.getArray(index); this.verify(); assert value == array; } /** * @see java.sql.CallableStatement#getArray(int) */ @Override public Array getArray(int index) throws SQLException { return this.statement.getArray(index); } @Test(dataProvider = "string") public void testGetArray(String name) throws SQLException { Array array = EasyMock.createMock(Array.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getArray(name)).andReturn(array); this.replay(); Array value = this.getArray(name); this.verify(); assert value == array; } /** * @see java.sql.CallableStatement#getArray(java.lang.String) */ @Override public Array getArray(String name) throws SQLException { return this.statement.getArray(name); } @Test(dataProvider = "int") public void testGetBigDecimal(int index) throws SQLException { BigDecimal decimal = new BigDecimal(10); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getBigDecimal(index)).andReturn(decimal); this.replay(); BigDecimal value = this.getBigDecimal(index); this.verify(); assert value == decimal; } /** * @see java.sql.CallableStatement#getBigDecimal(int) */ @Override public BigDecimal getBigDecimal(int index) throws SQLException { return this.statement.getBigDecimal(index); } @Test(dataProvider = "int-int") @Deprecated public void testGetBigDecimal(int index, int scale) throws SQLException { BigDecimal decimal = new BigDecimal(10); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getBigDecimal(index, scale)).andReturn(decimal); this.replay(); BigDecimal value = this.getBigDecimal(index, scale); this.verify(); assert value == decimal; } /** * @see java.sql.CallableStatement#getBigDecimal(int, int) */ @SuppressWarnings("deprecation") @Override @Deprecated public BigDecimal getBigDecimal(int index, int scale) throws SQLException { return this.statement.getBigDecimal(index, scale); } @Test(dataProvider = "string") public void testGetBigDecimal(String name) throws SQLException { BigDecimal decimal = new BigDecimal(10); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getBigDecimal(name)).andReturn(decimal); this.replay(); BigDecimal value = this.getBigDecimal(name); this.verify(); assert value == decimal; } /** * @see java.sql.CallableStatement#getBigDecimal(java.lang.String) */ @Override public BigDecimal getBigDecimal(String name) throws SQLException { return this.statement.getBigDecimal(name); } @Test(dataProvider = "int") public void testGetBlob(int index) throws SQLException { Blob blob = EasyMock.createMock(Blob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getBlob(index)).andReturn(blob); this.replay(); Blob value = this.getBlob(index); this.verify(); assert value == blob; } /** * @see java.sql.CallableStatement#getBlob(int) */ @Override public Blob getBlob(int index) throws SQLException { return this.statement.getBlob(index); } @Test(dataProvider = "string") public void testGetBlog(String name) throws SQLException { Blob blob = EasyMock.createMock(Blob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getBlob(name)).andReturn(blob); this.replay(); Blob value = this.statement.getBlob(name); this.verify(); assert value == blob; } /** * @see java.sql.CallableStatement#getBlob(java.lang.String) */ @Override public Blob getBlob(String name) throws SQLException { return this.statement.getBlob(name); } @Test(dataProvider = "int") public void testGetBoolean(int index) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getBoolean(index)).andReturn(true); this.replay(); boolean value = this.getBoolean(index); this.verify(); assert value; } /** * @see java.sql.CallableStatement#getBoolean(int) */ @Override public boolean getBoolean(int index) throws SQLException { return this.statement.getBoolean(index); } @Test(dataProvider = "string") public void testGetBoolean(String name) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getBoolean(name)).andReturn(true); this.replay(); boolean value = this.getBoolean(name); this.verify(); assert value; } /** * @see java.sql.CallableStatement#getBoolean(java.lang.String) */ @Override public boolean getBoolean(String name) throws SQLException { return this.statement.getBoolean(name); } @Test(dataProvider = "int") public void testGetByte(int index) throws SQLException { byte b = Integer.valueOf(1).byteValue(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getByte(index)).andReturn(b); this.replay(); byte value = this.getByte(index); this.verify(); assert value == b; } /** * @see java.sql.CallableStatement#getByte(int) */ @Override public byte getByte(int index) throws SQLException { return this.statement.getByte(index); } @Test(dataProvider = "string") public void testGetByte(String name) throws SQLException { byte b = Integer.valueOf(1).byteValue(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getByte(name)).andReturn(b); this.replay(); byte value = this.getByte(name); this.verify(); assert value == b; } /** * @see java.sql.CallableStatement#getByte(java.lang.String) */ @Override public byte getByte(String name) throws SQLException { return this.statement.getByte(name); } @Test(dataProvider = "int") public void testGetBytes(int index) throws SQLException { byte[] bytes = new byte[0]; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getBytes(index)).andReturn(bytes); this.replay(); byte[] value = this.getBytes(index); this.verify(); assert value == bytes; } /** * @see java.sql.CallableStatement#getBytes(int) */ @Override public byte[] getBytes(int index) throws SQLException { return this.statement.getBytes(index); } @Test(dataProvider = "string") public void testGetBytes(String name) throws SQLException { byte[] bytes = new byte[0]; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getBytes(name)).andReturn(bytes); this.replay(); byte[] value = this.getBytes(name); this.verify(); assert value == bytes; } /** * @see java.sql.CallableStatement#getBytes(java.lang.String) */ @Override public byte[] getBytes(String name) throws SQLException { return this.statement.getBytes(name); } @Test(dataProvider = "int") public void testGetClob(int index) throws SQLException { Clob clob = EasyMock.createMock(Clob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getClob(index)).andReturn(clob); this.replay(); Clob value = this.getClob(index); this.verify(); assert value == clob; } /** * @see java.sql.CallableStatement#getClob(int) */ @Override public Clob getClob(int index) throws SQLException { return this.statement.getClob(index); } @Test(dataProvider = "string") public void testGetClob(String name) throws SQLException { Clob clob = EasyMock.createMock(Clob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getClob(name)).andReturn(clob); this.replay(); Clob value = this.getClob(name); this.verify(); assert value == clob; } /** * @see java.sql.CallableStatement#getClob(java.lang.String) */ @Override public Clob getClob(String name) throws SQLException { return this.statement.getClob(name); } @Test(dataProvider = "int") public void testGetDate(int index) throws SQLException { Date date = new Date(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getDate(index)).andReturn(date); this.replay(); Date value = this.getDate(index); this.verify(); assert value == date; } /** * @see java.sql.CallableStatement#getDate(int) */ @Override public Date getDate(int index) throws SQLException { return this.statement.getDate(index); } @DataProvider(name = "int-calendar") Object[][] intCalendarProvider() { return new Object[][] { new Object[] { 1, Calendar.getInstance() } }; } @Test(dataProvider = "int-calendar") public void testGetDate(int index, Calendar calendar) throws SQLException { Date date = new Date(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getDate(index, calendar)).andReturn(date); this.replay(); Date value = this.getDate(index, calendar); this.verify(); assert value == date; } /** * @see java.sql.CallableStatement#getDate(int, java.util.Calendar) */ @Override public Date getDate(int index, Calendar calendar) throws SQLException { return this.statement.getDate(index, calendar); } @Test(dataProvider = "string") public void testGetDate(String name) throws SQLException { Date date = new Date(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getDate(name)).andReturn(date); this.replay(); Date value = this.getDate(name); this.verify(); assert value == date; } /** * @see java.sql.CallableStatement#getDate(java.lang.String) */ @Override public Date getDate(String name) throws SQLException { return this.statement.getDate(name); } @DataProvider(name = "string-calendar") Object[][] stringCalendarProvider() { return new Object[][] { new Object[] { "column", Calendar.getInstance() } }; } @Test(dataProvider = "string-calendar") public void testGetDate(String name, Calendar calendar) throws SQLException { Date date = new Date(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getDate(name, calendar)).andReturn(date); this.replay(); Date value = this.getDate(name, calendar); this.verify(); assert value == date; } /** * @see java.sql.CallableStatement#getDate(java.lang.String, java.util.Calendar) */ @Override public Date getDate(String name, Calendar calendar) throws SQLException { return this.statement.getDate(name, calendar); } @Test(dataProvider = "int") public void testGetDouble(int index) throws SQLException { double d = 1.0; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getDouble(index)).andReturn(d); this.replay(); double value = this.getDouble(index); this.verify(); assert value == d; } /** * @see java.sql.CallableStatement#getDouble(int) */ @Override public double getDouble(int index) throws SQLException { return this.statement.getDouble(index); } @Test(dataProvider = "string") public void testGetDouble(String name) throws SQLException { double d = 1.0; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getDouble(name)).andReturn(d); this.replay(); double value = this.getDouble(name); this.verify(); assert value == d; } /** * @see java.sql.CallableStatement#getDouble(java.lang.String) */ @Override public double getDouble(String name) throws SQLException { return this.statement.getDouble(name); } @Test(dataProvider = "int") public void testGetFloat(int index) throws SQLException { float f = 1.0f; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getFloat(index)).andReturn(f); this.replay(); float value = this.getFloat(index); this.verify(); assert value == f; } /** * @see java.sql.CallableStatement#getFloat(int) */ @Override public float getFloat(int index) throws SQLException { return this.statement.getFloat(index); } @Test(dataProvider = "string") public void testGetFloat(String name) throws SQLException { float f = 1.0f; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getFloat(name)).andReturn(f); this.replay(); float value = this.getFloat(name); this.verify(); assert value == f; } /** * @see java.sql.CallableStatement#getFloat(java.lang.String) */ @Override public float getFloat(String name) throws SQLException { return this.statement.getFloat(name); } @Test(dataProvider = "int") public void testGetInt(int index) throws SQLException { int i = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getInt(index)).andReturn(i); this.replay(); int value = this.getInt(index); this.verify(); assert value == i; } /** * @see java.sql.CallableStatement#getInt(int) */ @Override public int getInt(int index) throws SQLException { return this.statement.getInt(index); } @Test(dataProvider = "string") public void testGetInt(String name) throws SQLException { int i = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getInt(name)).andReturn(i); this.replay(); int value = this.getInt(name); this.verify(); assert value == i; } /** * @see java.sql.CallableStatement#getInt(java.lang.String) */ @Override public int getInt(String name) throws SQLException { return this.statement.getInt(name); } @Test(dataProvider = "int") public void testGetLong(int index) throws SQLException { long i = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getLong(index)).andReturn(i); this.replay(); long value = this.getLong(index); this.verify(); assert value == i; } /** * @see java.sql.CallableStatement#getLong(int) */ @Override public long getLong(int index) throws SQLException { return this.statement.getLong(index); } @Test(dataProvider = "string") public void testGetLong(String name) throws SQLException { long i = 1; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getLong(name)).andReturn(i); this.replay(); long value = this.statement.getLong(name); this.verify(); assert value == i; } /** * @see java.sql.CallableStatement#getLong(java.lang.String) */ @Override public long getLong(String name) throws SQLException { return this.statement.getLong(name); } @Test(dataProvider = "int") public void testGetObject(int index) throws SQLException { Object object = new Object(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getObject(index)).andReturn(object); this.replay(); Object value = this.getObject(index); this.verify(); assert value == object; } /** * @see java.sql.CallableStatement#getObject(int) */ @Override public Object getObject(int index) throws SQLException { return this.statement.getObject(index); } @DataProvider(name = "int-map") Object[][] intMapProvider() { return new Object[][] { new Object[] { 1, Collections.EMPTY_MAP } }; } @Test(dataProvider = "int-map") public void testGetObject(int index, Map> map) throws SQLException { Object object = new Object(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getObject(index, map)).andReturn(object); this.replay(); Object value = this.getObject(index, map); this.verify(); assert value == object; } /** * @see java.sql.CallableStatement#getObject(int, java.util.Map) */ @Override public Object getObject(int index, Map> map) throws SQLException { return this.statement.getObject(index, map); } @Test(dataProvider = "string") public void testGetObject(String name) throws SQLException { Object object = new Object(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getObject(name)).andReturn(object); this.replay(); Object value = this.getObject(name); this.verify(); assert value == object; } /** * @see java.sql.CallableStatement#getObject(java.lang.String) */ @Override public Object getObject(String name) throws SQLException { return this.statement.getObject(name); } @DataProvider(name = "string-map") Object[][] stringMapProvider() { return new Object[][] { new Object[] { "column", Collections.EMPTY_MAP } }; } @Test(dataProvider = "string-map") public void testGetObject(String name, Map> map) throws SQLException { Object object = new Object(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getObject(name, map)).andReturn(object); this.replay(); Object value = this.getObject(name, map); this.verify(); assert value == object; } /** * @see java.sql.CallableStatement#getObject(java.lang.String, java.util.Map) */ @Override public Object getObject(String name, Map> map) throws SQLException { return this.statement.getObject(name, map); } @Test(dataProvider = "int") public void testGetRef(int index) throws SQLException { Ref ref = EasyMock.createMock(Ref.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getRef(index)).andReturn(ref); this.replay(); Ref value = this.getRef(index); this.verify(); assert value == ref; } /** * @see java.sql.CallableStatement#getRef(int) */ @Override public Ref getRef(int index) throws SQLException { return this.statement.getRef(index); } @Test(dataProvider = "string") public void testGetRef(String name) throws SQLException { Ref ref = EasyMock.createMock(Ref.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getRef(name)).andReturn(ref); this.replay(); Ref value = this.getRef(name); this.verify(); assert value == ref; } /** * @see java.sql.CallableStatement#getRef(java.lang.String) */ @Override public Ref getRef(String name) throws SQLException { return this.statement.getRef(name); } @Test(dataProvider = "int") public void testGetShort(int index) throws SQLException { short s = Integer.valueOf(1).shortValue(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getShort(index)).andReturn(s); this.replay(); short value = this.getShort(index); this.verify(); assert value == s; } /** * @see java.sql.CallableStatement#getShort(int) */ @Override public short getShort(int index) throws SQLException { return this.statement.getShort(index); } @Test(dataProvider = "string") public void testGetShort(String name) throws SQLException { short s = Integer.valueOf(1).shortValue(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getShort(name)).andReturn(s); this.replay(); short value = this.getShort(name); this.verify(); assert value == s; } /** * @see java.sql.CallableStatement#getShort(java.lang.String) */ @Override public short getShort(String name) throws SQLException { return this.statement.getShort(name); } @Test(dataProvider = "int") public void testGetString(int index) throws SQLException { String s = ""; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getString(index)).andReturn(s); this.replay(); String value = this.getString(index); this.verify(); assert value == s; } /** * @see java.sql.CallableStatement#getString(int) */ @Override public String getString(int index) throws SQLException { return this.statement.getString(index); } @Test(dataProvider = "string") public void testGetString(String name) throws SQLException { String s = ""; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getString(name)).andReturn(s); this.replay(); String value = this.getString(name); this.verify(); assert value == s; } /** * @see java.sql.CallableStatement#getString(java.lang.String) */ @Override public String getString(String name) throws SQLException { return this.statement.getString(name); } @Test(dataProvider = "int") public void testGetTime(int index) throws SQLException { Time time = new Time(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getTime(index)).andReturn(time); this.replay(); Time value = this.getTime(index); this.verify(); assert value == time; } /** * @see java.sql.CallableStatement#getTime(int) */ @Override public Time getTime(int index) throws SQLException { return this.statement.getTime(index); } @Test(dataProvider = "int-calendar") public void testGetTime(int index, Calendar calendar) throws SQLException { Time time = new Time(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getTime(index, calendar)).andReturn(time); this.replay(); Time value = this.getTime(index, calendar); this.verify(); assert value == time; } /** * @see java.sql.CallableStatement#getTime(int, java.util.Calendar) */ @Override public Time getTime(int index, Calendar calendar) throws SQLException { return this.statement.getTime(index, calendar); } @Test(dataProvider = "string") public void testGetTime(String name) throws SQLException { Time time = new Time(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getTime(name)).andReturn(time); this.replay(); Time value = this.getTime(name); this.verify(); assert value == time; } /** * @see java.sql.CallableStatement#getTime(java.lang.String) */ @Override public Time getTime(String name) throws SQLException { return this.statement.getTime(name); } @Test(dataProvider = "string-calendar") public void testGetTime(String name, Calendar calendar) throws SQLException { Time time = new Time(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getTime(name, calendar)).andReturn(time); this.replay(); Time value = this.getTime(name, calendar); this.verify(); assert value == time; } /** * @see java.sql.CallableStatement#getTime(java.lang.String, java.util.Calendar) */ @Override public Time getTime(String name, Calendar calendar) throws SQLException { return this.statement.getTime(name, calendar); } @Test(dataProvider = "int") public void testGetTimestamp(int index) throws SQLException { Timestamp timestamp = new Timestamp(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getTimestamp(index)).andReturn(timestamp); this.replay(); Timestamp value = this.getTimestamp(index); this.verify(); assert value == timestamp; } /** * @see java.sql.CallableStatement#getTimestamp(int) */ @Override public Timestamp getTimestamp(int index) throws SQLException { return this.statement.getTimestamp(index); } @Test(dataProvider = "int-calendar") public void testGetTimestamp(int index, Calendar calendar) throws SQLException { Timestamp timestamp = new Timestamp(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getTimestamp(index, calendar)).andReturn(timestamp); this.replay(); Timestamp value = this.getTimestamp(index, calendar); this.verify(); assert value == timestamp; } /** * @see java.sql.CallableStatement#getTimestamp(int, java.util.Calendar) */ @Override public Timestamp getTimestamp(int index, Calendar calendar) throws SQLException { return this.statement.getTimestamp(index, calendar); } @Test(dataProvider = "string") public void testGetTimestamp(String name) throws SQLException { Timestamp timestamp = new Timestamp(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getTimestamp(name)).andReturn(timestamp); this.replay(); Timestamp value = this.getTimestamp(name); this.verify(); assert value == timestamp; } /** * @see java.sql.CallableStatement#getTimestamp(java.lang.String) */ @Override public Timestamp getTimestamp(String name) throws SQLException { return this.statement.getTimestamp(name); } @Test(dataProvider = "string-calendar") public void testGetTimestamp(String name, Calendar calendar) throws SQLException { Timestamp timestamp = new Timestamp(System.currentTimeMillis()); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getTimestamp(name, calendar)).andReturn(timestamp); this.replay(); Timestamp value = this.getTimestamp(name, calendar); this.verify(); assert value == timestamp; } /** * @see java.sql.CallableStatement#getTimestamp(java.lang.String, java.util.Calendar) */ @Override public Timestamp getTimestamp(String name, Calendar calendar) throws SQLException { return this.statement.getTimestamp(name, calendar); } @Test(dataProvider = "int") public void testGetURL(int index) throws SQLException { try { URL url = new URL("http://ha-jdbc.sf.net"); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getURL(index)).andReturn(url); this.replay(); URL value = this.getURL(index); this.verify(); assert value == url; } catch (MalformedURLException e) { assert false : e; } } /** * @see java.sql.CallableStatement#getURL(int) */ @Override public URL getURL(int index) throws SQLException { return this.statement.getURL(index); } @Test(dataProvider = "string") public void testGetURL(String name) throws SQLException { try { URL url = new URL("http://ha-jdbc.sf.net"); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getURL(name)).andReturn(url); this.replay(); URL value = this.getURL(name); this.verify(); assert value == url; } catch (MalformedURLException e) { assert false : e; } } /** * @see java.sql.CallableStatement#getURL(java.lang.String) */ @Override public URL getURL(String name) throws SQLException { return this.statement.getURL(name); } /** * @see java.sql.CallableStatement#registerOutParameter(int, int) */ @Test(dataProvider = "int-int") public void registerOutParameter(int index, int sqlType) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.registerOutParameter(index, sqlType); this.statement2.registerOutParameter(index, sqlType); this.replay(); this.statement.registerOutParameter(index, sqlType); this.verify(); } @DataProvider(name = "int-int-int") Object[][] intIntIntProvider() { return new Object[][] { new Object[] { 1, Types.INTEGER, 1 } }; } /** * @see java.sql.CallableStatement#registerOutParameter(int, int, int) */ @Test(dataProvider = "int-int-int") public void registerOutParameter(int index, int sqlType, int scale) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.registerOutParameter(index, sqlType, scale); this.statement2.registerOutParameter(index, sqlType, scale); this.replay(); this.statement.registerOutParameter(index, sqlType, scale); this.verify(); } /** * @see java.sql.CallableStatement#registerOutParameter(int, int, java.lang.String) */ @Test(dataProvider = "int-int-string") public void registerOutParameter(int index, int sqlType, String typeName) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.registerOutParameter(index, sqlType, typeName); this.statement2.registerOutParameter(index, sqlType, typeName); this.replay(); this.statement.registerOutParameter(index, sqlType, typeName); this.verify(); } /** * @see java.sql.CallableStatement#registerOutParameter(java.lang.String, int) */ @Test(dataProvider = "string-int") public void registerOutParameter(String name, int sqlType) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.registerOutParameter(name, sqlType); this.statement2.registerOutParameter(name, sqlType); this.replay(); this.statement.registerOutParameter(name, sqlType); this.verify(); } @DataProvider(name = "string-int-int") Object[][] stringIntIntProvider() { return new Object[][] { new Object[] { "column", Types.INTEGER, 1 } }; } /** * @see java.sql.CallableStatement#registerOutParameter(java.lang.String, int, int) */ @Test(dataProvider = "string-int-int") public void registerOutParameter(String name, int sqlType, int scale) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.registerOutParameter(name, sqlType, scale); this.statement2.registerOutParameter(name, sqlType, scale); this.replay(); this.statement.registerOutParameter(name, sqlType, scale); this.verify(); } @DataProvider(name = "string-int-string") Object[][] stringIntStringProvider() { return new Object[][] { new Object[] { "column", Types.INTEGER, "int" } }; } /** * @see java.sql.CallableStatement#registerOutParameter(java.lang.String, int, java.lang.String) */ @Test(dataProvider = "string-int-string") public void registerOutParameter(String name, int sqlType, String typeName) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.registerOutParameter(name, sqlType, typeName); this.statement2.registerOutParameter(name, sqlType, typeName); this.replay(); this.statement.registerOutParameter(name, sqlType, typeName); this.verify(); } @DataProvider(name = "string-inputStream-int") Object[][] stringInputStreamIntProvider() { return new Object[][] { new Object[] { "column", new ByteArrayInputStream(new byte[0]), 0 } }; } /** * @see java.sql.CallableStatement#setAsciiStream(java.lang.String, java.io.InputStream, int) */ @Test(dataProvider = "string-inputStream-int") public void setAsciiStream(String name, InputStream value, int length) throws SQLException { InputStream inputStream1 = new ByteArrayInputStream(new byte[0]); InputStream inputStream2 = new ByteArrayInputStream(new byte[0]); File file = new File(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(inputStream1); this.statement1.setAsciiStream(name, inputStream1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(inputStream2); this.statement2.setAsciiStream(name, inputStream2, length); this.replay(); this.statement.setAsciiStream(name, value, length); this.verify(); } @DataProvider(name = "string-bigDecimal") Object[][] stringBigDecimalProvider() { return new Object[][] { new Object[] { "column", new BigDecimal(1.0) } }; } /** * @see java.sql.CallableStatement#setBigDecimal(java.lang.String, java.math.BigDecimal) */ @Test(dataProvider = "string-bigDecimal") public void setBigDecimal(String name, BigDecimal value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setBigDecimal(name, value); this.statement2.setBigDecimal(name, value); this.replay(); this.statement.setBigDecimal(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setBinaryStream(java.lang.String, java.io.InputStream, int) */ @Test(dataProvider = "string-inputStream-int") public void setBinaryStream(String name, InputStream value, int length) throws SQLException { InputStream inputStream1 = new ByteArrayInputStream(new byte[0]); InputStream inputStream2 = new ByteArrayInputStream(new byte[0]); File file = new File(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(inputStream1); this.statement1.setBinaryStream(name, inputStream1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(inputStream2); this.statement2.setBinaryStream(name, inputStream2, length); this.replay(); this.statement.setBinaryStream(name, value, length); this.verify(); } @DataProvider(name = "string-boolean") Object[][] stringBooleanProvider() { return new Object[][] { new Object[] { "column", true } }; } /** * @see java.sql.CallableStatement#setBoolean(java.lang.String, boolean) */ @Test(dataProvider = "string-boolean") public void setBoolean(String name, boolean value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setBoolean(name, value); this.statement2.setBoolean(name, value); this.replay(); this.statement.setBoolean(name, value); this.verify(); } @DataProvider(name = "string-byte") Object[][] stringByteProvider() { return new Object[][] { new Object[] { "column", Integer.valueOf(1).byteValue() } }; } /** * @see java.sql.CallableStatement#setByte(java.lang.String, byte) */ @Test(dataProvider = "string-byte") public void setByte(String name, byte value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setByte(name, value); this.statement2.setByte(name, value); this.replay(); this.statement.setByte(name, value); this.verify(); } @DataProvider(name = "string-bytes") Object[][] stringBytesProvider() { return new Object[][] { new Object[] { "column", new byte[0] } }; } /** * @see java.sql.CallableStatement#setBytes(java.lang.String, byte[]) */ @Test(dataProvider = "string-bytes") public void setBytes(String name, byte[] value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setBytes(name, value); this.statement2.setBytes(name, value); this.replay(); this.statement.setBytes(name, value); this.verify(); } @DataProvider(name = "string-reader-int") Object[][] stringReaderIntProvider() { return new Object[][] { new Object[] { "column", new CharArrayReader(new char[0]), 0 } }; } /** * @see java.sql.CallableStatement#setCharacterStream(java.lang.String, java.io.Reader, int) */ @Test(dataProvider = "string-reader-int") public void setCharacterStream(String name, Reader value, int length) throws SQLException { Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); File file = new File(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setCharacterStream(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setCharacterStream(name, reader2, length); this.replay(); this.statement.setCharacterStream(name, value, length); this.verify(); } @DataProvider(name = "string-date") Object[][] stringDateProvider() { return new Object[][] { new Object[] { "column", new Date(System.currentTimeMillis()) } }; } /** * @see java.sql.CallableStatement#setDate(java.lang.String, java.sql.Date) */ @Test(dataProvider = "string-date") public void setDate(String name, Date value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setDate(name, value); this.statement2.setDate(name, value); this.replay(); this.statement.setDate(name, value); this.verify(); } @DataProvider(name = "string-date-calendar") Object[][] stringDateCalendarProvider() { return new Object[][] { new Object[] { "column", new Date(System.currentTimeMillis()), Calendar.getInstance() } }; } /** * @see java.sql.CallableStatement#setDate(java.lang.String, java.sql.Date, java.util.Calendar) */ @Test(dataProvider = "string-date-calendar") public void setDate(String name, Date value, Calendar calendar) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setDate(name, value, calendar); this.statement2.setDate(name, value, calendar); this.replay(); this.statement.setDate(name, value, calendar); this.verify(); } @DataProvider(name = "string-double") Object[][] stringDoubleProvider() { return new Object[][] { new Object[] { "column", 1.0 } }; } /** * @see java.sql.CallableStatement#setDouble(java.lang.String, double) */ @Test(dataProvider = "string-double") public void setDouble(String name, double value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setDouble(name, value); this.statement2.setDouble(name, value); this.replay(); this.statement.setDouble(name, value); this.verify(); } @DataProvider(name = "string-float") Object[][] stringFloatProvider() { return new Object[][] { new Object[] { "column", 1.0F } }; } /** * @see java.sql.CallableStatement#setFloat(java.lang.String, float) */ @Test(dataProvider = "string-float") public void setFloat(String name, float value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setFloat(name, value); this.statement2.setFloat(name, value); this.replay(); this.statement.setFloat(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setInt(java.lang.String, int) */ @Test(dataProvider = "string-int") public void setInt(String name, int value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setInt(name, value); this.statement2.setInt(name, value); this.replay(); this.statement.setInt(name, value); this.verify(); } @DataProvider(name = "string-long") Object[][] stringLongProvider() { return new Object[][] { new Object[] { "column", 1L } }; } /** * @see java.sql.CallableStatement#setLong(java.lang.String, long) */ @Test(dataProvider = "string-long") public void setLong(String name, long value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setLong(name, value); this.statement2.setLong(name, value); this.replay(); this.statement.setLong(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setNull(java.lang.String, int) */ @Test(dataProvider = "string-int") public void setNull(String name, int sqlType) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setNull(name, sqlType); this.statement2.setNull(name, sqlType); this.replay(); this.statement.setNull(name, sqlType); this.verify(); } /** * @see java.sql.CallableStatement#setNull(java.lang.String, int, java.lang.String) */ @Test(dataProvider = "string-int-string") public void setNull(String name, int sqlType, String typeName) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setNull(name, sqlType, typeName); this.statement2.setNull(name, sqlType, typeName); this.replay(); this.statement.setNull(name, sqlType, typeName); this.verify(); } @DataProvider(name = "string-object") Object[][] stringObjectProvider() { return new Object[][] { new Object[] { "column", new Object() } }; } /** * @see java.sql.CallableStatement#setObject(java.lang.String, java.lang.Object) */ @Test(dataProvider = "string-object") public void setObject(String name, Object value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setObject(name, value); this.statement2.setObject(name, value); this.replay(); this.statement.setObject(name, value); this.verify(); } @DataProvider(name = "string-object-int") Object[][] stringObjectIntProvider() { return new Object[][] { new Object[] { "column", new Object(), Types.INTEGER } }; } /** * @see java.sql.CallableStatement#setObject(java.lang.String, java.lang.Object, int) */ @Test(dataProvider = "string-object-int") public void setObject(String name, Object value, int targetSqlType) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setObject(name, value, targetSqlType); this.statement2.setObject(name, value, targetSqlType); this.replay(); this.statement.setObject(name, value, targetSqlType); this.verify(); } @DataProvider(name = "string-object-int-int") Object[][] stringObjectIntIntProvider() { return new Object[][] { new Object[] { "column", new Object(), Types.INTEGER, 1 } }; } /** * @see java.sql.CallableStatement#setObject(java.lang.String, java.lang.Object, int, int) */ @Test(dataProvider = "string-object-int-int") public void setObject(String name, Object value, int targetSqlType, int scale) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setObject(name, value, targetSqlType, scale); this.statement2.setObject(name, value, targetSqlType, scale); this.replay(); this.statement.setObject(name, value, targetSqlType, scale); this.verify(); } @DataProvider(name = "string-short") Object[][] stringShortProvider() { return new Object[][] { new Object[] { "column", Integer.valueOf(1).shortValue() } }; } /** * @see java.sql.CallableStatement#setShort(java.lang.String, short) */ @Test(dataProvider = "string-short") public void setShort(String name, short value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setShort(name, value); this.statement2.setShort(name, value); this.replay(); this.statement.setShort(name, value); this.verify(); } @DataProvider(name = "string-string") Object[][] stringStringProvider() { return new Object[][] { new Object[] { "column", "" } }; } /** * @see java.sql.CallableStatement#setString(java.lang.String, java.lang.String) */ @Test(dataProvider = "string-string") public void setString(String name, String value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setString(name, value); this.statement2.setString(name, value); this.replay(); this.statement.setString(name, value); this.verify(); } @DataProvider(name = "string-time") Object[][] stringTimeProvider() { return new Object[][] { new Object[] { "column", new Time(System.currentTimeMillis()) } }; } /** * @see java.sql.CallableStatement#setTime(java.lang.String, java.sql.Time) */ @Test(dataProvider = "string-time") public void setTime(String name, Time value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setTime(name, value); this.statement2.setTime(name, value); this.replay(); this.statement.setTime(name, value); this.verify(); } @DataProvider(name = "string-time-calendar") Object[][] stringTimeCalendarProvider() { return new Object[][] { new Object[] { "column", new Time(System.currentTimeMillis()), Calendar.getInstance() } }; } /** * @see java.sql.CallableStatement#setTime(java.lang.String, java.sql.Time, java.util.Calendar) */ @Test(dataProvider = "string-time-calendar") public void setTime(String name, Time value, Calendar calendar) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setTime(name, value, calendar); this.statement2.setTime(name, value, calendar); this.replay(); this.statement.setTime(name, value, calendar); this.verify(); } @DataProvider(name = "string-timestamp") Object[][] stringTimestampProvider() { return new Object[][] { new Object[] { "column", new Timestamp(System.currentTimeMillis()) } }; } /** * @see java.sql.CallableStatement#setTimestamp(java.lang.String, java.sql.Timestamp) */ @Test(dataProvider = "string-timestamp") public void setTimestamp(String name, Timestamp value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setTimestamp(name, value); this.statement2.setTimestamp(name, value); this.replay(); this.statement.setTimestamp(name, value); this.verify(); } @DataProvider(name = "string-timestamp-calendar") Object[][] stringTimestampCalendarProvider() { return new Object[][] { new Object[] { "column", new Timestamp(System.currentTimeMillis()), Calendar.getInstance() } }; } /** * @see java.sql.CallableStatement#setTimestamp(java.lang.String, java.sql.Timestamp, java.util.Calendar) */ @Test(dataProvider = "string-timestamp-calendar") public void setTimestamp(String name, Timestamp value, Calendar calendar) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setTimestamp(name, value, calendar); this.statement2.setTimestamp(name, value, calendar); this.replay(); this.statement.setTimestamp(name, value, calendar); this.verify(); } @DataProvider(name = "string-url") Object[][] stringUrlProvider() throws MalformedURLException { return new Object[][] { new Object[] { "column", new URL("http://ha-jdbc.sf.net") } }; } /** * @see java.sql.CallableStatement#setURL(java.lang.String, java.net.URL) */ @Test(dataProvider = "string-url") public void setURL(String name, URL value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setURL(name, value); this.statement2.setURL(name, value); this.replay(); this.statement.setURL(name, value); this.verify(); } public void testWasNull() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.wasNull()).andReturn(true); this.replay(); boolean result = this.wasNull(); this.verify(); assert result; } /** * @see java.sql.CallableStatement#wasNull() */ public boolean wasNull() throws SQLException { return this.statement.wasNull(); } @Test(dataProvider = "int") public void testGetCharacterStream(int index) throws SQLException { Reader reader = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getCharacterStream(index)).andReturn(reader); this.replay(); Reader result = this.getCharacterStream(index); this.verify(); assert result == reader; } /** * @see java.sql.CallableStatement#getCharacterStream(int) */ @Override public Reader getCharacterStream(int index) throws SQLException { return this.statement.getCharacterStream(index); } @Test(dataProvider = "string") public void testGetCharacterStream(String name) throws SQLException { Reader reader = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getCharacterStream(name)).andReturn(reader); this.replay(); Reader result = this.getCharacterStream(name); this.verify(); assert result == reader; } /** * @see java.sql.CallableStatement#getCharacterStream(java.lang.String) */ @Override public Reader getCharacterStream(String name) throws SQLException { return this.statement.getCharacterStream(name); } @Test(dataProvider = "int") public void testGetNCharacterStream(int index) throws SQLException { Reader reader = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getNCharacterStream(index)).andReturn(reader); this.replay(); Reader result = this.getNCharacterStream(index); this.verify(); assert result == reader; } /** * @see java.sql.CallableStatement#getNCharacterStream(int) */ @Override public Reader getNCharacterStream(int index) throws SQLException { return this.statement.getNCharacterStream(index); } @Test(dataProvider = "string") public void testGetNCharacterStream(String name) throws SQLException { Reader reader = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getNCharacterStream(name)).andReturn(reader); this.replay(); Reader result = this.getNCharacterStream(name); this.verify(); assert result == reader; } /** * @see java.sql.CallableStatement#getNCharacterStream(java.lang.String) */ @Override public Reader getNCharacterStream(String name) throws SQLException { return this.statement.getNCharacterStream(name); } @Test(dataProvider = "int") public void testGetNClob(int index) throws SQLException { NClob clob = EasyMock.createMock(NClob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getNClob(index)).andReturn(clob); this.replay(); NClob result = this.getNClob(index); this.verify(); assert result == clob; } /** * @see java.sql.CallableStatement#getNClob(int) */ @Override public NClob getNClob(int index) throws SQLException { return this.statement.getNClob(index); } @Test(dataProvider = "string") public void testGetNClob(String name) throws SQLException { NClob clob = EasyMock.createMock(NClob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getNClob(name)).andReturn(clob); this.replay(); NClob result = this.getNClob(name); this.verify(); assert result == clob; } /** * @see java.sql.CallableStatement#getNClob(java.lang.String) */ @Override public NClob getNClob(String name) throws SQLException { return this.statement.getNClob(name); } @Test(dataProvider = "int") public void testGetNString(int index) throws SQLException { String string = ""; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getNString(index)).andReturn(string); this.replay(); String result = this.getNString(index); this.verify(); assert result == string; } /** * @see java.sql.CallableStatement#getNString(int) */ @Override public String getNString(int index) throws SQLException { return this.statement.getNString(index); } @Test(dataProvider = "string") public void testGetNString(String name) throws SQLException { String string = ""; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getNString(name)).andReturn(string); this.replay(); String result = this.getNString(name); this.verify(); assert result == string; } /** * @see java.sql.CallableStatement#getNString(java.lang.String) */ @Override public String getNString(String name) throws SQLException { return this.statement.getNString(name); } @Test(dataProvider = "int") public void testGetRowId(int index) throws SQLException { RowId rowId = EasyMock.createMock(RowId.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getRowId(index)).andReturn(rowId); this.replay(); RowId result = this.getRowId(index); this.verify(); assert result == rowId; } /** * @see java.sql.CallableStatement#getRowId(int) */ @Override public RowId getRowId(int index) throws SQLException { return this.statement.getRowId(index); } @Test(dataProvider = "string") public void testGetRowId(String name) throws SQLException { RowId rowId = EasyMock.createMock(RowId.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getRowId(name)).andReturn(rowId); this.replay(); RowId result = this.getRowId(name); this.verify(); assert result == rowId; } /** * @see java.sql.CallableStatement#getRowId(java.lang.String) */ @Override public RowId getRowId(String name) throws SQLException { return this.statement.getRowId(name); } @Test(dataProvider = "int") public void testGetSQLXML(int index) throws SQLException { SQLXML xml = EasyMock.createMock(SQLXML.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getSQLXML(index)).andReturn(xml); this.replay(); SQLXML result = this.getSQLXML(index); this.verify(); assert result == xml; } /** * @see java.sql.CallableStatement#getSQLXML(int) */ @Override public SQLXML getSQLXML(int index) throws SQLException { return this.statement.getSQLXML(index); } @Test(dataProvider = "string") public void testGetSQLXML(String name) throws SQLException { SQLXML xml = EasyMock.createMock(SQLXML.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.statement1.getSQLXML(name)).andReturn(xml); this.replay(); SQLXML result = this.getSQLXML(name); this.verify(); assert result == xml; } /** * @see java.sql.CallableStatement#getSQLXML(java.lang.String) */ @Override public SQLXML getSQLXML(String name) throws SQLException { return this.statement.getSQLXML(name); } @DataProvider(name = "string-inputStream") Object[][] stringInputStreamProvider() { return new Object[][] { new Object[] { "", new ByteArrayInputStream(new byte[0]) } }; } /** * @see java.sql.CallableStatement#setAsciiStream(java.lang.String, java.io.InputStream) */ @Test(dataProvider = "string-inputStream") public void setAsciiStream(String name, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setAsciiStream(name, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setAsciiStream(name, input2); this.replay(); this.statement.setAsciiStream(name, value); this.verify(); } @DataProvider(name = "string-inputStream-long") Object[][] stringInputStreamLongProvider() { return new Object[][] { new Object[] { "", new ByteArrayInputStream(new byte[0]), 1L } }; } /** * @see java.sql.CallableStatement#setAsciiStream(java.lang.String, java.io.InputStream, long) */ @Test(dataProvider = "string-inputStream-long") public void setAsciiStream(String name, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setAsciiStream(name, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setAsciiStream(name, input2, length); this.replay(); this.statement.setAsciiStream(name, value, length); this.verify(); } /** * @see java.sql.CallableStatement#setBinaryStream(java.lang.String, java.io.InputStream) */ @Test(dataProvider = "string-inputStream") public void setBinaryStream(String name, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setBinaryStream(name, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setBinaryStream(name, input2); this.replay(); this.statement.setBinaryStream(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setBinaryStream(java.lang.String, java.io.InputStream, long) */ @Test(dataProvider = "string-inputStream-long") public void setBinaryStream(String name, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setBinaryStream(name, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setBinaryStream(name, input2, length); this.replay(); this.statement.setBinaryStream(name, value, length); this.verify(); } @DataProvider(name = "string-blob") Object[][] stringBlobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.blob1); map.put(this.database2, this.blob2); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(BlobInvocationHandler.class)); this.replay(); Blob blob = ProxyFactory.createProxy(Blob.class, new BlobInvocationHandler(null, this.parent, null, map)); this.verify(); this.reset(); return new Object[][] { new Object[] { "", new MockBlob() }, new Object[] { "", blob } }; } /** * @see java.sql.CallableStatement#setBlob(java.lang.String, java.sql.Blob) */ @Test(dataProvider = "string-blob") public void setBlob(String name, Blob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.statement1.setBlob(name, this.blob1); this.statement2.setBlob(name, this.blob2); } else { this.statement1.setBlob(EasyMock.eq(name), EasyMock.isA(SerialBlob.class)); this.statement2.setBlob(EasyMock.eq(name), EasyMock.isA(SerialBlob.class)); } this.replay(); this.statement.setBlob(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setBlob(java.lang.String, java.io.InputStream) */ @Test(dataProvider = "string-inputStream") public void setBlob(String name, InputStream value) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setBlob(name, input1); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setBlob(name, input2); this.replay(); this.statement.setBlob(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setBlob(java.lang.String, java.io.InputStream, long) */ @Test(dataProvider = "string-inputStream-long") public void setBlob(String name, InputStream value, long length) throws SQLException { File file = new File(""); InputStream input1 = new ByteArrayInputStream(new byte[0]); InputStream input2 = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input1); this.statement1.setBlob(name, input1, length); EasyMock.expect(this.fileSupport.getInputStream(file)).andReturn(input2); this.statement2.setBlob(name, input2, length); this.replay(); this.statement.setBlob(name, value, length); this.verify(); } @DataProvider(name = "string-reader") Object[][] stringReaderProvider() { return new Object[][] { new Object[] { "", new StringReader("") } }; } /** * @see java.sql.CallableStatement#setCharacterStream(java.lang.String, java.io.Reader) */ @Test(dataProvider = "string-reader") public void setCharacterStream(String name, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setCharacterStream(name, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setCharacterStream(name, reader2); this.replay(); this.statement.setCharacterStream(name, value); this.verify(); } @DataProvider(name = "string-reader-long") Object[][] stringReaderLongProvider() { return new Object[][] { new Object[] { "", new StringReader(""), 1L } }; } /** * @see java.sql.CallableStatement#setCharacterStream(java.lang.String, java.io.Reader, long) */ @Test(dataProvider = "string-reader-long") public void setCharacterStream(String name, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setCharacterStream(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setCharacterStream(name, reader2, length); this.replay(); this.statement.setCharacterStream(name, value, length); this.verify(); } @DataProvider(name = "string-clob") Object[][] stringClobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.clob1); map.put(this.database2, this.clob2); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(ClobInvocationHandler.class)); this.replay(); Clob clob = ProxyFactory.createProxy(Clob.class, new ClobInvocationHandler(null, this.parent, null, map)); this.verify(); this.reset(); return new Object[][] { new Object[] { "", new MockClob() }, new Object[] { "", clob } }; } /** * @see java.sql.CallableStatement#setClob(java.lang.String, java.sql.Clob) */ @Test(dataProvider = "string-clob") public void setClob(String name, Clob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.statement1.setClob(name, this.clob1); this.statement2.setClob(name, this.clob2); } else { this.statement1.setClob(EasyMock.eq(name), EasyMock.isA(SerialClob.class)); this.statement2.setClob(EasyMock.eq(name), EasyMock.isA(SerialClob.class)); } this.replay(); this.statement.setClob(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setClob(java.lang.String, java.io.Reader) */ @Test(dataProvider = "string-reader") public void setClob(String name, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setClob(name, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setClob(name, reader2); this.replay(); this.statement.setClob(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setClob(java.lang.String, java.io.Reader, long) */ @Test(dataProvider = "string-reader-long") public void setClob(String name, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setClob(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setClob(name, reader2, length); this.replay(); this.statement.setClob(name, value, length); this.verify(); } /** * @see java.sql.CallableStatement#setNCharacterStream(java.lang.String, java.io.Reader) */ @Test(dataProvider = "string-reader") public void setNCharacterStream(String name, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setNCharacterStream(name, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setNCharacterStream(name, reader2); this.replay(); this.statement.setNCharacterStream(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setNCharacterStream(java.lang.String, java.io.Reader, long) */ @Test(dataProvider = "string-reader-long") public void setNCharacterStream(String name, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setNCharacterStream(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setNCharacterStream(name, reader2, length); this.replay(); this.statement.setNCharacterStream(name, value, length); this.verify(); } @DataProvider(name = "string-nclob") Object[][] stringNClobProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.nClob1); map.put(this.database2, this.nClob2); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(ClobInvocationHandler.class)); this.replay(); NClob nClob = ProxyFactory.createProxy(NClob.class, new ClobInvocationHandler(null, this.parent, null, map)); this.verify(); this.reset(); return new Object[][] { new Object[] { "", new MockClob() }, new Object[] { "", nClob } }; } /** * @see java.sql.CallableStatement#setNClob(java.lang.String, java.sql.NClob) */ @Test(dataProvider = "string-nclob") public void setNClob(String name, NClob value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); if (Proxy.isProxyClass(value.getClass())) { this.statement1.setNClob(name, this.nClob1); this.statement2.setNClob(name, this.nClob2); } else { this.statement1.setNClob(EasyMock.eq(name), EasyMock.isA(NClob.class)); this.statement2.setNClob(EasyMock.eq(name), EasyMock.isA(NClob.class)); } this.replay(); this.statement.setNClob(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setNClob(java.lang.String, java.io.Reader) */ @Test(dataProvider = "string-reader") public void setNClob(String name, Reader value) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setNClob(name, reader1); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setNClob(name, reader2); this.replay(); this.statement.setNClob(name, value); this.verify(); } /** * @see java.sql.CallableStatement#setNClob(java.lang.String, java.io.Reader, long) */ @Test(dataProvider = "string-reader-long") public void setNClob(String name, Reader value, long length) throws SQLException { File file = new File(""); Reader reader1 = new CharArrayReader(new char[0]); Reader reader2 = new CharArrayReader(new char[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.fileSupport.createFile(value)).andReturn(file); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader1); this.statement1.setNClob(name, reader1, length); EasyMock.expect(this.fileSupport.getReader(file)).andReturn(reader2); this.statement2.setNClob(name, reader2, length); this.replay(); this.statement.setNClob(name, value, length); this.verify(); } /** * @see java.sql.CallableStatement#setNString(java.lang.String, java.lang.String) */ @Test(dataProvider = "string-string") public void setNString(String name, String value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setNString(name, value); this.statement2.setNString(name, value); this.replay(); this.statement.setNString(name, value); this.verify(); } @DataProvider(name = "string-rowId") Object[][] stringRowIdProvider() { return new Object[][] { new Object[] { "", EasyMock.createMock(RowId.class) } }; } /** * @see java.sql.CallableStatement#setRowId(java.lang.String, java.sql.RowId) */ @Test(dataProvider = "string-rowId") public void setRowId(String name, RowId value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setRowId(name, value); this.statement2.setRowId(name, value); this.replay(); this.statement.setRowId(name, value); this.verify(); } @DataProvider(name = "string-xml") Object[][] stringSQLXMLProvider() { return new Object[][] { new Object[] { "", EasyMock.createMock(SQLXML.class) } }; } /** * @see java.sql.CallableStatement#setSQLXML(java.lang.String, java.sql.SQLXML) */ @Test(dataProvider = "string-xml") public void setSQLXML(String name, SQLXML value) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.statement1.setSQLXML(name, value); this.statement2.setSQLXML(name, value); this.replay(); this.statement.setSQLXML(name, value); this.verify(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/MockDataSource.java0000644000175000017500000000332311151703043023323 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import javax.sql.DataSource; import org.easymock.EasyMock; /** * @author Paul Ferraro * */ public class MockDataSource extends MockCommonDataSource implements DataSource { /** * @see javax.sql.DataSource#getConnection() */ public Connection getConnection() { return EasyMock.createMock(Connection.class); // return new MockConnection(); } /** * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) */ public Connection getConnection(String arg0, String arg1) { return this.getConnection(); } /** * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ @Override public boolean isWrapperFor(Class arg0) { return false; } /** * @see java.sql.Wrapper#unwrap(java.lang.Class) */ @Override public T unwrap(Class arg0) { return null; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/MockConnection.java0000644000175000017500000005263011151703043023375 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.RowIdLifetime; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Savepoint; import java.sql.Statement; import java.sql.Struct; import java.util.Map; import java.util.Properties; import org.easymock.EasyMock; /** * Mock connection that creates mock statements * @author Paul Ferraro * @since 1.1 */ public class MockConnection implements Connection { /** * @see java.sql.Connection#createStatement() */ public Statement createStatement() { return EasyMock.createMock(Statement.class); } /** * @see java.sql.Connection#prepareStatement(java.lang.String) */ public PreparedStatement prepareStatement(String arg0) { return null; } /** * @see java.sql.Connection#prepareCall(java.lang.String) */ public CallableStatement prepareCall(String arg0) { return null; } /** * @see java.sql.Connection#nativeSQL(java.lang.String) */ public String nativeSQL(String arg0) { return null; } /** * @see java.sql.Connection#setAutoCommit(boolean) */ public void setAutoCommit(boolean arg0) { } /** * @see java.sql.Connection#getAutoCommit() */ public boolean getAutoCommit() { return false; } /** * @see java.sql.Connection#commit() */ public void commit() { } /** * @see java.sql.Connection#rollback() */ public void rollback() { } /** * @see java.sql.Connection#close() */ public void close() { } /** * @see java.sql.Connection#isClosed() */ public boolean isClosed() { return false; } /** * @see java.sql.Connection#getMetaData() */ public DatabaseMetaData getMetaData() { return new DatabaseMetaData() { public boolean allProceduresAreCallable() { return false; } public boolean allTablesAreSelectable() { return false; } public String getURL() { return null; } public String getUserName() { return null; } public boolean isReadOnly() { return false; } public boolean nullsAreSortedHigh() { return false; } public boolean nullsAreSortedLow() { return false; } public boolean nullsAreSortedAtStart() { return false; } public boolean nullsAreSortedAtEnd() { return false; } public String getDatabaseProductName() { return null; } public String getDatabaseProductVersion() { return null; } public String getDriverName() { return null; } public String getDriverVersion() { return null; } public int getDriverMajorVersion() { return 0; } public int getDriverMinorVersion() { return 0; } public boolean usesLocalFiles() { return false; } public boolean usesLocalFilePerTable() { return false; } public boolean supportsMixedCaseIdentifiers() { return false; } public boolean storesUpperCaseIdentifiers() { return false; } public boolean storesLowerCaseIdentifiers() { return false; } public boolean storesMixedCaseIdentifiers() { return false; } public boolean supportsMixedCaseQuotedIdentifiers() { return false; } public boolean storesUpperCaseQuotedIdentifiers() { return false; } public boolean storesLowerCaseQuotedIdentifiers() { return false; } public boolean storesMixedCaseQuotedIdentifiers() { return false; } public String getIdentifierQuoteString() { return null; } public String getSQLKeywords() { return ""; //$NON-NLS-1$ } public String getNumericFunctions() { return null; } public String getStringFunctions() { return null; } public String getSystemFunctions() { return null; } public String getTimeDateFunctions() { return null; } public String getSearchStringEscape() { return null; } public String getExtraNameCharacters() { return ""; //$NON-NLS-1$ } public boolean supportsAlterTableWithAddColumn() { return false; } public boolean supportsAlterTableWithDropColumn() { return false; } public boolean supportsColumnAliasing() { return false; } public boolean nullPlusNonNullIsNull() { return false; } public boolean supportsConvert() { return false; } public boolean supportsConvert(int fromType, int toType) { return false; } public boolean supportsTableCorrelationNames() { return false; } public boolean supportsDifferentTableCorrelationNames() { return false; } public boolean supportsExpressionsInOrderBy() { return false; } public boolean supportsOrderByUnrelated() { return false; } public boolean supportsGroupBy() { return false; } public boolean supportsGroupByUnrelated() { return false; } public boolean supportsGroupByBeyondSelect() { return false; } public boolean supportsLikeEscapeClause() { return false; } public boolean supportsMultipleResultSets() { return false; } public boolean supportsMultipleTransactions() { return false; } public boolean supportsNonNullableColumns() { return false; } public boolean supportsMinimumSQLGrammar() { return false; } public boolean supportsCoreSQLGrammar() { return false; } public boolean supportsExtendedSQLGrammar() { return false; } public boolean supportsANSI92EntryLevelSQL() { return false; } public boolean supportsANSI92IntermediateSQL() { return false; } public boolean supportsANSI92FullSQL() { return false; } public boolean supportsIntegrityEnhancementFacility() { return false; } public boolean supportsOuterJoins() { return false; } public boolean supportsFullOuterJoins() { return false; } public boolean supportsLimitedOuterJoins() { return false; } public String getSchemaTerm() { return null; } public String getProcedureTerm() { return null; } public String getCatalogTerm() { return null; } public boolean isCatalogAtStart() { return false; } public String getCatalogSeparator() { return null; } public boolean supportsSchemasInDataManipulation() { return false; } public boolean supportsSchemasInProcedureCalls() { return false; } public boolean supportsSchemasInTableDefinitions() { return false; } public boolean supportsSchemasInIndexDefinitions() { return false; } public boolean supportsSchemasInPrivilegeDefinitions() { return false; } public boolean supportsCatalogsInDataManipulation() { return false; } public boolean supportsCatalogsInProcedureCalls() { return false; } public boolean supportsCatalogsInTableDefinitions() { return false; } public boolean supportsCatalogsInIndexDefinitions() { return false; } public boolean supportsCatalogsInPrivilegeDefinitions() { return false; } public boolean supportsPositionedDelete() { return false; } public boolean supportsPositionedUpdate() { return false; } public boolean supportsSelectForUpdate() { return false; } public boolean supportsStoredProcedures() { return false; } public boolean supportsSubqueriesInComparisons() { return false; } public boolean supportsSubqueriesInExists() { return false; } public boolean supportsSubqueriesInIns() { return false; } public boolean supportsSubqueriesInQuantifieds() { return false; } public boolean supportsCorrelatedSubqueries() { return false; } public boolean supportsUnion() { return false; } public boolean supportsUnionAll() { return false; } public boolean supportsOpenCursorsAcrossCommit() { return false; } public boolean supportsOpenCursorsAcrossRollback() { return false; } public boolean supportsOpenStatementsAcrossCommit() { return false; } public boolean supportsOpenStatementsAcrossRollback() { return false; } public int getMaxBinaryLiteralLength() { return 0; } public int getMaxCharLiteralLength() { return 0; } public int getMaxColumnNameLength() { return 0; } public int getMaxColumnsInGroupBy() { return 0; } public int getMaxColumnsInIndex() { return 0; } public int getMaxColumnsInOrderBy() { return 0; } public int getMaxColumnsInSelect() { return 0; } public int getMaxColumnsInTable() { return 0; } public int getMaxConnections() { return 0; } public int getMaxCursorNameLength() { return 0; } public int getMaxIndexLength() { return 0; } public int getMaxSchemaNameLength() { return 0; } public int getMaxProcedureNameLength() { return 0; } public int getMaxCatalogNameLength() { return 0; } public int getMaxRowSize() { return 0; } public boolean doesMaxRowSizeIncludeBlobs() { return false; } public int getMaxStatementLength() { return 0; } public int getMaxStatements() { return 0; } public int getMaxTableNameLength() { return 0; } public int getMaxTablesInSelect() { return 0; } public int getMaxUserNameLength() { return 0; } public int getDefaultTransactionIsolation() { return 0; } public boolean supportsTransactions() { return false; } public boolean supportsTransactionIsolationLevel(int level) { return false; } public boolean supportsDataDefinitionAndDataManipulationTransactions() { return false; } public boolean supportsDataManipulationTransactionsOnly() { return false; } public boolean dataDefinitionCausesTransactionCommit() { return false; } public boolean dataDefinitionIgnoredInTransactions() { return false; } public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) { return null; } public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) { return null; } public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) { return null; } public ResultSet getSchemas() { return null; } public ResultSet getCatalogs() { return null; } public ResultSet getTableTypes() { return null; } public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) { return null; } public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) { return null; } public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) { return null; } public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) { return null; } public ResultSet getVersionColumns(String catalog, String schema, String table) { return null; } public ResultSet getPrimaryKeys(String catalog, String schema, String table) { return null; } public ResultSet getImportedKeys(String catalog, String schema, String table) { return null; } public ResultSet getExportedKeys(String catalog, String schema, String table) { return null; } public ResultSet getCrossReference(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable) { return null; } public ResultSet getTypeInfo() { return null; } public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) { return null; } public boolean supportsResultSetType(int type) { return false; } public boolean supportsResultSetConcurrency(int type, int concurrency) { return false; } public boolean ownUpdatesAreVisible(int type) { return false; } public boolean ownDeletesAreVisible(int type) { return false; } public boolean ownInsertsAreVisible(int type) { return false; } public boolean othersUpdatesAreVisible(int type) { return false; } public boolean othersDeletesAreVisible(int type) { return false; } public boolean othersInsertsAreVisible(int type) { return false; } public boolean updatesAreDetected(int type) { return false; } public boolean deletesAreDetected(int type) { return false; } public boolean insertsAreDetected(int type) { return false; } public boolean supportsBatchUpdates() { return false; } public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) { return null; } public Connection getConnection() { return null; } public boolean supportsSavepoints() { return false; } public boolean supportsNamedParameters() { return false; } public boolean supportsMultipleOpenResults() { return false; } public boolean supportsGetGeneratedKeys() { return false; } public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) { return null; } public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) { return null; } public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) { return null; } public boolean supportsResultSetHoldability(int holdability) { return false; } public int getResultSetHoldability() { return 0; } public int getDatabaseMajorVersion() { return 0; } public int getDatabaseMinorVersion() { return 0; } public int getJDBCMajorVersion() { return 0; } public int getJDBCMinorVersion() { return 0; } public int getSQLStateType() { return 0; } public boolean locatorsUpdateCopy() { return false; } public boolean supportsStatementPooling() { return false; } @Override public boolean autoCommitFailureClosesAllResultSets() { return false; } @Override public ResultSet getClientInfoProperties() { return null; } @Override public ResultSet getFunctionColumns(String arg0, String arg1, String arg2, String arg3) { return null; } @Override public ResultSet getFunctions(String arg0, String arg1, String arg2) { return null; } @Override public RowIdLifetime getRowIdLifetime() { return null; } @Override public ResultSet getSchemas(String arg0, String arg1) { return null; } @Override public boolean supportsStoredFunctionsUsingCallSyntax() { return false; } @Override public boolean isWrapperFor(Class arg0) { return false; } @Override public T unwrap(Class arg0) { return null; } }; } /** * @see java.sql.Connection#setReadOnly(boolean) */ public void setReadOnly(boolean arg0) { } /** * @see java.sql.Connection#isReadOnly() */ public boolean isReadOnly() { return false; } /** * @see java.sql.Connection#setCatalog(java.lang.String) */ public void setCatalog(String arg0) { } /** * @see java.sql.Connection#getCatalog() */ public String getCatalog() { return null; } /** * @see java.sql.Connection#setTransactionIsolation(int) */ public void setTransactionIsolation(int arg0) { } /** * @see java.sql.Connection#getTransactionIsolation() */ public int getTransactionIsolation() { return 0; } /** * @see java.sql.Connection#getWarnings() */ public SQLWarning getWarnings() { return null; } /** * @see java.sql.Connection#clearWarnings() */ public void clearWarnings() { } /** * @see java.sql.Connection#createStatement(int, int) */ public Statement createStatement(int arg0, int arg1) { return null; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, int, int) */ public PreparedStatement prepareStatement(String arg0, int arg1, int arg2) { return null; } /** * @see java.sql.Connection#prepareCall(java.lang.String, int, int) */ public CallableStatement prepareCall(String arg0, int arg1, int arg2) { return null; } /** * @see java.sql.Connection#getTypeMap() */ public Map> getTypeMap() { return null; } /** * @see java.sql.Connection#setHoldability(int) */ public void setHoldability(int arg0) { } /** * @see java.sql.Connection#getHoldability() */ public int getHoldability() { return 0; } /** * @see java.sql.Connection#setSavepoint() */ public Savepoint setSavepoint() { return null; } /** * @see java.sql.Connection#setSavepoint(java.lang.String) */ public Savepoint setSavepoint(String arg0) { return null; } /** * @see java.sql.Connection#rollback(java.sql.Savepoint) */ public void rollback(Savepoint arg0) { } /** * @see java.sql.Connection#releaseSavepoint(java.sql.Savepoint) */ public void releaseSavepoint(Savepoint arg0) { } /** * @see java.sql.Connection#createStatement(int, int, int) */ public Statement createStatement(int arg0, int arg1, int arg2) { return null; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, int, int, int) */ public PreparedStatement prepareStatement(String arg0, int arg1, int arg2, int arg3) { return null; } /** * @see java.sql.Connection#prepareCall(java.lang.String, int, int, int) */ public CallableStatement prepareCall(String arg0, int arg1, int arg2, int arg3) { return null; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, int) */ public PreparedStatement prepareStatement(String arg0, int arg1) { return null; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, int[]) */ public PreparedStatement prepareStatement(String arg0, int[] arg1) { return null; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, java.lang.String[]) */ public PreparedStatement prepareStatement(String arg0, String[] arg1) { return null; } /** * @see java.sql.Connection#createArrayOf(java.lang.String, java.lang.Object[]) */ @Override public Array createArrayOf(String arg0, Object[] arg1) { return null; } /** * @see java.sql.Connection#createBlob() */ @Override public Blob createBlob() { return null; } /** * @see java.sql.Connection#createClob() */ @Override public Clob createClob() { return null; } /** * @see java.sql.Connection#createNClob() */ @Override public NClob createNClob() { return null; } /** * @see java.sql.Connection#createSQLXML() */ @Override public SQLXML createSQLXML() { return null; } /** * @see java.sql.Connection#createStruct(java.lang.String, java.lang.Object[]) */ @Override public Struct createStruct(String arg0, Object[] arg1) { return null; } /** * @see java.sql.Connection#getClientInfo() */ @Override public Properties getClientInfo() { return null; } /** * @see java.sql.Connection#getClientInfo(java.lang.String) */ @Override public String getClientInfo(String arg0) { return null; } /** * @see java.sql.Connection#isValid(int) */ @Override public boolean isValid(int arg0) { return false; } /** * @see java.sql.Connection#setClientInfo(java.util.Properties) */ @Override public void setClientInfo(Properties arg0) { } /** * @see java.sql.Connection#setClientInfo(java.lang.String, java.lang.String) */ @Override public void setClientInfo(String arg0, String arg1) { } /** * @see java.sql.Connection#setTypeMap(java.util.Map) */ @Override public void setTypeMap(Map> arg0) { } /** * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ @Override public boolean isWrapperFor(Class arg0) { return false; } /** * @see java.sql.Wrapper#unwrap(java.lang.Class) */ @Override public T unwrap(Class arg0) { return null; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestFileSupportImpl.java0000644000175000017500000001174311151703043024422 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.ByteArrayInputStream; import java.io.CharArrayReader; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.Writer; import java.sql.SQLException; import java.util.Arrays; import org.easymock.EasyMock; import org.easymock.IMocksControl; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Unit test for {@link FileSupportImpl}. * * @author Paul Ferraro * @since 1.1 */ @Test @SuppressWarnings("nls") public class TestFileSupportImpl implements FileSupport { private IMocksControl control = EasyMock.createStrictControl(); private FileSupport fileSupport = new FileSupportImpl(); @AfterMethod void reset() { this.fileSupport.close(); this.control.reset(); } /** * @see net.sf.hajdbc.sql.FileSupport#close() */ @Test public void close() { try { File file = this.fileSupport.createFile(new ByteArrayInputStream(new byte[0])); assert file.exists(); this.fileSupport.close(); assert !file.exists(); } catch (SQLException e) { assert false : e; } } @DataProvider(name = "inputStream") Object[][] inputStreamProvider() { return new Object[][] { new Object[] { new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 }) } }; } @Test(dataProvider = "inputStream") public void testCreateFile(InputStream inputStream) throws SQLException { File file = this.createFile(inputStream); assert file != null; assert file.exists(); assert file.getName().startsWith("ha-jdbc-") : file.getName(); assert file.getName().endsWith(".lob") : file.getName(); assert file.length() == 4 : file.length(); } /** * @see net.sf.hajdbc.sql.FileSupport#createFile(java.io.InputStream) */ @Override public File createFile(InputStream inputStream) throws SQLException { return this.fileSupport.createFile(inputStream); } @DataProvider(name = "reader") Object[][] readerProvider() { return new Object[][] { new Object[] { new CharArrayReader("abcd".toCharArray()) } }; } @Test(dataProvider = "reader") public void testCreateFile(Reader reader) throws SQLException { File file = this.createFile(reader); assert file != null; assert file.exists(); assert file.getName().startsWith("ha-jdbc-") : file.getName(); assert file.getName().endsWith(".lob") : file.getName(); assert file.length() == 4 : file.length(); } /** * @see net.sf.hajdbc.sql.FileSupport#createFile(java.io.Reader) */ @Override public File createFile(Reader reader) throws SQLException { return this.fileSupport.createFile(reader); } @DataProvider(name = "file") Object[][] fileProvider() throws IOException { File file = File.createTempFile("test", ".test"); Writer writer = new FileWriter(file); writer.write("abcd"); writer.flush(); writer.close(); return new Object[][] { new Object[] { file } }; } @Test(dataProvider = "file") public void testGetInputStream(File file) throws SQLException { InputStream inputStream = this.getInputStream(file); byte[] buffer = new byte[4]; assert inputStream != null; try { assert inputStream.read(buffer) == 4; assert Arrays.equals(buffer, "abcd".getBytes()); assert inputStream.read(buffer) < 0; } catch (IOException e) { assert false : e; } } /** * @see net.sf.hajdbc.sql.FileSupport#getInputStream(java.io.File) */ @Override public InputStream getInputStream(File file) throws SQLException { return this.fileSupport.getInputStream(file); } @Test(dataProvider = "file") public void testGetReader(File file) throws SQLException { Reader reader = this.getReader(file); char[] buffer = new char[4]; assert reader != null; try { assert reader.read(buffer) == 4; assert new String(buffer).equals("abcd"); assert reader.read(buffer) < 0; } catch (IOException e) { assert false : e; } } /** * @see net.sf.hajdbc.sql.FileSupport#getReader(java.io.File) */ @Override public Reader getReader(File file) throws SQLException { return this.fileSupport.getReader(file); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestClob.java0000644000175000017500000003721011216572372022213 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.sql.Clob; import java.sql.NClob; import java.sql.SQLException; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.MockDatabase; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test @SuppressWarnings({ "unchecked", "nls" }) public class TestClob implements NClob { private Balancer balancer = EasyMock.createStrictMock(Balancer.class); private DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); private Lock readLock = EasyMock.createStrictMock(Lock.class); private Lock writeLock1 = EasyMock.createStrictMock(Lock.class); private Lock writeLock2 = EasyMock.createStrictMock(Lock.class); private LockManager lockManager = EasyMock.createStrictMock(LockManager.class); private NClob clob1 = EasyMock.createStrictMock(NClob.class); private NClob clob2 = EasyMock.createStrictMock(NClob.class); private SQLProxy parent = EasyMock.createStrictMock(SQLProxy.class); private SQLProxy root = EasyMock.createStrictMock(SQLProxy.class); private Database database1 = new MockDatabase("1"); private Database database2 = new MockDatabase("2"); private Set databaseSet; private ExecutorService executor = Executors.newSingleThreadExecutor(); private NClob clob; private ClobInvocationHandler handler; @BeforeClass void init() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.clob1); map.put(this.database2, this.clob2); this.databaseSet = map.keySet(); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(ClobInvocationHandler.class)); this.replay(); this.handler = new ClobInvocationHandler(new Object(), this.parent, EasyMock.createMock(Invoker.class), map); this.clob = ProxyFactory.createProxy(NClob.class, this.handler); this.verify(); this.reset(); } private Object[] objects() { return new Object[] { this.cluster, this.balancer, this.clob1, this.clob2, this.readLock, this.writeLock1, this.writeLock2, this.lockManager, this.parent, this.root }; } void replay() { EasyMock.replay(this.objects()); } void verify() { EasyMock.verify(this.objects()); } @AfterMethod void reset() { EasyMock.reset(this.objects()); } /** * @see java.sql.Clob#free() */ @Test public void free() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.parent.removeChild(this.handler); this.clob1.free(); this.clob2.free(); this.replay(); this.clob.free(); this.verify(); } public void testGetAsciiStream() throws SQLException { InputStream input = new ByteArrayInputStream(new byte[0]); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.clob2.getAsciiStream()).andReturn(input); this.balancer.afterInvocation(this.database2); this.replay(); InputStream result = this.getAsciiStream(); this.verify(); assert result == input; } /** * @see java.sql.Clob#getAsciiStream() */ @Override public InputStream getAsciiStream() throws SQLException { return this.clob.getAsciiStream(); } public void testGetCharacterStream() throws SQLException { Reader reader = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.clob2.getCharacterStream()).andReturn(reader); this.balancer.afterInvocation(this.database2); this.replay(); Reader result = this.getCharacterStream(); this.verify(); assert result == reader; } /** * @see java.sql.Clob#getCharacterStream() */ @Override public Reader getCharacterStream() throws SQLException { return this.clob.getCharacterStream(); } @DataProvider(name = "long-long") Object[][] longLongProvider() { return new Object[][] { new Object[] { 1L, 1L } }; } @Test(dataProvider = "long-long") public void testGetCharacterStream(long position, long length) throws SQLException { Reader reader = new StringReader(""); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.clob2.getCharacterStream(position, length)).andReturn(reader); this.balancer.afterInvocation(this.database2); this.replay(); Reader result = this.getCharacterStream(position, length); this.verify(); assert result == reader; } /** * @see java.sql.Clob#getCharacterStream(long, long) */ @Override public Reader getCharacterStream(long position, long length) throws SQLException { return this.clob.getCharacterStream(position, length); } @DataProvider(name = "long-int") Object[][] longIntProvider() { return new Object[][] { new Object[] { 1L, 1 } }; } @Test(dataProvider = "long-int") public void testGetSubString(long position, int length) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.clob2.getSubString(position, length)).andReturn(""); this.balancer.afterInvocation(this.database2); this.replay(); String result = this.getSubString(position, length); this.verify(); assert result.equals(""); } /** * @see java.sql.Clob#getSubString(long, int) */ @Override public String getSubString(long position, int length) throws SQLException { return this.clob.getSubString(position, length); } public void testLength() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.clob2.length()).andReturn(1L); this.balancer.afterInvocation(this.database2); this.replay(); long result = this.length(); this.verify(); assert result == 1L; } /** * @see java.sql.Clob#length() */ @Override public long length() throws SQLException { return this.clob.length(); } @DataProvider(name = "string-long") Object[][] stringLongProvider() { return new Object[][] { new Object[] { "", 1L } }; } @Test(dataProvider = "string-long") public void testPosition(String pattern, long start) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.clob2.position(pattern, start)).andReturn(1L); this.balancer.afterInvocation(this.database2); this.replay(); long result = this.position(pattern, start); this.verify(); assert result == 1L; } /** * @see java.sql.Clob#position(java.lang.String, long) */ @Override public long position(String pattern, long start) throws SQLException { return this.clob.position(pattern, start); } @DataProvider(name = "clob-long") Object[][] clobLongProvider() { return new Object[][] { new Object[] { EasyMock.createMock(Clob.class), 1L } }; } @Test(dataProvider = "clob-long") public void testPosition(Clob pattern, long start) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.clob2.position(pattern, start)).andReturn(1L); this.balancer.afterInvocation(this.database2); this.replay(); long result = this.position(pattern, start); this.verify(); assert result == 1L; } /** * @see java.sql.Clob#position(java.sql.Clob, long) */ @Override public long position(Clob pattern, long start) throws SQLException { return this.clob.position(pattern, start); } @DataProvider(name = "long") Object[][] longProvider() { return new Object[][] { new Object[] { 1L } }; } @Test(dataProvider = "long") public void testSetAsciiStream(long position) throws SQLException { OutputStream output1 = new ByteArrayOutputStream(); OutputStream output2 = new ByteArrayOutputStream(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.clob1.setAsciiStream(position)).andReturn(output1); EasyMock.expect(this.clob2.setAsciiStream(position)).andReturn(output2); this.replay(); OutputStream result = this.setAsciiStream(position); this.verify(); assert result == output1; } /** * @see java.sql.Clob#setAsciiStream(long) */ @Override public OutputStream setAsciiStream(long position) throws SQLException { return this.clob.setAsciiStream(position); } @Test(dataProvider = "long") public void testSetCharacterStream(long position) throws SQLException { Writer writer1 = new StringWriter(); Writer writer2 = new StringWriter(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.clob1.setCharacterStream(position)).andReturn(writer1); EasyMock.expect(this.clob2.setCharacterStream(position)).andReturn(writer2); this.replay(); Writer result = this.setCharacterStream(position); this.verify(); assert result == writer1; } /** * @see java.sql.Clob#setCharacterStream(long) */ @Override public Writer setCharacterStream(long position) throws SQLException { return this.clob.setCharacterStream(position); } @DataProvider(name = "long-string") Object[][] longBytesProvider() { return new Object[][] { new Object[] { 1L, "" } }; } @Test(dataProvider = "long-string") public void testSetString(long position, String string) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.clob1.setString(position, string)).andReturn(1); EasyMock.expect(this.clob2.setString(position, string)).andReturn(1); this.replay(); int result = this.setString(position, string); this.verify(); assert result == 1; } /** * @see java.sql.Clob#setString(long, java.lang.String) */ @Override public int setString(long position, String string) throws SQLException { return this.clob.setString(position, string); } @DataProvider(name = "long-string-int-int") Object[][] longBytesIntIntProvider() { return new Object[][] { new Object[] { 1L, "", 1, 1 } }; } @Test(dataProvider = "long-string-int-int") public void testSetString(long position, String string, int offset, int length) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.clob1.setString(position, string, offset, length)).andReturn(1); EasyMock.expect(this.clob2.setString(position, string, offset, length)).andReturn(1); this.replay(); int result = this.setString(position, string, offset, length); this.verify(); assert result == 1; } /** * @see java.sql.Clob#setString(long, java.lang.String, int, int) */ @Override public int setString(long position, String string, int offset, int length) throws SQLException { return this.clob.setString(position, string, offset, length); } /** * @see java.sql.Clob#truncate(long) */ @Test(dataProvider = "long") public void truncate(long position) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.clob1.truncate(position); this.clob2.truncate(position); this.replay(); this.clob.truncate(position); this.verify(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/MockDataSourceFactory.java0000644000175000017500000000277411151703044024665 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.spi.ObjectFactory; /** * Mock data source factory that creates a mock data source that references a mock connection. * * @author Paul Ferraro * @since 1.1 */ public class MockDataSourceFactory implements ObjectFactory { /** * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable) */ public Object getObjectInstance(Object arg0, Name arg1, Context arg2, Hashtable arg3) throws Exception { return new MockDataSource(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/MockClob.java0000644000175000017500000000527111151703043022154 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.sql.Clob; import java.sql.NClob; /** * @author Paul Ferraro * */ public class MockClob implements NClob { /** * @see java.sql.Clob#free() */ public void free() { } /** * @see java.sql.Clob#getAsciiStream() */ public InputStream getAsciiStream() { return null; } /** * @see java.sql.Clob#getCharacterStream() */ public Reader getCharacterStream() { return new StringReader(""); //$NON-NLS-1$ } /** * @see java.sql.Clob#getCharacterStream(long, long) */ public Reader getCharacterStream(long arg0, long arg1) { return new StringReader(""); //$NON-NLS-1$ } /** * @see java.sql.Clob#getSubString(long, int) */ public String getSubString(long arg0, int arg1) { return null; } /** * @see java.sql.Clob#length() */ public long length() { return 0; } /** * @see java.sql.Clob#position(java.lang.String, long) */ public long position(String arg0, long arg1) { return 0; } /** * @see java.sql.Clob#position(java.sql.Clob, long) */ public long position(Clob arg0, long arg1) { return 0; } /** * @see java.sql.Clob#setAsciiStream(long) */ public OutputStream setAsciiStream(long arg0) { return null; } /** * @see java.sql.Clob#setCharacterStream(long) */ public Writer setCharacterStream(long arg0) { return null; } /** * @see java.sql.Clob#setString(long, java.lang.String) */ public int setString(long arg0, String arg1) { return 0; } /** * @see java.sql.Clob#setString(long, java.lang.String, int, int) */ public int setString(long arg0, String arg1, int arg2, int arg3) { return 0; } /** * @see java.sql.Clob#truncate(long) */ public void truncate(long arg0) { } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestConnection.java0000644000175000017500000015135011151703043023422 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Proxy; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLClientInfoException; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Savepoint; import java.sql.Statement; import java.sql.Struct; import java.util.Collections; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.MockDatabase; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.easymock.IAnswer; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Unit test for {@link Connection} * @author Paul Ferraro */ @SuppressWarnings({ "unchecked", "nls" }) @Test public class TestConnection implements Connection { private TransactionContext transactionContext = EasyMock.createStrictMock(TransactionContext.class); private Balancer balancer = EasyMock.createStrictMock(Balancer.class); private DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); private Dialect dialect = EasyMock.createStrictMock(Dialect.class); private DatabaseMetaDataCache cache = EasyMock.createStrictMock(DatabaseMetaDataCache.class); private DatabaseProperties databaseProperties = EasyMock.createStrictMock(DatabaseProperties.class); private TableProperties tableProperties = EasyMock.createStrictMock(TableProperties.class); private ColumnProperties columnProperties = EasyMock.createStrictMock(ColumnProperties.class); private Connection connection1 = EasyMock.createStrictMock(java.sql.Connection.class); private Connection connection2 = EasyMock.createStrictMock(java.sql.Connection.class); private SQLProxy parent = EasyMock.createStrictMock(SQLProxy.class); private SQLProxy root = EasyMock.createStrictMock(SQLProxy.class); private Savepoint savepoint1 = EasyMock.createStrictMock(Savepoint.class); private Savepoint savepoint2 = EasyMock.createStrictMock(Savepoint.class); private Database database1 = new MockDatabase("1"); private Database database2 = new MockDatabase("2"); private Set databaseSet; private ExecutorService executor = Executors.newSingleThreadExecutor(); private Connection connection; private ConnectionInvocationHandler handler; private IAnswer anwser = new IAnswer() { @Override public InvocationStrategy answer() throws Throwable { return (InvocationStrategy) EasyMock.getCurrentArguments()[0]; } }; @BeforeClass void init() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.connection1); map.put(this.database2, this.connection2); this.databaseSet = map.keySet(); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(ConnectionInvocationHandler.class)); this.replay(); this.handler = new ConnectionInvocationHandler(new Object(), this.parent, EasyMock.createMock(Invoker.class), map, this.transactionContext); this.connection = ProxyFactory.createProxy(Connection.class, this.handler); this.verify(); this.reset(); } private Object[] objects() { return new Object[] { this.cluster, this.balancer, this.connection1, this.connection2, this.parent, this.root, this.savepoint1, this.savepoint2, this.dialect, this.cache, this.databaseProperties, this.tableProperties, this.columnProperties, this.transactionContext }; } void replay() { EasyMock.replay(this.objects()); } void verify() { EasyMock.verify(this.objects()); } @AfterMethod void reset() { EasyMock.reset(this.objects()); } /** * @see java.sql.Connection#clearWarnings() */ @Override public void clearWarnings() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.clearWarnings(); this.connection2.clearWarnings(); this.replay(); this.connection.clearWarnings(); this.verify(); } /** * @see java.sql.Connection#close() */ @Override public void close() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.close(); this.connection2.close(); this.transactionContext.close(); this.parent.removeChild(this.handler); this.replay(); this.connection.close(); this.verify(); } /** * @see java.sql.Connection#commit() */ @Override public void commit() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.end(EasyMock.isA(DatabaseWriteInvocationStrategy.class))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.connection1.commit(); this.connection2.commit(); this.replay(); this.connection.commit(); this.verify(); } public void testCreateStatement() throws SQLException { Statement statement1 = EasyMock.createMock(Statement.class); Statement statement2 = EasyMock.createMock(Statement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.createStatement()).andReturn(statement1); EasyMock.expect(this.connection2.createStatement()).andReturn(statement2); this.replay(); Statement result = this.createStatement(); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#createStatement() */ @Override public Statement createStatement() throws SQLException { return this.connection.createStatement(); } @DataProvider(name = "int-int") Object[][] intIntProvider() { return new Object[][] { new Object[] { ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY }, new Object[] { ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY }, new Object[] { ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY }, new Object[] { ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE }, new Object[] { ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE }, new Object[] { ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE }, }; } @Test(dataProvider = "int-int") public void testCreateStatement(int type, int concurrency) throws SQLException { Statement statement1 = EasyMock.createMock(Statement.class); Statement statement2 = EasyMock.createMock(Statement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.createStatement(type, concurrency)).andReturn(statement1); EasyMock.expect(this.connection2.createStatement(type, concurrency)).andReturn(statement2); this.replay(); Statement result = this.createStatement(type, concurrency); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#createStatement(int, int) */ @Override public Statement createStatement(int type, int concurrency) throws SQLException { return this.connection.createStatement(type, concurrency); } @DataProvider(name = "int-int-int") Object[][] intIntIntProvider() { return new Object[][] { new Object[] { ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT }, }; } @Test(dataProvider = "int-int-int") public void testCreateStatement(int type, int concurrency, int holdability) throws SQLException { Statement statement1 = EasyMock.createMock(Statement.class); Statement statement2 = EasyMock.createMock(Statement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.createStatement(type, concurrency, holdability)).andReturn(statement1); EasyMock.expect(this.connection2.createStatement(type, concurrency, holdability)).andReturn(statement2); this.replay(); Statement result = this.createStatement(type, concurrency, holdability); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#createStatement(int, int, int) */ @Override public Statement createStatement(int type, int concurrency, int holdability) throws SQLException { return this.connection.createStatement(type, concurrency, holdability); } public void testGetAutoCommit() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.getAutoCommit()).andReturn(true); this.replay(); boolean autoCommit = this.getAutoCommit(); this.verify(); assert autoCommit; } /** * @see java.sql.Connection#getAutoCommit() */ @Override public boolean getAutoCommit() throws SQLException { return this.connection.getAutoCommit(); } public void testGetCatalog() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.getCatalog()).andReturn("catalog"); this.replay(); String catalog = this.getCatalog(); this.verify(); assert catalog.equals("catalog") : catalog; } /** * @see java.sql.Connection#getCatalog() */ @Override public String getCatalog() throws SQLException { return this.connection.getCatalog(); } public void testGetHoldability() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.getHoldability()).andReturn(ResultSet.HOLD_CURSORS_OVER_COMMIT); this.replay(); int holdability = this.getHoldability(); this.verify(); assert holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT : holdability; } /** * @see java.sql.Connection#getHoldability() */ @Override public int getHoldability() throws SQLException { return this.connection.getHoldability(); } public void testGetMetaData() throws SQLException { DatabaseMetaData metaData = EasyMock.createMock(DatabaseMetaData.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.connection2.getMetaData()).andReturn(metaData); this.balancer.afterInvocation(this.database2); this.replay(); DatabaseMetaData result = this.getMetaData(); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database2) == metaData; } /** * @see java.sql.Connection#getMetaData() */ @Override public DatabaseMetaData getMetaData() throws SQLException { return this.connection.getMetaData(); } public void testGetTransactionIsolation() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.connection2.getTransactionIsolation()).andReturn(java.sql.Connection.TRANSACTION_NONE); this.balancer.afterInvocation(this.database2); this.replay(); int isolation = this.getTransactionIsolation(); this.verify(); assert isolation == java.sql.Connection.TRANSACTION_NONE : isolation; } /** * @see java.sql.Connection#getTransactionIsolation() */ @Override public int getTransactionIsolation() throws SQLException { return this.connection.getTransactionIsolation(); } public void testGetTypeMap() throws SQLException { Map> map = Collections.emptyMap(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.getTypeMap()).andReturn(map); this.replay(); Map> result = this.getTypeMap(); this.verify(); assert result == map; } /** * @see java.sql.Connection#getTypeMap() */ @Override public Map> getTypeMap() throws SQLException { return this.connection.getTypeMap(); } public void testGetWarnings() throws SQLException { SQLWarning warning = new SQLWarning(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.getWarnings()).andReturn(warning); this.replay(); SQLWarning result = this.getWarnings(); this.verify(); assert result == warning; } /** * @see java.sql.Connection#getWarnings() */ @Override public SQLWarning getWarnings() throws SQLException { return this.connection.getWarnings(); } public void testIsClosed() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.isClosed()).andReturn(true); this.replay(); boolean closed = this.isClosed(); this.verify(); assert closed; } /** * @see java.sql.Connection#isClosed() */ @Override public boolean isClosed() throws SQLException { return this.connection.isClosed(); } public void testIsReadOnly() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.isReadOnly()).andReturn(true); this.replay(); boolean readOnly = this.isReadOnly(); this.verify(); assert readOnly; } /** * @see java.sql.Connection#isReadOnly() */ @Override public boolean isReadOnly() throws SQLException { return this.connection.isReadOnly(); } public void testNativeSQL() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.nativeSQL("sql")).andReturn("native-sql"); this.replay(); String nativeSQL = this.nativeSQL("sql"); this.verify(); assert nativeSQL.equals("native-sql") : nativeSQL; } /** * @see java.sql.Connection#nativeSQL(java.lang.String) */ @Override public String nativeSQL(String sql) throws SQLException { return this.connection.nativeSQL(sql); } @DataProvider(name = "string") Object[][] stringProvider() { return new Object[][] { new Object[] { "sql" } }; } @Test(dataProvider = "string") public void testPrepareCall(String sql) throws SQLException { CallableStatement statement1 = EasyMock.createMock(CallableStatement.class); CallableStatement statement2 = EasyMock.createMock(CallableStatement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.prepareCall(sql)).andReturn(statement1); EasyMock.expect(this.connection2.prepareCall(sql)).andReturn(statement2); this.replay(); CallableStatement result = this.prepareCall(sql); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#prepareCall(java.lang.String) */ @Override public CallableStatement prepareCall(String sql) throws SQLException { return this.connection.prepareCall(sql); } @DataProvider(name = "string-int-int") Object[][] stringIntIntProvider() { return new Object[][] { new Object[] { "sql", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY }, new Object[] { "sql", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY }, new Object[] { "sql", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY }, new Object[] { "sql", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE }, new Object[] { "sql", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE }, new Object[] { "sql", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE }, }; } @Test(dataProvider = "string-int-int") public void testPrepareCall(String sql, int type, int concurrency) throws SQLException { CallableStatement statement1 = EasyMock.createMock(CallableStatement.class); CallableStatement statement2 = EasyMock.createMock(CallableStatement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.prepareCall(sql, type, concurrency)).andReturn(statement1); EasyMock.expect(this.connection2.prepareCall(sql, type, concurrency)).andReturn(statement2); this.replay(); CallableStatement result = this.prepareCall(sql, type, concurrency); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#prepareCall(java.lang.String, int, int) */ @Override public CallableStatement prepareCall(String sql, int type, int concurrency) throws SQLException { return this.connection.prepareCall(sql, type, concurrency); } @DataProvider(name = "string-int-int-int") Object[][] stringIntIntIntProvider() { return new Object[][] { new Object[] { "sql", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { "sql", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { "sql", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { "sql", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { "sql", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { "sql", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { "sql", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { "sql", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { "sql", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { "sql", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { "sql", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT }, new Object[] { "sql", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT }, }; } @Test(dataProvider = "string-int-int-int") public void testPrepareCall(String sql, int type, int concurrency, int holdability) throws SQLException { CallableStatement statement1 = EasyMock.createMock(CallableStatement.class); CallableStatement statement2 = EasyMock.createMock(CallableStatement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.prepareCall(sql, type, concurrency, holdability)).andReturn(statement1); EasyMock.expect(this.connection2.prepareCall(sql, type, concurrency, holdability)).andReturn(statement2); this.replay(); CallableStatement result = this.prepareCall(sql, type, concurrency, holdability); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#prepareCall(java.lang.String, int, int, int) */ @Override public CallableStatement prepareCall(String sql, int type, int concurrency, int holdability) throws SQLException { return this.connection.prepareCall(sql, type, concurrency, holdability); } @Test(dataProvider = "string") public void testPrepareStatement(String sql) throws SQLException { PreparedStatement statement1 = EasyMock.createMock(PreparedStatement.class); PreparedStatement statement2 = EasyMock.createMock(PreparedStatement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.prepareStatement(sql)).andReturn(statement1); EasyMock.expect(this.connection2.prepareStatement(sql)).andReturn(statement2); this.extractIdentifiers(sql); this.replay(); PreparedStatement result = this.prepareStatement(sql); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#prepareStatement(java.lang.String) */ @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return this.connection.prepareStatement(sql); } @DataProvider(name = "string-int") Object[][] stringIntProvider() { return new Object[][] { new Object[] { "sql", Statement.NO_GENERATED_KEYS }, new Object[] { "sql", Statement.RETURN_GENERATED_KEYS }, }; } @Test(dataProvider = "string-int") public void testPrepareStatement(String sql, int autoGeneratedKeys) throws SQLException { PreparedStatement statement1 = EasyMock.createMock(PreparedStatement.class); PreparedStatement statement2 = EasyMock.createMock(PreparedStatement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.prepareStatement(sql, autoGeneratedKeys)).andReturn(statement1); EasyMock.expect(this.connection2.prepareStatement(sql, autoGeneratedKeys)).andReturn(statement2); this.extractIdentifiers(sql); this.replay(); PreparedStatement result = this.prepareStatement(sql, autoGeneratedKeys); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, int) */ @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { return this.connection.prepareStatement(sql, autoGeneratedKeys); } @Test(dataProvider = "string-int-int") public void testPrepareStatement(String sql, int type, int concurrency) throws SQLException { PreparedStatement statement1 = EasyMock.createMock(PreparedStatement.class); PreparedStatement statement2 = EasyMock.createMock(PreparedStatement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.prepareStatement(sql, type, concurrency)).andReturn(statement1); EasyMock.expect(this.connection2.prepareStatement(sql, type, concurrency)).andReturn(statement2); this.extractIdentifiers(sql); this.replay(); PreparedStatement result = this.prepareStatement(sql, type, concurrency); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, int, int) */ @Override public PreparedStatement prepareStatement(String sql, int type, int concurrency) throws SQLException { return this.connection.prepareStatement(sql, type, concurrency); } @Test(dataProvider = "string-int-int-int") public void testPrepareStatement(String sql, int type, int concurrency, int holdability) throws SQLException { PreparedStatement statement1 = EasyMock.createMock(PreparedStatement.class); PreparedStatement statement2 = EasyMock.createMock(PreparedStatement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.prepareStatement(sql, type, concurrency, holdability)).andReturn(statement1); EasyMock.expect(this.connection2.prepareStatement(sql, type, concurrency, holdability)).andReturn(statement2); this.extractIdentifiers(sql); this.replay(); PreparedStatement result = this.prepareStatement(sql, type, concurrency, holdability); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, int, int, int) */ @Override public PreparedStatement prepareStatement(String sql, int type, int concurrency, int holdability) throws SQLException { return this.connection.prepareStatement(sql, type, concurrency, holdability); } @DataProvider(name = "string-ints") Object[][] stringIntsProvider() { return new Object[][] { new Object[] { "sql", new int[] { 1 } } }; } @Test(dataProvider = "string-ints") public void testPrepareStatement(String sql, int[] columnIndexes) throws SQLException { PreparedStatement statement1 = EasyMock.createMock(PreparedStatement.class); PreparedStatement statement2 = EasyMock.createMock(PreparedStatement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.prepareStatement(sql, columnIndexes)).andReturn(statement1); EasyMock.expect(this.connection2.prepareStatement(sql, columnIndexes)).andReturn(statement2); this.extractIdentifiers(sql); this.replay(); PreparedStatement result = this.prepareStatement(sql, columnIndexes); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, int[]) */ @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { return this.connection.prepareStatement(sql, columnIndexes); } @DataProvider(name = "string-strings") Object[][] stringStringsProvider() { return new Object[][] { new Object[] { "sql", new String[] { "col1" } } }; } @Test(dataProvider = "string-strings") public void testPrepareStatement(String sql, String[] columnNames) throws SQLException { PreparedStatement statement1 = EasyMock.createMock(PreparedStatement.class); PreparedStatement statement2 = EasyMock.createMock(PreparedStatement.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.isCurrentTimestampEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentDateEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isCurrentTimeEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.isRandEvaluationEnabled()).andReturn(false); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.prepareStatement(sql, columnNames)).andReturn(statement1); EasyMock.expect(this.connection2.prepareStatement(sql, columnNames)).andReturn(statement2); this.extractIdentifiers(sql); this.replay(); PreparedStatement result = this.connection.prepareStatement(sql, columnNames); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == statement1; assert proxy.getObject(this.database2) == statement2; } /** * @see java.sql.Connection#prepareStatement(java.lang.String, java.lang.String[]) */ @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { return this.connection.prepareStatement(sql, columnNames); } @DataProvider(name = "savepoint") Object[][] savepointProvider() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.savepoint1); map.put(this.database2, this.savepoint2); return new Object[][] { new Object[] { ProxyFactory.createProxy(Savepoint.class, new SavepointInvocationHandler(this.connection, this.handler, EasyMock.createMock(Invoker.class), map)) } }; } /** * @see java.sql.Connection#releaseSavepoint(Savepoint) */ @Test(dataProvider = "savepoint") public void releaseSavepoint(Savepoint savepoint) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.connection1.releaseSavepoint(this.savepoint1); this.connection2.releaseSavepoint(this.savepoint2); this.replay(); this.connection.releaseSavepoint(savepoint); this.verify(); } /** * @see java.sql.Connection#rollback() */ @Test public void rollback() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.end(EasyMock.isA(DatabaseWriteInvocationStrategy.class))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.connection1.rollback(); this.connection2.rollback(); this.replay(); this.connection.rollback(); this.verify(); } /** * @see java.sql.Connection#rollback(Savepoint) */ @Test(dataProvider = "savepoint") public void rollback(Savepoint savepoint) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.transactionContext.end(EasyMock.isA(DatabaseWriteInvocationStrategy.class))).andAnswer(this.anwser); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.connection1.rollback(this.savepoint1); this.connection2.rollback(this.savepoint2); this.replay(); this.connection.rollback(savepoint); this.verify(); } @DataProvider(name = "boolean") Object[][] booleanProvider() { return new Object[][] { new Object[] { true } }; } /** * @see java.sql.Connection#setAutoCommit(boolean) */ @Test(dataProvider = "boolean") public void setAutoCommit(boolean autoCommit) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.setAutoCommit(autoCommit); this.connection2.setAutoCommit(autoCommit); this.replay(); this.connection.setAutoCommit(autoCommit); this.verify(); } /** * @see java.sql.Connection#setCatalog(java.lang.String) */ @Test(dataProvider = "string") public void setCatalog(String catalog) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.connection1.setCatalog(catalog); this.connection2.setCatalog(catalog); this.replay(); this.connection.setCatalog(catalog); this.verify(); } @DataProvider(name = "holdability") Object[][] holdabilityProvider() { return new Object[][] { new Object[] { ResultSet.CLOSE_CURSORS_AT_COMMIT }, new Object[] { ResultSet.HOLD_CURSORS_OVER_COMMIT }, }; } /** * @see java.sql.Connection#setHoldability(int) */ @Test(dataProvider = "holdability") public void setHoldability(int holdability) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.setHoldability(holdability); this.connection2.setHoldability(holdability); this.replay(); this.connection.setHoldability(holdability); this.verify(); } /** * @see java.sql.Connection#setReadOnly(boolean) */ @Test(dataProvider = "boolean") public void setReadOnly(boolean readOnly) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.connection1.setReadOnly(readOnly); this.connection2.setReadOnly(readOnly); this.replay(); this.connection.setReadOnly(readOnly); this.verify(); } public void testSetSavepoint() throws SQLException { Savepoint savepoint1 = EasyMock.createMock(Savepoint.class); Savepoint savepoint2 = EasyMock.createMock(Savepoint.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.setSavepoint()).andReturn(savepoint1); EasyMock.expect(this.connection2.setSavepoint()).andReturn(savepoint2); this.replay(); Savepoint result = this.setSavepoint(); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == savepoint1; assert proxy.getObject(this.database2) == savepoint2; } /** * @see java.sql.Connection#setSavepoint() */ @Override public Savepoint setSavepoint() throws SQLException { return this.connection.setSavepoint(); } @Test(dataProvider = "string") public void testSetSavepoint(String name) throws SQLException { Savepoint savepoint1 = EasyMock.createMock(Savepoint.class); Savepoint savepoint2 = EasyMock.createMock(Savepoint.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.setSavepoint(name)).andReturn(savepoint1); EasyMock.expect(this.connection2.setSavepoint(name)).andReturn(savepoint2); this.replay(); Savepoint result = this.setSavepoint(name); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == savepoint1; assert proxy.getObject(this.database2) == savepoint2; } /** * @see java.sql.Connection#setSavepoint(java.lang.String) */ @Override public Savepoint setSavepoint(String name) throws SQLException { return this.connection.setSavepoint(name); } @DataProvider(name = "isolation") Object[][] isolationProvider() { return new Object[][] { new Object[] { java.sql.Connection.TRANSACTION_NONE } }; } /** * @see java.sql.Connection#setTransactionIsolation(int) */ @Test(dataProvider = "isolation") public void setTransactionIsolation(int level) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.connection1.setTransactionIsolation(level); this.connection2.setTransactionIsolation(level); this.replay(); this.connection.setTransactionIsolation(level); this.verify(); } @DataProvider(name = "map") Object[][] mapProvider() { return new Object[][] { new Object[] { Collections.EMPTY_MAP } }; } /** * @see java.sql.Connection#setTypeMap(java.util.Map) */ @Test(dataProvider = "map") public void setTypeMap(Map> map) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.setTypeMap(map); this.connection2.setTypeMap(map); this.replay(); this.connection.setTypeMap(map); this.verify(); } public void testCreateArrayOf() throws SQLException { Object[] objects = new Object[0]; Array array = EasyMock.createMock(Array.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.createArrayOf("", objects)).andReturn(array); this.replay(); Array result = this.createArrayOf("", objects); this.verify(); assert result == array; } /** * @see java.sql.Connection#createArrayOf(java.lang.String, java.lang.Object[]) */ @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { return this.connection.createArrayOf(typeName, elements); } public void testCreateBlob() throws SQLException { Blob blob = EasyMock.createMock(Blob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.createBlob()).andReturn(blob); this.replay(); Blob result = this.createBlob(); this.verify(); assert result == blob; } /** * @see java.sql.Connection#createBlob() */ @Override public Blob createBlob() throws SQLException { return this.connection.createBlob(); } public void testCreateClob() throws SQLException { Clob clob = EasyMock.createMock(Clob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.createClob()).andReturn(clob); this.replay(); Clob result = this.createClob(); this.verify(); assert result == clob; } /** * @see java.sql.Connection#createClob() */ @Override public Clob createClob() throws SQLException { return this.connection.createClob(); } public void testCreateNClob() throws SQLException { NClob clob = EasyMock.createMock(NClob.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.createNClob()).andReturn(clob); this.replay(); NClob result = this.createNClob(); this.verify(); assert result == clob; } /** * @see java.sql.Connection#createNClob() */ @Override public NClob createNClob() throws SQLException { return this.connection.createNClob(); } public void testCreateSQLXML() throws SQLException { SQLXML xml = EasyMock.createMock(SQLXML.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.createSQLXML()).andReturn(xml); this.replay(); SQLXML result = this.createSQLXML(); this.verify(); assert result == xml; } /** * @see java.sql.Connection#createSQLXML() */ @Override public SQLXML createSQLXML() throws SQLException { return this.connection.createSQLXML(); } public void testCreateStruct() throws SQLException { Object[] elements = new Object[0]; Struct struct = EasyMock.createMock(Struct.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.createStruct("", elements)).andReturn(struct); this.replay(); Struct result = this.createStruct("", elements); this.verify(); assert result == struct; } /** * @see java.sql.Connection#createStruct(java.lang.String, java.lang.Object[]) */ @Override public Struct createStruct(String typeName, Object[] elements) throws SQLException { return this.connection.createStruct(typeName, elements); } public void testGetClientInfo() throws SQLException { Properties properties = new Properties(); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.getClientInfo()).andReturn(properties); this.replay(); Properties result = this.getClientInfo(); this.verify(); assert result == properties; } /** * @see java.sql.Connection#getClientInfo() */ @Test public Properties getClientInfo() throws SQLException { return this.connection.getClientInfo(); } @Test(dataProvider = "string") public void testGetClientInfo(String property) throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.getClientInfo(property)).andReturn("value"); this.replay(); String result = this.getClientInfo(property); this.verify(); assert result.equals("value"); } /** * @see java.sql.Connection#getClientInfo(java.lang.String) */ @Override public String getClientInfo(String property) throws SQLException { return this.connection.getClientInfo(property); } public void testIsValid() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.next()).andReturn(this.database2); this.balancer.beforeInvocation(this.database2); EasyMock.expect(this.connection2.isValid(1)).andReturn(true); this.balancer.afterInvocation(this.database2); this.replay(); boolean result = this.isValid(1); this.verify(); assert result; } /** * @see java.sql.Connection#isValid(int) */ @Test(dataProvider = "int") public boolean isValid(int timeout) throws SQLException { return this.connection.isValid(timeout); } @DataProvider(name = "properties") Object[][] propertiesProvider() { return new Object[][] { new Object[] { new Properties() } }; } /** * @see java.sql.Connection#setClientInfo(java.util.Properties) */ @Test(dataProvider = "properties") public void setClientInfo(Properties properties) throws SQLClientInfoException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.setClientInfo(properties); this.connection2.setClientInfo(properties); this.replay(); this.connection.setClientInfo(properties); this.verify(); } @DataProvider(name = "string-string") Object[][] stringStringProvider() { return new Object[][] { new Object[] { "name", "value" } }; } /** * @see java.sql.Connection#setClientInfo(java.lang.String, java.lang.String) */ @Test(dataProvider = "string-string") public void setClientInfo(String property, String value) throws SQLClientInfoException { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.setClientInfo(property, value); this.connection2.setClientInfo(property, value); this.replay(); this.connection.setClientInfo(property, value); this.verify(); } public void testIsWrapperFor() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.isWrapperFor(Connection.class)).andReturn(true); this.replay(); boolean result = this.isWrapperFor(Connection.class); this.verify(); assert result; } /** * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ @Override public boolean isWrapperFor(Class targetClass) throws SQLException { return this.connection.isWrapperFor(targetClass); } public void testUnwrap() throws SQLException { Connection connection = EasyMock.createMock(Connection.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.connection1.unwrap(Connection.class)).andReturn(connection); this.replay(); Connection result = this.connection.unwrap(Connection.class); this.verify(); assert result == connection; } /** * @see java.sql.Wrapper#unwrap(java.lang.Class) */ @Override public T unwrap(Class targetClass) throws SQLException { return this.connection.unwrap(targetClass); } protected void extractIdentifiers(String sql) throws SQLException { EasyMock.expect(this.cluster.isSequenceDetectionEnabled()).andReturn(false); EasyMock.expect(this.cluster.isIdentityColumnDetectionEnabled()).andReturn(false); EasyMock.expect(this.cluster.getDatabaseMetaDataCache()).andReturn(this.cache); EasyMock.expect(this.cache.getDatabaseProperties(EasyMock.same(this.connection))).andReturn(this.databaseProperties); EasyMock.expect(this.databaseProperties.supportsSelectForUpdate()).andReturn(false); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestDriverDatabase.java0000644000175000017500000001605511151703043024205 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import javax.management.DynamicMBean; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Unit test for {@link DriverDatabase} * @author Paul Ferraro * @since 1.0 */ @SuppressWarnings("nls") public class TestDriverDatabase extends TestDatabase implements InactiveDriverDatabaseMBean { static { try { DriverManager.registerDriver(new MockDriver(null)); } catch (SQLException e) { assert false : e; } } /** * @see net.sf.hajdbc.sql.TestDatabase#createDatabase(java.lang.String) */ @Override protected DriverDatabase createDatabase(String id) { DriverDatabase database = new DriverDatabase(); database.setId(id); return database; } private Driver driver = EasyMock.createStrictMock(Driver.class); void replay() { EasyMock.replay(this.driver); } void verify() { EasyMock.verify(this.driver); EasyMock.reset(this.driver); } @DataProvider(name = "driver-class") public Object[][] driverClassProvider() { return new Object[][] { new Object[] { MockDriver.class.getName() }, new Object[] { Object.class.getName() }, new Object[] { "invalid.class" }, new Object[] { "" }, new Object[] { null } }; } @Test(dataProvider = "driver-class") public void setDriver(String driver) { boolean isDriver = false; try { isDriver = (driver == null) || driver.isEmpty() || Driver.class.isAssignableFrom(Class.forName(driver)); } catch (ClassNotFoundException e) { // Ignore } this.database.clean(); try { this.database.setDriver(driver); assert isDriver : driver; if ((driver == null) || driver.isEmpty()) { assert !this.database.isDirty(); } else { assert this.database.isDirty(); this.database.clean(); } this.database.setDriver(driver); assert !this.database.isDirty(); } catch (IllegalArgumentException e) { assert !isDriver : driver; assert !this.database.isDirty(); } } @DataProvider(name = "driver") Object[][] driverProvider() { return new Object[][] { new Object[] { this.driver } }; } /** * @see net.sf.hajdbc.sql.TestDatabase#testConnect() */ @Override public void testConnect() throws SQLException { this.database.setUrl("jdbc:mock:test"); Connection connection = EasyMock.createMock(Connection.class); EasyMock.expect(this.driver.connect("jdbc:mock:test", new Properties())).andReturn(connection); this.replay(); Connection result = this.database.connect(this.driver); this.verify(); assert connection == result; this.database.setUser("a"); this.database.setPassword("b"); Properties properties = new Properties(); properties.setProperty("user", "a"); properties.setProperty("password", "b"); EasyMock.expect(this.driver.connect("jdbc:mock:test", properties)).andReturn(connection); this.replay(); result = this.database.connect(this.driver); this.verify(); assert result == connection; this.database.setProperty("ssl", "true"); EasyMock.expect(this.driver.connect("jdbc:mock:test", properties)).andReturn(connection); this.replay(); result = this.database.connect(this.driver); this.verify(); assert result == connection; } /** * @see net.sf.hajdbc.sql.TestDatabase#testCreateConnectionFactory() */ @Override public void testCreateConnectionFactory() { this.database.setDriver(MockDriver.class.getName()); this.database.setUrl("jdbc:mock:test"); Driver driver = this.database.createConnectionFactory(); assert driver.getClass().equals(MockDriver.class) : driver.getClass().getName(); } /** * @see net.sf.hajdbc.sql.TestDatabase#testGetActiveMBean() */ @Override public void testGetActiveMBean() { DynamicMBean mbean = this.getActiveMBean(); String className = mbean.getMBeanInfo().getClassName(); try { assert ActiveDriverDatabaseMBean.class.isAssignableFrom(Class.forName(className)) : className; } catch (ClassNotFoundException e) { assert false : e; } } /** * @see net.sf.hajdbc.sql.TestDatabase#testGetInactiveMBean() */ @Override public void testGetInactiveMBean() { DynamicMBean mbean = this.getInactiveMBean(); String className = mbean.getMBeanInfo().getClassName(); try { assert InactiveDriverDatabaseMBean.class.isAssignableFrom(Class.forName(className)) : className; } catch (ClassNotFoundException e) { assert false : e; } } @DataProvider(name = "url") Object[][] urlProvider() { return new Object[][] { new Object[] { "jdbc:mock:test" }, new Object[] { "jdbc:invalid" } }; } /** * @see net.sf.hajdbc.sql.InactiveDriverDatabaseMBean#setUrl(java.lang.String) */ @Test(dataProvider = "url") public void setUrl(String url) { this.database.clean(); boolean accepted = url.startsWith("jdbc:mock"); try { this.database.setUrl(url); assert accepted : url; String value = this.database.getUrl(); assert value.equals(url) : value; assert this.database.isDirty(); this.database.clean(); assert !this.database.isDirty(); this.database.setUrl(url); assert !this.database.isDirty(); } catch (IllegalArgumentException e) { assert !accepted : url; assert !this.database.isDirty(); } } public void testGetUrl() { String url = this.getUrl(); assert url == null : url; this.database.setUrl("jdbc:mock:test"); url = this.getUrl(); assert url.equals("jdbc:mock:test") : url; } /** * @see net.sf.hajdbc.sql.ActiveDriverDatabaseMBean#getUrl() */ @Override public String getUrl() { return this.database.getUrl(); } public void testGetDriver() { String driver = this.getDriver(); assert driver == null : driver; this.database.setDriver(MockDriver.class.getName()); driver = this.getDriver(); assert driver.equals(MockDriver.class.getName()) : driver; } /** * @see net.sf.hajdbc.sql.ActiveDriverDatabaseMBean#getDriver() */ @Override public String getDriver() { return this.database.getDriver(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/pool/0000755000175000017500000000000011674455606020607 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/pool/TestConnectionPoolDataSourceDatabase.java0000644000175000017500000000673111151703043030627 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.sql.Connection; import java.sql.SQLException; import javax.naming.spi.ObjectFactory; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import net.sf.hajdbc.sql.TestCommonDataSourceDatabase; import org.easymock.EasyMock; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test @SuppressWarnings("nls") public class TestConnectionPoolDataSourceDatabase extends TestCommonDataSourceDatabase { public TestConnectionPoolDataSourceDatabase() { super(ConnectionPoolDataSource.class); } /** * @see net.sf.hajdbc.sql.TestDatabase#createDatabase(java.lang.String) */ @Override protected ConnectionPoolDataSourceDatabase createDatabase(String id) { ConnectionPoolDataSourceDatabase database = new ConnectionPoolDataSourceDatabase(); database.setId(id); return database; } /** * @see net.sf.hajdbc.sql.TestCommonDataSourceDatabase#mockDataSourceClass() */ @Override protected Class mockDataSourceClass() { return MockConnectionPoolDataSource.class; } /** * @see net.sf.hajdbc.sql.TestCommonDataSourceDatabase#objectFactoryClass() */ @Override protected Class objectFactoryClass() { return MockConnectionPoolDataSourceFactory.class; } /** * @see net.sf.hajdbc.sql.TestDatabase#testConnect() */ @Override public void testConnect() throws SQLException { ConnectionPoolDataSource dataSource = EasyMock.createStrictMock(ConnectionPoolDataSource.class); PooledConnection pooledConnection = EasyMock.createStrictMock(PooledConnection.class); Connection connection = EasyMock.createMock(Connection.class); EasyMock.expect(dataSource.getPooledConnection()).andReturn(pooledConnection); EasyMock.expect(pooledConnection.getConnection()).andReturn(connection); EasyMock.replay(dataSource, pooledConnection); Connection result = this.connect(dataSource); EasyMock.verify(dataSource, pooledConnection); assert result == connection : result.getClass().getName(); EasyMock.reset(dataSource, pooledConnection); this.database.setUser("user"); this.database.setPassword("password"); EasyMock.expect(dataSource.getPooledConnection("user", "password")).andReturn(pooledConnection); EasyMock.expect(pooledConnection.getConnection()).andReturn(connection); EasyMock.replay(dataSource, pooledConnection); result = this.database.connect(dataSource); EasyMock.verify(dataSource, pooledConnection); assert result == connection : result.getClass().getName(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/pool/TestPooledConnection.java0000644000175000017500000000243711151703043025537 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import javax.sql.PooledConnection; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test public class TestPooledConnection extends AbstractTestPooledConnection { /** * @see net.sf.hajdbc.sql.pool.AbstractTestPooledConnection#getConnectionClass() */ @Override protected Class getConnectionClass() { return PooledConnection.class; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/pool/MockConnectionPoolDataSourceFactory.java0000644000175000017500000000270011151703043030474 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.spi.ObjectFactory; /** * @author Paul Ferraro * */ public class MockConnectionPoolDataSourceFactory implements ObjectFactory { /** * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable) */ @Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { return new MockConnectionPoolDataSource(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/pool/MockConnectionPoolDataSource.java0000644000175000017500000000325711151703043027154 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.sql.SQLException; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import org.easymock.EasyMock; import net.sf.hajdbc.sql.MockCommonDataSource; /** * @author Paul Ferraro * */ public class MockConnectionPoolDataSource extends MockCommonDataSource implements ConnectionPoolDataSource { /** * @see javax.sql.ConnectionPoolDataSource#getPooledConnection() */ @Override public PooledConnection getPooledConnection() throws SQLException { return EasyMock.createMock(PooledConnection.class); } /** * @see javax.sql.ConnectionPoolDataSource#getPooledConnection(java.lang.String, java.lang.String) */ @Override public PooledConnection getPooledConnection(String arg0, String arg1) throws SQLException { return this.getPooledConnection(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/pool/TestConnectionPoolDataSourceFactory.java0000644000175000017500000001226711151703043030533 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.lang.reflect.Proxy; import java.sql.Driver; import java.sql.SQLException; import java.util.Hashtable; import java.util.Properties; import java.util.prefs.Preferences; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Name; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; import javax.sql.ConnectionPoolDataSource; import net.sf.hajdbc.local.LocalStateManager; import net.sf.hajdbc.sql.MockInitialContextFactory; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test public class TestConnectionPoolDataSourceFactory implements ObjectFactory { private ConnectionPoolDataSourceFactory factory = new ConnectionPoolDataSourceFactory(); private Context context; @BeforeClass protected void setUp() throws Exception { Preferences.userNodeForPackage(LocalStateManager.class).put("test-pool-datasource-cluster", "datasource1,datasource2"); Properties properties = new Properties(); properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, MockInitialContextFactory.class.getName()); this.context = new InitialContext(properties); Reference reference = new Reference(ConnectionPoolDataSourceFactory.class.getName(), MockConnectionPoolDataSourceFactory.class.getName(), null); this.context.bind("datasource1", reference); this.context.bind("datasource2", reference); this.context.bind("datasource", new ConnectionPoolDataSourceReference("test-pool-datasource-cluster")); } @AfterClass protected void tearDown() throws Exception { this.context.unbind("datasource"); this.context.unbind("datasource1"); this.context.unbind("datasource2"); Preferences.userNodeForPackage(LocalStateManager.class).remove("test-pool-datasource-cluster"); } @DataProvider(name = "factory") Object[][] objectInstanceProvider() { return new Object[][] { new Object[] { null, null, null, null }, new Object[] { new Object(), null, null, null }, new Object[] { new Reference(ConnectionPoolDataSource.class.getName(), new StringRefAddr("cluster", "test-pool-datasource-cluster")), null, null, null }, new Object[] { new Reference(ConnectionPoolDataSource.class.getName(), new StringRefAddr("cluster", null)), null, null, null }, new Object[] { new Reference(Driver.class.getName(), new StringRefAddr("cluster", "test-pool-datasource-cluster")), null, null, null }, new Object[] { new Reference(ConnectionPoolDataSource.class.getName()), null, null, null }, new Object[] { new Reference(ConnectionPoolDataSource.class.getName(), new StringRefAddr("cluster", "invalid-cluster")), null, null, null } }; } @Test(dataProvider = "factory") public void testGetObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { try { Object result = this.factory.getObjectInstance(obj, name, nameCtx, environment); if ((obj == null) || !Reference.class.isInstance(obj)) { assert result == null; } else { Reference reference = (Reference) obj; if (!reference.getClassName().equals(ConnectionPoolDataSource.class.getName())) { assert result == null; } else { RefAddr addr = reference.get("cluster"); if ((addr == null) || (addr.getContent() == null)) { assert result == null; } else { String id = (String) addr.getContent(); if ((id == null) || !id.equals("test-pool-datasource-cluster")) { assert result == null; } else { assert result != null; assert Proxy.isProxyClass(result.getClass()) : result.getClass().getName(); } } } } } catch (SQLException e) { assert ((Reference) obj).get("cluster").getContent().equals("invalid-cluster"); } } /** * @throws Exception * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable) */ @Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { return this.factory.getObjectInstance(obj, name, nameCtx, environment); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/pool/AbstractTestPooledConnection.java0000644000175000017500000002106411151703043027220 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.SQLException; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import javax.sql.ConnectionEventListener; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import javax.sql.StatementEventListener; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.MockDatabase; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings({ "unchecked", "nls" }) public abstract class AbstractTestPooledConnection implements PooledConnection { protected Balancer balancer = EasyMock.createStrictMock(Balancer.class); protected DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); protected C connection1 = EasyMock.createStrictMock(this.getConnectionClass()); protected C connection2 = EasyMock.createStrictMock(this.getConnectionClass()); protected SQLProxy parent = EasyMock.createStrictMock(SQLProxy.class); protected SQLProxy root = EasyMock.createStrictMock(SQLProxy.class); private LockManager lockManager = EasyMock.createStrictMock(LockManager.class); private Lock lock = EasyMock.createStrictMock(Lock.class); protected Database database1 = new MockDatabase("1"); protected Database database2 = new MockDatabase("2"); protected Set databaseSet; protected ExecutorService executor = Executors.newSingleThreadExecutor(); private AbstractPooledConnectionInvocationHandler handler; protected C connection; protected abstract Class getConnectionClass(); protected AbstractPooledConnectionInvocationHandler getInvocationHandler(Map map) throws Exception { return new PooledConnectionInvocationHandler(EasyMock.createStrictMock(ConnectionPoolDataSource.class), this.parent, EasyMock.createMock(Invoker.class), map); } @BeforeClass protected void init() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.connection1); map.put(this.database2, this.connection2); this.databaseSet = map.keySet(); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(AbstractPooledConnectionInvocationHandler.class)); this.replay(); this.handler = this.getInvocationHandler(map); this.connection = ProxyFactory.createProxy(this.getConnectionClass(), this.handler); this.verify(); this.reset(); } private Object[] objects() { return new Object[] { this.cluster, this.balancer, this.connection1, this.connection2, this.parent, this.root, this.lock, this.lockManager }; } protected void replay() { EasyMock.replay(this.objects()); } protected void verify() { EasyMock.verify(this.objects()); } @AfterMethod protected void reset() { EasyMock.reset(this.objects()); } @DataProvider(name = "connection-listener") protected Object[][] connectionListenerParameters() { return new Object[][] { new Object[] { EasyMock.createMock(ConnectionEventListener.class) } }; } /** * @see javax.sql.PooledConnection#addConnectionEventListener(javax.sql.ConnectionEventListener) */ @Override @Test(dataProvider = "connection-listener") public void addConnectionEventListener(ConnectionEventListener listener) { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.addConnectionEventListener(listener); this.connection2.addConnectionEventListener(listener); this.replay(); this.connection.addConnectionEventListener(listener); this.verify(); } @DataProvider(name = "statement-listener") protected Object[][] statementListenerParameters() { return new Object[][] { new Object[] { EasyMock.createMock(StatementEventListener.class) } }; } /** * @see javax.sql.PooledConnection#addStatementEventListener(javax.sql.StatementEventListener) */ @Override @Test(dataProvider = "statement-listener") public void addStatementEventListener(StatementEventListener listener) { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.addStatementEventListener(listener); this.connection2.addStatementEventListener(listener); this.replay(); this.connection.addStatementEventListener(listener); this.verify(); } /** * @see javax.sql.PooledConnection#close() */ @Override public void close() throws SQLException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.connection1.close(); this.connection2.close(); this.parent.removeChild(this.handler); this.replay(); this.connection.close(); this.verify(); } public void testGetConnection() throws SQLException { Connection connection1 = EasyMock.createStrictMock(Connection.class); Connection connection2 = EasyMock.createStrictMock(Connection.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getLockManager()).andReturn(this.lockManager); EasyMock.expect(this.lockManager.readLock(LockManager.GLOBAL)).andReturn(this.lock); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.connection1.getConnection()).andReturn(connection1); EasyMock.expect(this.connection2.getConnection()).andReturn(connection2); this.replay(); Connection result = this.getConnection(); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == connection1; assert proxy.getObject(this.database2) == connection2; } /** * @see javax.sql.PooledConnection#getConnection() */ @Override public Connection getConnection() throws SQLException { return this.connection.getConnection(); } /** * @see javax.sql.PooledConnection#removeConnectionEventListener(javax.sql.ConnectionEventListener) */ @Override @Test(dataProvider = "connection-listener") public void removeConnectionEventListener(ConnectionEventListener listener) { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.removeConnectionEventListener(listener); this.connection2.removeConnectionEventListener(listener); this.replay(); this.connection.removeConnectionEventListener(listener); this.verify(); } /** * @see javax.sql.PooledConnection#removeStatementEventListener(javax.sql.StatementEventListener) */ @Override @Test(dataProvider = "statement-listener") public void removeStatementEventListener(StatementEventListener listener) { EasyMock.expect(this.cluster.isActive()).andReturn(true); this.connection1.removeStatementEventListener(listener); this.connection2.removeStatementEventListener(listener); this.replay(); this.connection.removeStatementEventListener(listener); this.verify(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestPreparedStatement.java0000644000175000017500000000326511217530600024753 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.PreparedStatement; import java.util.Map; import net.sf.hajdbc.Database; import org.easymock.EasyMock; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test public class TestPreparedStatement extends AbstractTestPreparedStatement { /** * @see net.sf.hajdbc.sql.AbstractTestStatement#getStatementClass() */ @Override protected Class getStatementClass() { return PreparedStatement.class; } @Override protected AbstractStatementInvocationHandler getInvocationHandler(Map map) throws Exception { return new PreparedStatementInvocationHandler(this.connection, this.parent, EasyMock.createMock(Invoker.class), map, this.transactionContext, this.fileSupport, this.sql); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestDriver.java0000644000175000017500000001320311151703043022550 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.util.Collections; import java.util.Properties; import java.util.prefs.Preferences; import net.sf.hajdbc.local.LocalStateManager; import org.easymock.EasyMock; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Unit test for {@link Driver}. * @author Paul Ferraro * @since 1.0 */ @SuppressWarnings("nls") @Test public class TestDriver implements java.sql.Driver { private java.sql.Driver driver = new Driver(); private Connection connection = EasyMock.createMock(Connection.class); @BeforeClass protected void setUp() throws Exception { DriverManager.registerDriver(new MockDriver(this.connection)); Preferences.userNodeForPackage(LocalStateManager.class).put("test-database-cluster", "database1,database2"); } @AfterClass protected void tearDown() throws Exception { DriverManager.deregisterDriver(new MockDriver(this.connection)); Preferences.userNodeForPackage(LocalStateManager.class).remove("test-database-cluster"); } /** * Test method for {@link Driver} static initialization. */ public void testRegister() { boolean registered = false; for (java.sql.Driver driver: Collections.list(DriverManager.getDrivers())) { if (Driver.class.isInstance(driver)) { registered = true; } } assert registered; } @DataProvider(name = "connect") public Object[][] getConnectProvider() { return new Object[][] { new Object[] { "jdbc:ha-jdbc:test-database-cluster", new Properties() }, new Object[] { "jdbc:ha-jdbc:invalid-cluster", new Properties() }, new Object[] { "jdbc:mock", new Properties() } }; } @Test(dataProvider = "connect") public void testConnect(String url, Properties properties) { try { Connection connection = this.connect(url, properties); if (url.equals("jdbc:mock")) { assert connection == null : url; } else { assert connection != null : url; assert Proxy.isProxyClass(connection.getClass()); assert Proxy.getInvocationHandler(connection).getClass().equals(ConnectionInvocationHandler.class); } } catch (SQLException e) { assert !url.equals("jdbc:ha-jdbc:test-database-cluster") : e; } } /** * @see java.sql.Driver#connect(java.lang.String, java.util.Properties) */ @Override public Connection connect(String url, Properties properties) throws SQLException { return this.driver.connect(url, properties); } @DataProvider(name = "url") public Object[][] getUrlProvider() { return new Object[][] { new Object[] { "jdbc:ha-jdbc:test-database-cluster" }, new Object[] { "jdbc:ha-jdbc:" }, new Object[] { "jdbc:ha-jdbc" }, new Object[] { "jdbc:mock" } }; } @Test(dataProvider = "url") public void testAcceptsURL(String url) { boolean accepted = url.startsWith("jdbc:ha-jdbc:") && url.length() > 13; boolean result = this.acceptsURL(url); assert result == accepted : url; } /** * @see java.sql.Driver#acceptsURL(java.lang.String) */ @Override public boolean acceptsURL(String url) { try { return this.driver.acceptsURL(url); } catch (SQLException e) { throw new AssertionError(e); } } @Test(dataProvider = "connect") public void testGetPropertyInfo(String url, Properties properties) { try { DriverPropertyInfo[] info = this.getPropertyInfo(url, properties); if (url.equals("jdbc:mock")) { assert info == null : url; } else { assert info != null : url; } } catch (SQLException e) { assert !url.equals("jdbc:ha-jdbc:test-database-cluster") : e; } } /** * @see java.sql.Driver#getPropertyInfo(java.lang.String, java.util.Properties) */ @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties properties) throws SQLException { return this.driver.getPropertyInfo(url, properties); } public void testGetMajorVersion() { int version = this.getMajorVersion(); assert version == 2 : version; } /** * @see java.sql.Driver#getMajorVersion() */ @Override public int getMajorVersion() { return this.driver.getMajorVersion(); } public void testGetMinorVersion() { int version = this.getMinorVersion(); assert version == 0 : version; } /** * @see java.sql.Driver#getMinorVersion() */ @Override public int getMinorVersion() { return this.driver.getMinorVersion(); } public void testJdbcCompliant() { boolean compliant = this.jdbcCompliant(); assert compliant; } /** * @see java.sql.Driver#jdbcCompliant() */ @Override public boolean jdbcCompliant() { return this.driver.jdbcCompliant(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestLocalTransactionContext.java0000644000175000017500000001627211151703043026133 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.SQLException; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.LockManager; import org.easymock.EasyMock; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test @SuppressWarnings("unchecked") public class TestLocalTransactionContext implements TransactionContext { private Connection connection = EasyMock.createStrictMock(Connection.class); private DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); private InvocationStrategy strategy = EasyMock.createStrictMock(InvocationStrategy.class); private LockManager lockManager = EasyMock.createStrictMock(LockManager.class); private Lock lock = EasyMock.createStrictMock(Lock.class); private TransactionContext context; private Object[] objects() { return new Object[] { this.connection, this.cluster, this.strategy, this.lock, this.lockManager }; } @BeforeMethod void init() { EasyMock.expect(this.cluster.getLockManager()).andReturn(this.lockManager); EasyMock.expect(this.lockManager.readLock(LockManager.GLOBAL)).andReturn(this.lock); this.replay(); this.context = new LocalTransactionContext(this.cluster); this.verify(); this.reset(); } void replay() { EasyMock.replay(this.objects()); } void verify() { EasyMock.verify(this.objects()); } @AfterMethod void reset() { EasyMock.reset(this.objects()); } @DataProvider(name = "start") Object[][] startParameters() { return new Object[][] { new Object[] { this.strategy, this.connection } }; } @Test(dataProvider = "start") public void testStart(InvocationStrategy strategy, Connection connection) throws SQLException { SQLProxy proxy = EasyMock.createMock(SQLProxy.class); Invoker invoker = EasyMock.createMock(Invoker.class); // Auto-commit on EasyMock.expect(this.connection.getAutoCommit()).andReturn(true); this.replay(); InvocationStrategy result = this.start(strategy, connection); this.verify(); assert result != null; assert result != strategy; assert LockingInvocationStrategy.class.isInstance(result) : result.getClass().getName(); this.reset(); try { Object object = new Object(); this.lock.lock(); EasyMock.expect(strategy.invoke(proxy, invoker)).andReturn(object); this.lock.unlock(); this.replay(); Object invocationResult = result.invoke(proxy, invoker); this.verify(); assert invocationResult == object; this.reset(); } catch (Exception e) { assert false : e; } // Auto-commit off EasyMock.expect(this.connection.getAutoCommit()).andReturn(false); this.replay(); result = this.start(strategy, connection); this.verify(); assert result != null; assert result != strategy; assert !LockingInvocationStrategy.class.isInstance(result); this.reset(); try { Object object = new Object(); this.lock.lock(); EasyMock.expect(strategy.invoke(proxy, invoker)).andReturn(object); this.replay(); Object invocationResult = result.invoke(proxy, invoker); this.verify(); assert invocationResult == object; this.reset(); } catch (Exception e) { assert false : e; } // Already locked this.replay(); result = this.start(strategy, connection); this.verify(); assert result == strategy; } @Override public InvocationStrategy start(InvocationStrategy strategy, Connection connection) throws SQLException { return this.context.start(strategy, connection); } @DataProvider(name = "end") Object[][] endParameters() { return new Object[][] { new Object[] { this.strategy } }; } @Test(dataProvider = "end") public void testEnd(InvocationStrategy strategy) throws SQLException { // Not locked this.replay(); InvocationStrategy result = this.end(strategy); this.verify(); assert result == strategy; this.reset(); // Simulate transaction start EasyMock.expect(this.connection.getAutoCommit()).andReturn(false); this.replay(); result = this.start(this.strategy, this.connection); this.verify(); this.reset(); SQLProxy proxy = EasyMock.createMock(SQLProxy.class); Invoker invoker = EasyMock.createMock(Invoker.class); Object object = new Object(); try { this.lock.lock(); EasyMock.expect(this.strategy.invoke(proxy, invoker)).andReturn(object); this.replay(); Object invocationResult = result.invoke(proxy, invoker); this.verify(); assert invocationResult == object; this.reset(); } catch (Exception e) { assert false : e; } // Locked this.replay(); result = this.end(strategy); this.verify(); assert result != strategy; this.reset(); try { EasyMock.expect(strategy.invoke(proxy, invoker)).andReturn(object); this.lock.unlock(); this.replay(); Object invocationResult = result.invoke(proxy, invoker); this.verify(); assert invocationResult == object; } catch (Exception e) { assert false : e; } } @Override public InvocationStrategy end(InvocationStrategy strategy) throws SQLException { return this.context.end(strategy); } @Override public void close() { // Normally uneventful this.replay(); this.context.close(); this.verify(); this.reset(); // Simulate transaction start try { EasyMock.expect(this.connection.getAutoCommit()).andReturn(false); this.replay(); InvocationStrategy result = this.start(this.strategy, this.connection); this.verify(); this.reset(); SQLProxy proxy = EasyMock.createMock(SQLProxy.class); Invoker invoker = EasyMock.createMock(Invoker.class); Object object = new Object(); this.lock.lock(); EasyMock.expect(this.strategy.invoke(proxy, invoker)).andReturn(object); this.replay(); Object invocationResult = result.invoke(proxy, invoker); this.verify(); assert invocationResult == object; this.reset(); } catch (Exception e) { assert false : e; } // Closing with uncommitted transaction this.lock.unlock(); this.replay(); this.context.close(); this.verify(); } }ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/xa/0000755000175000017500000000000011674455606020246 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/xa/TestXAConnection.java0000644000175000017500000000650511151703043024264 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.lang.reflect.Proxy; import java.sql.SQLException; import java.util.Map; import javax.sql.PooledConnection; import javax.sql.XAConnection; import javax.sql.XADataSource; import javax.transaction.xa.XAResource; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.sql.pool.AbstractPooledConnectionInvocationHandler; import net.sf.hajdbc.sql.pool.AbstractTestPooledConnection; import org.easymock.EasyMock; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test @SuppressWarnings("unchecked") public class TestXAConnection extends AbstractTestPooledConnection implements XAConnection { /** * @see net.sf.hajdbc.sql.pool.AbstractTestPooledConnection#getConnectionClass() */ @Override protected Class getConnectionClass() { return XAConnection.class; } /** * @see net.sf.hajdbc.sql.pool.AbstractTestPooledConnection#getInvocationHandler(java.util.Map) */ @Override protected AbstractPooledConnectionInvocationHandler getInvocationHandler(Map map) throws Exception { return new XAConnectionInvocationHandler(EasyMock.createStrictMock(XADataSource.class), this.parent, EasyMock.createMock(Invoker.class), map); } public void testGetXAResource() throws SQLException { XAResource resource1 = EasyMock.createStrictMock(XAResource.class); XAResource resource2 = EasyMock.createStrictMock(XAResource.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.connection1.getXAResource()).andReturn(resource1); EasyMock.expect(this.connection2.getXAResource()).andReturn(resource2); this.replay(); XAResource result = this.getXAResource(); this.verify(); assert Proxy.isProxyClass(result.getClass()); SQLProxy proxy = SQLProxy.class.cast(Proxy.getInvocationHandler(result)); assert proxy.getObject(this.database1) == resource1; assert proxy.getObject(this.database2) == resource2; } /** * @see javax.sql.XAConnection#getXAResource() */ @Override public XAResource getXAResource() throws SQLException { return this.connection.getXAResource(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/xa/TestXADataSourceDatabase.java0000644000175000017500000000615211151703043025642 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.sql.Connection; import java.sql.SQLException; import javax.naming.spi.ObjectFactory; import javax.sql.XAConnection; import javax.sql.XADataSource; import net.sf.hajdbc.sql.TestCommonDataSourceDatabase; import org.easymock.EasyMock; /** * @author Paul Ferraro * */ public class TestXADataSourceDatabase extends TestCommonDataSourceDatabase { public TestXADataSourceDatabase() { super(XADataSource.class); } /** * @see net.sf.hajdbc.sql.TestDatabase#createDatabase(java.lang.String) */ @Override protected XADataSourceDatabase createDatabase(String id) { XADataSourceDatabase database = new XADataSourceDatabase(); database.setId(id); return database; } /** * @see net.sf.hajdbc.sql.TestCommonDataSourceDatabase#mockDataSourceClass() */ @Override protected Class mockDataSourceClass() { return MockXADataSource.class; } /** * @see net.sf.hajdbc.sql.TestCommonDataSourceDatabase#objectFactoryClass() */ @Override protected Class objectFactoryClass() { return MockXADataSourceFactory.class; } @Override public void testConnect() throws SQLException { XADataSource dataSource = EasyMock.createStrictMock(XADataSource.class); XAConnection xaConnection = EasyMock.createStrictMock(XAConnection.class); Connection connection = EasyMock.createMock(Connection.class); EasyMock.expect(dataSource.getXAConnection()).andReturn(xaConnection); EasyMock.expect(xaConnection.getConnection()).andReturn(connection); EasyMock.replay(dataSource, xaConnection); Connection result = this.connect(dataSource); EasyMock.verify(dataSource, xaConnection); assert result == connection : result.getClass().getName(); EasyMock.reset(dataSource, xaConnection); this.database.setUser("user"); this.database.setPassword("password"); EasyMock.expect(dataSource.getXAConnection("user", "password")).andReturn(xaConnection); EasyMock.expect(xaConnection.getConnection()).andReturn(connection); EasyMock.replay(dataSource, xaConnection); result = this.connect(dataSource); EasyMock.verify(dataSource, xaConnection); assert result == connection : result.getClass().getName(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/xa/MockXADataSourceFactory.java0000644000175000017500000000264611151703043025523 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.spi.ObjectFactory; /** * @author Paul Ferraro * */ public class MockXADataSourceFactory implements ObjectFactory { /** * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable) */ @Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { return new MockXADataSource(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/xa/TestXADataSourceFactory.java0000644000175000017500000001201311151703043025536 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.lang.reflect.Proxy; import java.sql.Driver; import java.sql.SQLException; import java.util.Hashtable; import java.util.Properties; import java.util.prefs.Preferences; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Name; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; import javax.sql.XADataSource; import net.sf.hajdbc.local.LocalStateManager; import net.sf.hajdbc.sql.MockInitialContextFactory; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ public class TestXADataSourceFactory implements ObjectFactory { private XADataSourceFactory factory = new XADataSourceFactory(); private Context context; @BeforeClass protected void setUp() throws Exception { Preferences.userNodeForPackage(LocalStateManager.class).put("test-xa-datasource-cluster", "datasource1,datasource2"); Properties properties = new Properties(); properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, MockInitialContextFactory.class.getName()); this.context = new InitialContext(properties); Reference reference = new Reference(XADataSourceFactory.class.getName(), MockXADataSourceFactory.class.getName(), null); this.context.bind("datasource1", reference); this.context.bind("datasource2", reference); this.context.bind("datasource", new XADataSourceReference("test-xa-datasource-cluster")); } @AfterClass protected void tearDown() throws Exception { this.context.unbind("datasource"); this.context.unbind("datasource1"); this.context.unbind("datasource2"); Preferences.userNodeForPackage(LocalStateManager.class).remove("test-xa-datasource-cluster"); } @DataProvider(name = "factory") Object[][] objectInstanceProvider() { return new Object[][] { new Object[] { null, null, null, null }, new Object[] { new Object(), null, null, null }, new Object[] { new Reference(XADataSource.class.getName(), new StringRefAddr("cluster", "test-xa-datasource-cluster")), null, null, null }, new Object[] { new Reference(XADataSource.class.getName(), new StringRefAddr("cluster", null)), null, null, null }, new Object[] { new Reference(Driver.class.getName(), new StringRefAddr("cluster", "test-xa-datasource-cluster")), null, null, null }, new Object[] { new Reference(XADataSource.class.getName()), null, null, null }, new Object[] { new Reference(XADataSource.class.getName(), new StringRefAddr("cluster", "invalid-cluster")), null, null, null } }; } @Test(dataProvider = "factory") public void testGetObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { try { Object result = this.getObjectInstance(obj, name, nameCtx, environment); if ((obj == null) || !Reference.class.isInstance(obj)) { assert result == null; } else { Reference reference = (Reference) obj; if (!reference.getClassName().equals(XADataSource.class.getName())) { assert result == null; } else { RefAddr addr = reference.get("cluster"); if ((addr == null) || (addr.getContent() == null)) { assert result == null; } else { String id = (String) addr.getContent(); if ((id == null) || !id.equals("test-xa-datasource-cluster")) { assert result == null; } else { assert result != null; assert Proxy.isProxyClass(result.getClass()) : result.getClass().getName(); } } } } } catch (SQLException e) { assert ((Reference) obj).get("cluster").getContent().equals("invalid-cluster"); } } /** * @throws Exception * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable) */ @Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception { return this.factory.getObjectInstance(obj, name, nameCtx, environment); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/xa/TestXAResource.java0000644000175000017500000003615211151703043023755 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import javax.sql.XAConnection; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.MockDatabase; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.easymock.EasyMock; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("unchecked") public class TestXAResource implements XAResource { private Balancer balancer = EasyMock.createStrictMock(Balancer.class); private DatabaseCluster cluster = EasyMock.createStrictMock(DatabaseCluster.class); private XAResource resource1 = EasyMock.createStrictMock(XAResource.class); private XAResource resource2 = EasyMock.createStrictMock(XAResource.class); private SQLProxy parent = EasyMock.createStrictMock(SQLProxy.class); private SQLProxy root = EasyMock.createStrictMock(SQLProxy.class); private LockManager lockManager = EasyMock.createStrictMock(LockManager.class); private Lock lock = EasyMock.createStrictMock(Lock.class); private Database database1 = new MockDatabase("1"); private Database database2 = new MockDatabase("2"); private Set databaseSet; private ExecutorService executor = Executors.newSingleThreadExecutor(); private XAResourceInvocationHandler handler; private XAResource resource; @BeforeClass protected void init() throws Exception { Map map = new TreeMap(); map.put(this.database1, this.resource1); map.put(this.database2, this.resource2); this.databaseSet = map.keySet(); EasyMock.expect(this.parent.getDatabaseCluster()).andReturn(this.cluster); this.parent.addChild(EasyMock.isA(XAResourceInvocationHandler.class)); this.replay(); this.handler = new XAResourceInvocationHandler(EasyMock.createStrictMock(XAConnection.class), this.parent, EasyMock.createMock(Invoker.class), map); this.resource = ProxyFactory.createProxy(XAResource.class, this.handler); this.verify(); this.reset(); } private Object[] objects() { return new Object[] { this.cluster, this.balancer, this.resource1, this.resource2, this.parent, this.root, this.lock, this.lockManager }; } protected void replay() { EasyMock.replay(this.objects()); } protected void verify() { EasyMock.verify(this.objects()); } @AfterMethod protected void reset() { EasyMock.reset(this.objects()); } @DataProvider(name = "xid-boolean") Object[][] xidBooleanProvider() { return new Object[][] { new Object[] { EasyMock.createMock(Xid.class), false } }; } /** * @see javax.transaction.xa.XAResource#commit(javax.transaction.xa.Xid, boolean) */ @Override @Test(dataProvider = "xid-boolean") public void commit(Xid xid, boolean onePhase) throws XAException { // Simulate start transaction EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getLockManager()).andReturn(this.lockManager); EasyMock.expect(this.lockManager.readLock(LockManager.GLOBAL)).andReturn(this.lock); this.lock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resource1.start(xid, XAResource.TMNOFLAGS); this.resource2.start(xid, XAResource.TMNOFLAGS); this.replay(); this.resource.start(xid, XAResource.TMNOFLAGS); this.verify(); this.reset(); // Begin test EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resource1.commit(xid, onePhase); this.resource2.commit(xid, onePhase); this.lock.unlock(); this.replay(); this.resource.commit(xid, onePhase); this.verify(); } @DataProvider(name = "xid-flags") Object[][] xidIntProvider() { return new Object[][] { new Object[] { EasyMock.createMock(Xid.class), XAResource.TMNOFLAGS } }; } /** * @see javax.transaction.xa.XAResource#end(javax.transaction.xa.Xid, int) */ @Override @Test(dataProvider = "xid-flags") public void end(Xid xid, int flags) throws XAException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resource1.end(xid, flags); this.resource2.end(xid, flags); this.replay(); this.resource.end(xid, flags); this.verify(); } @DataProvider(name = "xid") Object[][] xidProvider() { return new Object[][] { new Object[] { EasyMock.createMock(Xid.class) } }; } /** * @see javax.transaction.xa.XAResource#forget(javax.transaction.xa.Xid) */ @Override @Test(dataProvider = "xid") public void forget(Xid xid) throws XAException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resource1.forget(xid); this.resource2.forget(xid); this.replay(); this.resource.forget(xid); this.verify(); } public void testGetTransactionTimeout() throws XAException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resource1.getTransactionTimeout()).andReturn(1); this.replay(); int timeout = this.getTransactionTimeout(); this.verify(); assert timeout == 1 : timeout; } /** * @see javax.transaction.xa.XAResource#getTransactionTimeout() */ @Override public int getTransactionTimeout() throws XAException { return this.resource.getTransactionTimeout(); } public void testIsSameRM() throws XAException { XAResource resource = EasyMock.createMock(XAResource.class); EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.resource1.isSameRM(resource)).andReturn(true); this.replay(); boolean same = this.isSameRM(resource); this.verify(); assert same; } /** * @see javax.transaction.xa.XAResource#isSameRM(javax.transaction.xa.XAResource) */ @Override public boolean isSameRM(XAResource resource) throws XAException { return this.resource.isSameRM(resource); } @Test(dataProvider = "xid") public void testPrepare(Xid xid) throws XAException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.resource1.prepare(xid)).andReturn(XAResource.XA_OK); EasyMock.expect(this.resource2.prepare(xid)).andReturn(XAResource.XA_OK); this.replay(); int result = this.prepare(xid); this.verify(); assert result == XAResource.XA_OK : result; } /** * @see javax.transaction.xa.XAResource#prepare(javax.transaction.xa.Xid) */ @Override public int prepare(Xid xid) throws XAException { return this.resource.prepare(xid); } @DataProvider(name = "flags") Object[][] flagsProvider() { return new Object[][] { new Object[] { XAResource.TMNOFLAGS }, }; } @Test(dataProvider = "flags") public void testRecover(int flags) throws XAException { Xid[] xids = new Xid[0]; EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.resource1.recover(flags)).andReturn(xids); EasyMock.expect(this.resource2.recover(flags)).andReturn(xids); this.replay(); Xid[] result = this.recover(flags); this.verify(); assert result == xids; } /** * @see javax.transaction.xa.XAResource#recover(int) */ @Override public Xid[] recover(int flags) throws XAException { return this.resource.recover(flags); } /** * @see javax.transaction.xa.XAResource#rollback(javax.transaction.xa.Xid) */ @Override @Test(dataProvider = "xid") public void rollback(Xid xid) throws XAException { // Simulate start transaction EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getLockManager()).andReturn(this.lockManager); EasyMock.expect(this.lockManager.readLock(LockManager.GLOBAL)).andReturn(this.lock); this.lock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resource1.start(xid, XAResource.TMNOFLAGS); this.resource2.start(xid, XAResource.TMNOFLAGS); this.replay(); this.resource.start(xid, XAResource.TMNOFLAGS); this.verify(); this.reset(); // Start test EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resource1.rollback(xid); this.resource2.rollback(xid); this.lock.unlock(); this.replay(); this.resource.rollback(xid); this.verify(); } @Test(dataProvider = "flags") public void testSetTransactionTimeout(int timeout) throws XAException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getNonTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); EasyMock.expect(this.resource1.setTransactionTimeout(timeout)).andReturn(true); EasyMock.expect(this.resource2.setTransactionTimeout(timeout)).andReturn(true); this.replay(); boolean result = this.setTransactionTimeout(timeout); this.verify(); assert result; } /** * @see javax.transaction.xa.XAResource#setTransactionTimeout(int) */ @Override public boolean setTransactionTimeout(int timeout) throws XAException { return this.resource.setTransactionTimeout(timeout); } /** * @see javax.transaction.xa.XAResource#start(javax.transaction.xa.Xid, int) */ @Override @Test(dataProvider = "xid-flags") public void start(Xid xid, int flags) throws XAException { EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getLockManager()).andReturn(this.lockManager); EasyMock.expect(this.lockManager.readLock(LockManager.GLOBAL)).andReturn(this.lock); this.lock.lock(); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resource1.start(xid, flags); this.resource2.start(xid, flags); this.replay(); this.resource.start(xid, flags); this.verify(); this.reset(); // Test resume EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getLockManager()).andReturn(this.lockManager); EasyMock.expect(this.lockManager.readLock(LockManager.GLOBAL)).andReturn(this.lock); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resource1.start(xid, flags); this.resource2.start(xid, flags); this.replay(); this.resource.start(xid, flags); this.verify(); this.reset(); // Simulate transaction rollback EasyMock.expect(this.cluster.isActive()).andReturn(true); EasyMock.expect(this.cluster.getTransactionalExecutor()).andReturn(this.executor); EasyMock.expect(this.cluster.getBalancer()).andReturn(this.balancer); EasyMock.expect(this.balancer.all()).andReturn(this.databaseSet); EasyMock.expect(this.parent.getRoot()).andReturn(this.root); this.root.retain(this.databaseSet); this.resource1.rollback(xid); this.resource2.rollback(xid); this.lock.unlock(); this.replay(); this.resource.rollback(xid); this.verify(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/xa/MockXADataSource.java0000644000175000017500000000311511151703043024163 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.sql.SQLException; import javax.sql.XAConnection; import javax.sql.XADataSource; import org.easymock.EasyMock; import net.sf.hajdbc.sql.MockCommonDataSource; /** * @author Paul Ferraro * */ public class MockXADataSource extends MockCommonDataSource implements XADataSource { /** * @see javax.sql.XADataSource#getXAConnection() */ @Override public XAConnection getXAConnection() throws SQLException { return EasyMock.createMock(XAConnection.class); } /** * @see javax.sql.XADataSource#getXAConnection(java.lang.String, java.lang.String) */ @Override public XAConnection getXAConnection(String arg0, String arg1) throws SQLException { return this.getXAConnection(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sql/TestStatement.java0000644000175000017500000000330111151703043023257 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Statement; import java.util.Map; import net.sf.hajdbc.Database; import org.easymock.EasyMock; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test public class TestStatement extends AbstractTestStatement { /** * @see net.sf.hajdbc.sql.AbstractTestStatement#getStatementClass() */ @Override protected Class getStatementClass() { return Statement.class; } /** * @see net.sf.hajdbc.sql.AbstractTestStatement#getInvocationHandler(java.util.Map) */ @Override protected AbstractStatementInvocationHandler getInvocationHandler(Map map) throws Exception { return new StatementInvocationHandler(this.connection, this.parent, EasyMock.createMock(Invoker.class), map, this.transactionContext, this.fileSupport); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/balancer/0000755000175000017500000000000011674455606020606 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/balancer/TestBalancer.java0000644000175000017500000001161311151703044024000 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import java.util.NoSuchElementException; import java.util.Set; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.MockDatabase; import org.easymock.EasyMock; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @SuppressWarnings("nls") public abstract class TestBalancer implements Balancer { private Balancer balancer; protected TestBalancer(Balancer balancer) { this.balancer = balancer; } @DataProvider(name = "database") Object[][] databaseProvider() { return new Object[][] { new Object[] { new MockDatabase("1", 1) } }; } public void testAdd() { Database database = new MockDatabase("1", 1); boolean result = this.add(database); assert result; result = this.add(database); assert !result; } @Override public boolean add(Database database) { return this.balancer.add(database); } @SuppressWarnings("unchecked") public void testAfterInvocation() { Database database = EasyMock.createStrictMock(Database.class); EasyMock.replay(database); this.afterInvocation(database); EasyMock.verify(database); } @Override @Test(enabled = false) public void afterInvocation(Database database) { this.balancer.afterInvocation(database); } @SuppressWarnings("unchecked") public void testBeforeInvocation() { Database database = EasyMock.createStrictMock(Database.class); EasyMock.replay(database); this.beforeInvocation(database); EasyMock.verify(database); } @Override @Test(enabled = false) public void beforeInvocation(Database database) { this.balancer.beforeInvocation(database); } public void testAll() { Set> databaseList = this.all(); assert databaseList.isEmpty() : databaseList.size(); Database database1 = new MockDatabase("db1", 1); this.add(database1); databaseList = this.all(); assert databaseList.size() == 1 : databaseList.size(); assert databaseList.contains(database1); Database database2 = new MockDatabase("db2", 1); this.add(database2); databaseList = this.all(); assert databaseList.size() == 2 : databaseList.size(); assert databaseList.contains(database1) && databaseList.contains(database2); this.remove(database1); databaseList = this.all(); assert databaseList.size() == 1 : databaseList.size(); assert databaseList.contains(database2); this.remove(database2); databaseList = this.all(); assert databaseList.isEmpty() : databaseList.size(); } @Override public Set> all() { return this.balancer.all(); } public void testEmptyNext() { try { Database database = this.next(); assert false : database.getId(); } catch (NoSuchElementException e) { assert true; } } public abstract void testNext(); @Override public Database next() { return this.balancer.next(); } public void testRemove() { Database database1 = new MockDatabase("1", 1); boolean removed = this.remove(database1); assert !removed; this.add(database1); Database database2 = new MockDatabase("2", 1); this.add(database2); removed = this.remove(database2); assert removed; removed = this.remove(database2); assert !removed; removed = this.remove(database1); assert removed; removed = this.remove(database1); assert !removed; } @Override public boolean remove(Database database) { return this.balancer.remove(database); } public void testClear() { int size = this.all().size(); assert size == 0 : size; this.clear(); assert size == 0 : size; this.add(new MockDatabase("1")); this.add(new MockDatabase("2")); size = this.all().size(); assert size == 2 : size; this.clear(); size = this.all().size(); assert size == 0 : size; } @Override @AfterMethod public void clear() { this.balancer.clear(); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/balancer/TestRandomBalancer.java0000644000175000017500000000427211151703044025144 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import java.util.Arrays; import org.testng.annotations.Test; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.MockDatabase; /** * @author Paul Ferraro * @since 1.0 */ @Test @SuppressWarnings("nls") public class TestRandomBalancer extends TestBalancer { public TestRandomBalancer() { super(new RandomBalancer()); } /** * @see net.sf.hajdbc.balancer.TestBalancer#testNext() */ @Override public void testNext() { int count = 100; int[] results = new int[3]; Arrays.fill(results, 0); this.add(new MockDatabase("0", 0)); for (int i = 0; i < count; ++i) { results[this.next().getWeight()] += 1; } assert results[0] == count : results[0]; assert results[1] == 0 : results[1]; assert results[2] == 0 : results[2]; this.add(new MockDatabase("1", 1)); Arrays.fill(results, 0); for (int i = 0; i < count; ++i) { results[this.next().getWeight()] += 1; } assert results[0] == 0 : results[0]; assert results[1] == count : results[1]; assert results[2] == 0 : results[2]; this.add(new MockDatabase("2", 2)); Arrays.fill(results, 0); for (int i = 0; i < count; ++i) { results[this.next().getWeight()] += 1; } assert results[0] == 0 : results[0]; assert results[1] < 50 : results[1]; assert results[2] > 50 : results[2]; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/balancer/TestBalancerClass.java0000644000175000017500000000514711151703044024773 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import net.sf.hajdbc.Balancer; import org.easymock.EasyMock; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @Test @SuppressWarnings({ "unchecked", "nls" }) public class TestBalancerClass { /** * Test for {@link BalancerClass#serialize(Balancer)}. */ public void serialize() { this.assertBalancer(new SimpleBalancer(), "simple"); this.assertBalancer(new RandomBalancer(), "random"); this.assertBalancer(new RoundRobinBalancer(), "round-robin"); this.assertBalancer(new LoadBalancer(), "load"); try { String balancer = BalancerClass.serialize(EasyMock.createMock(Balancer.class)); assert false : balancer; } catch (IllegalArgumentException e) { assert true; } } private void assertBalancer(Balancer balancer, String id) { String name = BalancerClass.serialize(balancer); assert name.equals(id) : name; } /** * Test for {@link BalancerClass#deserialize(String)}. */ public void deserialize() { this.assertBalancer("simple", SimpleBalancer.class); this.assertBalancer("random", RandomBalancer.class); this.assertBalancer("round-robin", RoundRobinBalancer.class); this.assertBalancer("load", LoadBalancer.class); try { Balancer balancer = BalancerClass.deserialize("invalid"); assert false : balancer.getClass().getName(); } catch (Exception e) { assert true; } } private void assertBalancer(String id, Class balancerClass) { try { Balancer balancer = BalancerClass.deserialize("load"); assert LoadBalancer.class.isInstance(balancer); } catch (Exception e) { assert false : e; } } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/balancer/TestRoundRobinBalancer.java0000644000175000017500000000350311151703044026001 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import net.sf.hajdbc.MockDatabase; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @Test @SuppressWarnings("nls") public class TestRoundRobinBalancer extends TestBalancer { public TestRoundRobinBalancer() { super(new RoundRobinBalancer()); } /** * @see net.sf.hajdbc.balancer.TestBalancer#testNext() */ @Override public void testNext() { int count = 100; this.add(new MockDatabase("0", 0)); for (int i = 0; i < count; ++i) { int weight = this.next().getWeight(); assert weight == 0 : weight; } this.add(new MockDatabase("1", 1)); for (int i = 0; i < count; ++i) { int weight = this.next().getWeight(); assert weight == 1 : weight; } this.add(new MockDatabase("2", 2)); int[] expected = new int[] { 1, 2, 2 }; for (int i = 0; i < count; ++i) { int weight = this.next().getWeight(); assert expected[i % 3] == weight : weight; } } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/balancer/TestSimpleBalancer.java0000644000175000017500000000401511151703044025150 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import java.util.Arrays; import net.sf.hajdbc.MockDatabase; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @Test @SuppressWarnings("nls") public class TestSimpleBalancer extends TestBalancer { public TestSimpleBalancer() { super(new SimpleBalancer()); } /** * @see net.sf.hajdbc.balancer.TestBalancer#testNext() */ @Override public void testNext() { this.add(new MockDatabase("0", 0)); String[] results = new String[20]; for (int i = 0; i < results.length; ++i) { results[i] = this.next().getId(); } String[] expected = new String[results.length]; Arrays.fill(expected, "0"); assert Arrays.equals(results, expected) : Arrays.asList(results); this.add(new MockDatabase("2", 2)); for (int i = 0; i < results.length; ++i) { results[i] = this.next().getId(); } Arrays.fill(expected, "2"); assert Arrays.equals(results, expected) : Arrays.asList(results); this.add(new MockDatabase("1", 1)); for (int i = 0; i < results.length; ++i) { results[i] = this.next().getId(); } assert Arrays.equals(results, expected) : Arrays.asList(results); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/balancer/TestLoadBalancer.java0000644000175000017500000001024511151703044024600 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.MockDatabase; import net.sf.hajdbc.sql.Invoker; import org.testng.annotations.Test; /** * @author Paul Ferraro * @version $Revision: 2042 $ * @since 1.0 */ @Test @SuppressWarnings("nls") public class TestLoadBalancer extends TestBalancer { public TestLoadBalancer() { super(new LoadBalancer()); } /** * @see net.sf.hajdbc.balancer.TestBalancer#testNext() */ @Override public void testNext() { Database database0 = new MockDatabase("0", 0); Database database1 = new MockDatabase("1", 1); Database database2 = new MockDatabase("2", 2); this.add(database0); Database next = this.next(); assert database0.equals(next) : next; this.add(database2); next = this.next(); assert database2.equals(next) : next; this.add(database1); next = this.next(); assert database2.equals(next) : next; // Add enough load to database2 to shift relative effective load Thread[] database2Threads = new Thread[2]; for (int i = 0; i < 2; ++i) { database2Threads[i] = new InvokerThread(this, new MockInvoker(), database2); database2Threads[i].start(); } next = this.next(); assert database1.equals(next) : next; // Add enough load to database1 to shift relative effective load Thread database1Thread = new InvokerThread(this, new MockInvoker(), database1); database1Thread.start(); next = this.next(); assert database2.equals(next) : next; database1Thread.interrupt(); next = this.next(); assert database1.equals(next) : next; for (int i = 0; i < 2; ++i) { database2Threads[i].interrupt(); } next = this.next(); assert database2.equals(next) : next; } private static class InvokerThread extends Thread { private Balancer balancer; private Invoker invoker; private Database database; /** * Constructs a new InvokerThread. * @param balancer * @param invoker * @param database */ public InvokerThread(Balancer balancer, Invoker invoker, Database database) { super(); this.balancer = balancer; this.invoker = invoker; this.database = database; this.setDaemon(true); } /** * @see java.lang.Runnable#run() */ @Override public void run() { this.balancer.beforeInvocation(this.database); try { this.invoker.invoke(this.database, null); this.balancer.afterInvocation(this.database); } catch (Exception e) { assert false : e; } } /** * @see java.lang.Thread#start() */ @Override public synchronized void start() { super.start(); this.pause(); } /** * @see java.lang.Thread#interrupt() */ @Override public void interrupt() { super.interrupt(); this.pause(); } private void pause() { try { Thread.sleep(10); } catch (InterruptedException e) { assert false : e; } } } static class MockInvoker implements Invoker { @Override public Void invoke(Database database, Void object) { // Simulate a long operation try { Thread.sleep(10000); } catch (InterruptedException e) { // Ignore } return null; } } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/MockDatabase.java0000644000175000017500000000414211151703043022176 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.sql.Connection; import java.sql.SQLException; import javax.management.DynamicMBean; import net.sf.hajdbc.sql.AbstractDatabase; /** * @author Paul Ferraro * */ public class MockDatabase extends AbstractDatabase { public MockDatabase() { this(""); //$NON-NLS-1$ } public MockDatabase(String id) { this(id, 1); } public MockDatabase(String id, int weight) { this.setId(id); this.setWeight(weight); this.clean(); } /** * @see net.sf.hajdbc.Database#connect(T) */ @SuppressWarnings("unused") public Connection connect(Void connectionFactory) throws SQLException { return null; } /** * @see net.sf.hajdbc.Database#createConnectionFactory() */ public Void createConnectionFactory() { return null; } /** * @see net.sf.hajdbc.Database#getConnectionFactoryClass() */ public Class getConnectionFactoryClass() { return null; } /** * @see net.sf.hajdbc.Database#getActiveMBeanClass() */ public DynamicMBean getActiveMBean() { return null; } /** * @see net.sf.hajdbc.Database#getInactiveMBeanClass() */ public DynamicMBean getInactiveMBean() { return null; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/0000755000175000017500000000000011674455606020444 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestOracleDialect.java0000644000175000017500000001443611151703044024630 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.Iterator; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.cache.ForeignKeyConstraintImpl; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @SuppressWarnings("nls") @Test public class TestOracleDialect extends TestStandardDialect { public TestOracleDialect() { super(new OracleDialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetCreateForeignKeyConstraintSQL() */ @Override public void testGetCreateForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getCreateForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table ADD CONSTRAINT name FOREIGN KEY (column1, column2) REFERENCES foreign_table (foreign_column1, foreign_column2) ON DELETE CASCADE") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Connection connection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getConnection()).andReturn(connection); EasyMock.expect(connection.createStatement()).andReturn(statement); EasyMock.expect(statement.executeQuery("SELECT SEQUENCE_NAME FROM USER_SEQUENCES")).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("sequence1"); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("sequence2"); EasyMock.expect(resultSet.next()).andReturn(false); statement.close(); EasyMock.replay(metaData, connection, statement, resultSet); Collection result = this.getSequences(metaData); EasyMock.verify(metaData, connection, statement, resultSet); assert result.size() == 2 : result.size(); Iterator iterator = result.iterator(); QualifiedName sequence = iterator.next(); String schema = sequence.getSchema(); String name = sequence.getName(); assert schema == null : schema; assert name.equals("sequence1") : name; sequence = iterator.next(); schema = sequence.getSchema(); name = sequence.getName(); assert schema == null : schema; assert name.equals("sequence2") : name; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSimpleSQL() */ @Override public void testGetSimpleSQL() throws SQLException { String result = this.getSimpleSQL(); assert result.equals("SELECT CURRENT_TIMESTAMP FROM DUAL") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetTruncateTableSQL() */ @Override public void testGetTruncateTableSQL() throws SQLException { TableProperties table = EasyMock.createStrictMock(TableProperties.class); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.replay(table); String result = this.getTruncateTableSQL(table); EasyMock.verify(table); assert result.equals("TRUNCATE TABLE table") : result; } @Override @DataProvider(name = "sequence-sql") Object[][] sequenceSQLProvider() { return new Object[][] { new Object[] { "SELECT success.nextval" }, new Object[] { "SELECT success.currval" }, new Object[] { "SELECT success.nextval, * FROM table" }, new Object[] { "SELECT success.currval, * FROM table" }, new Object[] { "INSERT INTO table VALUES (success.nextval, 0)" }, new Object[] { "INSERT INTO table VALUES (success.currval, 0)" }, new Object[] { "UPDATE table SET id = success.nextval" }, new Object[] { "UPDATE table SET id = success.currval" }, new Object[] { "SELECT * FROM table" }, }; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testParseInsertTable(java.lang.String) */ @Override @Test(dataProvider = "insert-table-sql") public void testParseInsertTable(String sql) throws SQLException { String result = this.parseInsertTable(sql); assert (result == null) : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetNextSequenceValueSQL() */ @Override public void testGetNextSequenceValueSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getNextSequenceValueSQL(sequence); EasyMock.verify(sequence); assert result.equals("SELECT sequence.NEXTVAL FROM DUAL") : result; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestDerbyDialect.java0000644000175000017500000001506611175404640024476 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Collection; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.cache.ForeignKeyConstraintImpl; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") @Test public class TestDerbyDialect extends TestStandardDialect { public TestDerbyDialect() { super(new DerbyDialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetCreateForeignKeyConstraintSQL() */ @Override public void testGetCreateForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getCreateForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table ADD CONSTRAINT name FOREIGN KEY (column1, column2) REFERENCES foreign_table (foreign_column1, foreign_column2) ON DELETE CASCADE ON UPDATE RESTRICT") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSimpleSQL() */ @Override public void testGetSimpleSQL() throws SQLException { String result = this.getSimpleSQL(); assert result.equals("VALUES CURRENT_TIMESTAMP") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testParseSequence(java.lang.String) */ @Override @Test(dataProvider = "sequence-sql") public void testParseSequence(String sql) throws SQLException { String result = this.parseSequence(sql); assert result == null : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); EasyMock.replay(metaData); Collection result = this.getSequences(metaData); EasyMock.verify(metaData); assert result.isEmpty() : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetNextSequenceValueSQL() */ @Override public void testGetNextSequenceValueSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getNextSequenceValueSQL(sequence); EasyMock.verify(sequence); assert result.equals("VALUES NEXT VALUE FOR sequence") : result; } @Override @DataProvider(name = "current-date") Object[][] currentDateProvider() { java.sql.Date date = new java.sql.Date(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_DATE FROM success", date }, new Object[] { "SELECT CURRENT DATE FROM success", date }, new Object[] { "SELECT CCURRENT_DATE FROM failure", date }, new Object[] { "SELECT CURRENT_DATES FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @Test(dataProvider = "current-date") public void testEvaluateCurrentDate(String sql, java.sql.Date date) { String expected = sql.contains("success") ? String.format("SELECT DATE('%s') FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentDate(sql, date); assert evaluated.equals(expected) : evaluated; } @Override @DataProvider(name = "current-time") Object[][] currentTimeProvider() { java.sql.Time date = new java.sql.Time(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIME FROM success", date }, new Object[] { "SELECT CURRENT TIME FROM success", date }, new Object[] { "SELECT CCURRENT_TIME FROM failure", date }, new Object[] { "SELECT CURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @Test(dataProvider = "current-time") public void testEvaluateCurrentTime(String sql, java.sql.Time date) { String expected = sql.contains("success") ? String.format("SELECT TIME('%s') FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentTime(sql, date); assert evaluated.equals(expected) : evaluated; } @Override @DataProvider(name = "current-timestamp") Object[][] currentTimestampProvider() { java.sql.Timestamp date = new java.sql.Timestamp(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIMESTAMP FROM success", date }, new Object[] { "SELECT CURRENT TIMESTAMP FROM success", date }, new Object[] { "SELECT CCURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT CURRENT_TIMESTAMPS FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @Test(dataProvider = "current-timestamp") public void testEvaluateCurrentTimestamp(String sql, java.sql.Timestamp date) { String expected = sql.contains("success") ? String.format("SELECT TIMESTAMP('%s') FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentTimestamp(sql, date); assert evaluated.equals(expected) : evaluated; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestStandardDialect.java0000644000175000017500000004461511216574752025203 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.UniqueConstraint; import net.sf.hajdbc.cache.ForeignKeyConstraintImpl; import net.sf.hajdbc.cache.UniqueConstraintImpl; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") @Test public class TestStandardDialect implements Dialect { private Dialect dialect; public TestStandardDialect() { this(new StandardDialect()); } protected TestStandardDialect(Dialect dialect) { this.dialect = dialect; } public void testGetAlterSequenceSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getAlterSequenceSQL(sequence, 1000L); EasyMock.verify(sequence); assert result.equals("ALTER SEQUENCE sequence RESTART WITH 1000") : result; } @Override public String getAlterSequenceSQL(SequenceProperties sequence, long value) throws SQLException { return this.dialect.getAlterSequenceSQL(sequence, value); } public void testGetColumnType() throws SQLException { ColumnProperties column = EasyMock.createStrictMock(ColumnProperties.class); EasyMock.expect(column.getType()).andReturn(Types.INTEGER); EasyMock.replay(column); int result = this.getColumnType(column); EasyMock.verify(column); assert result == Types.INTEGER : result; } @Override public int getColumnType(ColumnProperties column) throws SQLException { return this.dialect.getColumnType(column); } public void testGetCreateForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getCreateForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table ADD CONSTRAINT name FOREIGN KEY (column1, column2) REFERENCES foreign_table (foreign_column1, foreign_column2) ON DELETE CASCADE ON UPDATE RESTRICT DEFERRABLE INITIALLY DEFERRED") : result; } @Override public String getCreateForeignKeyConstraintSQL(ForeignKeyConstraint constraint) throws SQLException { return this.dialect.getCreateForeignKeyConstraintSQL(constraint); } public void testGetCreateUniqueConstraintSQL() throws SQLException { UniqueConstraint key = new UniqueConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); String result = this.getCreateUniqueConstraintSQL(key); assert result.equals("ALTER TABLE table ADD CONSTRAINT name UNIQUE (column1, column2)") : result; } @Override public String getCreateUniqueConstraintSQL(UniqueConstraint constraint) throws SQLException { return this.dialect.getCreateUniqueConstraintSQL(constraint); } public void testGetDropForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getDropForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table DROP CONSTRAINT name") : result; } @Override public String getDropForeignKeyConstraintSQL(ForeignKeyConstraint constraint) throws SQLException { return this.dialect.getDropForeignKeyConstraintSQL(constraint); } public void testGetDropUniqueConstraintSQL() throws SQLException { UniqueConstraint key = new UniqueConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); String result = this.getDropUniqueConstraintSQL(key); assert result.equals("ALTER TABLE table DROP CONSTRAINT name") : result; } @Override public String getDropUniqueConstraintSQL(UniqueConstraint constraint) throws SQLException { return this.dialect.getDropUniqueConstraintSQL(constraint); } public void testGetNextSequenceValueSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getNextSequenceValueSQL(sequence); EasyMock.verify(sequence); assert result.equals("SELECT NEXT VALUE FOR sequence") : result; } @Override public String getNextSequenceValueSQL(SequenceProperties sequence) throws SQLException { return this.dialect.getNextSequenceValueSQL(sequence); } public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getTables(EasyMock.eq(""), EasyMock.eq((String) null), EasyMock.eq("%"), EasyMock.aryEq(new String[] { "SEQUENCE" }))).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString("TABLE_SCHEM")).andReturn("schema1"); EasyMock.expect(resultSet.getString("TABLE_NAME")).andReturn("sequence1"); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString("TABLE_SCHEM")).andReturn("schema2"); EasyMock.expect(resultSet.getString("TABLE_NAME")).andReturn("sequence2"); EasyMock.expect(resultSet.next()).andReturn(false); resultSet.close(); EasyMock.replay(metaData, resultSet); Collection results = this.getSequences(metaData); EasyMock.verify(metaData, resultSet); assert results.size() == 2 : results; Iterator iterator = results.iterator(); QualifiedName sequence = iterator.next(); String schema = sequence.getSchema(); String name = sequence.getName(); assert schema.equals("schema1") : schema; assert name.equals("sequence1") : name; sequence = iterator.next(); schema = sequence.getSchema(); name = sequence.getName(); assert schema.equals("schema2") : schema; assert name.equals("sequence2") : name; } @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { return this.dialect.getSequences(metaData); } public void testGetSimpleSQL() throws SQLException { String result = this.getSimpleSQL(); assert result.equals("SELECT CURRENT_TIMESTAMP") : result; } @Override public String getSimpleSQL() throws SQLException { return this.dialect.getSimpleSQL(); } public void testGetTruncateTableSQL() throws SQLException { TableProperties table = EasyMock.createStrictMock(TableProperties.class); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.replay(table); String result = this.getTruncateTableSQL(table); EasyMock.verify(table); assert result.equals("DELETE FROM table") : result; } @Override public String getTruncateTableSQL(TableProperties properties) throws SQLException { return this.dialect.getTruncateTableSQL(properties); } @DataProvider(name = "select-for-update-sql") Object[][] selectForUpdateProvider() { return new Object[][] { new Object[] { "SELECT * FROM success FOR UPDATE" }, new Object[] { "SELECT * FROM failure" }, }; } @Test(dataProvider = "select-for-update-sql") public void testIsSelectForUpdate(String sql) throws SQLException { boolean result = this.isSelectForUpdate(sql); assert result == sql.contains("success"); } @Override public boolean isSelectForUpdate(String sql) throws SQLException { return this.dialect.isSelectForUpdate(sql); } @DataProvider(name = "sequence-sql") Object[][] sequenceSQLProvider() { return new Object[][] { new Object[] { "SELECT NEXT VALUE FOR success" }, new Object[] { "SELECT NEXT VALUE FOR success, * FROM table" }, new Object[] { "INSERT INTO table VALUES (NEXT VALUE FOR success, 0)" }, new Object[] { "UPDATE table SET id = NEXT VALUE FOR success" }, new Object[] { "SELECT * FROM table" }, }; } @Test(dataProvider = "sequence-sql") public void testParseSequence(String sql) throws SQLException { String result = this.parseSequence(sql); if (sql.contains("success")) { assert (result != null); assert result.equals("success") : result; } else { assert (result == null) : result; } } @Override public String parseSequence(String sql) throws SQLException { return this.dialect.parseSequence(sql); } public void testGetDefaultSchemas() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); String user = "user"; EasyMock.expect(metaData.getUserName()).andReturn(user); EasyMock.replay(metaData); List result = this.getDefaultSchemas(metaData); EasyMock.verify(metaData); assert result.size() == 1 : result.size(); String schema = result.get(0); assert schema.equals(user) : schema; } @Override public List getDefaultSchemas(DatabaseMetaData metaData) throws SQLException { return this.dialect.getDefaultSchemas(metaData); } @DataProvider(name = "insert-table-sql") Object[][] insertTableProvider() { return new Object[][] { new Object[] { "INSERT INTO success (column1, column2) VALUES (1, 2)" }, new Object[] { "INSERT INTO success VALUES (1, 2)" }, new Object[] { "INSERT success (column1, column2) VALUES (1, 2)" }, new Object[] { "INSERT success VALUES (1, 2)" }, new Object[] { "INSERT INTO success (column1, column2) SELECT column1, column2 FROM dummy" }, new Object[] { "INSERT INTO success SELECT column1, column2 FROM dummy" }, new Object[] { "INSERT success (column1, column2) SELECT column1, column2 FROM dummy" }, new Object[] { "INSERT success SELECT column1, column2 FROM dummy" }, new Object[] { "SELECT * FROM failure WHERE 0=1" }, new Object[] { "UPDATE failure SET column = 0" }, }; } @Test(dataProvider = "insert-table-sql") public void testParseInsertTable(String sql) throws SQLException { String result = this.parseInsertTable(sql); if (sql.contains("success")) { assert result != null; assert result.equals("success"); } else { assert result == null : result; } } @Override public String parseInsertTable(String sql) throws SQLException { return this.dialect.parseInsertTable(sql); } public void testGetIdentifierPattern() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); EasyMock.expect(metaData.getExtraNameCharacters()).andReturn("$"); EasyMock.replay(metaData); String result = this.getIdentifierPattern(metaData).pattern(); EasyMock.verify(metaData); assert result.equals("[a-zA-Z][\\w\\Q$\\E]*") : result; } @Override public Pattern getIdentifierPattern(DatabaseMetaData metaData) throws SQLException { return this.dialect.getIdentifierPattern(metaData); } @DataProvider(name = "current-date") Object[][] currentDateProvider() { java.sql.Date date = new java.sql.Date(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_DATE FROM success", date }, new Object[] { "SELECT CCURRENT_DATE FROM failure", date }, new Object[] { "SELECT CURRENT_DATES FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Test(dataProvider = "current-date") public void testEvaluateCurrentDate(String sql, java.sql.Date date) { String expected = sql.contains("success") ? String.format("SELECT DATE '%s' FROM success", date.toString()) : sql; String result = this.evaluateCurrentDate(sql, date); assert result.equals(expected) : result; } @Override public String evaluateCurrentDate(String sql, java.sql.Date date) { return this.dialect.evaluateCurrentDate(sql, date); } @DataProvider(name = "current-time") Object[][] currentTimeProvider() { java.sql.Time date = new java.sql.Time(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIME FROM success", date }, new Object[] { "SELECT CURRENT_TIME(2) FROM success", date }, new Object[] { "SELECT CURRENT_TIME ( 2 ) FROM success", date }, new Object[] { "SELECT LOCALTIME FROM success", date }, new Object[] { "SELECT LOCALTIME(2) FROM success", date }, new Object[] { "SELECT LOCALTIME ( 2 ) FROM success", date }, new Object[] { "SELECT CCURRENT_TIME FROM failure", date }, new Object[] { "SELECT LLOCALTIME FROM failure", date }, new Object[] { "SELECT CURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT LOCALTIMESTAMP FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Test(dataProvider = "current-time") public void testEvaluateCurrentTime(String sql, java.sql.Time date) { String expected = sql.contains("success") ? String.format("SELECT TIME '%s' FROM success", date.toString()) : sql; String result = this.evaluateCurrentTime(sql, date); assert result.equals(expected) : result; } @Override public String evaluateCurrentTime(String sql, java.sql.Time date) { return this.dialect.evaluateCurrentTime(sql, date); } @DataProvider(name = "current-timestamp") Object[][] currentTimestampProvider() { java.sql.Timestamp date = new java.sql.Timestamp(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIMESTAMP FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMP(2) FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMP ( 2 ) FROM success", date }, new Object[] { "SELECT LOCALTIMESTAMP FROM success", date }, new Object[] { "SELECT LOCALTIMESTAMP(2) FROM success", date }, new Object[] { "SELECT LOCALTIMESTAMP ( 2 ) FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMPS FROM failure", date }, new Object[] { "SELECT CCURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT LOCALTIMESTAMPS FROM failure", date }, new Object[] { "SELECT LLOCALTIMESTAMP FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Test(dataProvider = "current-timestamp") public void testEvaluateCurrentTimestamp(String sql, java.sql.Timestamp date) { String expected = sql.contains("success") ? String.format("SELECT TIMESTAMP '%s' FROM success", date.toString()) : sql; String result = this.evaluateCurrentTimestamp(sql, date); assert result.equals(expected) : result; } @Override public String evaluateCurrentTimestamp(String sql, java.sql.Timestamp date) { return this.dialect.evaluateCurrentTimestamp(sql, date); } @DataProvider(name = "random") Object[][] randomProvider() { return new Object[][] { new Object[] { "SELECT RAND() FROM success" }, new Object[] { "SELECT RAND ( ) FROM success" }, new Object[] { "SELECT RAND FROM failure" }, new Object[] { "SELECT OPERAND() FROM failure" }, new Object[] { "SELECT 1 FROM failure" }, }; } @Test(dataProvider = "random") public void testEvaluateRand(String sql) { String result = this.evaluateRand(sql); if (sql.contains("success")) { assert Pattern.matches("SELECT ((0\\.\\d+)|([1-9]\\.\\d+E\\-\\d+)) FROM success", result) : result; } else { assert result.equals(sql) : result; } } @Override public String evaluateRand(String sql) { return this.dialect.evaluateRand(sql); } public void testGetAlterIdentityColumnSQL() throws SQLException { TableProperties table = EasyMock.createStrictMock(TableProperties.class); ColumnProperties column = EasyMock.createStrictMock(ColumnProperties.class); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.expect(column.getName()).andReturn("column"); EasyMock.replay(table, column); String result = this.getAlterIdentityColumnSQL(table, column, 1000L); EasyMock.verify(table, column); assert result.equals("ALTER TABLE table ALTER COLUMN column RESTART WITH 1000") : result; } @Override public String getAlterIdentityColumnSQL(TableProperties table, ColumnProperties column, long value) throws SQLException { return this.dialect.getAlterIdentityColumnSQL(table, column, value); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestH2Dialect.java0000644000175000017500000001636111151703044023673 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.Iterator; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.cache.ForeignKeyConstraintImpl; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @SuppressWarnings("nls") @Test public class TestH2Dialect extends TestStandardDialect { public TestH2Dialect() { super(new H2Dialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetCreateForeignKeyConstraintSQL() */ @Override public void testGetCreateForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getCreateForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table ADD CONSTRAINT name FOREIGN KEY (column1, column2) REFERENCES foreign_table (foreign_column1, foreign_column2) ON DELETE CASCADE ON UPDATE RESTRICT") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Connection connection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getConnection()).andReturn(connection); EasyMock.expect(connection.createStatement()).andReturn(statement); EasyMock.expect(statement.executeQuery("SELECT SEQUENCE_SCHEMA, SEQUENCE_NAME FROM INFORMATION_SCHEMA.SYSTEM_SEQUENCES")).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("schema1"); EasyMock.expect(resultSet.getString(2)).andReturn("sequence1"); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("schema2"); EasyMock.expect(resultSet.getString(2)).andReturn("sequence2"); EasyMock.expect(resultSet.next()).andReturn(false); statement.close(); EasyMock.replay(metaData, connection, statement, resultSet); Collection result = this.getSequences(metaData); EasyMock.verify(metaData, connection, statement, resultSet); assert result.size() == 2 : result; Iterator iterator = result.iterator(); QualifiedName sequence = iterator.next(); String schema = sequence.getSchema(); String name = sequence.getName(); assert schema.equals("schema1") : schema; assert name.equals("sequence1") : name; sequence = iterator.next(); schema = sequence.getSchema(); name = sequence.getName(); assert schema.equals("schema2") : schema; assert name.equals("sequence2") : name; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSimpleSQL() */ @Override public void testGetSimpleSQL() throws SQLException { String result = this.getSimpleSQL(); assert result.equals("CALL CURRENT_TIMESTAMP") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetNextSequenceValueSQL() */ @Override public void testGetNextSequenceValueSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getNextSequenceValueSQL(sequence); EasyMock.verify(sequence); assert result.equals("CALL NEXT VALUE FOR sequence") : result; } @Override @DataProvider(name = "current-date") Object[][] currentDateProvider() { java.sql.Date date = new java.sql.Date(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_DATE FROM success", date }, new Object[] { "SELECT CURRENT_DATE() FROM success", date }, new Object[] { "SELECT CURRENT_DATE ( ) FROM success", date }, new Object[] { "SELECT CURDATE() FROM success", date }, new Object[] { "SELECT CURDATE ( ) FROM success", date }, new Object[] { "SELECT CURRENT_DATES FROM failure", date }, new Object[] { "SELECT CCURRENT_DATE FROM failure", date }, new Object[] { "SELECT CCURDATE() FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @DataProvider(name = "current-time") Object[][] currentTimeProvider() { java.sql.Time date = new java.sql.Time(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIME FROM success", date }, new Object[] { "SELECT CURRENT_TIME() FROM success", date }, new Object[] { "SELECT CURRENT_TIME ( ) FROM success", date }, new Object[] { "SELECT CURTIME() FROM success", date }, new Object[] { "SELECT CURTIME ( ) FROM success", date }, new Object[] { "SELECT CCURRENT_TIME FROM failure", date }, new Object[] { "SELECT CURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT CCURTIME() FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @DataProvider(name = "current-timestamp") Object[][] currentTimestampProvider() { java.sql.Timestamp date = new java.sql.Timestamp(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIMESTAMP FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMP() FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMP ( ) FROM success", date }, new Object[] { "SELECT NOW() FROM success", date }, new Object[] { "SELECT NOW ( ) FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMPS FROM failure", date }, new Object[] { "SELECT CCURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT NNOW() FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestHSQLDBDialect.java0000644000175000017500000001607011151703044024374 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.Iterator; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.cache.ForeignKeyConstraintImpl; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") @Test public class TestHSQLDBDialect extends TestStandardDialect { public TestHSQLDBDialect() { super(new HSQLDBDialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetCreateForeignKeyConstraintSQL() */ @Override public void testGetCreateForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getCreateForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table ADD CONSTRAINT name FOREIGN KEY (column1, column2) REFERENCES foreign_table (foreign_column1, foreign_column2) ON DELETE CASCADE ON UPDATE RESTRICT") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Connection connection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getConnection()).andReturn(connection); EasyMock.expect(connection.createStatement()).andReturn(statement); EasyMock.expect(statement.executeQuery("SELECT SEQUENCE_SCHEMA, SEQUENCE_NAME FROM INFORMATION_SCHEMA.SYSTEM_SEQUENCES")).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("schema1"); EasyMock.expect(resultSet.getString(2)).andReturn("sequence1"); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("schema2"); EasyMock.expect(resultSet.getString(2)).andReturn("sequence2"); EasyMock.expect(resultSet.next()).andReturn(false); statement.close(); EasyMock.replay(metaData, connection, statement, resultSet); Collection result = this.getSequences(metaData); EasyMock.verify(metaData, connection, statement, resultSet); assert result.size() == 2 : result; Iterator iterator = result.iterator(); QualifiedName sequence = iterator.next(); String schema = sequence.getSchema(); String name = sequence.getName(); assert schema.equals("schema1") : schema; assert name.equals("sequence1") : name; sequence = iterator.next(); schema = sequence.getSchema(); name = sequence.getName(); assert schema.equals("schema2") : schema; assert name.equals("sequence2") : name; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSimpleSQL() */ @Override public void testGetSimpleSQL() throws SQLException { String result = this.getSimpleSQL(); assert result.equals("CALL CURRENT_TIMESTAMP") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetNextSequenceValueSQL() */ @Override public void testGetNextSequenceValueSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getNextSequenceValueSQL(sequence); EasyMock.verify(sequence); assert result.equals("CALL NEXT VALUE FOR sequence") : result; } @Override @DataProvider(name = "current-date") Object[][] currentDateProvider() { java.sql.Date date = new java.sql.Date(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_DATE FROM success", date }, new Object[] { "SELECT CURDATE() FROM success", date }, new Object[] { "SELECT CURDATE ( ) FROM success", date }, new Object[] { "SELECT CCURRENT_DATE FROM failure", date }, new Object[] { "SELECT CURRENT_DATES FROM failure", date }, new Object[] { "SELECT CCURDATE() FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @DataProvider(name = "current-time") Object[][] currentTimeProvider() { java.sql.Time date = new java.sql.Time(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIME FROM success", date }, new Object[] { "SELECT CURTIME() FROM success", date }, new Object[] { "SELECT CURTIME ( ) FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT CCURRENT_TIME FROM failure", date }, new Object[] { "SELECT CCURTIME() FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @DataProvider(name = "current-timestamp") Object[][] currentTimestampProvider() { java.sql.Timestamp date = new java.sql.Timestamp(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIMESTAMP FROM success", date }, new Object[] { "SELECT NOW() FROM success", date }, new Object[] { "SELECT NOW ( ) FROM success", date }, new Object[] { "SELECT CCURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT CURRENT_TIMESTAMPS FROM failure", date }, new Object[] { "SELECT NNOW() FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestDB2Dialect.java0000644000175000017500000001335411151703044023770 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.Iterator; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") @Test public class TestDB2Dialect extends TestStandardDialect { public TestDB2Dialect() { super(new DB2Dialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Connection connection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getConnection()).andReturn(connection); EasyMock.expect(connection.createStatement()).andReturn(statement); EasyMock.expect(statement.executeQuery("SELECT SEQSCHEMA, SEQNAME FROM SYSCAT.SEQUENCES")).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("schema1"); EasyMock.expect(resultSet.getString(2)).andReturn("sequence1"); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("schema2"); EasyMock.expect(resultSet.getString(2)).andReturn("sequence2"); EasyMock.expect(resultSet.next()).andReturn(false); statement.close(); EasyMock.replay(metaData, connection, statement, resultSet); Collection result = this.getSequences(metaData); EasyMock.verify(metaData, connection, statement, resultSet); assert result.size() == 2 : result.size(); Iterator iterator = result.iterator(); QualifiedName sequence = iterator.next(); String schema = sequence.getSchema(); String name = sequence.getName(); assert schema.equals("schema1") : schema; assert name.equals("sequence1") : name; sequence = iterator.next(); schema = sequence.getSchema(); name = sequence.getName(); assert schema.equals("schema2") : schema; assert name.equals("sequence2") : name; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetNextSequenceValueSQL() */ @Override public void testGetNextSequenceValueSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getNextSequenceValueSQL(sequence); EasyMock.verify(sequence); assert result.equals("VALUES NEXTVAL FOR sequence") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSimpleSQL() */ @Override public void testGetSimpleSQL() throws SQLException { String result = this.getSimpleSQL(); assert result.equals("VALUES CURRENT_TIMESTAMP") : result; } @Override @DataProvider(name = "sequence-sql") Object[][] sequenceSQLProvider() { return new Object[][] { new Object[] { "VALUES NEXTVAL FOR success" }, new Object[] { "VALUES PREVVAL FOR success" }, new Object[] { "INSERT INTO table VALUES (NEXTVAL FOR success, 0)" }, new Object[] { "INSERT INTO table VALUES (PREVVAL FOR success, 0)" }, new Object[] { "UPDATE table SET id = NEXTVAL FOR success" }, new Object[] { "UPDATE table SET id = PREVVAL FOR success" }, new Object[] { "SELECT * FROM table" }, }; } @Override @Test(dataProvider = "current-date") public void testEvaluateCurrentDate(String sql, java.sql.Date date) { String expected = sql.contains("success") ? String.format("SELECT '%s' FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentDate(sql, date); assert evaluated.equals(expected) : evaluated; } @Override @Test(dataProvider = "current-time") public void testEvaluateCurrentTime(String sql, java.sql.Time date) { String expected = sql.contains("success") ? String.format("SELECT '%s' FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentTime(sql, date); assert evaluated.equals(expected) : evaluated; } @Override @Test(dataProvider = "current-timestamp") public void testEvaluateCurrentTimestamp(String sql, java.sql.Timestamp date) { String expected = sql.contains("success") ? String.format("SELECT '%s' FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentTimestamp(sql, date); assert evaluated.equals(expected) : evaluated; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestFirebirdDialect.java0000644000175000017500000001237311151703044025147 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.Iterator; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") @Test public class TestFirebirdDialect extends TestStandardDialect { public TestFirebirdDialect() { super(new FirebirdDialect()); } @Override public void testGetAlterSequenceSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getAlterSequenceSQL(sequence, 1000L); EasyMock.verify(sequence); assert result.equals("SET GENERATOR sequence TO 1000") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Connection connection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getConnection()).andReturn(connection); EasyMock.expect(connection.createStatement()).andReturn(statement); EasyMock.expect(statement.executeQuery("SELECT RDB$GENERATOR_NAME FROM RDB$GENERATORS")).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("sequence1"); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("sequence2"); EasyMock.expect(resultSet.next()).andReturn(false); statement.close(); EasyMock.replay(metaData, connection, statement, resultSet); Collection results = this.getSequences(metaData); EasyMock.verify(metaData, connection, statement, resultSet); assert results.size() == 2 : results; Iterator iterator = results.iterator(); QualifiedName sequence = iterator.next(); String schema = sequence.getSchema(); String name = sequence.getName(); assert schema == null : schema; assert name.equals("sequence1") : name; sequence = iterator.next(); schema = sequence.getSchema(); name = sequence.getName(); assert schema == null : schema; assert name.equals("sequence2") : name; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetNextSequenceValueSQL() */ @Override public void testGetNextSequenceValueSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String sql = this.getNextSequenceValueSQL(sequence); EasyMock.verify(sequence); assert sql.equals("SELECT GEN_ID(sequence, 1) FROM RDB$DATABASE") : sql; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSimpleSQL() */ @Override public void testGetSimpleSQL() throws SQLException { String result = this.getSimpleSQL(); assert result.equals("SELECT CURRENT_TIMESTAMP FROM RDB$DATABASE") : result; } @Override @DataProvider(name = "select-for-update-sql") Object[][] selectForUpdateProvider() { return new Object[][] { new Object[] { "SELECT * FROM success WITH LOCK" }, new Object[] { "SELECT * FROM failure" }, }; } @Override @DataProvider(name = "sequence-sql") Object[][] sequenceSQLProvider() { return new Object[][] { new Object[] { "SELECT GEN_ID(success, 1) FROM RDB$DATABASE" }, new Object[] { "SELECT GEN_ID(success, 1), * FROM table" }, new Object[] { "INSERT INTO table VALUES (GEN_ID(success, 1), 0)" }, new Object[] { "UPDATE table SET id = GEN_ID(success, 1)" }, new Object[] { "SELECT * FROM table" }, }; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testParseInsertTable(java.lang.String) */ @Override @Test(dataProvider = "insert-table-sql") public void testParseInsertTable(String sql) throws SQLException { String result = this.parseInsertTable(sql); assert result == null : result; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestIngresDialect.java0000644000175000017500000001564111151703044024651 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.Iterator; import net.sf.hajdbc.QualifiedName; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @SuppressWarnings("nls") @Test public class TestIngresDialect extends TestStandardDialect { public TestIngresDialect() { super(new IngresDialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testParseInsertTable(java.lang.String) */ @Override @Test(dataProvider = "insert-table-sql") public void testParseInsertTable(String sql) throws SQLException { String result = this.parseInsertTable(sql); assert (result == null) : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Connection connection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getConnection()).andReturn(connection); EasyMock.expect(connection.createStatement()).andReturn(statement); EasyMock.expect(statement.executeQuery("SELECT seq_name FROM iisequence")).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("sequence1"); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("sequence2"); EasyMock.expect(resultSet.next()).andReturn(false); statement.close(); EasyMock.replay(metaData, connection, statement, resultSet); Collection result = this.getSequences(metaData); EasyMock.verify(metaData, connection, statement, resultSet); assert result.size() == 2 : result; Iterator iterator = result.iterator(); QualifiedName sequence = iterator.next(); String schema = sequence.getSchema(); String name = sequence.getName(); assert (schema == null) : schema; assert name.equals("sequence1") : name; sequence = iterator.next(); schema = sequence.getSchema(); name = sequence.getName(); assert (schema == null) : schema; assert name.equals("sequence2") : name; } @Override @DataProvider(name = "sequence-sql") Object[][] sequenceSQLProvider() { return new Object[][] { new Object[] { "SELECT NEXT VALUE FOR success" }, new Object[] { "SELECT CURRENT VALUE FOR success" }, new Object[] { "SELECT NEXT VALUE FOR success, * FROM table" }, new Object[] { "SELECT CURRENT VALUE FOR success, * FROM table" }, new Object[] { "INSERT INTO table VALUES (NEXT VALUE FOR success, 0)" }, new Object[] { "INSERT INTO table VALUES (CURRENT VALUE FOR success, 0)" }, new Object[] { "UPDATE table SET id = NEXT VALUE FOR success" }, new Object[] { "UPDATE table SET id = CURRENT VALUE FOR success" }, new Object[] { "SELECT success.nextval" }, new Object[] { "SELECT success.currval" }, new Object[] { "SELECT success.nextval, * FROM table" }, new Object[] { "SELECT success.currval, * FROM table" }, new Object[] { "INSERT INTO table VALUES (success.nextval, 0)" }, new Object[] { "INSERT INTO table VALUES (success.currval, 0)" }, new Object[] { "UPDATE table SET id = success.nextval" }, new Object[] { "UPDATE table SET id = success.currval" }, new Object[] { "SELECT * FROM table" }, }; } @Override @DataProvider(name = "current-date") Object[][] currentDateProvider() { java.sql.Date date = new java.sql.Date(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_DATE FROM success", date }, new Object[] { "SELECT DATE('TODAY') FROM success", date }, new Object[] { "SELECT DATE ( 'TODAY' ) FROM success", date }, new Object[] { "SELECT CURRENT_DATES FROM failure", date }, new Object[] { "SELECT CCURRENT_DATE FROM failure", date }, new Object[] { "SELECT DDATE('TODAY') FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @DataProvider(name = "current-time") Object[][] currentTimeProvider() { java.sql.Time date = new java.sql.Time(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIME FROM success", date }, new Object[] { "SELECT LOCAL_TIME FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT CCURRENT_TIME FROM failure", date }, new Object[] { "SELECT LOCAL_TIMESTAMP FROM failure", date }, new Object[] { "SELECT LLOCAL_TIME FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @DataProvider(name = "current-timestamp") Object[][] currentTimestampProvider() { java.sql.Timestamp date = new java.sql.Timestamp(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIMESTAMP FROM success", date }, new Object[] { "SELECT LOCAL_TIMESTAMP FROM success", date }, new Object[] { "SELECT DATE('NOW') FROM success", date }, new Object[] { "SELECT DATE( 'NOW' ) FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMPS FROM failure", date }, new Object[] { "SELECT CCURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT LOCAL_TIMESTAMPS FROM failure", date }, new Object[] { "SELECT LLOCAL_TIMESTAMP FROM failure", date }, new Object[] { "SELECT DDATE('NOW') FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @DataProvider(name = "random") Object[][] randomProvider() { return new Object[][] { new Object[] { "SELECT RANDOMF() FROM success" }, new Object[] { "SELECT RANDOMF ( ) FROM success" }, new Object[] { "SELECT OPERANDOMF( ) FROM failure" }, new Object[] { "SELECT RAND() FROM failure" }, new Object[] { "SELECT 1 FROM failure" }, }; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestDialectClass.java0000644000175000017500000000706311151703044024466 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import net.sf.hajdbc.Dialect; import org.easymock.EasyMock; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") public class TestDialectClass { /** * Test method for {@link DialectClass#serialize(Dialect)}. */ @Test public void serialize() { Dialect dialect = EasyMock.createStrictMock(Dialect.class); this.assertDialect(dialect, dialect.getClass().getName()); this.assertDialect(new DB2Dialect(), "db2"); this.assertDialect(new DerbyDialect(), "derby"); this.assertDialect(new FirebirdDialect(), "firebird"); this.assertDialect(new H2Dialect(), "h2"); this.assertDialect(new HSQLDBDialect(), "hsqldb"); this.assertDialect(new IngresDialect(), "ingres"); this.assertDialect(new MaxDBDialect(), "maxdb"); this.assertDialect(new MySQLDialect(), "mysql"); this.assertDialect(new OracleDialect(), "oracle"); this.assertDialect(new PostgreSQLDialect(), "postgresql"); this.assertDialect(new StandardDialect(), "standard"); } private void assertDialect(Dialect dialect, String id) { String result = DialectClass.serialize(dialect); assert result.equals(id) : result; } /** * Test method for {@link DialectClass#deserialize(String)}. */ @Test public void deserialize() { this.assertDialect(null, StandardDialect.class); this.assertDialect("net.sf.hajdbc.dialect.StandardDialect", StandardDialect.class); this.assertDialect("standard", StandardDialect.class); this.assertDialect("db2", DB2Dialect.class); this.assertDialect("derby", DerbyDialect.class); this.assertDialect("firebird", StandardDialect.class); this.assertDialect("h2", H2Dialect.class); this.assertDialect("hsqldb", HSQLDBDialect.class); this.assertDialect("ingres", IngresDialect.class); this.assertDialect("maxdb", MaxDBDialect.class); this.assertDialect("mckoi", MckoiDialect.class); this.assertDialect("mysql", MySQLDialect.class); this.assertDialect("oracle", OracleDialect.class); this.assertDialect("postgresql", PostgreSQLDialect.class); this.assertDialect("PostgreSQL", PostgreSQLDialect.class); this.assertDialect("POSTGRESQL", PostgreSQLDialect.class); try { Dialect dialect = DialectClass.deserialize("invalid"); assert false : dialect.getClass().getName(); } catch (Exception e) { assert true; } } private void assertDialect(String id, Class dialectClass) { try { Dialect dialect = DialectClass.deserialize(id); assert dialectClass.isInstance(dialect) : dialect.getClass().getName(); } catch (Exception e) { assert false : e; } } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestMaxDBDialect.java0000644000175000017500000001472411151703044024356 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.Iterator; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.cache.ForeignKeyConstraintImpl; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") @Test public class TestMaxDBDialect extends TestStandardDialect { public TestMaxDBDialect() { super(new MaxDBDialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetCreateForeignKeyConstraintSQL() */ @Override public void testGetCreateForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getCreateForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table ADD CONSTRAINT name FOREIGN KEY (column1, column2) REFERENCES foreign_table (foreign_column1, foreign_column2) ON DELETE CASCADE") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Connection connection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getConnection()).andReturn(connection); EasyMock.expect(connection.createStatement()).andReturn(statement); EasyMock.expect(statement.executeQuery("SELECT SEQUENCE_NAME FROM USER_SEQUENCES")).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("sequence1"); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(resultSet.getString(1)).andReturn("sequence2"); EasyMock.expect(resultSet.next()).andReturn(false); statement.close(); EasyMock.replay(metaData, connection, statement, resultSet); Collection result = this.getSequences(metaData); EasyMock.verify(metaData, connection, statement, resultSet); assert result.size() == 2 : result; Iterator iterator = result.iterator(); QualifiedName sequence = iterator.next(); String schema = sequence.getSchema(); String name = sequence.getName(); assert (schema == null) : schema; assert name.equals("sequence1") : name; sequence = iterator.next(); schema = sequence.getSchema(); name = sequence.getName(); assert (schema == null) : schema; assert name.equals("sequence2") : name; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSimpleSQL() */ @Override public void testGetSimpleSQL() throws SQLException { String result = this.getSimpleSQL(); assert result.equals("SELECT SYSDATE FROM DUAL") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetTruncateTableSQL() */ @Override public void testGetTruncateTableSQL() throws SQLException { TableProperties table = EasyMock.createStrictMock(TableProperties.class); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.replay(table); String result = this.getTruncateTableSQL(table); EasyMock.verify(table); assert result.equals("TRUNCATE TABLE table") : result; } @Override @DataProvider(name = "sequence-sql") Object[][] sequenceSQLProvider() { return new Object[][] { new Object[] { "SELECT success.nextval" }, new Object[] { "SELECT success.currval" }, new Object[] { "SELECT success.nextval, * FROM table" }, new Object[] { "SELECT success.currval, * FROM table" }, new Object[] { "INSERT INTO table VALUES (success.nextval, 0)" }, new Object[] { "INSERT INTO table VALUES (success.currval, 0)" }, new Object[] { "UPDATE table SET id = success.nextval" }, new Object[] { "UPDATE table SET id = success.currval" }, new Object[] { "SELECT * FROM table" }, }; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testParseInsertTable(java.lang.String) */ @Override @Test(dataProvider = "insert-table-sql") public void testParseInsertTable(String sql) throws SQLException { String result = this.parseInsertTable(sql); assert (result == null) : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetNextSequenceValueSQL() */ @Override public void testGetNextSequenceValueSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getNextSequenceValueSQL(sequence); EasyMock.verify(sequence); assert result.equals("SELECT sequence.NEXTVAL FROM DUAL") : result; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestMckoiDialect.java0000644000175000017500000000521311151703044024456 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.SQLException; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @SuppressWarnings("nls") @Test public class TestMckoiDialect extends TestStandardDialect { public TestMckoiDialect() { super(new MckoiDialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testParseInsertTable(java.lang.String) */ @Override @Test(dataProvider = "insert-table-sql") public void testParseInsertTable(String sql) throws SQLException { String result = this.parseInsertTable(sql); assert (result == null) : result; } @Override @DataProvider(name = "sequence-sql") Object[][] sequenceSQLProvider() { return new Object[][] { new Object[] { "SELECT NEXTVAL('success')" }, new Object[] { "SELECT NEXTVAL ( 'success' )" }, new Object[] { "SELECT CURRVAL('success')" }, new Object[] { "SELECT CURRVAL ( 'success' )" }, new Object[] { "SELECT NEXTVAL('success'), * FROM table" }, new Object[] { "SELECT NEXTVAL ( 'success' ) , * FROM table" }, new Object[] { "SELECT CURRVAL('success'), * FROM table" }, new Object[] { "SELECT CURRVAL ( 'success' ) , * FROM table" }, new Object[] { "INSERT INTO table VALUES (NEXTVAL('success'), 0)" }, new Object[] { "INSERT INTO table VALUES (NEXTVAL ( 'success' ) , 0)" }, new Object[] { "INSERT INTO table VALUES (CURRVAL('success'), 0)" }, new Object[] { "INSERT INTO table VALUES (CURRVAL ( 'success' ) , 0)" }, new Object[] { "UPDATE table SET id = NEXTVAL('success')" }, new Object[] { "UPDATE table SET id = NEXTVAL ( 'success' )" }, new Object[] { "UPDATE table SET id = CURRVAL('success')" }, new Object[] { "UPDATE table SET id = CURRVAL ( 'success' )" }, new Object[] { "SELECT * FROM table" }, }; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestMySQLDialect.java0000644000175000017500000002517411175404621024376 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.List; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.UniqueConstraint; import net.sf.hajdbc.cache.ForeignKeyConstraintImpl; import net.sf.hajdbc.cache.UniqueConstraintImpl; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") @Test public class TestMySQLDialect extends TestStandardDialect { public TestMySQLDialect() { super(new MySQLDialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetCreateForeignKeyConstraintSQL() */ @Override public void testGetCreateForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getCreateForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table ADD CONSTRAINT name FOREIGN KEY (column1, column2) REFERENCES foreign_table (foreign_column1, foreign_column2) ON DELETE CASCADE ON UPDATE RESTRICT") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetDropForeignKeyConstraintSQL() */ @Override public void testGetDropForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getDropForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table DROP FOREIGN KEY name") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetCreateUniqueConstraintSQL() */ @Override public void testGetCreateUniqueConstraintSQL() throws SQLException { UniqueConstraint key = new UniqueConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); String result = this.getCreateUniqueConstraintSQL(key); assert result.equals("ALTER TABLE table ADD UNIQUE name (column1, column2)") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetDropUniqueConstraintSQL() */ @Override public void testGetDropUniqueConstraintSQL() throws SQLException { UniqueConstraint key = new UniqueConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); String result = this.getDropUniqueConstraintSQL(key); assert result.equals("ALTER TABLE table DROP INDEX name") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testParseSequence(java.lang.String) */ @Override @Test(dataProvider = "sequence-sql") public void testParseSequence(String sql) throws SQLException { String result = this.parseSequence(sql); assert (result == null) : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Collection result = this.getSequences(metaData); assert result.isEmpty() : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetDefaultSchemas() */ @Override public void testGetDefaultSchemas() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Connection connection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getConnection()).andReturn(connection); EasyMock.expect(connection.createStatement()).andReturn(statement); EasyMock.expect(statement.executeQuery("SELECT DATABASE()")).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(false); EasyMock.expect(resultSet.getString(1)).andReturn("database"); resultSet.close(); statement.close(); EasyMock.replay(metaData, connection, statement, resultSet); List result = this.getDefaultSchemas(metaData); EasyMock.verify(metaData, connection, statement, resultSet); assert result.size() == 1 : result.size(); assert result.get(0).equals("database") : result.get(0); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetAlterIdentityColumnSQL() */ @Override public void testGetAlterIdentityColumnSQL() throws SQLException { TableProperties table = EasyMock.createStrictMock(TableProperties.class); ColumnProperties column = EasyMock.createStrictMock(ColumnProperties.class); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.expect(column.getName()).andReturn("column"); EasyMock.replay(table, column); String result = this.getAlterIdentityColumnSQL(table, column, 1000L); EasyMock.verify(table, column); assert result.equals("ALTER TABLE table AUTO_INCREMENT = 1000") : result; } @Override @DataProvider(name = "current-date") Object[][] currentDateProvider() { java.sql.Date date = new java.sql.Date(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_DATE FROM success", date }, new Object[] { "SELECT CURDATE() FROM success", date }, new Object[] { "SELECT CURDATE ( ) FROM success", date }, new Object[] { "SELECT CCURRENT_DATE FROM failure", date }, new Object[] { "SELECT CURRENT_DATES FROM failure", date }, new Object[] { "SELECT CCURDATE() FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @Test(dataProvider = "current-date") public void testEvaluateCurrentDate(String sql, java.sql.Date date) { String expected = sql.contains("success") ? String.format("SELECT '%s' FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentDate(sql, date); assert evaluated.equals(expected) : evaluated; } @Override @DataProvider(name = "current-time") Object[][] currentTimeProvider() { java.sql.Time date = new java.sql.Time(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIME FROM success", date }, new Object[] { "SELECT CURRENT_TIME(2) FROM success", date }, new Object[] { "SELECT CURRENT_TIME ( 2 ) FROM success", date }, new Object[] { "SELECT LOCALTIME FROM success", date }, new Object[] { "SELECT LOCALTIME(2) FROM success", date }, new Object[] { "SELECT LOCALTIME ( 2 ) FROM success", date }, new Object[] { "SELECT CURTIME() FROM success", date }, new Object[] { "SELECT CURTIME ( ) FROM success", date }, new Object[] { "SELECT CCURRENT_TIME FROM failure", date }, new Object[] { "SELECT CURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT LLOCALTIME FROM failure", date }, new Object[] { "SELECT LOCALTIMESTAMP FROM failure", date }, new Object[] { "SELECT CCURTIME() FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @Test(dataProvider = "current-time") public void testEvaluateCurrentTime(String sql, java.sql.Time date) { String expected = sql.contains("success") ? String.format("SELECT '%s' FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentTime(sql, date); assert evaluated.equals(expected) : evaluated; } @Override @DataProvider(name = "current-timestamp") Object[][] currentTimestampProvider() { java.sql.Timestamp date = new java.sql.Timestamp(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT_TIMESTAMP FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMP(2) FROM success", date }, new Object[] { "SELECT CURRENT_TIMESTAMP ( 2 ) FROM success", date }, new Object[] { "SELECT LOCALTIMESTAMP FROM success", date }, new Object[] { "SELECT LOCALTIMESTAMP(2) FROM success", date }, new Object[] { "SELECT LOCALTIMESTAMP ( 2 ) FROM success", date }, new Object[] { "SELECT NOW() FROM success", date }, new Object[] { "SELECT NOW ( ) FROM success", date }, new Object[] { "SELECT SYSDATE() FROM success", date }, new Object[] { "SELECT SYSDATE ( ) FROM success", date }, new Object[] { "SELECT CCURRENT_TIMESTAMP FROM failure", date }, new Object[] { "SELECT CURRENT_TIMESTAMPS FROM failure", date }, new Object[] { "SELECT LLOCALTIMESTAMP FROM failure", date }, new Object[] { "SELECT LOCALTIMESTAMPS FROM failure", date }, new Object[] { "SELECT NNOW() FROM failure", date }, new Object[] { "SELECT SSYSDATE() FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @Test(dataProvider = "current-timestamp") public void testEvaluateCurrentTimestamp(String sql, java.sql.Timestamp date) { String expected = sql.contains("success") ? String.format("SELECT '%s' FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentTimestamp(sql, date); assert evaluated.equals(expected) : evaluated; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestPostgreSQLDialect.java0000644000175000017500000001604411216575123025432 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.List; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.TableProperties; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") @Test public class TestPostgreSQLDialect extends TestStandardDialect { public TestPostgreSQLDialect() { super(new PostgreSQLDialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetColumnType() */ @Override public void testGetColumnType() throws SQLException { ColumnProperties column = EasyMock.createStrictMock(ColumnProperties.class); EasyMock.expect(column.getNativeType()).andReturn("oid"); EasyMock.replay(column); int result = this.getColumnType(column); EasyMock.verify(column); assert result == Types.BLOB : result; EasyMock.reset(column); EasyMock.expect(column.getNativeType()).andReturn("int"); EasyMock.expect(column.getType()).andReturn(Types.INTEGER); EasyMock.replay(column); result = this.getColumnType(column); EasyMock.verify(column); assert result == Types.INTEGER : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetTruncateTableSQL() */ @Override public void testGetTruncateTableSQL() throws SQLException { TableProperties table = EasyMock.createStrictMock(TableProperties.class); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.replay(table); String result = this.getTruncateTableSQL(table); EasyMock.verify(table); assert result.equals("TRUNCATE TABLE table") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetNextSequenceValueSQL() */ @Override public void testGetNextSequenceValueSQL() throws SQLException { SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.expect(sequence.getName()).andReturn("sequence"); EasyMock.replay(sequence); String result = this.getNextSequenceValueSQL(sequence); EasyMock.verify(sequence); assert result.equals("SELECT NEXTVAL('sequence')") : result; } @Override @DataProvider(name = "sequence-sql") Object[][] sequenceSQLProvider() { return new Object[][] { new Object[] { "SELECT CURRVAL('success')" }, new Object[] { "SELECT nextval('success'), * FROM table" }, new Object[] { "INSERT INTO table VALUES (NEXTVAL('success'), 0)" }, new Object[] { "UPDATE table SET id = NEXTVAL('success')" }, new Object[] { "SELECT * FROM table" }, }; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetDefaultSchemas() */ @Override public void testGetDefaultSchemas() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); Connection connection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); EasyMock.expect(metaData.getConnection()).andReturn(connection); EasyMock.expect(connection.createStatement()).andReturn(statement); EasyMock.expect(statement.executeQuery("SHOW search_path")).andReturn(resultSet); EasyMock.expect(resultSet.next()).andReturn(false); EasyMock.expect(resultSet.getString(1)).andReturn("$user,public"); resultSet.close(); statement.close(); EasyMock.expect(metaData.getUserName()).andReturn("user"); EasyMock.replay(metaData, connection, statement, resultSet); List result = this.getDefaultSchemas(metaData); EasyMock.verify(metaData, connection, statement, resultSet); assert result.size() == 2 : result.size(); assert result.get(0).equals("user") : result.get(0); assert result.get(1).equals("public") : result.get(1); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetAlterIdentityColumnSQL() */ @Override public void testGetAlterIdentityColumnSQL() throws SQLException { TableProperties table = EasyMock.createStrictMock(TableProperties.class); ColumnProperties column = EasyMock.createStrictMock(ColumnProperties.class); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.expect(column.getName()).andReturn("column"); EasyMock.replay(table, column); String result = this.getAlterIdentityColumnSQL(table, column, 1000L); EasyMock.verify(table, column); assert result.equals("ALTER SEQUENCE table_column_seq RESTART WITH 1000") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetIdentifierPattern() */ @Override public void testGetIdentifierPattern() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); EasyMock.expect(metaData.getDriverMajorVersion()).andReturn(8); EasyMock.expect(metaData.getDriverMinorVersion()).andReturn(0); EasyMock.expect(metaData.getExtraNameCharacters()).andReturn("$"); EasyMock.replay(metaData); String result = this.getIdentifierPattern(metaData).pattern(); EasyMock.verify(metaData); assert result.equals("[a-zA-Z][\\w\\Q$\\E]*") : result; EasyMock.reset(metaData); EasyMock.expect(metaData.getDriverMajorVersion()).andReturn(8); EasyMock.expect(metaData.getDriverMinorVersion()).andReturn(1); EasyMock.replay(metaData); result = this.getIdentifierPattern(metaData).pattern(); EasyMock.verify(metaData); assert result.equals("[A-Za-z\\0200-\\0377_][A-Za-z\\0200-\\0377_0-9\\$]*") : result; } @Override @DataProvider(name = "random") Object[][] randomProvider() { return new Object[][] { new Object[] { "SELECT RANDOM() FROM success" }, new Object[] { "SELECT RANDOM ( ) FROM success" }, new Object[] { "SELECT OPERANDOM() FROM failure" }, new Object[] { "SELECT 1 FROM failure" }, }; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/dialect/TestSybaseDialect.java0000644000175000017500000001516611175404607024663 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Collection; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.cache.ForeignKeyConstraintImpl; import org.easymock.EasyMock; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @SuppressWarnings("nls") @Test public class TestSybaseDialect extends TestStandardDialect { public TestSybaseDialect() { super(new SybaseDialect()); } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSimpleSQL() */ @Override public void testGetSimpleSQL() throws SQLException { String result = this.getSimpleSQL(); assert result.equals("SELECT GETDATE()") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetTruncateTableSQL() */ @Override public void testGetTruncateTableSQL() throws SQLException { TableProperties table = EasyMock.createStrictMock(TableProperties.class); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.replay(table); String result = this.getTruncateTableSQL(table); EasyMock.verify(table); assert result.equals("TRUNCATE TABLE table") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetCreateForeignKeyConstraintSQL() */ @Override public void testGetCreateForeignKeyConstraintSQL() throws SQLException { ForeignKeyConstraint key = new ForeignKeyConstraintImpl("name", "table"); key.getColumnList().add("column1"); key.getColumnList().add("column2"); key.setForeignTable("foreign_table"); key.getForeignColumnList().add("foreign_column1"); key.getForeignColumnList().add("foreign_column2"); key.setDeferrability(DatabaseMetaData.importedKeyInitiallyDeferred); key.setDeleteRule(DatabaseMetaData.importedKeyCascade); key.setUpdateRule(DatabaseMetaData.importedKeyRestrict); String result = this.getCreateForeignKeyConstraintSQL(key); assert result.equals("ALTER TABLE table ADD CONSTRAINT name FOREIGN KEY (column1, column2) REFERENCES foreign_table (foreign_column1, foreign_column2) ON DELETE CASCADE ON UPDATE RESTRICT") : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testParseSequence(java.lang.String) */ @Override @Test(dataProvider = "sequence-sql") public void testParseSequence(String sql) throws SQLException { String result = this.parseSequence(sql); assert (result == null) : result; } /** * @see net.sf.hajdbc.dialect.TestStandardDialect#testGetSequences() */ @Override public void testGetSequences() throws SQLException { DatabaseMetaData metaData = EasyMock.createStrictMock(DatabaseMetaData.class); EasyMock.replay(metaData); Collection result = this.getSequences(metaData); EasyMock.verify(metaData); assert result.isEmpty() : result; } @Override @DataProvider(name = "current-date") Object[][] currentDateProvider() { java.sql.Date date = new java.sql.Date(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT DATE FROM success", date }, new Object[] { "SELECT TODAY(*) FROM success", date }, new Object[] { "SELECT TODAY ( * ) FROM success", date }, new Object[] { "SELECT CURRENT DATES FROM failure", date }, new Object[] { "SELECT CCURRENT DATE FROM failure", date }, new Object[] { "SELECT NOTTODAY(*) FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @Test(dataProvider = "current-date") public void testEvaluateCurrentDate(String sql, java.sql.Date date) { String expected = sql.contains("success") ? String.format("SELECT '%s' FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentDate(sql, date); assert evaluated.equals(expected) : evaluated; } @Override @DataProvider(name = "current-time") Object[][] currentTimeProvider() { java.sql.Time date = new java.sql.Time(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT TIME FROM success", date }, new Object[] { "SELECT CCURRENT TIME FROM failure", date }, new Object[] { "SELECT CURRENT TIMESTAMP FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @Test(dataProvider = "current-time") public void testEvaluateCurrentTime(String sql, java.sql.Time date) { String expected = sql.contains("success") ? String.format("SELECT '%s' FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentTime(sql, date); assert evaluated.equals(expected) : evaluated; } @Override @DataProvider(name = "current-timestamp") Object[][] currentTimestampProvider() { java.sql.Timestamp date = new java.sql.Timestamp(System.currentTimeMillis()); return new Object[][] { new Object[] { "SELECT CURRENT TIMESTAMP FROM success", date }, new Object[] { "SELECT GETDATE() FROM success", date }, new Object[] { "SELECT GETDATE ( ) FROM success", date }, new Object[] { "SELECT NOW(*) FROM success", date }, new Object[] { "SELECT NOW ( * ) FROM success", date }, new Object[] { "SELECT CCURRENT TIMESTAMP FROM failure", date }, new Object[] { "SELECT CURRENT TIMESTAMPS FROM failure", date }, new Object[] { "SELECT FORGETDATE() FROM failure", date }, new Object[] { "SELECT NNOW(*) FROM failure", date }, new Object[] { "SELECT 1 FROM failure", date }, }; } @Override @Test(dataProvider = "current-timestamp") public void testEvaluateCurrentTimestamp(String sql, java.sql.Timestamp date) { String expected = sql.contains("success") ? String.format("SELECT '%s' FROM success", date.toString()) : sql; String evaluated = this.evaluateCurrentTimestamp(sql, date); assert evaluated.equals(expected) : evaluated; } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sync/0000755000175000017500000000000011674455606020013 5ustar moellermoellerha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sync/TestPassiveSynchronizationStrategy.java0000644000175000017500000000302711151703044027755 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import net.sf.hajdbc.SynchronizationContext; import org.easymock.EasyMock; /** * @author Paul Ferraro * */ public class TestPassiveSynchronizationStrategy extends TestSynchronizationStrategy { public TestPassiveSynchronizationStrategy() { super(new PassiveSynchronizationStrategy()); } /** * @see net.sf.hajdbc.sync.TestSynchronizationStrategy#testSynchronize() */ @SuppressWarnings("unchecked") @Override public void testSynchronize() { SynchronizationContext context = EasyMock.createStrictMock(SynchronizationContext.class); EasyMock.replay(context); this.synchronize(context); EasyMock.verify(context); } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sync/TestSynchronizationStrategy.java0000644000175000017500000000315011151703044026417 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import java.sql.SQLException; import org.testng.annotations.Test; import net.sf.hajdbc.SynchronizationContext; import net.sf.hajdbc.SynchronizationStrategy; /** * @author Paul Ferraro * */ public abstract class TestSynchronizationStrategy implements SynchronizationStrategy { private SynchronizationStrategy strategy; protected TestSynchronizationStrategy(SynchronizationStrategy strategy) { this.strategy = strategy; } @Override @SuppressWarnings("unchecked") @Test(enabled = false) public void synchronize(SynchronizationContext context) { try { this.strategy.synchronize(context); } catch (SQLException e) { throw new AssertionError(e); } } public abstract void testSynchronize(); } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sync/TestFullSynchronizationStrategy.java0000644000175000017500000003230411151703044027245 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.Arrays; import java.util.Collections; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.SynchronizationContext; import net.sf.hajdbc.TableProperties; import org.easymock.EasyMock; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @SuppressWarnings("nls") @Test public class TestFullSynchronizationStrategy extends TestSynchronizationStrategy { public TestFullSynchronizationStrategy() { super(new FullSynchronizationStrategy()); } /** * @see net.sf.hajdbc.sync.TestSynchronizationStrategy#testSynchronize() */ @SuppressWarnings("unchecked") @Override public void testSynchronize() { SynchronizationContext context = EasyMock.createStrictMock(SynchronizationContext.class); Database sourceDatabase = EasyMock.createStrictMock(Database.class); Database targetDatabase = EasyMock.createStrictMock(Database.class); Connection sourceConnection = EasyMock.createStrictMock(Connection.class); Connection targetConnection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); DatabaseMetaDataCache metaData = EasyMock.createStrictMock(DatabaseMetaDataCache.class); DatabaseProperties sourceProperties = EasyMock.createStrictMock(DatabaseProperties.class); DatabaseProperties targetProperties = EasyMock.createStrictMock(DatabaseProperties.class); TableProperties table = EasyMock.createStrictMock(TableProperties.class); Dialect dialect = EasyMock.createStrictMock(Dialect.class); Statement targetStatement = EasyMock.createStrictMock(Statement.class); Statement sourceStatement = EasyMock.createStrictMock(Statement.class); ResultSet sourceResultSet = EasyMock.createStrictMock(ResultSet.class); ForeignKeyConstraint foreignKey = EasyMock.createStrictMock(ForeignKeyConstraint.class); Statement selectStatement = EasyMock.createStrictMock(Statement.class); ResultSet resultSet = EasyMock.createStrictMock(ResultSet.class); Statement deleteStatement = EasyMock.createStrictMock(Statement.class); PreparedStatement insertStatement = EasyMock.createStrictMock(PreparedStatement.class); ColumnProperties column1 = EasyMock.createStrictMock(ColumnProperties.class); ColumnProperties column2 = EasyMock.createStrictMock(ColumnProperties.class); ExecutorService executor = Executors.newSingleThreadExecutor(); SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.makeThreadSafe(selectStatement, true); EasyMock.makeThreadSafe(context, true); EasyMock.makeThreadSafe(sourceConnection, true); EasyMock.makeThreadSafe(sourceStatement, true); EasyMock.makeThreadSafe(sourceResultSet, true); try { EasyMock.expect(context.getSourceDatabase()).andReturn(sourceDatabase); EasyMock.expect(context.getConnection(sourceDatabase)).andReturn(sourceConnection); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getExecutor()).andReturn(executor); EasyMock.expect(targetConnection.getAutoCommit()).andReturn(false); targetConnection.setAutoCommit(true); { EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(context.getTargetDatabaseProperties()).andReturn(targetProperties); EasyMock.expect(targetProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getForeignKeyConstraints()).andReturn(Collections.singleton(foreignKey)); EasyMock.expect(dialect.getDropForeignKeyConstraintSQL(foreignKey)).andReturn("drop fk"); targetStatement.addBatch("drop fk"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); targetStatement.close(); } targetConnection.setAutoCommit(false); EasyMock.expect(context.getSourceDatabaseProperties()).andReturn(sourceProperties); EasyMock.expect(sourceProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.expect(table.getColumns()).andReturn(Arrays.asList(new String[] { "column1", "column2" })); EasyMock.expect(sourceConnection.createStatement()).andReturn(selectStatement); selectStatement.setFetchSize(0); EasyMock.checkOrder(dialect, false); EasyMock.checkOrder(targetConnection, false); EasyMock.checkOrder(deleteStatement, false); EasyMock.checkOrder(selectStatement, false); EasyMock.expect(dialect.getTruncateTableSQL(table)).andReturn("DELETE FROM table"); EasyMock.expect(targetConnection.createStatement()).andReturn(deleteStatement); EasyMock.expect(deleteStatement.executeUpdate("DELETE FROM table")).andReturn(0); deleteStatement.close(); EasyMock.expect(selectStatement.executeQuery("SELECT column1, column2 FROM table")).andReturn(resultSet); EasyMock.checkOrder(dialect, true); EasyMock.checkOrder(targetConnection, true); EasyMock.checkOrder(deleteStatement, true); EasyMock.checkOrder(selectStatement, true); EasyMock.expect(targetConnection.prepareStatement("INSERT INTO table (column1, column2) VALUES (?, ?)")).andReturn(insertStatement); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(table.getColumnProperties("column1")).andReturn(column1); EasyMock.expect(dialect.getColumnType(column1)).andReturn(Types.INTEGER); EasyMock.expect(resultSet.getObject(1)).andReturn(1); EasyMock.expect(resultSet.wasNull()).andReturn(false); insertStatement.setObject(1, 1, Types.INTEGER); EasyMock.expect(table.getColumnProperties("column2")).andReturn(column2); EasyMock.expect(dialect.getColumnType(column2)).andReturn(Types.VARCHAR); EasyMock.expect(resultSet.getObject(2)).andReturn(""); EasyMock.expect(resultSet.wasNull()).andReturn(false); insertStatement.setObject(2, "", Types.VARCHAR); insertStatement.addBatch(); insertStatement.clearParameters(); EasyMock.expect(resultSet.next()).andReturn(true); EasyMock.expect(table.getColumnProperties("column1")).andReturn(column1); EasyMock.expect(dialect.getColumnType(column1)).andReturn(Types.BLOB); EasyMock.expect(resultSet.getBlob(1)).andReturn(null); EasyMock.expect(resultSet.wasNull()).andReturn(true); insertStatement.setNull(1, Types.BLOB); EasyMock.expect(table.getColumnProperties("column2")).andReturn(column2); EasyMock.expect(dialect.getColumnType(column2)).andReturn(Types.CLOB); EasyMock.expect(resultSet.getClob(2)).andReturn(null); EasyMock.expect(resultSet.wasNull()).andReturn(true); insertStatement.setNull(2, Types.CLOB); insertStatement.addBatch(); insertStatement.clearParameters(); EasyMock.expect(resultSet.next()).andReturn(false); EasyMock.expect(insertStatement.executeBatch()).andReturn(null); insertStatement.close(); selectStatement.close(); targetConnection.commit(); targetConnection.setAutoCommit(true); { EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(context.getSourceDatabaseProperties()).andReturn(sourceProperties); EasyMock.expect(sourceProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getForeignKeyConstraints()).andReturn(Collections.singleton(foreignKey)); EasyMock.expect(dialect.getCreateForeignKeyConstraintSQL(foreignKey)).andReturn("create fk"); targetStatement.addBatch("create fk"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); targetStatement.close(); } { EasyMock.expect(context.getSourceDatabase()).andReturn(sourceDatabase); EasyMock.expect(context.getConnection(sourceDatabase)).andReturn(sourceConnection); EasyMock.expect(sourceConnection.createStatement()).andReturn(sourceStatement); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getSourceDatabaseProperties()).andReturn(sourceProperties); EasyMock.expect(sourceProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getIdentityColumns()).andReturn(Collections.singleton("column")); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.expect(sourceStatement.executeQuery("SELECT max(column) FROM table")).andReturn(sourceResultSet); EasyMock.expect(sourceResultSet.next()).andReturn(true); EasyMock.expect(sourceResultSet.getLong(1)).andReturn(1L); sourceResultSet.close(); EasyMock.expect(table.getColumnProperties("column")).andReturn(column1); EasyMock.expect(dialect.getAlterIdentityColumnSQL(table, column1, 2L)).andReturn("column = 1"); targetStatement.addBatch("column = 1"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); sourceStatement.close(); targetStatement.close(); } { EasyMock.expect(context.getSourceDatabaseProperties()).andReturn(sourceProperties); EasyMock.expect(sourceProperties.getSequences()).andReturn(Collections.singleton(sequence)); EasyMock.expect(context.getSourceDatabase()).andReturn(sourceDatabase); EasyMock.expect(context.getActiveDatabaseSet()).andReturn(Collections.singleton(sourceDatabase)); EasyMock.expect(context.getExecutor()).andReturn(executor); EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(dialect.getNextSequenceValueSQL(sequence)).andReturn("sequence next value"); EasyMock.expect(context.getConnection(sourceDatabase)).andReturn(sourceConnection); EasyMock.expect(sourceConnection.createStatement()).andReturn(sourceStatement); EasyMock.expect(sourceStatement.executeQuery("sequence next value")).andReturn(sourceResultSet); EasyMock.expect(sourceResultSet.next()).andReturn(true); EasyMock.expect(sourceResultSet.getLong(1)).andReturn(1L); sourceStatement.close(); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(dialect.getAlterSequenceSQL(sequence, 2L)).andReturn("alter sequence"); targetStatement.addBatch("alter sequence"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); targetStatement.close(); } targetConnection.setAutoCommit(false); EasyMock.replay(context, sourceDatabase, targetDatabase, sourceConnection, targetConnection, statement, metaData, sourceProperties, targetProperties, table, dialect, targetStatement, sourceStatement, sourceResultSet, foreignKey, selectStatement, resultSet, deleteStatement, insertStatement, column1, column2); this.synchronize(context); EasyMock.verify(context, sourceDatabase, targetDatabase, sourceConnection, targetConnection, statement, metaData, sourceProperties, targetProperties, table, dialect, targetStatement, sourceStatement, sourceResultSet, foreignKey, selectStatement, resultSet, deleteStatement, insertStatement, column1, column2); } catch (SQLException e) { assert false : e; } } } ha-jdbc-2.0.16+rc1/test/net/sf/hajdbc/sync/TestDifferentialSynchronizationStrategy.java0000644000175000017500000005066211151703044030746 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.SynchronizationContext; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.UniqueConstraint; import org.easymock.EasyMock; import org.testng.annotations.Test; /** * @author Paul Ferraro */ @SuppressWarnings("nls") @Test public class TestDifferentialSynchronizationStrategy extends TestSynchronizationStrategy { public TestDifferentialSynchronizationStrategy() { super(new DifferentialSynchronizationStrategy()); } /** * @see net.sf.hajdbc.sync.TestSynchronizationStrategy#testSynchronize() */ @SuppressWarnings("unchecked") @Override public void testSynchronize() { SynchronizationContext context = EasyMock.createStrictMock(SynchronizationContext.class); Database sourceDatabase = EasyMock.createStrictMock(Database.class); Database targetDatabase = EasyMock.createStrictMock(Database.class); Connection sourceConnection = EasyMock.createStrictMock(Connection.class); Connection targetConnection = EasyMock.createStrictMock(Connection.class); Statement statement = EasyMock.createStrictMock(Statement.class); DatabaseMetaDataCache metaData = EasyMock.createStrictMock(DatabaseMetaDataCache.class); DatabaseProperties sourceProperties = EasyMock.createStrictMock(DatabaseProperties.class); DatabaseProperties targetProperties = EasyMock.createStrictMock(DatabaseProperties.class); TableProperties table = EasyMock.createStrictMock(TableProperties.class); Dialect dialect = EasyMock.createStrictMock(Dialect.class); ForeignKeyConstraint foreignKey = EasyMock.createStrictMock(ForeignKeyConstraint.class); UniqueConstraint primaryKey = EasyMock.createStrictMock(UniqueConstraint.class); UniqueConstraint uniqueKey = EasyMock.createStrictMock(UniqueConstraint.class); Statement targetStatement = EasyMock.createStrictMock(Statement.class); ResultSet targetResultSet = EasyMock.createStrictMock(ResultSet.class); Statement sourceStatement = EasyMock.createStrictMock(Statement.class); ResultSet sourceResultSet = EasyMock.createStrictMock(ResultSet.class); PreparedStatement deleteStatement = EasyMock.createStrictMock(PreparedStatement.class); PreparedStatement insertStatement = EasyMock.createStrictMock(PreparedStatement.class); PreparedStatement updateStatement = EasyMock.createStrictMock(PreparedStatement.class); ColumnProperties column1 = EasyMock.createStrictMock(ColumnProperties.class); ColumnProperties column2 = EasyMock.createStrictMock(ColumnProperties.class); ColumnProperties column3 = EasyMock.createStrictMock(ColumnProperties.class); ColumnProperties column4 = EasyMock.createStrictMock(ColumnProperties.class); ExecutorService executor = Executors.newSingleThreadExecutor(); SequenceProperties sequence = EasyMock.createStrictMock(SequenceProperties.class); EasyMock.makeThreadSafe(targetStatement, true); EasyMock.makeThreadSafe(context, true); EasyMock.makeThreadSafe(sourceConnection, true); EasyMock.makeThreadSafe(sourceStatement, true); EasyMock.makeThreadSafe(sourceResultSet, true); try { EasyMock.expect(context.getSourceDatabase()).andReturn(sourceDatabase); EasyMock.expect(context.getConnection(sourceDatabase)).andReturn(sourceConnection); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getExecutor()).andReturn(executor); EasyMock.expect(targetConnection.getAutoCommit()).andReturn(false); targetConnection.setAutoCommit(true); { EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(context.getTargetDatabaseProperties()).andReturn(targetProperties); EasyMock.expect(targetProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getForeignKeyConstraints()).andReturn(Collections.singleton(foreignKey)); EasyMock.expect(dialect.getDropForeignKeyConstraintSQL(foreignKey)).andReturn("drop fk"); targetStatement.addBatch("drop fk"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); targetStatement.close(); } { EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(context.getTargetDatabaseProperties()).andReturn(targetProperties); EasyMock.expect(targetProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getUniqueConstraints()).andReturn(new ArrayList(Arrays.asList(new UniqueConstraint[] { uniqueKey }))); EasyMock.expect(dialect.getDropUniqueConstraintSQL(uniqueKey)).andReturn("drop uk"); targetStatement.addBatch("drop uk"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); targetStatement.close(); } targetConnection.setAutoCommit(false); EasyMock.expect(context.getSourceDatabaseProperties()).andReturn(sourceProperties); EasyMock.expect(sourceProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.expect(table.getPrimaryKey()).andReturn(primaryKey); EasyMock.expect(primaryKey.getColumnList()).andReturn(Arrays.asList(new String[] { "column1", "column2" })); EasyMock.expect(table.getColumns()).andReturn(Arrays.asList(new String[] { "column1", "column2", "column3", "column4" })); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); targetStatement.setFetchSize(0); // Disable order checking, since statement is executed asynchronously EasyMock.checkOrder(targetStatement, false); EasyMock.checkOrder(sourceConnection, false); EasyMock.checkOrder(sourceStatement, false); EasyMock.expect(targetStatement.executeQuery("SELECT column1, column2, column3, column4 FROM table ORDER BY column1, column2")).andReturn(targetResultSet); EasyMock.expect(sourceConnection.createStatement()).andReturn(sourceStatement); sourceStatement.setFetchSize(0); EasyMock.expect(sourceStatement.executeQuery("SELECT column1, column2, column3, column4 FROM table ORDER BY column1, column2")).andReturn(sourceResultSet); EasyMock.checkOrder(targetStatement, true); EasyMock.checkOrder(sourceConnection, true); EasyMock.checkOrder(sourceStatement, true); EasyMock.expect(targetConnection.prepareStatement("DELETE FROM table WHERE column1 = ? AND column2 = ?")).andReturn(deleteStatement); EasyMock.expect(targetConnection.prepareStatement("INSERT INTO table (column1, column2, column3, column4) VALUES (?, ?, ?, ?)")).andReturn(insertStatement); EasyMock.expect(targetConnection.prepareStatement("UPDATE table SET column3 = ?, column4 = ? WHERE column1 = ? AND column2 = ?")).andReturn(updateStatement); EasyMock.expect(sourceResultSet.next()).andReturn(true); EasyMock.expect(targetResultSet.next()).andReturn(true); // Trigger insert EasyMock.expect(sourceResultSet.getObject(1)).andReturn(1); EasyMock.expect(targetResultSet.getObject(1)).andReturn(1); EasyMock.expect(sourceResultSet.getObject(2)).andReturn(1); EasyMock.expect(targetResultSet.getObject(2)).andReturn(2); insertStatement.clearParameters(); EasyMock.expect(table.getColumnProperties("column1")).andReturn(column1); EasyMock.expect(dialect.getColumnType(column1)).andReturn(Types.INTEGER); EasyMock.expect(sourceResultSet.getObject(1)).andReturn(1); EasyMock.expect(sourceResultSet.wasNull()).andReturn(false); insertStatement.setObject(1, 1, Types.INTEGER); EasyMock.expect(table.getColumnProperties("column2")).andReturn(column2); EasyMock.expect(dialect.getColumnType(column2)).andReturn(Types.INTEGER); EasyMock.expect(sourceResultSet.getObject(2)).andReturn(1); EasyMock.expect(sourceResultSet.wasNull()).andReturn(false); insertStatement.setObject(2, 1, Types.INTEGER); EasyMock.expect(table.getColumnProperties("column3")).andReturn(column3); EasyMock.expect(dialect.getColumnType(column3)).andReturn(Types.BLOB); EasyMock.expect(sourceResultSet.getBlob(3)).andReturn(null); EasyMock.expect(sourceResultSet.wasNull()).andReturn(true); insertStatement.setNull(3, Types.BLOB); EasyMock.expect(table.getColumnProperties("column4")).andReturn(column4); EasyMock.expect(dialect.getColumnType(column4)).andReturn(Types.CLOB); EasyMock.expect(sourceResultSet.getClob(4)).andReturn(null); EasyMock.expect(sourceResultSet.wasNull()).andReturn(true); insertStatement.setNull(4, Types.CLOB); insertStatement.addBatch(); EasyMock.expect(sourceResultSet.next()).andReturn(true); // Trigger update EasyMock.expect(sourceResultSet.getObject(1)).andReturn(1); EasyMock.expect(targetResultSet.getObject(1)).andReturn(1); EasyMock.expect(sourceResultSet.getObject(2)).andReturn(2); EasyMock.expect(targetResultSet.getObject(2)).andReturn(2); updateStatement.clearParameters(); // Nothing to update EasyMock.expect(table.getColumnProperties("column3")).andReturn(column3); EasyMock.expect(dialect.getColumnType(column3)).andReturn(Types.VARCHAR); EasyMock.expect(sourceResultSet.getObject(3)).andReturn(""); EasyMock.expect(targetResultSet.getObject(3)).andReturn(""); EasyMock.expect(sourceResultSet.wasNull()).andReturn(false); updateStatement.setObject(1, "", Types.VARCHAR); EasyMock.expect(targetResultSet.wasNull()).andReturn(false); // Nothing to update EasyMock.expect(table.getColumnProperties("column4")).andReturn(column4); EasyMock.expect(dialect.getColumnType(column4)).andReturn(Types.VARCHAR); EasyMock.expect(sourceResultSet.getObject(4)).andReturn(null); EasyMock.expect(targetResultSet.getObject(4)).andReturn(null); EasyMock.expect(sourceResultSet.wasNull()).andReturn(true); updateStatement.setNull(2, Types.VARCHAR); EasyMock.expect(targetResultSet.wasNull()).andReturn(true); EasyMock.expect(sourceResultSet.next()).andReturn(true); EasyMock.expect(targetResultSet.next()).andReturn(true); // Trigger update EasyMock.expect(sourceResultSet.getObject(1)).andReturn(1); EasyMock.expect(targetResultSet.getObject(1)).andReturn(1); EasyMock.expect(sourceResultSet.getObject(2)).andReturn(3); EasyMock.expect(targetResultSet.getObject(2)).andReturn(3); updateStatement.clearParameters(); EasyMock.expect(table.getColumnProperties("column3")).andReturn(column3); EasyMock.expect(dialect.getColumnType(column3)).andReturn(Types.VARCHAR); EasyMock.expect(sourceResultSet.getObject(3)).andReturn(""); EasyMock.expect(targetResultSet.getObject(3)).andReturn(null); EasyMock.expect(sourceResultSet.wasNull()).andReturn(false); updateStatement.setObject(1, "", Types.VARCHAR); EasyMock.expect(targetResultSet.wasNull()).andReturn(true); EasyMock.expect(table.getColumnProperties("column4")).andReturn(column4); EasyMock.expect(dialect.getColumnType(column4)).andReturn(Types.VARCHAR); EasyMock.expect(sourceResultSet.getObject(4)).andReturn(null); EasyMock.expect(targetResultSet.getObject(4)).andReturn(""); EasyMock.expect(sourceResultSet.wasNull()).andReturn(true); updateStatement.setNull(2, Types.VARCHAR); EasyMock.expect(targetResultSet.wasNull()).andReturn(false); EasyMock.expect(table.getColumnProperties("column1")).andReturn(column1); EasyMock.expect(dialect.getColumnType(column1)).andReturn(Types.INTEGER); EasyMock.expect(targetResultSet.getObject(1)).andReturn(1); updateStatement.setObject(3, 1, Types.INTEGER); EasyMock.expect(table.getColumnProperties("column2")).andReturn(column2); EasyMock.expect(dialect.getColumnType(column2)).andReturn(Types.INTEGER); EasyMock.expect(targetResultSet.getObject(2)).andReturn(3); updateStatement.setObject(4, 3, Types.INTEGER); updateStatement.addBatch(); EasyMock.expect(sourceResultSet.next()).andReturn(false); EasyMock.expect(targetResultSet.next()).andReturn(true); deleteStatement.clearParameters(); EasyMock.expect(table.getColumnProperties("column1")).andReturn(column1); EasyMock.expect(dialect.getColumnType(column1)).andReturn(Types.INTEGER); EasyMock.expect(targetResultSet.getObject(1)).andReturn(2); deleteStatement.setObject(1, 2, Types.INTEGER); EasyMock.expect(table.getColumnProperties("column2")).andReturn(column2); EasyMock.expect(dialect.getColumnType(column2)).andReturn(Types.INTEGER); EasyMock.expect(targetResultSet.getObject(2)).andReturn(1); deleteStatement.setObject(2, 1, Types.INTEGER); deleteStatement.addBatch(); EasyMock.expect(targetResultSet.next()).andReturn(false); EasyMock.expect(deleteStatement.executeBatch()).andReturn(null); deleteStatement.close(); EasyMock.expect(insertStatement.executeBatch()).andReturn(null); insertStatement.close(); EasyMock.expect(updateStatement.executeBatch()).andReturn(null); updateStatement.close(); targetStatement.close(); sourceStatement.close(); targetConnection.commit(); targetConnection.setAutoCommit(true); { EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(context.getSourceDatabaseProperties()).andReturn(sourceProperties); EasyMock.expect(sourceProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getUniqueConstraints()).andReturn(Collections.singleton(uniqueKey)); EasyMock.expect(dialect.getCreateUniqueConstraintSQL(uniqueKey)).andReturn("create uk"); targetStatement.addBatch("create uk"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); targetStatement.close(); } { EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(context.getSourceDatabaseProperties()).andReturn(sourceProperties); EasyMock.expect(sourceProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getForeignKeyConstraints()).andReturn(Collections.singleton(foreignKey)); EasyMock.expect(dialect.getCreateForeignKeyConstraintSQL(foreignKey)).andReturn("create fk"); targetStatement.addBatch("create fk"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); targetStatement.close(); } { EasyMock.expect(context.getSourceDatabase()).andReturn(sourceDatabase); EasyMock.expect(context.getConnection(sourceDatabase)).andReturn(sourceConnection); EasyMock.expect(sourceConnection.createStatement()).andReturn(sourceStatement); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(context.getSourceDatabaseProperties()).andReturn(sourceProperties); EasyMock.expect(sourceProperties.getTables()).andReturn(Collections.singleton(table)); EasyMock.expect(table.getIdentityColumns()).andReturn(Collections.singleton("column")); EasyMock.expect(table.getName()).andReturn("table"); EasyMock.expect(sourceStatement.executeQuery("SELECT max(column) FROM table")).andReturn(sourceResultSet); EasyMock.expect(sourceResultSet.next()).andReturn(true); EasyMock.expect(sourceResultSet.getLong(1)).andReturn(1L); sourceResultSet.close(); EasyMock.expect(table.getColumnProperties("column")).andReturn(column1); EasyMock.expect(dialect.getAlterIdentityColumnSQL(table, column1, 2L)).andReturn("column = 1"); targetStatement.addBatch("column = 1"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); sourceStatement.close(); targetStatement.close(); } { EasyMock.expect(context.getSourceDatabaseProperties()).andReturn(sourceProperties); EasyMock.expect(sourceProperties.getSequences()).andReturn(Collections.singleton(sequence)); EasyMock.expect(context.getSourceDatabase()).andReturn(sourceDatabase); EasyMock.expect(context.getActiveDatabaseSet()).andReturn(Collections.singleton(sourceDatabase)); EasyMock.expect(context.getExecutor()).andReturn(executor); EasyMock.expect(context.getDialect()).andReturn(dialect); EasyMock.expect(dialect.getNextSequenceValueSQL(sequence)).andReturn("sequence next value"); EasyMock.expect(context.getConnection(sourceDatabase)).andReturn(sourceConnection); EasyMock.expect(sourceConnection.createStatement()).andReturn(sourceStatement); EasyMock.expect(sourceStatement.executeQuery("sequence next value")).andReturn(sourceResultSet); EasyMock.expect(sourceResultSet.next()).andReturn(true); EasyMock.expect(sourceResultSet.getLong(1)).andReturn(1L); sourceStatement.close(); EasyMock.expect(context.getTargetDatabase()).andReturn(targetDatabase); EasyMock.expect(context.getConnection(targetDatabase)).andReturn(targetConnection); EasyMock.expect(targetConnection.createStatement()).andReturn(targetStatement); EasyMock.expect(dialect.getAlterSequenceSQL(sequence, 2L)).andReturn("alter sequence"); targetStatement.addBatch("alter sequence"); EasyMock.expect(targetStatement.executeBatch()).andReturn(null); targetStatement.close(); } targetConnection.setAutoCommit(false); EasyMock.replay(context, sourceDatabase, targetDatabase, sourceConnection, targetConnection, statement, metaData, sourceProperties, targetProperties, table, dialect, foreignKey, primaryKey, uniqueKey, targetStatement, targetResultSet, sourceStatement, sourceResultSet, deleteStatement, insertStatement, updateStatement, column1, column2, column3, column4); this.synchronize(context); EasyMock.verify(context, sourceDatabase, targetDatabase, sourceConnection, targetConnection, statement, metaData, sourceProperties, targetProperties, table, dialect, foreignKey, primaryKey, uniqueKey, targetStatement, targetResultSet, sourceStatement, sourceResultSet, deleteStatement, insertStatement, updateStatement, column1, column2, column3, column4); } catch (SQLException e) { assert false : e; } } } ha-jdbc-2.0.16+rc1/test/ha-jdbc-test-pool-datasource-cluster.xml0000644000175000017500000000116211217564673024171 0ustar moellermoeller datasource1 net.sf.hajdbc.sql.MockInitialContextFactory datasource2 net.sf.hajdbc.sql.MockInitialContextFactory ha-jdbc-2.0.16+rc1/src/0000775000175000017500000000000011674455605014237 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/0000755000175000017500000000000011151703042015000 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/0000755000175000017500000000000011151703042015410 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/0000755000175000017500000000000011205302071016620 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Messages.properties0000644000175000017500000001011411151703042022505 0ustar moellermoeller#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) # # HA-JDBC: High-Availability JDBC # Copyright (c) 2004-2007 Paul Ferraro # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation; either version 2.1 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Contact: ferraro@users.sourceforge.net # cluster-not-active = Database cluster {0} is not active. cluster-panic-detected = Cluster panic detected on database cluster {0}. cluster-start-failed = Failed to start database cluster {0}. cluster-state-load-failed = Failed to load state of database cluster {0}. cluster-state-store-failed = Failed to store state of database cluster {0}. command-received = Command received: {0} config-load-failed = Failed to load HA-JDBC configuration from {0} config-not-found = Failed to locate database cluster configuration file: {0} config-store-failed = Failed to save HA-JDBC configuration to {0} database-activate-failed = Failed to activate database {0} from cluster {1} database-activated = Database {0} from cluster {1} was activated database-already-exists = Cluster {1} already contains database {0}. database-deactivated = Database {0} from cluster {1} was deactivated database-not-active = Database was not active at the time {0} was created database-not-alive = Database {0} from cluster {1} is not responding. database-still-active = Database {0} from cluster {1} could not be removed because it is still active. database-sync-end = Finished synchronization of database {0} of cluster {1}. database-sync-start = Starting synchronization of database {0} from cluster {1}. delete-count = Deleted {0} rows from {1} driver-not-found = Failed to locate driver {0} driver-register-failed = Failed to register driver {0} group-member-joined = {0} joined {1} channel group-member-left = {0} left {1} channel ha-jdbc-init = Initializing HA-JDBC {0} from {1} initial-cluster-state-local = Using local initial cluster state {0}. initial-cluster-state-none = No initial cluster state found. initial-cluster-state-remote = Using remote initial cluster state {0} from {1}. insert-count = Inserted {0} rows into {1} invalid-balancer = {0} is not a valid balancer. invalid-database = Database cluster {1} does not contain database {0} invalid-database-cluster = {0} is not a valid database cluster. invalid-meta-data-cache = {0} is not a valid meta-data cache. invalid-property = {0} is not a valid property of {1} invalid-property-value = {0} is not a valid {1} value for {2} invalid-sync-strategy = {0} is not a valid synchronization strategy. jdbc-url-rejected = No registered driver will accept url {0} jndi-lookup-failed = Failed to perform naming lookup of {0} mbean-server-not-found = No mbean server found. no-active-databases = No active databases in cluster {0} primary-key-required = Table {1} does not contain a primary key - this is required by synchronization strategy {0}. schema-lookup-failed = Failed to locate {0} in the following schemas: {1}. Verify implementation of {2}. sequence-out-of-sync = Next value ({2}) for sequence {0} from database {1} does not match next value ({4}) from database {3}. shut-down = Shutting down HA-JDBC. sql-object-init-failed = Failed to initialize {0} for database {1} statement-failed = Failed to execute statement: {0} table-lock-acquire = Acquiring table locks on active databases. table-lock-release = Releasing table locks on active databases. update-count = Updated {0} rows in {1} write-lock-failed = Failed to acquire exclusive lock on database cluster {0}. ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Lifecycle.java0000644000175000017500000000240311151703042021364 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; /** * Interface implemented by HA-JDBC services that participate in the lifecycle of a database cluster. * @author Paul Ferraro */ public interface Lifecycle { /** * Called upon database cluster start. * @throws Exception if this service fails to start. */ public void start() throws Exception; /** * Called when database cluster is stopped. */ public void stop(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/SynchronizationListener.java0000644000175000017500000000265311151703042024403 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.EventListener; /** * Event listener for synchronization notifications. * @author Paul Ferraro */ public interface SynchronizationListener extends EventListener { /** * Triggered just before synchronization commences. * @param event identifies the database to be synchronized. */ public void beforeSynchronization(DatabaseEvent event); /** * Triggered immediately after synchronization completes. * @param event identifies the database to be synchronized. */ public void afterSynchronization(DatabaseEvent event); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/0000755000175000017500000000000011674455606017712 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/UniqueConstraintImpl.java0000644000175000017500000000464211151703042024674 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.util.LinkedList; import java.util.List; import net.sf.hajdbc.UniqueConstraint; /** * @author Paul Ferraro * */ public class UniqueConstraintImpl implements UniqueConstraint { private String name; private String table; private List columnList = new LinkedList(); /** * Constructs a new UniqueConstraint. * @param name the name of this constraint * @param table a schema qualified table name */ public UniqueConstraintImpl(String name, String table) { this.name = name; this.table = table; } /** * @see net.sf.hajdbc.UniqueConstraint#getColumnList() */ @Override public List getColumnList() { return this.columnList; } /** * @see net.sf.hajdbc.UniqueConstraint#getName() */ @Override public String getName() { return this.name; } /** * @see net.sf.hajdbc.UniqueConstraint#getTable() */ @Override public String getTable() { return this.table; } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object object) { if ((object == null) || !(object instanceof UniqueConstraint)) return false; String name = ((UniqueConstraint) object).getName(); return (name != null) && name.equals(this.name); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return this.name.hashCode(); } /** * @see java.lang.Comparable#compareTo(java.lang.Object) */ @Override public int compareTo(UniqueConstraint constraint) { return this.name.compareTo(constraint.getName()); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/AbstractTableProperties.java0000644000175000017500000000501611151703042025323 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.SQLException; import java.util.Collection; import java.util.Map; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.TableProperties; /** * @author Paul Ferraro * */ public abstract class AbstractTableProperties implements TableProperties { private final String name; protected AbstractTableProperties(DatabaseMetaDataSupport support, QualifiedName table) { this.name = support.qualifyNameForDML(table); } /** * @see net.sf.hajdbc.TableProperties#getName() */ @Override public final String getName() { return this.name; } /** * @see net.sf.hajdbc.TableProperties#getColumns() */ @Override public final Collection getColumns() throws SQLException { return this.getColumnMap().keySet(); } /** * @see net.sf.hajdbc.TableProperties#getColumnProperties(java.lang.String) */ @Override public final ColumnProperties getColumnProperties(String column) throws SQLException { return this.getColumnMap().get(column); } protected abstract Map getColumnMap() throws SQLException; /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public final boolean equals(Object object) { if ((object == null) || !(object instanceof TableProperties)) return false; String name = ((TableProperties) object).getName(); return (name != null) && name.equals(this.name); } /** * @see java.lang.Object#hashCode() */ @Override public final int hashCode() { return this.name.hashCode(); } /** * @see java.lang.Object#toString() */ @Override public final String toString() { return this.name; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/EagerDatabaseMetaDataCache.java0000644000175000017500000000452611206340350025535 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.Connection; import java.sql.SQLException; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; /** * DatabaseMetaDataCache implementation that eagerly caches data when first flushed. * To be used when performance more of a concern than memory usage. * * @author Paul Ferraro * @since 2.0 */ public class EagerDatabaseMetaDataCache extends AbstractDatabaseMetaDataCache { private volatile DatabaseProperties properties; private final Balancer balancer; public EagerDatabaseMetaDataCache(Dialect dialect, Balancer balancer) { super(dialect); this.balancer = balancer; } /** * @see net.sf.hajdbc.DatabaseMetaDataCache#flush() */ @Override public void flush() throws SQLException { Database database = this.balancer.next(); this.setDatabaseProperties(database.connect(database.createConnectionFactory())); } /** * @see net.sf.hajdbc.DatabaseMetaDataCache#getDatabaseProperties(java.sql.Connection) */ @Override public synchronized DatabaseProperties getDatabaseProperties(Connection connection) throws SQLException { if (this.properties == null) { this.setDatabaseProperties(connection); } return this.properties; } private synchronized void setDatabaseProperties(Connection connection) throws SQLException { this.properties = new EagerDatabaseProperties(connection.getMetaData(), this.factory, this.dialect); } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/DatabaseMetaDataSupportFactory.java0000644000175000017500000000224611151703042026567 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2009 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; import net.sf.hajdbc.Dialect; /** * @author Paul Ferraro * */ public interface DatabaseMetaDataSupportFactory { DatabaseMetaDataSupport createSupport(DatabaseMetaData metaData, Dialect dialect) throws SQLException; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/AbstractDatabaseProperties.java0000644000175000017500000000610511216552012026001 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Collection; import java.util.List; import java.util.Map; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.TableProperties; /** * @author Paul Ferraro * */ public abstract class AbstractDatabaseProperties implements DatabaseProperties { protected final Dialect dialect; protected final DatabaseMetaDataSupport support; private final boolean supportsSelectForUpdate; protected AbstractDatabaseProperties(DatabaseMetaData metaData, DatabaseMetaDataSupportFactory factory, Dialect dialect) throws SQLException { this.dialect = dialect; this.support = factory.createSupport(metaData, dialect); this.supportsSelectForUpdate = metaData.supportsSelectForUpdate(); } /** * @see net.sf.hajdbc.DatabaseProperties#supportsSelectForUpdate() */ @Override public final boolean supportsSelectForUpdate() throws SQLException { return this.supportsSelectForUpdate; } /** * @see net.sf.hajdbc.DatabaseProperties#getTables() */ @Override public final Collection getTables() throws SQLException { return this.getTableMap().values(); } /** * @see net.sf.hajdbc.DatabaseProperties#getSequences() */ @Override public final Collection getSequences() throws SQLException { return this.getSequenceMap().values(); } /** * @see net.sf.hajdbc.DatabaseProperties#findTable(java.lang.String) */ @Override public final TableProperties findTable(String table) throws SQLException { return this.support.find(this.getTableMap(), table, this.getDefaultSchemaList()); } /** * @see net.sf.hajdbc.DatabaseProperties#findSequence(java.lang.String) */ @Override public final SequenceProperties findSequence(String sequence) throws SQLException { return this.support.find(this.getSequenceMap(), sequence, this.getDefaultSchemaList()); } protected abstract Map getTableMap() throws SQLException; protected abstract Map getSequenceMap() throws SQLException; protected abstract List getDefaultSchemaList() throws SQLException; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/SimpleDatabaseProperties.java0000644000175000017500000000303011151703042025460 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; import net.sf.hajdbc.Dialect; /** * @author Paul Ferraro * */ public class SimpleDatabaseProperties extends AbstractLazyDatabaseProperties { private DatabaseMetaData metaData; public SimpleDatabaseProperties(DatabaseMetaData metaData, DatabaseMetaDataSupportFactory factory, Dialect dialect) throws SQLException { super(metaData, factory, dialect); this.metaData = metaData; } /** * @see net.sf.hajdbc.cache.DatabaseMetaDataProvider#getDatabaseMetaData() */ @Override public DatabaseMetaData getDatabaseMetaData() throws SQLException { return this.metaData; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/SimpleDatabaseMetaDataCache.java0000644000175000017500000000341711151703042025741 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.Connection; import java.sql.SQLException; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; /** * DatabaseMetaDataCache implementation that does not cache data. * To be used when memory usage is more of a concern than performance. * * @author Paul Ferraro * @since 2.0 */ public class SimpleDatabaseMetaDataCache extends AbstractDatabaseMetaDataCache { public SimpleDatabaseMetaDataCache(Dialect dialect) { super(dialect); } /** * @see net.sf.hajdbc.DatabaseMetaDataCache#flush() */ @Override public void flush() { // Nothing to flush } /** * @see net.sf.hajdbc.DatabaseMetaDataCache#getDatabaseProperties(java.sql.Connection) */ @Override public DatabaseProperties getDatabaseProperties(Connection connection) throws SQLException { return new SimpleDatabaseProperties(connection.getMetaData(), this.factory, this.dialect); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/ColumnPropertiesImpl.java0000644000175000017500000000451111175404723024700 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import net.sf.hajdbc.ColumnProperties; /** * @author Paul Ferraro * */ public class ColumnPropertiesImpl implements ColumnProperties { private final String name; private final int type; private final String nativeType; private final boolean autoIncrement; public ColumnPropertiesImpl(String name, int type, String nativeType, String defaultValue, String remarks, Boolean autoIncrement) { this.name = name; this.type = type; this.nativeType = nativeType; this.autoIncrement = autoIncrement; } /** * @see net.sf.hajdbc.ColumnProperties#getName() */ @Override public String getName() { return this.name; } /** * @see net.sf.hajdbc.ColumnProperties#getType() */ @Override public int getType() { return this.type; } /** * @see net.sf.hajdbc.ColumnProperties#getNativeType() */ @Override public String getNativeType() { return this.nativeType; } /** * @see net.sf.hajdbc.ColumnProperties#isAutoIncrement() */ @Override public boolean isAutoIncrement() { return this.autoIncrement; } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object object) { if ((object == null) || !(object instanceof ColumnProperties)) return false; ColumnProperties column = (ColumnProperties) object; return this.name.equals(column.getName()); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return this.name.hashCode(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/SequencePropertiesImpl.java0000644000175000017500000000342111151703042025200 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import net.sf.hajdbc.SequenceProperties; /** * @author Paul Ferraro */ public class SequencePropertiesImpl implements SequenceProperties { private String name; public SequencePropertiesImpl(String name) { this.name = name; } /** * @see net.sf.hajdbc.SequenceProperties#getName() */ @Override public String getName() { return this.name; } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object object) { if ((object == null) || !(object instanceof SequenceProperties)) return false; SequenceProperties sequence = (SequenceProperties) object; return this.name.equals(sequence.getName()); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return this.name.hashCode(); } /** * @see java.lang.Object#toString() */ @Override public String toString() { return this.name; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/EagerTableProperties.java0000644000175000017500000000551011151703042024602 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Collection; import java.util.Map; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.UniqueConstraint; /** * @author Paul Ferraro * */ public class EagerTableProperties extends AbstractTableProperties { private Map columnMap; private UniqueConstraint primaryKey; private Collection uniqueConstraints; private Collection foreignKeyConstraints; private Collection identityColumns; public EagerTableProperties(DatabaseMetaData metaData, DatabaseMetaDataSupport support, QualifiedName table) throws SQLException { super(support, table); this.columnMap = support.getColumns(metaData, table); this.primaryKey = support.getPrimaryKey(metaData, table); this.uniqueConstraints = support.getUniqueConstraints(metaData, table, this.primaryKey); this.foreignKeyConstraints = support.getForeignKeyConstraints(metaData, table); this.identityColumns = support.getIdentityColumns(this.columnMap.values()); } @Override protected Map getColumnMap() { return this.columnMap; } /** * @see net.sf.hajdbc.TableProperties#getPrimaryKey() */ @Override public UniqueConstraint getPrimaryKey() { return this.primaryKey; } /** * @see net.sf.hajdbc.TableProperties#getForeignKeyConstraints() */ @Override public Collection getForeignKeyConstraints() { return this.foreignKeyConstraints; } /** * @see net.sf.hajdbc.TableProperties#getUniqueConstraints() */ @Override public Collection getUniqueConstraints() { return this.uniqueConstraints; } /** * @see net.sf.hajdbc.TableProperties#getIdentityColumns() */ @Override public Collection getIdentityColumns() throws SQLException { return this.identityColumns; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/DatabaseMetaDataCacheFactoryClass.java0000644000175000017500000000633711151703042027111 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import net.sf.hajdbc.DatabaseMetaDataCacheFactory; import net.sf.hajdbc.Messages; import net.sf.hajdbc.util.ClassEnum; import net.sf.hajdbc.util.Enums; /** * Factory for creating DatabaseMetaDataCache implementations. * * @author Paul Ferraro * @since 2.0 */ public enum DatabaseMetaDataCacheFactoryClass implements ClassEnum { NONE(SimpleDatabaseMetaDataCacheFactory.class), LAZY(LazyDatabaseMetaDataCacheFactory.class), EAGER(EagerDatabaseMetaDataCacheFactory.class); private Class cacheFactoryClass; private DatabaseMetaDataCacheFactoryClass(Class cacheFactoryClass) { this.cacheFactoryClass = cacheFactoryClass; } /** * @see net.sf.hajdbc.util.ClassEnum#isInstance(java.lang.Object) */ @Override public boolean isInstance(DatabaseMetaDataCacheFactory cache) { return this.cacheFactoryClass.equals(cache.getClass()); } /** * @see net.sf.hajdbc.util.ClassEnum#newInstance() */ @Override public DatabaseMetaDataCacheFactory newInstance() throws Exception { return this.cacheFactoryClass.newInstance(); } /** * Creates a new instance of the {@link net.sf.hajdbc.DatabaseMetaDataCacheFactory} implementation identified by the specified identifier * @param id an enumerated cache identifier * @return a new cache factory instance * @throws Exception if specified cache identifier is invalid */ public static DatabaseMetaDataCacheFactory deserialize(String id) throws Exception { try { return Enums.valueOf(DatabaseMetaDataCacheFactoryClass.class, id).newInstance(); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_META_DATA_CACHE, id)); } } /** * Return the identifier of the specified {@link net.sf.hajdbc.DatabaseMetaDataCacheFactory}. * @param factory a cache factory implementation * @return the class name of this cache */ public static String serialize(DatabaseMetaDataCacheFactory factory) { for (DatabaseMetaDataCacheFactoryClass cacheFactoryClass: DatabaseMetaDataCacheFactoryClass.values()) { if (cacheFactoryClass.isInstance(factory)) { return Enums.id(cacheFactoryClass); } } throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_META_DATA_CACHE, factory.getClass())); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/EagerDatabaseProperties.java0000644000175000017500000000517211151703042025263 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.TableProperties; /** * @author Paul Ferraro * */ public class EagerDatabaseProperties extends AbstractDatabaseProperties { private Map tableMap = new HashMap(); private Map sequenceMap = new HashMap(); private List defaultSchemaList; public EagerDatabaseProperties(DatabaseMetaData metaData, DatabaseMetaDataSupportFactory factory, Dialect dialect) throws SQLException { super(metaData, factory, dialect); Collection tables = this.support.getTables(metaData); for (QualifiedName table: tables) { TableProperties properties = new EagerTableProperties(metaData, this.support, table); this.tableMap.put(properties.getName(), properties); } List defaultSchemaList = this.dialect.getDefaultSchemas(metaData); this.defaultSchemaList = new ArrayList(defaultSchemaList); for (SequenceProperties sequence: this.support.getSequences(metaData)) { this.sequenceMap.put(sequence.getName(), sequence); } } @Override protected List getDefaultSchemaList() throws SQLException { return this.defaultSchemaList; } @Override protected Map getSequenceMap() throws SQLException { return this.sequenceMap; } @Override protected Map getTableMap() throws SQLException { return this.tableMap; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/EagerDatabaseMetaDataCacheFactory.java0000644000175000017500000000265011151703042027061 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseMetaDataCacheFactory; /** * @author Paul Ferraro * */ public class EagerDatabaseMetaDataCacheFactory implements DatabaseMetaDataCacheFactory { /** * @see net.sf.hajdbc.DatabaseMetaDataCacheFactory#createCache(net.sf.hajdbc.DatabaseCluster) */ @Override public DatabaseMetaDataCache createCache(DatabaseCluster cluster) { return new EagerDatabaseMetaDataCache(cluster.getDialect(), cluster.getBalancer()); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/DatabaseMetaDataProvider.java0000644000175000017500000000212611151703042025352 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; /** * @author Paul Ferraro * */ public interface DatabaseMetaDataProvider { DatabaseMetaData getDatabaseMetaData() throws SQLException; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/SimpleDatabaseMetaDataCacheFactory.java0000644000175000017500000000262011151703042027264 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseMetaDataCacheFactory; /** * @author Paul Ferraro * */ public class SimpleDatabaseMetaDataCacheFactory implements DatabaseMetaDataCacheFactory { /** * @see net.sf.hajdbc.DatabaseMetaDataCacheFactory#createCache(net.sf.hajdbc.DatabaseCluster) */ @Override public DatabaseMetaDataCache createCache(DatabaseCluster cluster) { return new SimpleDatabaseMetaDataCache(cluster.getDialect()); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/LazyTableProperties.java0000644000175000017500000001105311151703042024475 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.SQLException; import java.util.Collection; import java.util.Map; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.UniqueConstraint; import net.sf.hajdbc.util.ref.VolatileReference; /** * @author Paul Ferraro * */ public class LazyTableProperties extends AbstractTableProperties { private final DatabaseMetaDataProvider metaDataProvider; private final QualifiedName table; private final DatabaseMetaDataSupport support; private final VolatileReference> columnMapRef = new VolatileReference>(); private final VolatileReference primaryKeyRef = new VolatileReference(); private final VolatileReference> uniqueConstraintsRef = new VolatileReference>(); private final VolatileReference> foreignKeyConstraintsRef = new VolatileReference>(); private final VolatileReference> identityColumnsRef = new VolatileReference>(); public LazyTableProperties(DatabaseMetaDataProvider metaDataProvider, DatabaseMetaDataSupport support, QualifiedName table) { super(support, table); this.metaDataProvider = metaDataProvider; this.support = support; this.table = table; } protected Map getColumnMap() throws SQLException { synchronized (this.columnMapRef) { Map map = this.columnMapRef.get(); if (map == null) { map = this.support.getColumns(this.metaDataProvider.getDatabaseMetaData(), this.table); this.columnMapRef.set(map); } return map; } } /** * @see net.sf.hajdbc.TableProperties#getPrimaryKey() */ @Override public UniqueConstraint getPrimaryKey() throws SQLException { synchronized (this.primaryKeyRef) { UniqueConstraint key = this.primaryKeyRef.get(); if (key == null) { key = this.support.getPrimaryKey(this.metaDataProvider.getDatabaseMetaData(), this.table); this.primaryKeyRef.set(key); } return key; } } /** * @see net.sf.hajdbc.TableProperties#getForeignKeyConstraints() */ @Override public Collection getForeignKeyConstraints() throws SQLException { synchronized (this.foreignKeyConstraintsRef) { Collection keys = this.foreignKeyConstraintsRef.get(); if (keys == null) { keys = this.support.getForeignKeyConstraints(this.metaDataProvider.getDatabaseMetaData(), this.table); this.foreignKeyConstraintsRef.set(keys); } return keys; } } /** * @see net.sf.hajdbc.TableProperties#getUniqueConstraints() */ @Override public Collection getUniqueConstraints() throws SQLException { synchronized (this.uniqueConstraintsRef) { Collection keys = this.uniqueConstraintsRef.get(); if (keys == null) { keys = this.support.getUniqueConstraints(this.metaDataProvider.getDatabaseMetaData(), this.table, this.getPrimaryKey()); this.uniqueConstraintsRef.set(keys); } return keys; } } /** * @see net.sf.hajdbc.TableProperties#getIdentityColumns() */ @Override public Collection getIdentityColumns() throws SQLException { synchronized (this.identityColumnsRef) { Collection columns = this.identityColumnsRef.get(); if (columns == null) { columns = this.support.getIdentityColumns(this.getColumnMap().values()); this.identityColumnsRef.set(columns); } return columns; } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/ForeignKeyConstraintImpl.java0000644000175000017500000000567111151703042025473 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.util.LinkedList; import java.util.List; import net.sf.hajdbc.ForeignKeyConstraint; /** * @author Paul Ferraro */ public class ForeignKeyConstraintImpl extends UniqueConstraintImpl implements ForeignKeyConstraint { private String foreignTable; private List foreignColumnList = new LinkedList(); private int updateRule; private int deleteRule; private int deferrability; /** * Constructs a new ForeignKey. * @param name the name of this constraint * @param table a schema qualified table name */ public ForeignKeyConstraintImpl(String name, String table) { super(name, table); } /** * @see net.sf.hajdbc.ForeignKeyConstraint#getForeignTable() */ @Override public String getForeignTable() { return this.foreignTable; } /** * @see net.sf.hajdbc.ForeignKeyConstraint#getForeignColumnList() */ @Override public List getForeignColumnList() { return this.foreignColumnList; } /** * @see net.sf.hajdbc.ForeignKeyConstraint#getDeleteRule() */ @Override public int getDeleteRule() { return this.deleteRule; } /** * @see net.sf.hajdbc.ForeignKeyConstraint#getUpdateRule() */ @Override public int getUpdateRule() { return this.updateRule; } /** * @see net.sf.hajdbc.ForeignKeyConstraint#getDeferrability() */ @Override public int getDeferrability() { return this.deferrability; } /** * @see net.sf.hajdbc.ForeignKeyConstraint#setDeferrability(int) */ @Override public void setDeferrability(int deferrability) { this.deferrability = deferrability; } /** * @see net.sf.hajdbc.ForeignKeyConstraint#setDeleteRule(int) */ @Override public void setDeleteRule(int deleteRule) { this.deleteRule = deleteRule; } /** * @see net.sf.hajdbc.ForeignKeyConstraint#setForeignTable(java.lang.String) */ @Override public void setForeignTable(String foreignTable) { this.foreignTable = foreignTable; } /** * @see net.sf.hajdbc.ForeignKeyConstraint#setUpdateRule(int) */ @Override public void setUpdateRule(int updateRule) { this.updateRule = updateRule; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/DatabaseMetaDataSupport.java0000644000175000017500000001162711151703042025242 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Collection; import java.util.List; import java.util.Map; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.UniqueConstraint; /** * Processes database meta data into useful structures. * @author Paul Ferraro */ public interface DatabaseMetaDataSupport { /** * Returns all tables in this database mapped by schema. * @param metaData a DatabaseMetaData implementation * @return a Map of schema name to Collection of table names * @throws SQLException if an error occurs access DatabaseMetaData */ public Collection getTables(DatabaseMetaData metaData) throws SQLException; /** * Returns the columns of the specified table. * @param metaData a DatabaseMetaData implementation * @param table a schema qualified table name * @return a Map of column name to column properties * @throws SQLException if an error occurs access DatabaseMetaData */ public Map getColumns(DatabaseMetaData metaData, QualifiedName table) throws SQLException; /** * Returns the primary key of the specified table. * @param metaData a DatabaseMetaData implementation * @param table a schema qualified table name * @return a unique constraint * @throws SQLException if an error occurs access DatabaseMetaData */ public UniqueConstraint getPrimaryKey(DatabaseMetaData metaData, QualifiedName table) throws SQLException; /** * Returns the foreign key constraints on the specified table. * @param metaData a DatabaseMetaData implementation * @param table a schema qualified table name * @return a Collection of foreign key constraints. * @throws SQLException if an error occurs access DatabaseMetaData */ public Collection getForeignKeyConstraints(DatabaseMetaData metaData, QualifiedName table) throws SQLException; /** * Returns the unique constraints on the specified table - excluding the primary key of the table. * @param metaData a schema qualified table name * @param table a qualified table name * @param primaryKey the primary key of this table * @return a Collection of unique constraints. * @throws SQLException if an error occurs access DatabaseMetaData */ public Collection getUniqueConstraints(DatabaseMetaData metaData, QualifiedName table, UniqueConstraint primaryKey) throws SQLException; /** * Returns the schema qualified name of the specified table suitable for use in a data modification language (DML) statement. * @param name a schema qualified name * @return a Collection of unique constraints. */ public String qualifyNameForDML(QualifiedName name); /** * Returns the schema qualified name of the specified table suitable for use in a data definition language (DDL) statement. * @param name a schema qualified name * @return a Collection of unique constraints. */ public String qualifyNameForDDL(QualifiedName name); /** * Returns a collection of sequences using dialect specific logic. * @param metaData database meta data * @return a collection of sequences * @throws SQLException */ public Collection getSequences(DatabaseMetaData metaData) throws SQLException; /** * Locates an object from a map keyed by schema qualified name. * @param an object * @param map a map of database * @param name the name of the object to locate * @param defaultSchemaList a list of default schemas * @return the object with the specified name * @throws SQLException */ public T find(Map map, String name, List defaultSchemaList) throws SQLException; /** * Identifies any identity columns from the from the specified collection of columns * @param columns the columns of a table * @return a collection of column names * @throws SQLException */ public Collection getIdentityColumns(Collection columns) throws SQLException; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/LazyDatabaseProperties.java0000644000175000017500000000335111151703042025154 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; import net.sf.hajdbc.Dialect; /** * @author Paul Ferraro * */ public class LazyDatabaseProperties extends AbstractLazyDatabaseProperties { private final ThreadLocal threadLocal = new ThreadLocal(); public LazyDatabaseProperties(DatabaseMetaData metaData, DatabaseMetaDataSupportFactory factory, Dialect dialect) throws SQLException { super(metaData, factory, dialect); this.setConnection(metaData.getConnection()); } public void setConnection(Connection connection) { this.threadLocal.set(connection); } /** * @see net.sf.hajdbc.cache.DatabaseMetaDataProvider#getDatabaseMetaData() */ @Override public DatabaseMetaData getDatabaseMetaData() throws SQLException { return this.threadLocal.get().getMetaData(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/AbstractLazyDatabaseProperties.java0000644000175000017500000000647411151703042026651 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.util.ref.VolatileReference; /** * @author Paul Ferraro * */ public abstract class AbstractLazyDatabaseProperties extends AbstractDatabaseProperties implements DatabaseMetaDataProvider { private final VolatileReference> tableMapRef = new VolatileReference>(); private final VolatileReference> sequenceMapRef = new VolatileReference>(); private final VolatileReference> defaultSchemaListRef = new VolatileReference>(); protected AbstractLazyDatabaseProperties(DatabaseMetaData metaData, DatabaseMetaDataSupportFactory factory, Dialect dialect) throws SQLException { super(metaData, factory, dialect); } protected Map getTableMap() throws SQLException { synchronized (this.tableMapRef) { Map map = this.tableMapRef.get(); if (map == null) { map = new HashMap(); for (QualifiedName table: this.support.getTables(this.getDatabaseMetaData())) { TableProperties properties = new LazyTableProperties(this, this.support, table); map.put(properties.getName(), properties); } this.tableMapRef.set(map); } return map; } } protected Map getSequenceMap() throws SQLException { synchronized (this.sequenceMapRef) { Map map = this.sequenceMapRef.get(); if (map == null) { map = new HashMap(); for (SequenceProperties sequence: this.support.getSequences(this.getDatabaseMetaData())) { map.put(sequence.getName(), sequence); } this.sequenceMapRef.set(map); } return map; } } protected List getDefaultSchemaList() throws SQLException { synchronized (this.defaultSchemaListRef) { List list = this.defaultSchemaListRef.get(); if (list == null) { list = this.dialect.getDefaultSchemas(this.getDatabaseMetaData()); this.defaultSchemaListRef.set(list); } return list; } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/AbstractDatabaseMetaDataCache.java0000644000175000017500000000306411151703042026251 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2009 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.Dialect; /** * @author Paul Ferraro * */ public abstract class AbstractDatabaseMetaDataCache implements DatabaseMetaDataCache { protected final Dialect dialect; protected final DatabaseMetaDataSupportFactory factory = new DatabaseMetaDataSupportFactory() { @Override public DatabaseMetaDataSupport createSupport(DatabaseMetaData metaData, Dialect dialect) throws SQLException { return new DatabaseMetaDataSupportImpl(metaData, dialect); } }; protected AbstractDatabaseMetaDataCache(Dialect dialect) { this.dialect = dialect; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/LazyDatabaseMetaDataCacheFactory.java0000644000175000017500000000261411151703042026755 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseMetaDataCacheFactory; /** * @author Paul Ferraro * */ public class LazyDatabaseMetaDataCacheFactory implements DatabaseMetaDataCacheFactory { /** * @see net.sf.hajdbc.DatabaseMetaDataCacheFactory#createCache(net.sf.hajdbc.DatabaseCluster) */ @Override public DatabaseMetaDataCache createCache(DatabaseCluster cluster) { return new LazyDatabaseMetaDataCache(cluster.getDialect()); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/LazyDatabaseMetaDataCache.java0000644000175000017500000000456511151703042025434 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.sql.Connection; import java.sql.SQLException; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; /** * DatabaseMetaDataCache implementation that lazily caches data when requested. * Used when a compromise between memory usage and performance is desired. * Caches DatabaseProperties using a soft reference to prevent OutOfMemoryErrors. * * @author Paul Ferraro * @since 2.0 */ public class LazyDatabaseMetaDataCache extends AbstractDatabaseMetaDataCache { private volatile Reference propertiesRef = new SoftReference(null); public LazyDatabaseMetaDataCache(Dialect dialect) { super(dialect); } /** * @see net.sf.hajdbc.DatabaseMetaDataCache#flush() */ @Override public void flush() { this.propertiesRef.clear(); } /** * @see net.sf.hajdbc.DatabaseMetaDataCache#getDatabaseProperties(java.sql.Connection) */ @Override public synchronized DatabaseProperties getDatabaseProperties(Connection connection) throws SQLException { LazyDatabaseProperties properties = this.propertiesRef.get(); if (properties == null) { properties = new LazyDatabaseProperties(connection.getMetaData(), new DatabaseMetaDataSupportFactoryImpl(), this.dialect); this.propertiesRef = new SoftReference(properties); } else { properties.setConnection(connection); } return properties; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/DatabaseMetaDataSupportImpl.java0000644000175000017500000004273511175407467026112 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.Messages; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.UniqueConstraint; import net.sf.hajdbc.util.Strings; /** * Processes database meta data into useful structures. * @author Paul Ferraro */ @SuppressWarnings("nls") public class DatabaseMetaDataSupportImpl implements DatabaseMetaDataSupport { // As defined in SQL-92 specification: http://www.andrew.cmu.edu/user/shadow/sql/sql1992.txt private static final String[] SQL_92_RESERVED_WORDS = new String[] { "absolute", "action", "add", "all", "allocate", "alter", "and", "any", "are", "as", "asc", "assertion", "at", "authorization", "avg", "begin", "between", "bit", "bit_length", "both", "by", "cascade", "cascaded", "case", "cast", "catalog", "char", "character", "char_length", "character_length", "check", "close", "coalesce", "collate", "collation", "column", "commit", "connect", "connection", "constraint", "constraints", "continue", "convert", "corresponding", "count", "create", "cross", "current", "current_date", "current_time", "current_timestamp", "current_user", "cursor", "date", "day", "deallocate", "dec", "decimal", "declare", "default", "deferrable", "deferred", "delete", "desc", "describe", "descriptor", "diagnostics", "disconnect", "distinct", "domain", "double", "drop", "else", "end", "end-exec", "escape", "except", "exception", "exec", "execute", "exists", "external", "extract", "false", "fetch", "first", "float", "for", "foreign", "found", "from", "full", "get", "global", "go", "goto", "grant", "group", "having", "hour", "identity", "immediate", "in", "indicator", "initially", "inner", "input", "insensitive", "insert", "int", "integer", "intersect", "interval", "into", "is", "isolation", "join", "key", "language", "last", "leading", "left", "level", "like", "local", "lower", "match", "max", "min", "minute", "module", "month", "names", "national", "natural", "nchar", "next", "no", "not", "null", "nullif", "numeric", "octet_length", "of", "on", "only", "open", "option", "or", "order", "outer", "output", "overlaps", "pad", "partial", "position", "precision", "prepare", "preserve", "primary", "prior", "privileges", "procedure", "public", "read", "real", "references", "relative", "restrict", "revoke", "right", "rollback", "rows", "schema", "scroll", "second", "section", "select", "session", "session_user", "set", "size", "smallint", "some", "space", "sql", "sqlcode", "sqlerror", "sqlstate", "substring", "sum", "system_user", "table", "temporary", "then", "time", "timestamp", "timezone_hour", "timezone_minute", "to", "trailing", "transaction", "translate", "translation", "trim", "true", "union", "unique", "unknown", "update", "upper", "usage", "user", "using", "value", "values", "varchar", "varying", "view", "when", "whenever", "where", "with", "work", "write", "year", "zone" }; private static final Pattern UPPER_CASE_PATTERN = Pattern.compile("[A-Z]"); private static final Pattern LOWER_CASE_PATTERN = Pattern.compile("[a-z]"); private Dialect dialect; private Set reservedIdentifierSet = new HashSet(); private Pattern identifierPattern; private String quote; private boolean supportsMixedCaseIdentifiers; private boolean supportsMixedCaseQuotedIdentifiers; private boolean storesLowerCaseIdentifiers; private boolean storesLowerCaseQuotedIdentifiers; private boolean storesUpperCaseIdentifiers; private boolean storesUpperCaseQuotedIdentifiers; private boolean supportsSchemasInDDL; private boolean supportsSchemasInDML; /** * Constructs a new DatabaseMetaDataSupport using the specified DatabaseMetaData implementation. * @param metaData a DatabaseMetaData implementation * @param dialect the vendor-specific dialect of the cluster * @throws SQLException if an error occurs access DatabaseMetaData */ public DatabaseMetaDataSupportImpl(DatabaseMetaData metaData, Dialect dialect) throws SQLException { this.dialect = dialect; this.identifierPattern = dialect.getIdentifierPattern(metaData); this.quote = metaData.getIdentifierQuoteString(); this.supportsMixedCaseIdentifiers = metaData.supportsMixedCaseIdentifiers(); this.supportsMixedCaseQuotedIdentifiers = metaData.supportsMixedCaseQuotedIdentifiers(); this.storesLowerCaseIdentifiers = metaData.storesLowerCaseIdentifiers(); this.storesLowerCaseQuotedIdentifiers = metaData.storesLowerCaseQuotedIdentifiers(); this.storesUpperCaseIdentifiers = metaData.storesUpperCaseIdentifiers(); this.storesUpperCaseQuotedIdentifiers = metaData.storesUpperCaseQuotedIdentifiers(); this.supportsSchemasInDML = metaData.supportsSchemasInDataManipulation(); this.supportsSchemasInDDL = metaData.supportsSchemasInTableDefinitions(); for (String word: SQL_92_RESERVED_WORDS) { this.reservedIdentifierSet.add(this.normalizeCase(word)); } for (String word: metaData.getSQLKeywords().split(Strings.COMMA)) { this.reservedIdentifierSet.add(this.normalizeCase(word)); } } /** * Returns all tables in this database mapped by schema. * @param metaData a DatabaseMetaData implementation * @return a Map of schema name to Collection of table names * @throws SQLException if an error occurs access DatabaseMetaData */ @Override public Collection getTables(DatabaseMetaData metaData) throws SQLException { List list = new LinkedList(); ResultSet resultSet = metaData.getTables(this.getCatalog(metaData), null, Strings.ANY, new String[] { "TABLE" }); while (resultSet.next()) { list.add(new QualifiedName(resultSet.getString("TABLE_SCHEM"), resultSet.getString("TABLE_NAME"))); } resultSet.close(); return list; } /** * Returns the columns of the specified table. * @param metaData a DatabaseMetaData implementation * @param table a schema qualified table name * @return a Map of column name to column properties * @throws SQLException if an error occurs access DatabaseMetaData */ @Override public Map getColumns(DatabaseMetaData metaData, QualifiedName table) throws SQLException { Map columnMap = new HashMap(); Statement statement = metaData.getConnection().createStatement(); try { ResultSetMetaData resultSet = statement.executeQuery("SELECT * FROM " + this.qualifyNameForDML(table) + " WHERE 0=1").getMetaData(); for (int i = 1; i <= resultSet.getColumnCount(); ++i) { String column = this.quote(resultSet.getColumnName(i)); int type = resultSet.getColumnType(i); String nativeType = resultSet.getColumnTypeName(i); boolean autoIncrement = resultSet.isAutoIncrement(i); columnMap.put(column, new ColumnPropertiesImpl(column, type, nativeType, null, null, autoIncrement)); } } finally { statement.close(); } return columnMap; } /** * Returns the primary key of the specified table. * @param metaData a DatabaseMetaData implementation * @param table a schema qualified table name * @return a unique constraint * @throws SQLException if an error occurs access DatabaseMetaData */ @Override public UniqueConstraint getPrimaryKey(DatabaseMetaData metaData, QualifiedName table) throws SQLException { UniqueConstraint constraint = null; ResultSet resultSet = metaData.getPrimaryKeys(this.getCatalog(metaData), this.getSchema(table), table.getName()); while (resultSet.next()) { String name = this.quote(resultSet.getString("PK_NAME")); if (constraint == null) { constraint = new UniqueConstraintImpl(name, this.qualifyNameForDDL(table)); } String column = this.quote(resultSet.getString("COLUMN_NAME")); constraint.getColumnList().add(column); } resultSet.close(); return constraint; } /** * Returns the foreign key constraints on the specified table. * @param metaData a DatabaseMetaData implementation * @param table a schema qualified table name * @return a Collection of foreign key constraints. * @throws SQLException if an error occurs access DatabaseMetaData */ @Override public Collection getForeignKeyConstraints(DatabaseMetaData metaData, QualifiedName table) throws SQLException { Map foreignKeyMap = new HashMap(); ResultSet resultSet = metaData.getImportedKeys(this.getCatalog(metaData), this.getSchema(table), table.getName()); while (resultSet.next()) { String name = this.quote(resultSet.getString("FK_NAME")); ForeignKeyConstraint foreignKey = foreignKeyMap.get(name); if (foreignKey == null) { foreignKey = new ForeignKeyConstraintImpl(name, this.qualifyNameForDDL(table)); String foreignSchema = this.quote(resultSet.getString("PKTABLE_SCHEM")); String foreignTable = this.quote(resultSet.getString("PKTABLE_NAME")); foreignKey.setForeignTable(this.qualifyNameForDDL(new QualifiedName(foreignSchema, foreignTable))); foreignKey.setDeleteRule(resultSet.getInt("DELETE_RULE")); foreignKey.setUpdateRule(resultSet.getInt("UPDATE_RULE")); foreignKey.setDeferrability(resultSet.getInt("DEFERRABILITY")); foreignKeyMap.put(name, foreignKey); } String column = this.quote(resultSet.getString("FKCOLUMN_NAME")); String foreignColumn = this.quote(resultSet.getString("PKCOLUMN_NAME")); foreignKey.getColumnList().add(column); foreignKey.getForeignColumnList().add(foreignColumn); } resultSet.close(); return foreignKeyMap.values(); } /** * Returns the unique constraints on the specified table - excluding the primary key of the table. * @param metaData a schema qualified table name * @param table a qualified table name * @param primaryKey the primary key of this table * @return a Collection of unique constraints. * @throws SQLException if an error occurs access DatabaseMetaData */ @Override public Collection getUniqueConstraints(DatabaseMetaData metaData, QualifiedName table, UniqueConstraint primaryKey) throws SQLException { Map keyMap = new HashMap(); ResultSet resultSet = metaData.getIndexInfo(this.getCatalog(metaData), this.getSchema(table), table.getName(), true, false); while (resultSet.next()) { if (resultSet.getShort("TYPE") == DatabaseMetaData.tableIndexHashed) { String name = this.quote(resultSet.getString("INDEX_NAME")); // Don't include the primary key if ((primaryKey != null) && name.equals(primaryKey.getName())) continue; UniqueConstraint key = keyMap.get(name); if (key == null) { key = new UniqueConstraintImpl(name, this.qualifyNameForDDL(table)); keyMap.put(name, key); } String column = this.quote(resultSet.getString("COLUMN_NAME")); key.getColumnList().add(column); } } resultSet.close(); return keyMap.values(); } /** * Returns the schema qualified name of the specified table suitable for use in a data modification language (DML) statement. * @param name a schema qualified name * @return a Collection of unique constraints. */ @Override public String qualifyNameForDML(QualifiedName name) { return this.qualifyName(name, this.supportsSchemasInDML); } /** * Returns the schema qualified name of the specified table suitable for use in a data definition language (DDL) statement. * @param name a schema qualified name * @return a Collection of unique constraints. */ @Override public String qualifyNameForDDL(QualifiedName name) { return this.qualifyName(name, this.supportsSchemasInDDL); } private String qualifyName(QualifiedName name, boolean supportsSchemas) { StringBuilder builder = new StringBuilder(); String schema = name.getSchema(); if (supportsSchemas && (schema != null)) { builder.append(this.quote(schema)).append(Strings.DOT); } return builder.append(this.quote(name.getName())).toString(); } private String getCatalog(DatabaseMetaData metaData) throws SQLException { String catalog = metaData.getConnection().getCatalog(); return (catalog != null) ? catalog : Strings.EMPTY; } private String getSchema(QualifiedName name) { String schema = name.getSchema(); return (schema != null) ? schema : Strings.EMPTY; } private String quote(String identifier) { if (identifier == null) return null; int quoteLength = this.quote.length(); // Strip any existing quoting String raw = (identifier.startsWith(this.quote) && identifier.endsWith(this.quote)) ? identifier.substring(quoteLength, identifier.length() - quoteLength) : identifier; String normal = this.normalizeCase(raw); // Quote reserved identifiers boolean requiresQuoting = this.reservedIdentifierSet.contains(normal); // Quote identifiers containing special characters requiresQuoting |= !this.identifierPattern.matcher(raw).matches(); // Quote mixed-case identifiers if detected and supported by DBMS requiresQuoting |= !this.supportsMixedCaseIdentifiers && this.supportsMixedCaseQuotedIdentifiers && ((this.storesLowerCaseIdentifiers && !this.storesLowerCaseQuotedIdentifiers && UPPER_CASE_PATTERN.matcher(raw).find()) || (this.storesUpperCaseIdentifiers && !this.storesUpperCaseQuotedIdentifiers && LOWER_CASE_PATTERN.matcher(raw).find())); return requiresQuoting ? this.quote + this.normalizeCaseQuoted(raw) + this.quote : normal; } private String normalizeCase(String identifier) { if (this.storesLowerCaseIdentifiers) return identifier.toLowerCase(); if (this.storesUpperCaseIdentifiers) return identifier.toUpperCase(); return identifier; } private String normalizeCaseQuoted(String identifier) { if (this.storesLowerCaseQuotedIdentifiers) return identifier.toLowerCase(); if (this.storesUpperCaseQuotedIdentifiers) return identifier.toUpperCase(); return identifier; } private String normalize(String qualifiedName, String defaultSchema) { String parts[] = qualifiedName.split(Pattern.quote(Strings.DOT)); String name = parts[parts.length - 1]; String schema = (parts.length > 1) ? parts[parts.length - 2] : defaultSchema; return this.qualifyNameForDML(new QualifiedName(schema, name)); } /** * Returns a collection of sequences using dialect specific logic. * @param metaData database meta data * @return a collection of sequences * @throws SQLException */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { Collection sequences = this.dialect.getSequences(metaData); List sequenceList = new ArrayList(sequences.size()); for (QualifiedName sequence: sequences) { sequenceList.add(new SequencePropertiesImpl(this.qualifyNameForDML(sequence))); } return sequenceList; } /** * Locates an object from a map keyed by schema qualified name. * @param an object * @param map a map of database * @param name the name of the object to locate * @param defaultSchemaList a list of default schemas * @return the object with the specified name * @throws SQLException */ @Override public T find(Map map, String name, List defaultSchemaList) throws SQLException { T properties = map.get(this.normalize(name, null)); if (properties == null) { for (String schema: defaultSchemaList) { if (properties == null) { properties = map.get(this.normalize(name, schema)); } } } if (properties == null) { throw new SQLException(Messages.getMessage(Messages.SCHEMA_LOOKUP_FAILED, name, defaultSchemaList, this.dialect.getClass().getName() + ".getDefaultSchemas()")); } return properties; } /** * Identifies any identity columns from the from the specified collection of columns * @param columns the columns of a table * @return a collection of column names * @throws SQLException */ @Override public Collection getIdentityColumns(Collection columns) throws SQLException { List columnList = new LinkedList(); for (ColumnProperties column: columns) { if (column.isAutoIncrement()) { columnList.add(column.getName()); } } return columnList; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/cache/DatabaseMetaDataSupportFactoryImpl.java0000644000175000017500000000265311151703042027413 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2009 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.cache; import java.sql.DatabaseMetaData; import java.sql.SQLException; import net.sf.hajdbc.Dialect; /** * @author Paul Ferraro * */ public class DatabaseMetaDataSupportFactoryImpl implements DatabaseMetaDataSupportFactory { /** * @see net.sf.hajdbc.cache.DatabaseMetaDataSupportFactory#createSupport(java.sql.DatabaseMetaData, net.sf.hajdbc.Dialect) */ @Override public DatabaseMetaDataSupport createSupport(DatabaseMetaData metaData, Dialect dialect) throws SQLException { return new DatabaseMetaDataSupportImpl(metaData, dialect); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/local/0000755000175000017500000000000011674455606017741 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/local/LocalStateManager.java0000644000175000017500000000732511151703042024115 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.local; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseEvent; import net.sf.hajdbc.Messages; import net.sf.hajdbc.StateManager; import net.sf.hajdbc.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Paul Ferraro */ public class LocalStateManager implements StateManager { private static Preferences preferences = Preferences.userNodeForPackage(LocalStateManager.class); private static Logger logger = LoggerFactory.getLogger(LocalStateManager.class); private DatabaseCluster databaseCluster; /** * @param databaseCluster */ public LocalStateManager(DatabaseCluster databaseCluster) { this.databaseCluster = databaseCluster; } /** * @see net.sf.hajdbc.StateManager#getInitialState() */ @Override public Set getInitialState() { String state = preferences.get(this.statePreferenceKey(), null); if (state == null) { logger.info(Messages.getMessage(Messages.INITIAL_CLUSTER_STATE_NONE)); return null; } Set databaseSet = Collections.emptySet(); if (state.length() > 0) { databaseSet = new TreeSet(Arrays.asList(state.split(Strings.COMMA))); } logger.info(Messages.getMessage(Messages.INITIAL_CLUSTER_STATE_LOCAL, databaseSet)); return databaseSet; } /** * @see net.sf.hajdbc.Lifecycle#start() */ @Override public void start() throws Exception { preferences.sync(); } /** * @see net.sf.hajdbc.Lifecycle#stop() */ @Override public void stop() { // Nothing to do } private String statePreferenceKey() { return this.databaseCluster.getId(); } /** * @see net.sf.hajdbc.StateManager#isMembershipEmpty() */ @Override public boolean isMembershipEmpty() { return false; } /** * @see net.sf.hajdbc.DatabaseActivationListener#activated(net.sf.hajdbc.DatabaseEvent) */ @Override public void activated(DatabaseEvent event) { this.storeState(); } /** * @see net.sf.hajdbc.DatabaseDeactivationListener#deactivated(net.sf.hajdbc.DatabaseEvent) */ @Override public void deactivated(DatabaseEvent event) { this.storeState(); } private void storeState() { List databaseList = new ArrayList(); for (Database database: this.databaseCluster.getBalancer().all()) { databaseList.add(database.getId()); } preferences.put(this.statePreferenceKey(), Strings.join(databaseList, Strings.COMMA)); try { preferences.flush(); } catch (BackingStoreException e) { throw new RuntimeException(Messages.getMessage(Messages.CLUSTER_STATE_STORE_FAILED, this.databaseCluster), e); } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/local/LocalLockManager.java0000644000175000017500000000722511151703042023724 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.local; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.util.concurrent.SemaphoreReadWriteLock; /** * @author Paul Ferraro */ public class LocalLockManager implements LockManager { private Map lockMap = new HashMap(); /** * @see net.sf.hajdbc.LockManager#readLock(java.lang.String) */ @Override public Lock readLock(String object) { Lock lock = this.getReadWriteLock(null).readLock(); return (object == null) ? lock : new GlobalLock(lock, this.getReadWriteLock(object).readLock()); } /** * @see net.sf.hajdbc.LockManager#writeLock(java.lang.String) */ @Override public Lock writeLock(String object) { ReadWriteLock readWriteLock = this.getReadWriteLock(null); return (object == null) ? readWriteLock.writeLock() : new GlobalLock(readWriteLock.readLock(), this.getReadWriteLock(object).writeLock()); } private synchronized ReadWriteLock getReadWriteLock(String object) { ReadWriteLock lock = this.lockMap.get(object); if (lock == null) { lock = new SemaphoreReadWriteLock(true); this.lockMap.put(object, lock); } return lock; } private static class GlobalLock implements Lock { private Lock globalLock; private Lock lock; GlobalLock(Lock globalLock, Lock lock) { this.globalLock = globalLock; this.lock = lock; } @Override public void lock() { this.globalLock.lock(); this.lock.lock(); } @Override public void lockInterruptibly() throws InterruptedException { this.globalLock.lockInterruptibly(); try { this.lock.lockInterruptibly(); } catch (InterruptedException e) { this.globalLock.unlock(); throw e; } } @Override public boolean tryLock() { if (this.globalLock.tryLock()) { if (this.lock.tryLock()) { return true; } this.globalLock.unlock(); } return false; } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { if (this.globalLock.tryLock(time, unit)) { if (this.lock.tryLock(time, unit)) { return true; } this.globalLock.unlock(); } return false; } @Override public void unlock() { this.lock.unlock(); this.globalLock.unlock(); } @Override public Condition newCondition() { throw new UnsupportedOperationException(); } } /** * @see net.sf.hajdbc.Lifecycle#start() */ @Override public void start() throws Exception { // Do nothing } /** * @see net.sf.hajdbc.Lifecycle#stop() */ @Override public void stop() { // Do nothing } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Messages_fr.properties0000644000175000017500000001203311151703042023176 0ustar moellermoeller#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) # # HA-JDBC: High-Availability JDBC # Copyright (c) 2004-2007 Paul Ferraro # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation; either version 2.1 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Contact: ferraro@users.sourceforge.net # cluster-not-active = Le faisceau {0} de base de donn\u00E9es n'est pas en activit\u00E9. cluster-panic-detected = Panique de faisceau d\u00E9tect\u00E9e sur le faisceau {0} de base de donn\u00E9es. cluster-start-failed = N'a pas commenc\u00E9 le faisceau {0} de base de donn\u00E9es. cluster-state-load-failed = N'a pas charg\u00E9 l'\u00E9tat du faisceau de base de donn\u00E9es {0}. cluster-state-store-failed = N'a pas stock\u00E9 l'\u00E9tat du faisceau de base de donn\u00E9es {0}. command-received = Commande re\u00E7ue: {0} config-load-failed = N'a pas charg\u00E9 la configuration de HA-JDBC de {0} config-not-found = Pour localiser le fichier de configuration de faisceau de base de donn\u00E9es: {0} config-store-failed = N'a pas sauv\u00E9 la configuration de HA-JDBC \u00E0 {0} database-activate-failed = N'a pas activ\u00E9 la base de donn\u00E9es {0} du faisceau {1} database-activated = La base de donn\u00E9es {0} du faisceau {1} a \u00E9t\u00E9 activ\u00E9e database-already-exists = Le faisceau {1} contient d\u00E9j\u00E0 la base de donn\u00E9es {0}. database-deactivated = La base de donn\u00E9es {0} du faisceau {1} a \u00E9t\u00E9 mise hors tension database-not-active = La base de donn\u00E9es n'\u00E9tait pas en activit\u00E9 alors {0} a \u00E9t\u00E9 cr\u00E9\u00E9e database-not-alive = La base de donn\u00E9es {0} du faisceau {1} ne r\u00E9pond pas. database-still-active = La base de donn\u00E9es {0} du faisceau {1} ne pourrait pas \u00EAtre enlev\u00E9e parce qu'elle est encore en activit\u00E9. database-sync-end = Synchronisation finie de la base de donn\u00E9es {0} du faisceau {1}. database-sync-start = Commencer la synchronisation de la base de donn\u00E9es {0} du faisceau {1}. delete-count = Supprim\u00E9 {0} rame de {1} driver-not-found = N'a pas localis\u00E9 le conducteur {0} driver-register-failed = N'a pas enregistr\u00E9 le conducteur {0} group-member-joined = {0} a joint le canal {1} group-member-left = {0} a laiss\u00E9 le canal {1} ha-jdbc-init = Initialisation de HA-JDBC {0} de {1} initial-cluster-state-local = Employer l'\u00E9tat initial local de faisceau {0}. initial-cluster-state-none = Aucun \u00E9tat initial de faisceau trouv\u00E9. initial-cluster-state-remote = Employer l'\u00E9tat initial \u00E0 distance de faisceau {0} de {1}. insert-count = Ins\u00E9r\u00E9 {0} rame dans {1} invalid-balancer = {0} n'est pas un compensateur valide. invalid-database = Le faisceau de base de donn\u00E9es {1} ne contient pas la base de donn\u00E9es {0} invalid-database-cluster = {0} n'est pas un faisceau valide de base de donn\u00E9es. invalid-meta-data-cache = {0} n'est pas une cachette valide de m\u00E9ta-donn\u00E9es. invalid-property = {0} n'est pas une propri\u00E9t\u00E9 valide de {1} invalid-property-value = {0} n'est pas { une 1 } valeur valide pour {2} invalid-sync-strategy = {0} n'est pas une strat\u00E9gie valide de synchronisation pour le faisceau. jdbc-url-rejected = Aucun conducteur enregistr\u00E9 n'acceptera URL {0} jndi-lookup-failed = N'a pas effectu\u00E9 appeler la consultation de {0} mbean-server-not-found = Aucun mbean server trouv\u00E9. no-active-databases = Aucunes bases de donn\u00E9es actives dans le faisceau {0} primary-key-required = Le tableau {1} ne contient pas une clef primaire - ceci est exig\u00E9 par la strat\u00E9gie de synchronisation {0}. schema-lookup-failed = N'a pas localis\u00E9 {0} dans les sch\u00E9mas suivants : {1}. V\u00E9rifiez l'ex\u00E9cution de {2}. sequence-out-of-sync = La prochaine valeur ({2}) pour l'ordre {0} de la base de donn\u00E9es {1} n'assortit pas la prochaine valeur ({4}) de la base de donn\u00E9es {3}. shut-down = HA-JDBC d'arr\u00EAt. sql-object-init-failed = N'a pas initialis\u00E9 {0} pour la base de donn\u00E9es {1} statement-failed = A \u00E9chou\u00E9 \u00E0 ex\u00E9cutent le rapport: {0} table-lock-acquire = Acquisition des serrures de table sur les bases de donn\u00E9es actives. table-lock-release = Lib\u00E9rer des serrures de table sur les bases de donn\u00E9es actives. update-count = Mis \u00E0 jour {0} rame dedans {1} write-lock-failed = N'a pas acquis la serrure exclusive sur le faisceau {0} de base de donn\u00E9es. ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Balancer.java0000644000175000017500000000443211151703042021200 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.Set; /** * @author Paul Ferraro * @since 1.0 * @param either java.sql.Driver or javax.sql.DataSource */ public interface Balancer { /** * Removes the specified database from this balancer. * @param database a database descriptor * @return true, if the database was removed successfully, false if it did not exist. */ public boolean remove(Database database); /** * Adds the specified database to this balancer. * @param database a database descriptor * @return true, if the database was added successfully, false if already existed. */ public boolean add(Database database); /** * Returns the next database from this balancer * @return the next database from this balancer */ public Database next(); /** * Returns an unmodifiable collection of databases known to this balancer * @return a collection of database descriptors */ public Set> all(); /** * Called before an operation is performed on the specified database retrieved via {@link #next()}. * @param database a database descriptor */ public void beforeInvocation(Database database); /** * Called after an operation is performed on the specified database retrieved via {@link #next()}. * @param database a database descriptor */ public void afterInvocation(Database database); /** * Removes all databases from this balancer. */ public void clear(); }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseClusterFactory.java0000644000175000017500000001332111206340520024063 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.lang.management.ManagementFactory; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.sql.SQLException; import java.text.MessageFormat; import java.util.Hashtable; import java.util.ResourceBundle; import javax.management.JMException; import javax.management.MBeanServer; import javax.management.MBeanServerInvocationHandler; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import net.sf.hajdbc.util.SQLExceptionFactory; /** * @author Paul Ferraro */ public class DatabaseClusterFactory { private static final String CONFIG_FORMAT_PROPERTY = "ha-jdbc.{0}.configuration"; //$NON-NLS-1$ private static final String CONFIG_PROPERTY = "ha-jdbc.configuration"; //$NON-NLS-1$ private static final String DEFAULT_RESOURCE = "ha-jdbc-{0}.xml"; //$NON-NLS-1$ private static final String MBEAN_CLUSTER_KEY = "cluster"; //$NON-NLS-1$ private static final String MBEAN_DATABASE_KEY = "database"; //$NON-NLS-1$ private static final String VERSION = "version"; //$NON-NLS-1$ private static ResourceBundle resource = ResourceBundle.getBundle(DatabaseClusterFactory.class.getName()); /** * Convenience method for constructing a standardized mbean ObjectName for this cluster. * @param clusterId a cluster identifier * @return an ObjectName for this cluster * @throws MalformedObjectNameException if the ObjectName could not be constructed */ public static ObjectName getObjectName(String clusterId) throws MalformedObjectNameException { return ObjectName.getInstance(getDomain(), createProperties(clusterId)); } /** * Convenience method for constructing a standardized mbean ObjectName for this database. * @param clusterId a cluster identifier * @param databaseId a database identifier * @return an ObjectName for this cluster * @throws MalformedObjectNameException if the ObjectName could not be constructed */ public static ObjectName getObjectName(String clusterId, String databaseId) throws MalformedObjectNameException { Hashtable properties = createProperties(clusterId); properties.put(MBEAN_DATABASE_KEY, databaseId); return ObjectName.getInstance(getDomain(), properties); } private static Hashtable createProperties(String clusterId) { Hashtable properties = new Hashtable(); properties.put(MBEAN_CLUSTER_KEY, clusterId); return properties; } private static String getDomain() { return DatabaseClusterFactory.class.getPackage().getName(); } /** * Returns the current HA-JDBC version. * @return a version label */ public static String getVersion() { return resource.getString(VERSION); } public static synchronized > C getDatabaseCluster(String id, Class targetClass, Class mbeanInterface, String resource) throws SQLException { try { ObjectName name = getObjectName(id); MBeanServer server = ManagementFactory.getPlatformMBeanServer(); if (!server.isRegistered(name)) { URL url = findResource((resource == null) ? identifyResource(id) : resource); C cluster = targetClass.getConstructor(String.class, URL.class).newInstance(id, url); server.registerMBean(cluster, name); } return MBeanServerInvocationHandler.newProxyInstance(server, name, mbeanInterface, false); } catch (JMException e) { throw SQLExceptionFactory.createSQLException(e); } catch (InstantiationException e) { throw SQLExceptionFactory.createSQLException(e); } catch (IllegalAccessException e) { throw SQLExceptionFactory.createSQLException(e); } catch (NoSuchMethodException e) { throw SQLExceptionFactory.createSQLException(e); } catch (InvocationTargetException e) { throw SQLExceptionFactory.createSQLException(e); } } private static String identifyResource(String id) { String resource = System.getProperty(MessageFormat.format(CONFIG_FORMAT_PROPERTY, id)); return (resource != null) ? resource : MessageFormat.format(System.getProperty(CONFIG_PROPERTY, DEFAULT_RESOURCE), id); } /** * Algorithm for searching class loaders for HA-JDBC url. * @param resource a resource name * @return a URL for the HA-JDBC configuration resource */ private static URL findResource(String resource) throws SQLException { try { return new URL(resource); } catch (MalformedURLException e) { URL url = Thread.currentThread().getContextClassLoader().getResource(resource); if (url == null) { url = DatabaseClusterFactory.class.getClassLoader().getResource(resource); } if (url == null) { url = ClassLoader.getSystemResource(resource); } if (url == null) { throw new SQLException(Messages.getMessage(Messages.CONFIG_NOT_FOUND, resource)); } return url; } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/UniqueConstraint.java0000644000175000017500000000251711151703042023006 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.List; /** * Represents a unique constraint on a table. * * @author Paul Ferraro * @since 1.1 */ public interface UniqueConstraint extends Comparable { /** * @return the name of this constraint */ public String getName(); /** * @return the table of this constraint */ public String getTable(); /** * @return the list of columns in this unique constraint */ public List getColumnList(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/0000755000175000017500000000000011674455606017446 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/EagerResultSetInvocationStrategy.java0000644000175000017500000000423711151703042026746 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.ResultSet; import java.sql.Statement; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * @param * @param */ public class EagerResultSetInvocationStrategy extends DatabaseWriteInvocationStrategy { private S statement; private TransactionContext transactionContext; private FileSupport fileSupport; /** * @param cluster * @param statement * @param transactionContext * @param fileSupport */ public EagerResultSetInvocationStrategy(DatabaseCluster cluster, S statement, TransactionContext transactionContext, FileSupport fileSupport) { super(cluster.getTransactionalExecutor()); this.statement = statement; this.transactionContext = transactionContext; this.fileSupport = fileSupport; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public ResultSet invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(ResultSet.class, new ResultSetInvocationHandler(this.statement, proxy, invoker, this.invokeAll(proxy, invoker), this.transactionContext, this.fileSupport)); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/AbstractPreparedStatementInvocationHandler.java0000644000175000017500000002156111217246575030755 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Blob; import java.sql.Clob; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.Lock; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; import net.sf.hajdbc.util.reflect.ProxyFactory; import net.sf.hajdbc.util.reflect.SimpleInvocationHandler; /** * @author Paul Ferraro * @param * @param */ @SuppressWarnings("nls") public class AbstractPreparedStatementInvocationHandler extends AbstractStatementInvocationHandler { private static final Set databaseReadMethodSet = Methods.findMethods(PreparedStatement.class, "getMetaData", "getParameterMetaData"); private static final Method executeMethod = Methods.getMethod(PreparedStatement.class, "execute"); private static final Method executeUpdateMethod = Methods.getMethod(PreparedStatement.class, "executeUpdate"); private static final Method executeQueryMethod = Methods.getMethod(PreparedStatement.class, "executeQuery"); private static final Method clearParametersMethod = Methods.getMethod(PreparedStatement.class, "clearParameters"); private static final Method addBatchMethod = Methods.getMethod(PreparedStatement.class, "addBatch"); protected List lockList = Collections.emptyList(); protected boolean selectForUpdate = false; private Set setMethodSet; /** * @param connection * @param proxy * @param invoker * @param statementClass * @param statementMap * @param transactionContext * @param fileSupport * @throws Exception */ public AbstractPreparedStatementInvocationHandler(Connection connection, SQLProxy proxy, Invoker invoker, Class statementClass, Map, S> statementMap, TransactionContext transactionContext, FileSupport fileSupport, Set setMethods) throws Exception { super(connection, proxy, invoker, statementClass, statementMap, transactionContext, fileSupport); this.setMethodSet = setMethods; } /** * @see net.sf.hajdbc.sql.AbstractStatementInvocationHandler#getInvocationStrategy(java.sql.Statement, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(S statement, Method method, Object[] parameters) throws Exception { if (databaseReadMethodSet.contains(method)) { return new DatabaseReadInvocationStrategy(); } if (this.setMethodSet.contains(method) || method.equals(clearParametersMethod) || method.equals(addBatchMethod)) { return new DriverWriteInvocationStrategy(); } if (method.equals(executeMethod) || method.equals(executeUpdateMethod)) { return this.transactionContext.start(new LockingInvocationStrategy(new DatabaseWriteInvocationStrategy(this.cluster.getTransactionalExecutor()), this.lockList), this.getParent()); } if (method.equals(executeQueryMethod)) { int concurrency = statement.getResultSetConcurrency(); if (this.lockList.isEmpty() && (concurrency == ResultSet.CONCUR_READ_ONLY) && !this.selectForUpdate) { return new DatabaseReadInvocationStrategy(); } InvocationStrategy strategy = new LockingInvocationStrategy(new EagerResultSetInvocationStrategy(this.cluster, statement, this.transactionContext, this.fileSupport), this.lockList); return this.selectForUpdate ? this.transactionContext.start(strategy, this.getParent()) : strategy; } return super.getInvocationStrategy(statement, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvoker(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @SuppressWarnings("unchecked") @Override protected Invoker getInvoker(S statement, final Method method, final Object[] parameters) throws Exception { Class[] types = method.getParameterTypes(); if (this.isParameterSetMethod(method) && (parameters.length > 1) && (parameters[1] != null)) { Class type = types[1]; if (type.equals(InputStream.class)) { final File file = this.fileSupport.createFile((InputStream) parameters[1]); return new Invoker() { public Object invoke(Database database, S statement) throws SQLException { List parameterList = new ArrayList(Arrays.asList(parameters)); parameterList.set(1, AbstractPreparedStatementInvocationHandler.this.fileSupport.getInputStream(file)); return Methods.invoke(method, statement, parameterList.toArray()); } }; } if (type.equals(Reader.class)) { final File file = this.fileSupport.createFile((Reader) parameters[1]); return new Invoker() { public Object invoke(Database database, S statement) throws SQLException { List parameterList = new ArrayList(Arrays.asList(parameters)); parameterList.set(1, AbstractPreparedStatementInvocationHandler.this.fileSupport.getReader(file)); return Methods.invoke(method, statement, parameterList.toArray()); } }; } if (type.equals(Blob.class)) { Blob blob = (Blob) parameters[1]; if (Proxy.isProxyClass(blob.getClass())) { InvocationHandler handler = Proxy.getInvocationHandler(blob); if (SQLProxy.class.isInstance(handler)) { final SQLProxy proxy = (SQLProxy) handler; return new Invoker() { public Object invoke(Database database, S statement) throws SQLException { List parameterList = new ArrayList(Arrays.asList(parameters)); parameterList.set(1, proxy.getObject(database)); return Methods.invoke(method, statement, parameterList.toArray()); } }; } } parameters[1] = new SerialBlob(blob); } // Handle both clob and nclob if (Clob.class.isAssignableFrom(type)) { Clob clob = (Clob) parameters[1]; if (Proxy.isProxyClass(clob.getClass())) { InvocationHandler handler = Proxy.getInvocationHandler(clob); if (SQLProxy.class.isInstance(handler)) { final SQLProxy proxy = (SQLProxy) handler; return new Invoker() { public Object invoke(Database database, S statement) throws SQLException { List parameterList = new ArrayList(Arrays.asList(parameters)); parameterList.set(1, proxy.getObject(database)); return Methods.invoke(method, statement, parameterList.toArray()); } }; } } Clob serialClob = new SerialClob(clob); parameters[1] = type.equals(Clob.class) ? serialClob : ProxyFactory.createProxy(type, new SimpleInvocationHandler(serialClob)); } } return super.getInvoker(statement, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractStatementInvocationHandler#isBatchMethod(java.lang.reflect.Method) */ @Override protected boolean isBatchMethod(Method method) { return method.equals(addBatchMethod) || method.equals(clearParametersMethod) || this.isParameterSetMethod(method) || super.isBatchMethod(method); } private boolean isParameterSetMethod(Method method) { Class[] types = method.getParameterTypes(); return this.setMethodSet.contains(method) && (types.length > 0) && this.isIndexType(types[0]); } protected boolean isIndexType(Class type) { return type.equals(Integer.TYPE); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/SQLXMLInvocationStrategy.java0000644000175000017500000000354111216575543025104 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * Invocation strategy for creating SQLXML proxies. * @author Paul Ferraro * * @param * @param

*/ public class SQLXMLInvocationStrategy extends DatabaseWriteInvocationStrategy { private P parent; /** * @param cluster * @param parent the object that created sql xml objects */ public SQLXMLInvocationStrategy(DatabaseCluster cluster, P parent) { super(cluster.getNonTransactionalExecutor()); this.parent = parent; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public java.sql.SQLXML invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(java.sql.SQLXML.class, new SQLXMLInvocationHandler(this.parent, proxy, invoker, this.invokeAll(proxy, invoker))); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/ClobInvocationStrategy.java0000644000175000017500000000355211216575521024741 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Clob; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * @param * @param

*/ public class ClobInvocationStrategy extends DatabaseWriteInvocationStrategy { private P parent; private Class clobClass; /** * @param cluster * @param parent * @param clobClass */ public ClobInvocationStrategy(DatabaseCluster cluster, P parent, Class clobClass) { super(cluster.getNonTransactionalExecutor()); this.parent = parent; this.clobClass = clobClass; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public Clob invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(this.clobClass, new ClobInvocationHandler(this.parent, proxy, invoker, this.invokeAll(proxy, invoker))); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/FileSupportImpl.java0000644000175000017500000001105011151703042023360 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.Writer; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.sql.SQLException; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import net.sf.hajdbc.util.SQLExceptionFactory; /** * @author Paul Ferraro * @since 1.0 */ public class FileSupportImpl implements FileSupport { private static final String TEMP_FILE_PREFIX = "ha-jdbc-"; //$NON-NLS-1$ private static final String TEMP_FILE_SUFFIX = ".lob"; //$NON-NLS-1$ private static final int BUFFER_SIZE = 8192; private List fileList = new LinkedList(); /** * @see net.sf.hajdbc.sql.FileSupport#createFile(java.io.InputStream) */ @Override public File createFile(InputStream inputStream) throws SQLException { File file = this.createTempFile(); try { FileChannel fileChannel = new FileOutputStream(file).getChannel(); ReadableByteChannel inputChannel = Channels.newChannel(inputStream); ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); while (inputChannel.read(buffer) > 0) { buffer.flip(); fileChannel.write(buffer); buffer.compact(); } fileChannel.close(); return file; } catch (IOException e) { throw SQLExceptionFactory.createSQLException(e); } } /** * @see net.sf.hajdbc.sql.FileSupport#createFile(java.io.Reader) */ @Override public File createFile(Reader reader) throws SQLException { File file = this.createTempFile(); try { Writer writer = new FileWriter(file); CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE); while (reader.read(buffer) > 0) { buffer.flip(); writer.append(buffer); buffer.clear(); } writer.close(); return file; } catch (IOException e) { throw SQLExceptionFactory.createSQLException(e); } } /** * @see net.sf.hajdbc.sql.FileSupport#getReader(java.io.File) */ @Override public Reader getReader(File file) throws SQLException { try { return new BufferedReader(new FileReader(file), BUFFER_SIZE); } catch (IOException e) { throw SQLExceptionFactory.createSQLException(e); } } /** * @see net.sf.hajdbc.sql.FileSupport#getInputStream(java.io.File) */ @Override public InputStream getInputStream(File file) throws SQLException { try { return Channels.newInputStream(new FileInputStream(file).getChannel()); } catch (IOException e) { throw SQLExceptionFactory.createSQLException(e); } } /** * Creates a temp file and stores a reference to it so that it can be deleted later. * @return a temp file * @throws SQLException if an IO error occurs */ private File createTempFile() throws SQLException { try { File file = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX); this.fileList.add(file); return file; } catch (IOException e) { throw SQLExceptionFactory.createSQLException(e); } } /** * @see net.sf.hajdbc.sql.FileSupport#close() */ @Override public void close() { Iterator files = this.fileList.iterator(); while (files.hasNext()) { File file = files.next(); if (!file.delete()) { file.deleteOnExit(); } files.remove(); } } /** * @see java.lang.Object#finalize() */ @Override protected void finalize() throws Throwable { this.close(); super.finalize(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/AbstractDatabase.java0000644000175000017500000001177411205604266023477 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.util.Properties; import net.sf.hajdbc.Database; /** * @author Paul Ferraro * @param either java.sql.Driver or javax.sql.DataSource * @since 1.0 */ public abstract class AbstractDatabase implements Database { private String id; private String user; private String password; private Properties properties = new Properties(); private int weight = 1; private boolean dirty = false; private boolean local = false; /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getId() */ @Override public String getId() { return this.id; } /** * @param id */ public void setId(String id) { this.checkDirty(this.id, id); this.id = id; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getUser() */ @Override public String getUser() { return this.user; } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setUser(java.lang.String) */ @Override public void setUser(String user) { this.checkDirty(this.user, user); this.user = user; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getPassword() */ @Override public String getPassword() { return this.password; } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setPassword(java.lang.String) */ @Override public void setPassword(String password) { this.checkDirty(this.password, password); this.password = password; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getWeight() */ @Override public int getWeight() { return this.weight; } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setWeight(int) */ @Override public void setWeight(int weight) { if (weight < 0) { throw new IllegalArgumentException(); } this.checkDirty(this.weight, weight); this.weight = weight; } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return this.id.hashCode(); } /** * @see java.lang.Object#equals(java.lang.Object) */ @SuppressWarnings("unchecked") @Override public boolean equals(Object object) { if ((object == null) || !(object instanceof Database)) return false; String id = ((Database) object).getId(); return (id != null) && id.equals(this.id); } /** * @see java.lang.Object#toString() */ @Override public String toString() { return this.id; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#getProperties() */ @Override public Properties getProperties() { return this.properties; } /** * @param properties */ public void setProperties(Properties properties) { this.checkDirty(this.properties, properties); this.properties = properties; } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#removeProperty(java.lang.String) */ @Override public void removeProperty(String name) { this.dirty |= this.properties.containsKey(name); this.properties.remove(name); } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setProperty(java.lang.String, java.lang.String) */ @Override public void setProperty(String name, String value) { if ((name == null) || (value == null)) { throw new IllegalArgumentException(); } this.checkDirty(this.properties.getProperty(name), value); this.properties.setProperty(name, value); } /** * @see net.sf.hajdbc.InactiveDatabaseMBean#setLocal(boolean) */ @Override public void setLocal(boolean local) { this.checkDirty(this.local, local); this.local = local; } /** * @see net.sf.hajdbc.ActiveDatabaseMBean#isLocal() */ @Override public boolean isLocal() { return this.local; } /** * @see net.sf.hajdbc.Database#clean() */ @Override public void clean() { this.dirty = false; } /** * @see net.sf.hajdbc.Database#isDirty() */ @Override public boolean isDirty() { return this.dirty; } /** * Set the dirty flag if the new value differs from the old value. * @param oldValue * @param newValue */ protected void checkDirty(Object oldValue, Object newValue) { this.dirty |= ((oldValue != null) && (newValue != null)) ? !oldValue.equals(newValue) : (oldValue != newValue); } /** * @see java.lang.Comparable#compareTo(Object) */ @Override public int compareTo(Database database) { return this.id.compareTo(database.getId()); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/TransactionContext.java0000644000175000017500000000374611151703042024131 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.SQLException; /** * Decorates and invocation strategy with transaction boundary logic. * @author Paul Ferraro * @param DataSource or Driver */ public interface TransactionContext { /** * Decorates the specified invocation strategy with start transaction logic. * @param Target object type of the invocation * @param Return type of this invocation * @param strategy * @param connection * @return the decorated invocation strategy * @throws SQLException */ public InvocationStrategy start(InvocationStrategy strategy, Connection connection) throws SQLException; /** * Decorates the specified invocation strategy with end transaction logic. * @param Target object type of the invocation * @param Return type of this invocation * @param strategy * @return the decorated invocation strategy * @throws SQLException */ public InvocationStrategy end(InvocationStrategy strategy) throws SQLException; /** * Closes this transaction context. */ public void close(); }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DatabaseMetaDataInvocationStrategy.java0000644000175000017500000000314211151703042027147 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.DatabaseMetaData; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * */ public class DatabaseMetaDataInvocationStrategy extends DatabaseReadInvocationStrategy { private final Connection connection; public DatabaseMetaDataInvocationStrategy(Connection connection) { this.connection = connection; } @Override public DatabaseMetaData invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(DatabaseMetaData.class, new DatabaseMetaDataInvocationHandler(this.connection, proxy, invoker, this.invokeAll(proxy, invoker))); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/PreparedStatementInvocationHandler.java0000644000175000017500000000407311217246560027262 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Map; import java.util.Set; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * @param */ public class PreparedStatementInvocationHandler extends AbstractPreparedStatementInvocationHandler { private static final Set setMethodSet = Methods.findMethods(PreparedStatement.class, "set\\w+"); /** * @param connection * @param proxy * @param invoker * @param statementMap * @param transactionContext * @param fileSupport * @param sql * @throws Exception */ public PreparedStatementInvocationHandler(Connection connection, SQLProxy proxy, Invoker invoker, Map, PreparedStatement> statementMap, TransactionContext transactionContext, FileSupport fileSupport, String sql) throws Exception { super(connection, proxy, invoker, PreparedStatement.class, statementMap, transactionContext, fileSupport, setMethodSet); this.lockList = this.extractLocks(sql); this.selectForUpdate = this.isSelectForUpdate(sql); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DataSourceFactory.java0000644000175000017500000000335311151703042023653 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.InvocationHandler; import java.sql.SQLException; import javax.sql.DataSource; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseClusterFactory; /** * @author Paul Ferraro */ public class DataSourceFactory extends CommonDataSourceObjectFactory { /** * Constructs a new factory for creating a DataSource. */ public DataSourceFactory() { super(javax.sql.DataSource.class); } @Override protected DatabaseCluster getDatabaseCluster(String id, String config) throws SQLException { return DatabaseClusterFactory.getDatabaseCluster(id, DataSourceDatabaseCluster.class, DataSourceDatabaseClusterMBean.class, config); } @Override protected InvocationHandler getInvocationHandler(DatabaseCluster cluster) { return new DataSourceInvocationHandler(cluster); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/SQLXMLInvocationHandler.java0000644000175000017500000000336011216553127024650 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.util.Map; import java.util.Set; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; /** * Invocation handler for SQLXML objects. * @author Paul Ferraro * * @param * @param

*/ public class SQLXMLInvocationHandler extends LocatorInvocationHandler { private static final Set DATABASE_READ_METHOD_SET = Methods.findMethods(java.sql.SQLXML.class, "getBinaryStream", "getCharacterStream", "getSource", "getString"); public SQLXMLInvocationHandler(P object, SQLProxy proxy, Invoker invoker, Map, java.sql.SQLXML> objectMap) throws Exception { super(object, proxy, invoker, java.sql.SQLXML.class, objectMap); } @Override protected Set getDatabaseReadMethodSet() { return DATABASE_READ_METHOD_SET; } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DatabaseMetaDataInvocationHandler.java0000644000175000017500000000610011151703042026717 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Map; import java.util.Set; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * */ public class DatabaseMetaDataInvocationHandler extends AbstractChildInvocationHandler { private static final Set databaseReadMethodSet = Methods.findMethods(DatabaseMetaData.class, "getAttributes", "getBestRowIdentifier", "getCatalogs", "getColumnPrivileges", "getColumns", "getCrossReference", "getExportedKeys", "getFunctionColumns", "getFunctions", "getImportedKeys", "getIndexInfo", "getPrimaryKeys", "getProcedureColumns", "getProcedures", "getSchemas", "getSuperTables", "getSuperTypes", "getTablePrivileges", "getTables", "getUDTs", "getVersionColumns"); private static final Method getConnectionMethod = Methods.getMethod(DatabaseMetaData.class, "getConnection"); /** * @param parent * @param proxy * @param invoker * @param objectMap * @throws Exception */ public DatabaseMetaDataInvocationHandler(Connection parent, SQLProxy proxy, Invoker invoker, Map, DatabaseMetaData> objectMap) throws Exception { super(parent, proxy, invoker, DatabaseMetaData.class, objectMap); } @Override protected InvocationStrategy getInvocationStrategy(DatabaseMetaData object, Method method, Object[] parameters) throws Exception { if (databaseReadMethodSet.contains(method)) { return new DatabaseReadInvocationStrategy(); } if (method.equals(getConnectionMethod)) { return new InvocationStrategy() { public Connection invoke(SQLProxy proxy, Invoker invoker) throws Exception { return DatabaseMetaDataInvocationHandler.this.getParent(); } }; } return new DriverReadInvocationStrategy(); } @Override protected void close(Connection parent, DatabaseMetaData object) throws SQLException { // Nothing to close } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/BlobInvocationStrategy.java0000644000175000017500000000340611216575477024750 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Blob; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * @param * @param

*/ public class BlobInvocationStrategy extends DatabaseWriteInvocationStrategy { private P parent; /** * @param cluster * @param parent the object that created blobs */ public BlobInvocationStrategy(DatabaseCluster cluster, P parent) { super(cluster.getNonTransactionalExecutor()); this.parent = parent; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public Blob invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(Blob.class, new BlobInvocationHandler(this.parent, proxy, invoker, this.invokeAll(proxy, invoker))); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/ClobInvocationHandler.java0000644000175000017500000000361511216553017024510 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.sql.Clob; import java.util.Map; import java.util.Set; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * @param * @param

*/ @SuppressWarnings("nls") public class ClobInvocationHandler extends LocatorInvocationHandler { private static final Set DATABASE_READ_METHOD_SET = Methods.findMethods(Clob.class, "getAsciiStream", "getCharacterStream", "getSubString", "length", "position"); /** * @param object * @param proxy * @param invoker * @param objectMap * @throws Exception */ protected ClobInvocationHandler(P object, SQLProxy proxy, Invoker invoker, Map, Clob> objectMap) throws Exception { super(object, proxy, invoker, Clob.class, objectMap); } /** * @see net.sf.hajdbc.sql.LocatorInvocationHandler#getDatabaseReadMethodSet() */ @Override protected Set getDatabaseReadMethodSet() { return DATABASE_READ_METHOD_SET; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/ResultSetInvocationHandler.java0000644000175000017500000003172511217243620025563 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Blob; import java.sql.Clob; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import javax.sql.rowset.serial.SerialBlob; import javax.sql.rowset.serial.SerialClob; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; import net.sf.hajdbc.util.reflect.ProxyFactory; import net.sf.hajdbc.util.reflect.SimpleInvocationHandler; /** * @author Paul Ferraro * @param * @param */ @SuppressWarnings("nls") public class ResultSetInvocationHandler extends AbstractChildInvocationHandler { private static final Set driverReadMethodSet = Methods.findMethods(ResultSet.class, "findColumn", "getConcurrency", "getCursorName", "getFetchDirection", "getFetchSize", "getHoldability", "getMetaData", "getRow", "getType", "getWarnings", "isAfterLast", "isBeforeFirst", "isClosed", "isFirst", "isLast", "row(Deleted|Inserted|Updated)", "wasNull"); private static final Set driverWriteMethodSet = Methods.findMethods(ResultSet.class, "clearWarnings", "setFetchDirection", "setFetchSize"); private static final Set absoluteNavigationMethodSet = Methods.findMethods(ResultSet.class, "absolute", "afterLast", "beforeFirst", "first", "last"); private static final Set relativeNavigationMethodSet = Methods.findMethods(ResultSet.class, "moveTo(Current|Insert)Row", "next", "previous", "relative"); private static final Set transactionalWriteMethodSet = Methods.findMethods(ResultSet.class, "(delete|insert|update)Row"); private static final Method closeMethod = Methods.getMethod(ResultSet.class, "close"); private static final Method cancelRowUpdatesMethod = Methods.getMethod(ResultSet.class, "cancelRowUpdates"); private static final Method getStatementMethod = Methods.getMethod(ResultSet.class, "getStatement"); private static final Set getBlobMethodSet = Methods.findMethods(ResultSet.class, "getBlob"); private static final Set getClobMethodSet = Methods.findMethods(ResultSet.class, "getClob", "getNClob"); protected FileSupport fileSupport; private TransactionContext transactionContext; private List> updateInvokerList = new LinkedList>(); private Invoker absoluteNavigationInvoker = null; private List> relativeNavigationInvokerList = new LinkedList>(); /** * @param statement the statement that created this result set * @param proxy the invocation handler of the statement that created this result set * @param invoker the invoker that was used to create this result set * @param resultSetMap a map of database to underlying result set * @param transactionContext * @param fileSupport support for streams * @throws Exception */ protected ResultSetInvocationHandler(S statement, SQLProxy proxy, Invoker invoker, Map, ResultSet> resultSetMap, TransactionContext transactionContext, FileSupport fileSupport) throws Exception { super(statement, proxy, invoker, ResultSet.class, resultSetMap); this.transactionContext = transactionContext; this.fileSupport = fileSupport; } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(ResultSet resultSet, Method method, Object[] parameters) throws Exception { if (driverReadMethodSet.contains(method)) { return new DriverReadInvocationStrategy(); } if (driverWriteMethodSet.contains(method) || absoluteNavigationMethodSet.contains(method) || relativeNavigationMethodSet.contains(method) || method.equals(closeMethod) || method.equals(cancelRowUpdatesMethod)) { return new DriverWriteInvocationStrategy(); } if (transactionalWriteMethodSet.contains(method)) { return this.transactionContext.start(new DatabaseWriteInvocationStrategy(this.cluster.getTransactionalExecutor()), this.getParent().getConnection()); } if (method.equals(getStatementMethod)) { return new InvocationStrategy() { public S invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ResultSetInvocationHandler.this.getParent(); } }; } if (getBlobMethodSet.contains(method)) { return new BlobInvocationStrategy(this.cluster, resultSet); } if (getClobMethodSet.contains(method)) { return new ClobInvocationStrategy(this.cluster, resultSet, method.getReturnType().asSubclass(Clob.class)); } if (this.isGetMethod(method)) { return new DriverReadInvocationStrategy(); } if (this.isUpdateMethod(method)) { return new DriverWriteInvocationStrategy(); } return super.getInvocationStrategy(resultSet, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvoker(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @SuppressWarnings("unchecked") @Override protected Invoker getInvoker(ResultSet object, final Method method, final Object[] parameters) throws Exception { Class[] types = method.getParameterTypes(); if (this.isUpdateMethod(method) && (parameters.length > 1) && (parameters[1] != null)) { Class type = types[1]; if (type.equals(InputStream.class)) { final File file = this.fileSupport.createFile((InputStream) parameters[1]); return new Invoker() { public Object invoke(Database database, ResultSet resultSet) throws SQLException { List parameterList = new ArrayList(Arrays.asList(parameters)); parameterList.set(1, ResultSetInvocationHandler.this.fileSupport.getInputStream(file)); return Methods.invoke(method, resultSet, parameterList.toArray()); } }; } if (type.equals(Reader.class)) { final File file = this.fileSupport.createFile((Reader) parameters[1]); return new Invoker() { public Object invoke(Database database, ResultSet resultSet) throws SQLException { List parameterList = new ArrayList(Arrays.asList(parameters)); parameterList.set(1, ResultSetInvocationHandler.this.fileSupport.getReader(file)); return Methods.invoke(method, resultSet, parameterList.toArray()); } }; } if (type.equals(Blob.class)) { Blob blob = (Blob) parameters[1]; if (Proxy.isProxyClass(blob.getClass())) { InvocationHandler handler = Proxy.getInvocationHandler(blob); if (SQLProxy.class.isInstance(handler)) { final SQLProxy proxy = (SQLProxy) handler; return new Invoker() { public Object invoke(Database database, ResultSet resultSet) throws SQLException { List parameterList = new ArrayList(Arrays.asList(parameters)); parameterList.set(1, proxy.getObject(database)); return Methods.invoke(method, resultSet, parameterList.toArray()); } }; } } parameters[1] = new SerialBlob(blob); } // Handle both clob and nclob if (Clob.class.isAssignableFrom(type)) { Clob clob = (Clob) parameters[1]; if (Proxy.isProxyClass(clob.getClass())) { InvocationHandler handler = Proxy.getInvocationHandler(clob); if (SQLProxy.class.isInstance(handler)) { final SQLProxy proxy = (SQLProxy) handler; return new Invoker() { public Object invoke(Database database, ResultSet resultSet) throws SQLException { List parameterList = new ArrayList(Arrays.asList(parameters)); parameterList.set(1, proxy.getObject(database)); return Methods.invoke(method, resultSet, parameterList.toArray()); } }; } } Clob serialClob = new SerialClob(clob); parameters[1] = type.equals(Clob.class) ? serialClob : ProxyFactory.createProxy(type, new SimpleInvocationHandler(serialClob)); } } return super.getInvoker(object, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#postInvoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected void postInvoke(ResultSet object, Method method, Object[] parameters) { if (method.equals(closeMethod)) { this.getParentProxy().removeChild(this); } } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#handleFailures(java.util.SortedMap) */ @Override public SortedMap, R> handlePartialFailure(SortedMap, R> resultMap, SortedMap, Exception> exceptionMap) throws Exception { return this.getParentProxy().handlePartialFailure(resultMap, exceptionMap); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#close(java.lang.Object, java.lang.Object) */ @Override protected void close(S statement, ResultSet resultSet) throws SQLException { resultSet.close(); } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#record(net.sf.hajdbc.sql.Invoker, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected void record(Invoker invoker, Method method, Object[] parameters) { if (this.isUpdateMethod(method)) { synchronized (this.updateInvokerList) { this.updateInvokerList.add(invoker); } } else if (transactionalWriteMethodSet.contains(method) || method.equals(cancelRowUpdatesMethod)) { synchronized (this.updateInvokerList) { this.updateInvokerList.clear(); } } else if (absoluteNavigationMethodSet.contains(method)) { synchronized (this.relativeNavigationInvokerList) { this.absoluteNavigationInvoker = invoker; this.relativeNavigationInvokerList.clear(); } } else if (relativeNavigationMethodSet.contains(method)) { synchronized (this.relativeNavigationInvokerList) { this.relativeNavigationInvokerList.add(invoker); } } else { super.record(invoker, method, parameters); } } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#isRecordable(java.lang.reflect.Method) */ @Override protected boolean isRecordable(Method method) { return driverWriteMethodSet.contains(method); } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#replay(net.sf.hajdbc.Database, java.lang.Object) */ @Override protected void replay(Database database, ResultSet resultSet) throws Exception { super.replay(database, resultSet); synchronized (this.relativeNavigationInvokerList) { if (this.absoluteNavigationInvoker != null) { this.absoluteNavigationInvoker.invoke(database, resultSet); } for (Invoker invoker: this.relativeNavigationInvokerList) { invoker.invoke(database, resultSet); } } synchronized (this.updateInvokerList) { for (Invoker invoker: this.updateInvokerList) { invoker.invoke(database, resultSet); } } } private boolean isGetMethod(Method method) { Class[] types = method.getParameterTypes(); return method.getName().startsWith("get") && (types != null) && (types.length > 0) && (types[0].equals(String.class) || types[0].equals(Integer.TYPE)); } private boolean isUpdateMethod(Method method) { Class[] types = method.getParameterTypes(); return method.getName().startsWith("update") && (types != null) && (types.length > 0) && (types[0].equals(String.class) || types[0].equals(Integer.TYPE)); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/FileSupport.java0000644000175000017500000000437011151703042022545 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.sql.SQLException; /** * Provides temp file support for serializing data for streams. * Any files created by this object are deleted when {@link #close()} is called. * * @author Paul Ferraro * @version $Revision: 1612 $ * @since 1.0 */ public interface FileSupport { /** * Create a file from the specified binary input stream. * @param inputStream a binary stream of data * @return a temporary file * @throws SQLException if an IO error occurs */ public File createFile(InputStream inputStream) throws SQLException; /** * Create a file from the specified character input stream * @param reader a character stream of data * @return a temporary file * @throws SQLException if an IO error occurs */ public File createFile(Reader reader) throws SQLException; /** * Returns a reader for the specified file. * @param file a temp file * @return a reader * @throws SQLException if IO error occurs */ public Reader getReader(File file) throws SQLException; /** * Returns an input stream for the specified file. * @param file a temp file * @return an input stream * @throws SQLException if IO error occurs */ public InputStream getInputStream(File file) throws SQLException; /** * Deletes any files created by this object. */ public void close(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/TransactionMode.java0000644000175000017500000000353711151703042023367 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.util.concurrent.ExecutorService; import net.sf.hajdbc.util.Enums; import net.sf.hajdbc.util.concurrent.SynchronousExecutor; /** * @author Paul Ferraro * */ public enum TransactionMode { PARALLEL(null), SERIAL(new SynchronousExecutor()); private final ExecutorService executor; private TransactionMode(ExecutorService executor) { this.executor = executor; } /** * Used by JiBX to unmarshal a transaction mode * @param value transaction mode * @return transaction mode enum */ public static TransactionMode deserialize(String value) { return Enums.valueOf(TransactionMode.class, value); } /** * Used by JiBX to marshal a transaction mode * @param mode transaction mode enum * @return transaction mode */ public static String serialize(TransactionMode mode) { return Enums.id(mode); } public ExecutorService getTransactionExecutor(ExecutorService executor) { return (this.executor != null) ? this.executor : executor; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/ConnectionInvocationHandler.java0000644000175000017500000002142211217247506025730 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Clob; import java.sql.Connection; import java.sql.SQLException; import java.sql.Savepoint; import java.util.Map; import java.util.Set; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * @param * @param

*/ @SuppressWarnings("nls") public class ConnectionInvocationHandler extends AbstractChildInvocationHandler { private static final Set driverReadMethodSet = Methods.findMethods(Connection.class, "create(ArrayOf|Blob|Clob|NClob|SQLXML|Struct)", "getAutoCommit", "getCatalog", "getClientInfo", "getHoldability", "getTypeMap", "getWarnings", "isClosed", "isReadOnly", "nativeSQL"); private static final Set databaseReadMethodSet = Methods.findMethods(Connection.class, "getTransactionIsolation", "isValid"); private static final Set driverWriteMethodSet = Methods.findMethods(Connection.class, "clearWarnings", "setAutoCommit", "setClientInfo", "setHoldability", "setTypeMap"); private static final Set endTransactionMethodSet = Methods.findMethods(Connection.class, "commit", "rollback"); private static final Set createStatementMethodSet = Methods.findMethods(Connection.class, "createStatement"); private static final Set prepareStatementMethodSet = Methods.findMethods(Connection.class, "prepareStatement"); private static final Set prepareCallMethodSet = Methods.findMethods(Connection.class, "prepareCall"); private static final Set setSavepointMethodSet = Methods.findMethods(Connection.class, "setSavepoint"); private static final Set createClobMethodSet = Methods.findMethods(Connection.class, "createN?Clob"); private static final Method getMetaDataMethod = Methods.getMethod(Connection.class, "getMetaData"); private static final Method releaseSavepointMethod = Methods.getMethod(Connection.class, "releaseSavepoint", Savepoint.class); private static final Method rollbackSavepointMethod = Methods.getMethod(Connection.class, "rollback", Savepoint.class); private static final Method closeMethod = Methods.getMethod(Connection.class, "close"); private static final Method createArrayOfMethod = Methods.findMethod(Connection.class, "createArrayOf"); private static final Method createBlobMethod = Methods.findMethod(Connection.class, "createBlob"); private static final Method createSQLXMLMethod = Methods.findMethod(Connection.class, "createSQLXML"); private TransactionContext transactionContext; /** * @param proxy * @param handler * @param invoker * @param connectionMap * @param transactionContext * @throws Exception */ public ConnectionInvocationHandler(P proxy, SQLProxy handler, Invoker invoker, Map, Connection> connectionMap, TransactionContext transactionContext) throws Exception { super(proxy, handler, invoker, Connection.class, connectionMap); this.transactionContext = transactionContext; } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(Connection connection, Method method, Object[] parameters) throws Exception { if (driverReadMethodSet.contains(method)) { return new DriverReadInvocationStrategy(); } if (databaseReadMethodSet.contains(method)) { return new DatabaseReadInvocationStrategy(); } if (driverWriteMethodSet.contains(method) || method.equals(closeMethod)) { return new DriverWriteInvocationStrategy(); } if (endTransactionMethodSet.contains(method)) { return this.transactionContext.end(new DatabaseWriteInvocationStrategy(this.cluster.getTransactionalExecutor())); } if (method.equals(rollbackSavepointMethod) || method.equals(releaseSavepointMethod)) { return new DatabaseWriteInvocationStrategy(this.cluster.getTransactionalExecutor()); } if (createStatementMethodSet.contains(method)) { return new StatementInvocationStrategy(connection, this.transactionContext); } if (prepareStatementMethodSet.contains(method)) { return new PreparedStatementInvocationStrategy(this.cluster, connection, this.transactionContext, (String) parameters[0]); } if (prepareCallMethodSet.contains(method)) { return new CallableStatementInvocationStrategy(this.cluster, connection, this.transactionContext); } if (setSavepointMethodSet.contains(method)) { return new SavepointInvocationStrategy(this.cluster, connection); } if (method.equals(getMetaDataMethod)) { return new DatabaseMetaDataInvocationStrategy(connection); } if ((createBlobMethod != null) && method.equals(createBlobMethod)) { return new BlobInvocationStrategy(this.cluster, connection); } if (createClobMethodSet.contains(method)) { return new ClobInvocationStrategy(this.cluster, connection, method.getReturnType().asSubclass(Clob.class)); } if ((createArrayOfMethod != null) && method.equals(createArrayOfMethod)) { return new ArrayInvocationStrategy(this.cluster, connection); } if ((createSQLXMLMethod != null) && method.equals(createSQLXMLMethod)) { return new SQLXMLInvocationStrategy(this.cluster, connection); } return super.getInvocationStrategy(connection, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvoker(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @SuppressWarnings("unchecked") @Override protected Invoker getInvoker(Connection connection, Method method, Object[] parameters) throws Exception { if (method.equals(releaseSavepointMethod)) { final SQLProxy proxy = (SQLProxy) Proxy.getInvocationHandler(parameters[0]); return new Invoker() { public Void invoke(Database database, Connection connection) throws SQLException { connection.releaseSavepoint(proxy.getObject(database)); return null; } }; } if (method.equals(rollbackSavepointMethod)) { final SQLProxy proxy = (SQLProxy) Proxy.getInvocationHandler(parameters[0]); return new Invoker() { public Void invoke(Database database, Connection connection) throws SQLException { connection.rollback(proxy.getObject(database)); return null; } }; } return super.getInvoker(connection, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#isSQLMethod(java.lang.reflect.Method) */ @Override protected boolean isSQLMethod(Method method) { return prepareStatementMethodSet.contains(method); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#postInvoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @SuppressWarnings("unchecked") @Override protected void postInvoke(Connection object, Method method, Object[] parameters) { if (method.equals(closeMethod)) { this.transactionContext.close(); this.getParentProxy().removeChild(this); } else if (method.equals(releaseSavepointMethod)) { SQLProxy proxy = (SQLProxy) Proxy.getInvocationHandler(parameters[0]); this.removeChild(proxy); } } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#close(java.lang.Object, java.lang.Object) */ @Override protected void close(P parent, Connection connection) throws SQLException { connection.close(); } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#isRecordable(java.lang.reflect.Method) */ @Override protected boolean isRecordable(Method method) { return driverWriteMethodSet.contains(method); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/ArrayInvocationStrategy.java0000644000175000017500000000344011217567565025146 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2009 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Array; import java.sql.SQLException; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * */ public class ArrayInvocationStrategy extends DatabaseWriteInvocationStrategy { private P parent; /** * @param cluster * @param parent * @throws SQLException */ public ArrayInvocationStrategy(DatabaseCluster cluster, P parent) throws SQLException { super(cluster.getNonTransactionalExecutor()); this.parent = parent; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public Array invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(Array.class, new ArrayInvocationHandler(this.parent, proxy, invoker, this.invokeAll(proxy, invoker))); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CommonDataSourceDatabaseClusterMBean.java0000644000175000017500000000305111151703042027361 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseClusterMBean; /** * @author Paul Ferraro * @param */ public interface CommonDataSourceDatabaseClusterMBean extends DatabaseClusterMBean, DatabaseCluster { /** * Adds a new DataSource to this cluster using the specified identifier and JNDI name. * @param databaseId a database identifier * @param name the JNDI name use to lookup the DataSource * @throws IllegalArgumentException if this database already exists, or no DataSource was found using the specified name. * @throws IllegalStateException if mbean registration fails. */ public void add(String databaseId, String name); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/AbstractStatementInvocationHandler.java0000644000175000017500000003127311215615145027262 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeSet; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.Messages; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.util.SQLExceptionFactory; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * @param * @param */ @SuppressWarnings("nls") public abstract class AbstractStatementInvocationHandler extends AbstractChildInvocationHandler { private static final Set driverReadMethodSet = Methods.findMethods(Statement.class, "getFetchDirection", "getFetchSize", "getGeneratedKeys", "getMaxFieldSize", "getMaxRows", "getQueryTimeout", "getResultSetConcurrency", "getResultSetHoldability", "getResultSetType", "getUpdateCount", "getWarnings", "isClosed", "isPoolable"); private static final Set driverWriteMethodSet = Methods.findMethods(Statement.class, "clearWarnings", "setCursorName", "setEscapeProcessing", "setFetchDirection", "setFetchSize", "setMaxFieldSize", "setMaxRows", "setPoolable", "setQueryTimeout"); private static final Set executeMethodSet = Methods.findMethods(Statement.class, "execute(Update)?"); private static final Method getConnectionMethod = Methods.getMethod(Statement.class, "getConnection"); private static final Method executeQueryMethod = Methods.getMethod(Statement.class, "executeQuery", String.class); private static final Method clearBatchMethod = Methods.getMethod(Statement.class, "clearBatch"); private static final Method executeBatchMethod = Methods.getMethod(Statement.class, "executeBatch"); private static final Method getMoreResultsMethod = Methods.getMethod(Statement.class, "getMoreResults", Integer.TYPE); private static final Method getResultSetMethod = Methods.getMethod(Statement.class, "getResultSet"); private static final Method addBatchMethod = Methods.getMethod(Statement.class, "addBatch", String.class); private static final Method closeMethod = Methods.getMethod(Statement.class, "close"); protected TransactionContext transactionContext; protected FileSupport fileSupport; private List> invokerList = new LinkedList>(); private List sqlList = new LinkedList(); /** * @param connection the parent connection of this statement * @param proxy the parent invocation handler * @param invoker the invoker that created this statement * @param statementClass * @param statementMap a map of database to underlying statement * @param transactionContext * @param fileSupport support object for streams * @throws Exception */ protected AbstractStatementInvocationHandler(Connection connection, SQLProxy proxy, Invoker invoker, Class statementClass, Map, S> statementMap, TransactionContext transactionContext, FileSupport fileSupport) throws Exception { super(connection, proxy, invoker, statementClass, statementMap); this.transactionContext = transactionContext; this.fileSupport = fileSupport; } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(S statement, Method method, Object[] parameters) throws Exception { if (driverReadMethodSet.contains(method)) { return new DriverReadInvocationStrategy(); } if (driverWriteMethodSet.contains(method) || method.equals(closeMethod) || method.equals(addBatchMethod) || method.equals(clearBatchMethod)) { return new DriverWriteInvocationStrategy(); } if (executeMethodSet.contains(method)) { List lockList = this.extractLocks((String) parameters[0]); return this.transactionContext.start(new LockingInvocationStrategy(new DatabaseWriteInvocationStrategy(this.cluster.getTransactionalExecutor()), lockList), this.getParent()); } if (method.equals(getConnectionMethod)) { return new InvocationStrategy() { public Connection invoke(SQLProxy proxy, Invoker invoker) throws Exception { return AbstractStatementInvocationHandler.this.getParent(); } }; } if (method.equals(executeQueryMethod)) { String sql = (String) parameters[0]; List lockList = this.extractLocks(sql); int concurrency = statement.getResultSetConcurrency(); boolean selectForUpdate = this.isSelectForUpdate(sql); if (lockList.isEmpty() && (concurrency == ResultSet.CONCUR_READ_ONLY) && !selectForUpdate) { return new LazyResultSetInvocationStrategy(statement, this.transactionContext, this.fileSupport); } InvocationStrategy strategy = new LockingInvocationStrategy(new EagerResultSetInvocationStrategy(this.cluster, statement, this.transactionContext, this.fileSupport), lockList); return selectForUpdate ? this.transactionContext.start(strategy, this.getParent()) : strategy; } if (method.equals(executeBatchMethod)) { List lockList = this.extractLocks(this.sqlList); return this.transactionContext.start(new LockingInvocationStrategy(new DatabaseWriteInvocationStrategy(this.cluster.getTransactionalExecutor()), lockList), this.getParent()); } if (method.equals(getMoreResultsMethod)) { if (parameters[0].equals(Statement.KEEP_CURRENT_RESULT)) { return new DriverWriteInvocationStrategy(); } } if (method.equals(getResultSetMethod)) { if (statement.getResultSetConcurrency() == ResultSet.CONCUR_READ_ONLY) { return new LazyResultSetInvocationStrategy(statement, this.transactionContext, this.fileSupport); } return new EagerResultSetInvocationStrategy(this.cluster, statement, this.transactionContext, this.fileSupport); } return super.getInvocationStrategy(statement, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#isSQLMethod(java.lang.reflect.Method) */ @Override protected boolean isSQLMethod(Method method) { return method.equals(addBatchMethod) || method.equals(executeQueryMethod) || executeMethodSet.contains(method); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#postInvoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected void postInvoke(S statement, Method method, Object[] parameters) { if (method.equals(addBatchMethod)) { this.sqlList.add((String) parameters[0]); } else if (method.equals(closeMethod)) { this.fileSupport.close(); this.getParentProxy().removeChild(this); } else if (method.equals(clearBatchMethod) || method.equals(executeBatchMethod)) { this.sqlList.clear(); } } /** * @see net.sf.hajdbc.sql.SQLProxy#handlePartialFailure(java.util.SortedMap, java.util.SortedMap) */ @Override public SortedMap, R> handlePartialFailure(SortedMap, R> resultMap, SortedMap, Exception> exceptionMap) throws Exception { if (this.getParent().getAutoCommit()) { return super.handlePartialFailure(resultMap, exceptionMap); } // If auto-commit is off, throw exception to give client the opportunity to rollback the transaction Map>> aliveMap = this.cluster.getAliveMap(exceptionMap.keySet()); List> aliveList = aliveMap.get(true); int size = aliveList.size(); // Assume successful databases are alive aliveList.addAll(resultMap.keySet()); this.detectClusterPanic(aliveMap); List> deadList = aliveMap.get(false); for (Database database: deadList) { if (this.cluster.deactivate(database, this.cluster.getStateManager())) { this.logger.error(Messages.getMessage(Messages.DATABASE_DEACTIVATED, database, this.cluster), exceptionMap.get(database)); } } // If failed databases are all dead if (size == 0) { return resultMap; } // Chain exceptions from alive databases SQLException exception = SQLExceptionFactory.createSQLException(exceptionMap.get(aliveList.get(0))); for (Database database: aliveList.subList(1, size)) { exception.setNextException(SQLExceptionFactory.createSQLException(exceptionMap.get(database))); } throw exception; } protected boolean isSelectForUpdate(String sql) throws SQLException { return this.getDatabaseProperties().supportsSelectForUpdate() ? this.cluster.getDialect().isSelectForUpdate(sql) : false; } protected List extractLocks(String sql) throws SQLException { return this.extractLocks(Collections.singletonList(sql)); } private List extractLocks(List sqlList) throws SQLException { Set identifierSet = new TreeSet(); for (String sql: sqlList) { if (this.cluster.isSequenceDetectionEnabled()) { String sequence = this.cluster.getDialect().parseSequence(sql); if (sequence != null) { identifierSet.add(sequence); } } if (this.cluster.isIdentityColumnDetectionEnabled()) { String table = this.cluster.getDialect().parseInsertTable(sql); if (table != null) { TableProperties tableProperties = this.getDatabaseProperties().findTable(table); if (!tableProperties.getIdentityColumns().isEmpty()) { identifierSet.add(tableProperties.getName()); } } } } List lockList = new ArrayList(identifierSet.size()); if (!identifierSet.isEmpty()) { LockManager lockManager = this.cluster.getLockManager(); for (String identifier: identifierSet) { lockList.add(lockManager.writeLock(identifier)); } } return lockList; } protected DatabaseProperties getDatabaseProperties() throws SQLException { return this.cluster.getDatabaseMetaDataCache().getDatabaseProperties(this.getParent()); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#close(java.lang.Object, java.lang.Object) */ @Override protected void close(Connection connection, S statement) throws SQLException { statement.close(); } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#record(net.sf.hajdbc.sql.Invoker, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected void record(Invoker invoker, Method method, Object[] parameters) { if (this.isBatchMethod(method)) { synchronized (this.invokerList) { this.invokerList.add(invoker); } } else if (this.isEndBatchMethod(method)) { synchronized (this.invokerList) { this.invokerList.clear(); } } else { super.record(invoker, method, parameters); } } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#isRecordable(java.lang.reflect.Method) */ @Override protected boolean isRecordable(Method method) { return driverWriteMethodSet.contains(method); } protected boolean isBatchMethod(Method method) { return method.equals(addBatchMethod); } protected boolean isEndBatchMethod(Method method) { return method.equals(clearBatchMethod) || method.equals(executeBatchMethod); } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#replay(net.sf.hajdbc.Database, java.lang.Object) */ @Override protected void replay(Database database, S statement) throws Exception { super.replay(database, statement); synchronized (this.invokerList) { for (Invoker invoker: this.invokerList) { invoker.invoke(database, statement); } } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/SQLProxy.java0000644000175000017500000000353011151703042021767 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.util.Map; import java.util.Set; import java.util.SortedMap; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; /** * @author Paul Ferraro * @since 2.0 */ public interface SQLProxy { public DatabaseCluster getDatabaseCluster(); public Map.Entry, T> entry(); public Set, T>> entries(); public void addChild(SQLProxy child); public void removeChild(SQLProxy child); public void removeChildren(); public SQLProxy getRoot(); public T getObject(Database database); public void retain(Set> databaseSet); public void handleFailure(Database database, Exception cause) throws Exception; public void handleFailures(SortedMap, Exception> exceptionMap) throws Exception; public SortedMap, R> handlePartialFailure(SortedMap, R> resultMap, SortedMap, Exception> exceptionMap) throws Exception; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/InactiveDataSourceDatabaseMBean.java0000644000175000017500000000217011151703042026332 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import net.sf.hajdbc.InactiveDatabaseMBean; /** * @author Paul Ferraro * @since 1.1 */ public interface InactiveDataSourceDatabaseMBean extends ActiveDataSourceDatabaseMBean, InactiveDatabaseMBean { public void setName(String name); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CallableStatementInvocationStrategy.java0000644000175000017500000000417011151703042027430 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.CallableStatement; import java.sql.Connection; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * @param */ public class CallableStatementInvocationStrategy extends DatabaseWriteInvocationStrategy { private Connection connection; private TransactionContext context; /** * @param cluster * @param connection the connection from which to create statements * @param context transaction context */ public CallableStatementInvocationStrategy(DatabaseCluster cluster, Connection connection, TransactionContext context) { super(cluster.getNonTransactionalExecutor()); this.connection = connection; this.context = context; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public CallableStatement invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(CallableStatement.class, new CallableStatementInvocationHandler(this.connection, proxy, invoker, this.invokeAll(proxy, invoker), this.context, new FileSupportImpl())); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/LazyResultSetInvocationStrategy.java0000644000175000017500000000412611151703042026637 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.ResultSet; import java.sql.Statement; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * @param * @param */ public class LazyResultSetInvocationStrategy extends DatabaseReadInvocationStrategy { private S statement; private TransactionContext transactionContext; private FileSupport fileSupport; /** * @param statement the statement from which to create result sets * @param transactionContext * @param fileSupport */ public LazyResultSetInvocationStrategy(S statement, TransactionContext transactionContext, FileSupport fileSupport) { super(); this.statement = statement; this.transactionContext = transactionContext; this.fileSupport = fileSupport; } /** * @see net.sf.hajdbc.sql.DatabaseReadInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public ResultSet invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(ResultSet.class, new ResultSetInvocationHandler(this.statement, proxy, invoker, this.invokeAll(proxy, invoker), this.transactionContext, this.fileSupport)); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DriverWriteInvocationStrategy.java0000644000175000017500000000350111151703042026307 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import net.sf.hajdbc.Database; /** * @author Paul Ferraro * */ public class DriverWriteInvocationStrategy implements InvocationStrategy { /** * @see net.sf.hajdbc.sql.InvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public R invoke(SQLProxy proxy, Invoker invoker) throws Exception { SortedMap, R> map = this.invokeAll(proxy, invoker); return map.get(map.firstKey()); } protected SortedMap, R> invokeAll(SQLProxy proxy, Invoker invoker) throws Exception { SortedMap, R> resultMap = new TreeMap, R>(); for (Map.Entry, T> entry: proxy.entries()) { Database database = entry.getKey(); resultMap.put(database, invoker.invoke(database, entry.getValue())); } return resultMap; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CommonDataSourceProxy.java0000644000175000017500000000524611210306421024535 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.SQLException; import javax.naming.Referenceable; /** * @author Paul Ferraro * @param data source class */ public abstract class CommonDataSourceProxy implements Referenceable //, javax.sql.CommonDataSource { private String cluster; private String config; private CommonDataSourceFactory factory; private D proxy; protected CommonDataSourceProxy(CommonDataSourceFactory factory) { this.factory = factory; } protected synchronized D getProxy() throws SQLException { if (this.proxy == null) { this.proxy = this.factory.createProxy(this.cluster, this.config); } return this.proxy; } /** * @see javax.sql.CommonDataSource#getLogWriter() */ /* @Override public PrintWriter getLogWriter() throws SQLException { return this.getProxy().getLogWriter(); } */ /** * @see javax.sql.CommonDataSource#getLoginTimeout() */ /* @Override public int getLoginTimeout() throws SQLException { return this.getProxy().getLoginTimeout(); } */ /** * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter) */ /* @Override public void setLogWriter(PrintWriter writer) throws SQLException { this.getProxy().setLogWriter(writer); } */ /** * @see javax.sql.CommonDataSource#setLoginTimeout(int) */ /* @Override public void setLoginTimeout(int timeout) throws SQLException { this.getProxy().setLoginTimeout(timeout); } */ /** * @return the cluster */ public String getCluster() { return this.cluster; } /** * @param cluster the cluster to set */ public void setCluster(String cluster) { this.cluster = cluster; } /** * @return the config */ public String getConfig() { return this.config; } /** * @param config the config to set */ public void setConfig(String config) { this.config = config; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DriverDatabaseClusterMBean.java0000644000175000017500000000313211151703042025411 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Driver; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseClusterMBean; /** * @author Paul Ferraro * */ public interface DriverDatabaseClusterMBean extends DatabaseClusterMBean, DatabaseCluster { /** * Adds a new database to this cluster using the specified identifier, url, and driver. * @param databaseId a database identifier * @param url a JDBC url * @param driver a JDBC driver class name * @throws IllegalArgumentException if this database already exists, if the specified driver is invalid, or if the specified url is invalid. * @throws IllegalStateException if mbean registration fails. */ public void add(String databaseId, String driver, String url); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DriverDatabase.java0000644000175000017500000001011611205604415023150 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; import javax.management.DynamicMBean; import javax.management.NotCompliantMBeanException; import javax.management.StandardMBean; import net.sf.hajdbc.Messages; /** * @author Paul Ferraro * @version $Revision: 1777 $ * @since 1.0 */ public class DriverDatabase extends AbstractDatabase implements InactiveDriverDatabaseMBean { private static final String USER = "user"; //$NON-NLS-1$ private static final String PASSWORD = "password"; //$NON-NLS-1$ private String url; private Class driverClass; /** * @see net.sf.hajdbc.sql.ActiveDriverDatabaseMBean#getUrl() */ @Override public String getUrl() { return this.url; } /** * @see net.sf.hajdbc.sql.InactiveDriverDatabaseMBean#setUrl(java.lang.String) */ @Override public void setUrl(String url) { this.getDriver(url); this.checkDirty(this.url, url); this.url = url; } /** * @see net.sf.hajdbc.sql.ActiveDriverDatabaseMBean#getDriver() */ @Override public String getDriver() { return (this.driverClass != null) ? this.driverClass.getName() : null; } /** * @see net.sf.hajdbc.sql.InactiveDriverDatabaseMBean#setDriver(java.lang.String) */ @Override public void setDriver(String driver) { try { Class driverClass = null; if ((driver != null) && (driver.length() > 0)) { driverClass = Class.forName(driver).asSubclass(Driver.class); } this.checkDirty(this.driverClass, driverClass); this.driverClass = driverClass; } catch (ClassNotFoundException e) { throw new IllegalArgumentException(e); } catch (ClassCastException e) { throw new IllegalArgumentException(e); } } /** * @see net.sf.hajdbc.Database#connect(java.lang.Object) */ @Override public Connection connect(Driver driver) throws SQLException { Properties properties = new Properties(this.getProperties()); String user = this.getUser(); if (user != null) { properties.setProperty(USER, user); } String password = this.getPassword(); if (password != null) { properties.setProperty(PASSWORD, password); } return driver.connect(this.url, properties); } /** * @see net.sf.hajdbc.Database#createConnectionFactory() */ @Override public Driver createConnectionFactory() { return this.getDriver(this.url); } private Driver getDriver(String url) { try { return DriverManager.getDriver(url); } catch (SQLException e) { throw new IllegalArgumentException(Messages.getMessage(Messages.JDBC_URL_REJECTED, url), e); } } /** * @see net.sf.hajdbc.Database#getActiveMBean() */ @Override public DynamicMBean getActiveMBean() { try { return new StandardMBean(this, ActiveDriverDatabaseMBean.class); } catch (NotCompliantMBeanException e) { throw new IllegalStateException(e); } } /** * @see net.sf.hajdbc.Database#getInactiveMBean() */ @Override public DynamicMBean getInactiveMBean() { try { return new StandardMBean(this, InactiveDriverDatabaseMBean.class); } catch (NotCompliantMBeanException e) { throw new IllegalStateException(e); } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DataSource.java0000644000175000017500000000577411151703042022334 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import javax.naming.NamingException; import javax.naming.Reference; /** * @author Paul Ferraro */ public class DataSource extends CommonDataSourceProxy implements javax.sql.DataSource { /** * Constructs a new DataSource */ public DataSource() { super(new DataSourceFactory()); } /** * @see javax.sql.DataSource#getConnection() */ @Override public Connection getConnection() throws SQLException { return this.getProxy().getConnection(); } /** * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) */ @Override public Connection getConnection(String user, String password) throws SQLException { return this.getProxy().getConnection(user, password); } /** * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ @Override public boolean isWrapperFor(Class targetClass) throws SQLException { return this.getProxy().isWrapperFor(targetClass); } /** * @see java.sql.Wrapper#unwrap(java.lang.Class) */ @Override public T unwrap(Class targetClass) throws SQLException { return this.getProxy().unwrap(targetClass); } /** * @see javax.sql.CommonDataSource#getLoginTimeout() */ @Override public int getLoginTimeout() throws SQLException { return this.getProxy().getLoginTimeout(); } /** * @see javax.sql.CommonDataSource#getLogWriter() */ @Override public PrintWriter getLogWriter() throws SQLException { return this.getProxy().getLogWriter(); } /** * @see javax.sql.CommonDataSource#setLoginTimeout(int) */ @Override public void setLoginTimeout(int timeout) throws SQLException { this.getProxy().setLoginTimeout(timeout); } /** * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter) */ @Override public void setLogWriter(PrintWriter writer) throws SQLException { this.getProxy().setLogWriter(writer); } /** * @see javax.naming.Referenceable#getReference() */ @Override public Reference getReference() throws NamingException { return new DataSourceReference(this.getCluster(), this.getConfig()); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DataSourceInvocationHandler.java0000644000175000017500000000417211151703042025653 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.util.Set; import javax.sql.DataSource; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") public class DataSourceInvocationHandler extends CommonDataSourceInvocationHandler { private static final Set getConnectionMethods = Methods.findMethods(DataSource.class, "getConnection"); /** * @param databaseCluster */ public DataSourceInvocationHandler(DatabaseCluster databaseCluster) { super(databaseCluster, DataSource.class); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(DataSource dataSource, Method method, Object[] parameters) throws Exception { if (getConnectionMethods.contains(method)) { TransactionContext context = new LocalTransactionContext(this.cluster); return new ConnectionInvocationStrategy(this.cluster, dataSource, context); } return super.getInvocationStrategy(dataSource, method, parameters); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/StatementInvocationStrategy.java0000644000175000017500000000366411151703042026017 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.Statement; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * @param */ public class StatementInvocationStrategy extends DriverWriteInvocationStrategy { private Connection connection; private TransactionContext transactionContext; /** * @param connection * @param transactionContext */ public StatementInvocationStrategy(Connection connection, TransactionContext transactionContext) { this.connection = connection; this.transactionContext = transactionContext; } /** * @see net.sf.hajdbc.sql.DriverWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public Statement invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(java.sql.Statement.class, new StatementInvocationHandler(this.connection, proxy, invoker, this.invokeAll(proxy, invoker), this.transactionContext, new FileSupportImpl())); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/Driver.java0000644000175000017500000001275011203102020021510 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseClusterFactory; import net.sf.hajdbc.Messages; import net.sf.hajdbc.util.SQLExceptionFactory; import net.sf.hajdbc.util.Strings; import net.sf.hajdbc.util.reflect.ProxyFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Paul Ferraro * @version $Revision: 2015 $ */ public final class Driver implements java.sql.Driver { private static final Pattern URL_PATTERN = Pattern.compile("jdbc:ha-jdbc:(.+)"); //$NON-NLS-1$ private static final String CONFIG = "config"; //$NON-NLS-1$ private static Logger logger = LoggerFactory.getLogger(Driver.class); static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException e) { logger.error(Messages.getMessage(Messages.DRIVER_REGISTER_FAILED, Driver.class.getName()), e); } } /** * @see java.sql.Driver#acceptsURL(java.lang.String) */ @Override public boolean acceptsURL(String url) { return (this.parse(url) != null); } /** * @see java.sql.Driver#connect(java.lang.String, java.util.Properties) */ @Override public Connection connect(String url, final Properties properties) throws SQLException { String id = this.parse(url); if (id == null) return null; DatabaseCluster cluster = this.getDatabaseCluster(id, properties); DriverInvocationHandler handler = new DriverInvocationHandler(cluster); java.sql.Driver driver = ProxyFactory.createProxy(java.sql.Driver.class, handler); Invoker invoker = new Invoker() { public Connection invoke(Database database, java.sql.Driver driver) throws SQLException { String url = ((DriverDatabase) database).getUrl(); return driver.connect(url, properties); } }; TransactionContext context = new LocalTransactionContext(cluster); try { return new ConnectionInvocationStrategy(cluster, driver, context).invoke(handler, invoker); } catch (Exception e) { throw SQLExceptionFactory.createSQLException(e); } } /** * @see java.sql.Driver#getMajorVersion() */ @Override public int getMajorVersion() { return Integer.parseInt(version()[0]); } /** * @see java.sql.Driver#getMinorVersion() */ @Override public int getMinorVersion() { return Integer.parseInt(version()[1]); } private String[] version() { return DatabaseClusterFactory.getVersion().split(Strings.DASH)[0].split(Pattern.quote(Strings.DOT)); } /** * @see java.sql.Driver#getPropertyInfo(java.lang.String, java.util.Properties) */ @Override public DriverPropertyInfo[] getPropertyInfo(String url, final Properties properties) throws SQLException { String id = this.parse(url); if (id == null) return null; DatabaseCluster cluster = this.getDatabaseCluster(id, properties); DriverInvocationHandler handler = new DriverInvocationHandler(cluster); Invoker invoker = new Invoker() { public DriverPropertyInfo[] invoke(Database database, java.sql.Driver driver) throws SQLException { String url = ((DriverDatabase) database).getUrl(); return driver.getPropertyInfo(url, properties); } }; try { return new DriverReadInvocationStrategy().invoke(handler, invoker); } catch (Exception e) { throw SQLExceptionFactory.createSQLException(e); } } /** * @see java.sql.Driver#jdbcCompliant() */ @Override public boolean jdbcCompliant() { return true; } private DatabaseCluster getDatabaseCluster(String id, Properties properties) throws SQLException { DatabaseCluster cluster = DatabaseClusterFactory.getDatabaseCluster(id, DriverDatabaseCluster.class, DriverDatabaseClusterMBean.class, properties.getProperty(CONFIG)); if (cluster == null) { throw new SQLException(Messages.getMessage(Messages.INVALID_DATABASE_CLUSTER, id)); } return cluster; } private String parse(String url) { Matcher matcher = URL_PATTERN.matcher(url); if (!matcher.matches()) { return null; } return matcher.group(1); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CommonDataSourceObjectFactory.java0000644000175000017500000000676111151703042026161 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.InvocationHandler; import java.sql.SQLException; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.spi.ObjectFactory; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * * @param */ public abstract class CommonDataSourceObjectFactory implements ObjectFactory, CommonDataSourceFactory { private Class targetClass; /** * @param targetClass */ protected CommonDataSourceObjectFactory(Class targetClass) { this.targetClass = targetClass; } /** * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable) */ @Override public Object getObjectInstance(Object object, Name name, Context context, Hashtable environment) throws Exception { if ((object == null) || !(object instanceof Reference)) return null; Reference reference = (Reference) object; String className = reference.getClassName(); if ((className == null) || !className.equals(this.targetClass.getName())) return null; RefAddr idAddr = reference.get(CommonDataSourceReference.CLUSTER); if (idAddr == null) return null; Object idAddrContent = idAddr.getContent(); if ((idAddrContent == null) || !(idAddrContent instanceof String)) return null; String id = (String) idAddrContent; RefAddr configAddr = reference.get(CommonDataSourceReference.CONFIG); String config = null; if (configAddr != null) { Object configAddrContent = configAddr.getContent(); if ((configAddrContent != null) && (configAddrContent instanceof String)) { config = (String) configAddrContent; } } return this.createProxy(id, config); } /** * @see net.sf.hajdbc.sql.CommonDataSourceFactory#createProxy(java.lang.String, java.lang.String) */ public D createProxy(String id, String config) throws SQLException { DatabaseCluster cluster = this.getDatabaseCluster(id, config); if (cluster == null) return null; return ProxyFactory.createProxy(this.targetClass, this.getInvocationHandler(cluster)); } /** * @param id * @param config * @return the appropriate database cluster * @throws SQLException */ protected abstract DatabaseCluster getDatabaseCluster(String id, String config) throws SQLException; /** * @param cluster * @return the appropriate proxy invocation handler for this datasource */ protected abstract InvocationHandler getInvocationHandler(DatabaseCluster cluster); }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CommonDataSourceFactory.java0000644000175000017500000000266711151703042025033 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.SQLException; /** * @author Paul Ferraro * @param the data source class */ public interface CommonDataSourceFactory { /** * Creates a data source proxy to the specified cluster, using the configuration file at the specified location. * @param id a database cluster identifier * @param config the location of the configuration file for this cluster * @return a proxied data source * @throws SQLException if the data source proxy could not be created */ public D createProxy(String id, String config) throws SQLException; }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CallableStatementInvocationHandler.java0000644000175000017500000000700111217246644027214 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Map; import java.util.Set; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * @param */ @SuppressWarnings("nls") public class CallableStatementInvocationHandler extends AbstractPreparedStatementInvocationHandler { private static final Set registerOutParameterMethodSet = Methods.findMethods(CallableStatement.class, "registerOutParameter"); private static final Set setMethodSet = Methods.findMethods(CallableStatement.class, "set\\w+"); private static final Set driverReadMethodSet = Methods.findMethods(CallableStatement.class, "get\\w+", "wasNull"); { driverReadMethodSet.removeAll(Methods.findMethods(PreparedStatement.class, "get\\w+")); } /** * @param connection * @param proxy * @param invoker * @param statementMap * @param transactionContext * @param fileSupport * @throws Exception */ public CallableStatementInvocationHandler(Connection connection, SQLProxy proxy, Invoker invoker, Map, CallableStatement> statementMap, TransactionContext transactionContext, FileSupport fileSupport) throws Exception { super(connection, proxy, invoker, CallableStatement.class, statementMap, transactionContext, fileSupport, setMethodSet); } /** * @see net.sf.hajdbc.sql.AbstractStatementInvocationHandler#getInvocationStrategy(java.sql.Statement, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(CallableStatement statement, Method method, Object[] parameters) throws Exception { if (registerOutParameterMethodSet.contains(method)) { return new DriverWriteInvocationStrategy(); } if (driverReadMethodSet.contains(method)) { return new DriverReadInvocationStrategy(); } return super.getInvocationStrategy(statement, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractPreparedStatementInvocationHandler#isBatchMethod(java.lang.reflect.Method) */ @Override protected boolean isBatchMethod(Method method) { return registerOutParameterMethodSet.contains(method) || super.isBatchMethod(method); } /** * @see net.sf.hajdbc.sql.AbstractPreparedStatementInvocationHandler#isIndexType(java.lang.Class) */ @Override protected boolean isIndexType(Class type) { return type.equals(String.class) || super.isIndexType(type); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/AbstractRootInvocationHandler.java0000644000175000017500000000411211210570414026223 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.SQLException; import java.util.TreeMap; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; /** * @author Paul Ferraro * @param */ public abstract class AbstractRootInvocationHandler extends AbstractInvocationHandler { /** * Constructs a new AbstractRootInvocationHandler. * @param databaseCluster * @param proxyClass */ protected AbstractRootInvocationHandler(DatabaseCluster databaseCluster, Class proxyClass) { super(databaseCluster, proxyClass, new TreeMap, D>()); for (Database database: databaseCluster.getBalancer().all()) { this.getObject(database); } } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#close(net.sf.hajdbc.Database, java.lang.Object) */ @Override protected void close(Database database, D object) { // Nothing to close } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#createObject(net.sf.hajdbc.Database) */ @Override protected D createObject(Database database) throws SQLException { return database.createConnectionFactory(); } /** * @see net.sf.hajdbc.sql.SQLProxy#getRoot() */ @Override public SQLProxy getRoot() { return this; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/LocalTransactionContext.java0000644000175000017500000000607311151703042025100 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.SQLException; import java.util.Collections; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.LockManager; /** * @author Paul Ferraro * @param */ public class LocalTransactionContext implements TransactionContext { private Lock lock; private boolean locked = false; /** * @param cluster */ public LocalTransactionContext(DatabaseCluster cluster) { this.lock = cluster.getLockManager().readLock(LockManager.GLOBAL); } /** * @see net.sf.hajdbc.sql.TransactionContext#start(net.sf.hajdbc.sql.InvocationStrategy, java.sql.Connection) */ public InvocationStrategy start(final InvocationStrategy strategy, Connection connection) throws SQLException { if (this.locked) return strategy; if (connection.getAutoCommit()) { return new LockingInvocationStrategy(strategy, Collections.singletonList(this.lock)); } return new InvocationStrategy() { @Override public R invoke(SQLProxy proxy, Invoker invoker) throws Exception { LocalTransactionContext.this.lock(); try { return strategy.invoke(proxy, invoker); } catch (Exception e) { LocalTransactionContext.this.unlock(); throw e; } } }; } /** * @see net.sf.hajdbc.sql.TransactionContext#end(net.sf.hajdbc.sql.InvocationStrategy) */ public InvocationStrategy end(final InvocationStrategy strategy) { if (!this.locked) return strategy; return new InvocationStrategy() { @Override public R invoke(SQLProxy proxy, Invoker invoker) throws Exception { try { return strategy.invoke(proxy, invoker); } finally { LocalTransactionContext.this.unlock(); } } }; } /** * @see net.sf.hajdbc.sql.TransactionContext#close() */ @Override public void close() { // Tsk, tsk... User neglected to commit/rollback transaction if (this.locked) { this.unlock(); } } void lock() { this.lock.lock(); this.locked = true; } void unlock() { this.lock.unlock(); this.locked = false; } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DataSourceReference.java0000644000175000017500000000311711151703042024140 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import javax.sql.DataSource; /** * @author Paul Ferraro */ public class DataSourceReference extends CommonDataSourceReference { private static final long serialVersionUID = -3303639090879442549L; /** * Constructs a reference to a DataSource for the specified cluster * @param cluster a cluster identifier */ public DataSourceReference(String cluster) { this(cluster, null); } /** * Constructs a reference to a DataSource for the specified cluster * @param cluster a cluster identifier * @param config the uri of the configuration file */ public DataSourceReference(String cluster, String config) { super(DataSource.class, DataSourceFactory.class, cluster, config); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/ArrayInvocationHandler.java0000644000175000017500000000462711217567712024723 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2009 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.sql.Array; import java.util.Map; import java.util.Set; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * */ public class ArrayInvocationHandler extends LocatorInvocationHandler { private static final Set driverReadMethodSet = Methods.findMethods(Array.class, "getBaseType", "getBaseTypeName"); private static final Set databaseReadMethodSet = Methods.findMethods(Array.class, "getArray", "getResultSet"); /** * @param parent * @param proxy * @param invoker * @param objectMap * @throws Exception */ public ArrayInvocationHandler(P parent, SQLProxy proxy, Invoker invoker, Map, Array> objectMap) throws Exception { super(parent, proxy, invoker, Array.class, objectMap); } /** * {@inheritDoc} * @see net.sf.hajdbc.sql.LocatorInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(Array object, Method method, Object[] parameters) throws Exception { if (driverReadMethodSet.contains(method)) { return new DriverReadInvocationStrategy(); } return super.getInvocationStrategy(object, method, parameters); } /** * @see net.sf.hajdbc.sql.LocatorInvocationHandler#getDatabaseReadMethodSet() */ @Override protected Set getDatabaseReadMethodSet() { return databaseReadMethodSet; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DataSourceDatabaseCluster.java0000644000175000017500000000352511151703042025313 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.net.URL; import javax.sql.DataSource; import org.jibx.runtime.IUnmarshallingContext; /** * @author Paul Ferraro */ public class DataSourceDatabaseCluster extends CommonDataSourceDatabaseCluster implements DataSourceDatabaseClusterMBean { /** * Object factory for JiBX that pulls the cluster instance from the unmarshalling context * @param context unmarshalling context * @return a database cluster */ public static DataSourceDatabaseCluster extractDatabaseCluster(IUnmarshallingContext context) { return (DataSourceDatabaseCluster) context.getUserContext(); } /** * Constructs a new DataSourceDatabaseCluster * @param id * @param url */ public DataSourceDatabaseCluster(String id, URL url) { super(id, url); } /** * @see net.sf.hajdbc.sql.CommonDataSourceDatabaseCluster#createDatabase() */ @Override protected CommonDataSourceDatabase createDatabase() { return new DataSourceDatabase(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/ActiveDataSourceDatabaseMBean.java0000644000175000017500000000225611151703042026010 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import net.sf.hajdbc.ActiveDatabaseMBean; /** * @author Paul Ferraro * */ public interface ActiveDataSourceDatabaseMBean extends ActiveDatabaseMBean { /** * Return the JNDI name of this DataSource * @return a JNDI name */ public String getName(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DatabaseWriteInvocationStrategy.java0000644000175000017500000000741611151703042026571 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.Messages; /** * @author Paul Ferraro * @param * @param * @param */ public class DatabaseWriteInvocationStrategy implements InvocationStrategy { private ExecutorService executor; /** * @param executor */ public DatabaseWriteInvocationStrategy(ExecutorService executor) { this.executor = executor; } /** * @see net.sf.hajdbc.sql.InvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public R invoke(SQLProxy proxy, Invoker invoker) throws Exception { SortedMap, R> map = this.invokeAll(proxy, invoker); return map.get(map.firstKey()); } protected SortedMap, R> invokeAll(SQLProxy proxy, final Invoker invoker) throws Exception { SortedMap, R> resultMap = new TreeMap, R>(); SortedMap, Exception> exceptionMap = new TreeMap, Exception>(); Map, Future> futureMap = new HashMap, Future>(); DatabaseCluster cluster = proxy.getDatabaseCluster(); Set> databaseSet = cluster.getBalancer().all(); proxy.getRoot().retain(databaseSet); if (databaseSet.isEmpty()) { throw new SQLException(Messages.getMessage(Messages.NO_ACTIVE_DATABASES, cluster)); } for (final Database database: databaseSet) { final T object = proxy.getObject(database); Callable task = new Callable() { public R call() throws Exception { return invoker.invoke(database, object); } }; futureMap.put(database, this.executor.submit(task)); } for (Map.Entry, Future> futureMapEntry: futureMap.entrySet()) { Database database = futureMapEntry.getKey(); try { resultMap.put(database, futureMapEntry.getValue().get()); } catch (ExecutionException e) { Throwable cause = e.getCause(); Exception exception = (cause instanceof Exception) ? (Exception) cause : e; exceptionMap.put(database, exception); } catch (InterruptedException e) { Thread.currentThread().interrupt(); exceptionMap.put(database, e); } } // If no databases returned successfully, return an exception back to the caller if (resultMap.isEmpty()) { proxy.handleFailures(exceptionMap); } // If any databases failed, while others succeeded, handle the failures return exceptionMap.isEmpty() ? resultMap : proxy.handlePartialFailure(resultMap, exceptionMap); } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/ConnectionInvocationStrategy.java0000644000175000017500000000411411151703042026141 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * @param * @param

*/ public class ConnectionInvocationStrategy extends DatabaseWriteInvocationStrategy { private P connectionFactory; private TransactionContext transactionContext; /** * @param cluster * @param connectionFactory the factory from which to create connections * @param transactionContext */ public ConnectionInvocationStrategy(DatabaseCluster cluster, P connectionFactory, TransactionContext transactionContext) { super(cluster.getNonTransactionalExecutor()); this.connectionFactory = connectionFactory; this.transactionContext = transactionContext; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public Connection invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(Connection.class, new ConnectionInvocationHandler(this.connectionFactory, proxy, invoker, this.invokeAll(proxy, invoker), this.transactionContext)); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CommonDataSourceInvocationHandler.java0000644000175000017500000000467311210570725027040 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.util.Set; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * @param */ @SuppressWarnings("nls") public class CommonDataSourceInvocationHandler extends AbstractRootInvocationHandler { // private static final Set getMethodSet = Methods.findMethods(CommonDataSource.class, "get\\w+"); // private static final Set setMethodSet = Methods.findMethods(CommonDataSource.class, "set\\w+"); private final Set getMethodSet; private final Set setMethodSet; /** * @param databaseCluster * @param proxyClass */ protected CommonDataSourceInvocationHandler(DatabaseCluster databaseCluster, Class proxyClass) { super(databaseCluster, proxyClass); this.getMethodSet = Methods.findMethods(proxyClass, "get\\w+"); this.setMethodSet = Methods.findMethods(proxyClass, "set\\w+"); } @Override protected InvocationStrategy getInvocationStrategy(D object, Method method, Object[] parameters) throws Exception { if (this.getMethodSet.contains(method)) { return new DriverReadInvocationStrategy(); } if (this.setMethodSet.contains(method)) { return new DriverWriteInvocationStrategy(); } return super.getInvocationStrategy(object, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#isRecordable(java.lang.reflect.Method) */ @Override protected boolean isRecordable(Method method) { return this.setMethodSet.contains(method); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CommonDataSourceReference.java0000644000175000017500000000376311151703042025320 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; /** * @author Paul Ferraro * @param */ public abstract class CommonDataSourceReference extends Reference { private static final long serialVersionUID = 1408239702660701511L; protected static final String CLUSTER = "cluster"; //$NON-NLS-1$ protected static final String CONFIG = "config"; //$NON-NLS-1$ /** * Constructs a reference for a DataSource implementation. * @param targetClass the target class of the DataSource. * @param factoryClass the ObjectFactory class for creating a DataSource * @param cluster a cluster identifier * @param config the uri of the configuration file */ protected CommonDataSourceReference(Class targetClass, Class factoryClass, String cluster, String config) { super(targetClass.getName(), factoryClass.getName(), null); if (cluster == null) { throw new IllegalArgumentException(); } this.add(new StringRefAddr(CLUSTER, cluster)); if (config != null) { this.add(new StringRefAddr(CONFIG, config)); } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/AbstractDatabaseCluster.java0000644000175000017500000007265711213222145025037 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.Callable; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import javax.management.DynamicMBean; import javax.management.JMException; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.ObjectName; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseActivationListener; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseClusterDecorator; import net.sf.hajdbc.DatabaseClusterFactory; import net.sf.hajdbc.DatabaseClusterMBean; import net.sf.hajdbc.DatabaseDeactivationListener; import net.sf.hajdbc.DatabaseEvent; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseMetaDataCacheFactory; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.Messages; import net.sf.hajdbc.StateManager; import net.sf.hajdbc.SynchronizationContext; import net.sf.hajdbc.SynchronizationListener; import net.sf.hajdbc.SynchronizationStrategy; import net.sf.hajdbc.local.LocalLockManager; import net.sf.hajdbc.local.LocalStateManager; import net.sf.hajdbc.sync.SynchronizationContextImpl; import net.sf.hajdbc.sync.SynchronizationStrategyBuilder; import net.sf.hajdbc.util.concurrent.CronThreadPoolExecutor; import org.jibx.runtime.BindingDirectory; import org.jibx.runtime.IMarshallingContext; import org.jibx.runtime.IUnmarshallingContext; import org.jibx.runtime.JiBXException; import org.quartz.CronExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Paul Ferraro * @param either java.sql.Driver or javax.sql.DataSource * @since 1.0 */ public abstract class AbstractDatabaseCluster implements DatabaseCluster, DatabaseClusterMBean, MBeanRegistration { /** This is a work-around for Java 1.4, where Boolean does not implement Comparable */ private static final Comparator booleanComparator = new Comparator() { @Override public int compare(Boolean value1, Boolean value2) { return this.valueOf(value1) - this.valueOf(value2); } private int valueOf(Boolean value) { return value.booleanValue() ? 1 : 0; } }; static Logger logger = LoggerFactory.getLogger(AbstractDatabaseCluster.class); // private static final Method isValidMethod = Methods.findMethod(Connection.class, "isValid", Integer.TYPE); private String id; private Balancer balancer; private Dialect dialect; private DatabaseMetaDataCacheFactory databaseMetaDataCacheFactory; private DatabaseMetaDataCache databaseMetaDataCache; private String defaultSynchronizationStrategyId; private CronExpression failureDetectionExpression; private CronExpression autoActivationExpression; private int minThreads; private int maxThreads; private int maxIdle; private TransactionMode transactionMode; private boolean identityColumnDetectionEnabled; private boolean sequenceDetectionEnabled; private boolean currentDateEvaluationEnabled; private boolean currentTimeEvaluationEnabled; private boolean currentTimestampEvaluationEnabled; private boolean randEvaluationEnabled; private MBeanServer server; private URL url; private Map synchronizationStrategyMap = new HashMap(); private DatabaseClusterDecorator decorator; private Map> databaseMap = new HashMap>(); private ExecutorService executor; private CronThreadPoolExecutor cronExecutor = new CronThreadPoolExecutor(2); private LockManager lockManager = new LocalLockManager(); private StateManager stateManager = new LocalStateManager(this); private volatile boolean active = false; private List activationListenerList = new CopyOnWriteArrayList(); private List deactivationListenerList = new CopyOnWriteArrayList(); private List synchronizationListenerList = new CopyOnWriteArrayList(); protected AbstractDatabaseCluster(String id, URL url) { this.id = id; this.url = url; } /** * @see net.sf.hajdbc.DatabaseCluster#getId() */ @Override public String getId() { return this.id; } /** * @see net.sf.hajdbc.DatabaseClusterMBean#getVersion() */ @Override public String getVersion() { return DatabaseClusterFactory.getVersion(); } /** * @see net.sf.hajdbc.DatabaseCluster#getAliveMap(java.util.Collection) */ @Override public Map>> getAliveMap(Collection> databases) { Map, Future> futureMap = new TreeMap, Future>(); for (final Database database: databases) { Callable task = new Callable() { public Boolean call() throws Exception { return AbstractDatabaseCluster.this.isAlive(database); } }; futureMap.put(database, this.executor.submit(task)); } Map>> map = new TreeMap>>(booleanComparator); int size = databases.size(); map.put(false, new ArrayList>(size)); map.put(true, new ArrayList>(size)); for (Map.Entry, Future> futureMapEntry: futureMap.entrySet()) { try { map.get(futureMapEntry.getValue().get()).add(futureMapEntry.getKey()); } catch (ExecutionException e) { // isAlive does not throw an exception throw new IllegalStateException(e); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } return map; } boolean isAlive(Database database) { try { this.test(database); return true; } catch (SQLException e) { logger.warn(Messages.getMessage(Messages.DATABASE_NOT_ALIVE, database, this), e); return false; } } private void test(Database database) throws SQLException { Connection connection = null; try { connection = database.connect(database.createConnectionFactory()); Statement statement = connection.createStatement(); statement.execute(this.dialect.getSimpleSQL()); statement.close(); } finally { if (connection != null) { try { connection.close(); } catch (SQLException e) { logger.warn(e.toString(), e); } } } } /* boolean isAliveNew(Database database) { Connection connection = null; try { connection = database.connect(database.createConnectionFactory()); return this.isAlive(connection); } catch (SQLException e) { logger.warn(Messages.getMessage(Messages.DATABASE_NOT_ALIVE, database, this), e); return false; } finally { if (connection != null) { try { connection.close(); } catch (SQLException e) { logger.warn(e.getMessage(), e); } } } } private boolean isAlive(Connection connection) { if (isValidMethod != null) { try { return connection.isValid(0); } catch (SQLException e) { // isValid not yet supported } } try { Statement statement = connection.createStatement(); statement.execute(this.dialect.getSimpleSQL()); statement.close(); return true; } catch (SQLException e) { logger.warn(e.toString(), e); return false; } } */ /** * @see net.sf.hajdbc.DatabaseCluster#deactivate(net.sf.hajdbc.Database, net.sf.hajdbc.StateManager) */ @Override public boolean deactivate(Database database, StateManager manager) { synchronized (this.balancer) { this.unregister(database); // Reregister database mbean using "inactive" interface this.register(database, database.getInactiveMBean()); boolean removed = this.balancer.remove(database); if (removed) { DatabaseEvent event = new DatabaseEvent(database); manager.deactivated(event); for (DatabaseDeactivationListener listener: this.deactivationListenerList) { listener.deactivated(event); } } return removed; } } /** * @see net.sf.hajdbc.DatabaseCluster#activate(net.sf.hajdbc.Database, net.sf.hajdbc.StateManager) */ @Override public boolean activate(Database database, StateManager manager) { synchronized (this.balancer) { this.unregister(database); // Reregister database mbean using "active" interface this.register(database, database.getActiveMBean()); if (database.isDirty()) { this.export(); database.clean(); } boolean added = this.balancer.add(database); if (added) { DatabaseEvent event = new DatabaseEvent(database); manager.activated(event); for (DatabaseActivationListener listener: this.activationListenerList) { listener.activated(event); } } return added; } } /** * @see net.sf.hajdbc.DatabaseClusterMBean#getActiveDatabases() */ @Override public Set getActiveDatabases() { Set databaseSet = new TreeSet(); for (Database database: this.balancer.all()) { databaseSet.add(database.getId()); } return databaseSet; } /** * @see net.sf.hajdbc.DatabaseClusterMBean#getInactiveDatabases() */ @Override public Set getInactiveDatabases() { synchronized (this.databaseMap) { Set databaseSet = new TreeSet(this.databaseMap.keySet()); for (Database database: this.balancer.all()) { databaseSet.remove(database.getId()); } return databaseSet; } } /** * @see net.sf.hajdbc.DatabaseCluster#getDatabase(java.lang.String) */ @Override public Database getDatabase(String id) { synchronized (this.databaseMap) { Database database = this.databaseMap.get(id); if (database == null) { throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_DATABASE, id, this)); } return database; } } /** * @see net.sf.hajdbc.DatabaseClusterMBean#getDefaultSynchronizationStrategy() */ @Override public String getDefaultSynchronizationStrategy() { return this.defaultSynchronizationStrategyId; } /** * @see net.sf.hajdbc.DatabaseClusterMBean#getSynchronizationStrategies() */ @Override public Set getSynchronizationStrategies() { return new TreeSet(this.synchronizationStrategyMap.keySet()); } /** * @see net.sf.hajdbc.DatabaseCluster#getBalancer() */ @Override public Balancer getBalancer() { return this.balancer; } /** * @see net.sf.hajdbc.DatabaseCluster#getTransactionalExecutor() */ @Override public ExecutorService getTransactionalExecutor() { return this.transactionMode.getTransactionExecutor(this.executor); } /** * @see net.sf.hajdbc.DatabaseCluster#getNonTransactionalExecutor() */ @Override public ExecutorService getNonTransactionalExecutor() { return this.executor; } /** * @see net.sf.hajdbc.DatabaseCluster#getDialect() */ @Override public Dialect getDialect() { return this.dialect; } /** * @see net.sf.hajdbc.DatabaseCluster#getDatabaseMetaDataCache() */ @Override public DatabaseMetaDataCache getDatabaseMetaDataCache() { return this.databaseMetaDataCache; } /** * @see net.sf.hajdbc.DatabaseCluster#getLockManager() */ @Override public LockManager getLockManager() { return this.lockManager; } /** * @see net.sf.hajdbc.DatabaseClusterMBean#isAlive(java.lang.String) */ @Override public boolean isAlive(String id) { return this.isAlive(this.getDatabase(id)); } /** * @see net.sf.hajdbc.DatabaseClusterMBean#deactivate(java.lang.String) */ @Override public void deactivate(String databaseId) { if (this.deactivate(this.getDatabase(databaseId), this.stateManager)) { logger.info(Messages.getMessage(Messages.DATABASE_DEACTIVATED, databaseId, this)); } } /** * @see net.sf.hajdbc.DatabaseClusterMBean#activate(java.lang.String) */ @Override public void activate(String databaseId) { this.activate(databaseId, this.getDefaultSynchronizationStrategy()); } /** * @see net.sf.hajdbc.DatabaseClusterMBean#activate(java.lang.String, java.lang.String) */ @Override public void activate(String databaseId, String strategyId) { SynchronizationStrategy strategy = this.synchronizationStrategyMap.get(strategyId); if (strategy == null) { throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_SYNC_STRATEGY, strategyId)); } try { if (this.activate(this.getDatabase(databaseId), strategy)) { logger.info(Messages.getMessage(Messages.DATABASE_ACTIVATED, databaseId, this)); } } catch (SQLException e) { logger.warn(Messages.getMessage(Messages.DATABASE_ACTIVATE_FAILED, databaseId, this), e); SQLException exception = e.getNextException(); while (exception != null) { logger.error(exception.getMessage(), exception); exception = exception.getNextException(); } throw new IllegalStateException(e.toString()); } catch (InterruptedException e) { logger.warn(e.toString(), e); Thread.currentThread().interrupt(); } } protected void register(Database database, DynamicMBean mbean) { try { ObjectName name = DatabaseClusterFactory.getObjectName(this.id, database.getId()); this.server.registerMBean(mbean, name); } catch (JMException e) { logger.error(e.toString(), e); throw new IllegalStateException(e); } } /** * @see net.sf.hajdbc.DatabaseClusterMBean#remove(java.lang.String) */ @Override public void remove(String id) { synchronized (this.databaseMap) { Database database = this.getDatabase(id); if (this.balancer.all().contains(database)) { throw new IllegalStateException(Messages.getMessage(Messages.DATABASE_STILL_ACTIVE, id, this)); } this.unregister(database); this.databaseMap.remove(id); this.export(); } } private void unregister(Database database) { try { ObjectName name = DatabaseClusterFactory.getObjectName(this.id, database.getId()); if (this.server.isRegistered(name)) { this.server.unregisterMBean(name); } } catch (JMException e) { logger.error(e.toString(), e); throw new IllegalStateException(e); } } /** * @see net.sf.hajdbc.DatabaseCluster#isActive() */ @Override public boolean isActive() { return this.active; } /** * @see net.sf.hajdbc.Lifecycle#start() */ public synchronized void start() throws Exception { if (this.active) return; this.lockManager.start(); this.stateManager.start(); this.executor = new ThreadPoolExecutor(this.minThreads, this.maxThreads, this.maxIdle, TimeUnit.SECONDS, new SynchronousQueue(), new ThreadPoolExecutor.CallerRunsPolicy()); Set databaseSet = this.stateManager.getInitialState(); if (databaseSet != null) { for (String databaseId: databaseSet) { Database database = this.getDatabase(databaseId); if (database != null) { this.activate(database, this.stateManager); } } } else { for (Database database: this.getAliveMap(this.databaseMap.values()).get(true)) { this.activate(database, this.stateManager); } } this.databaseMetaDataCache = this.databaseMetaDataCacheFactory.createCache(this); try { this.flushMetaDataCache(); } catch (IllegalStateException e) { // Ignore - cache will initialize lazily. } if (this.failureDetectionExpression != null) { this.cronExecutor.schedule(new FailureDetectionTask(), this.failureDetectionExpression); } if (this.autoActivationExpression != null) { this.cronExecutor.schedule(new AutoActivationTask(), this.autoActivationExpression); } this.active = true; } /** * @see net.sf.hajdbc.Lifecycle#stop() */ public synchronized void stop() { if (!this.active) return; this.active = false; this.balancer.clear(); this.stateManager.stop(); this.lockManager.stop(); this.cronExecutor.shutdownNow(); if (this.executor != null) { this.executor.shutdownNow(); } } /** * @see net.sf.hajdbc.DatabaseClusterMBean#flushMetaDataCache() */ @Override public void flushMetaDataCache() { try { this.databaseMetaDataCache.flush(); } catch (SQLException e) { throw new IllegalStateException(e.toString(), e); } } /** * @see net.sf.hajdbc.DatabaseCluster#isIdentityColumnDetectionEnabled() */ @Override public boolean isIdentityColumnDetectionEnabled() { return this.identityColumnDetectionEnabled; } /** * @see net.sf.hajdbc.DatabaseCluster#isSequenceDetectionEnabled() */ @Override public boolean isSequenceDetectionEnabled() { return this.sequenceDetectionEnabled; } /** * @see net.sf.hajdbc.DatabaseCluster#isCurrentDateEvaluationEnabled() */ @Override public boolean isCurrentDateEvaluationEnabled() { return this.currentDateEvaluationEnabled; } /** * @see net.sf.hajdbc.DatabaseCluster#isCurrentTimeEvaluationEnabled() */ @Override public boolean isCurrentTimeEvaluationEnabled() { return this.currentTimeEvaluationEnabled; } /** * @see net.sf.hajdbc.DatabaseCluster#isCurrentTimestampEvaluationEnabled() */ @Override public boolean isCurrentTimestampEvaluationEnabled() { return this.currentTimestampEvaluationEnabled; } /** * @see net.sf.hajdbc.DatabaseCluster#isRandEvaluationEnabled() */ @Override public boolean isRandEvaluationEnabled() { return this.randEvaluationEnabled; } /** * @see java.lang.Object#toString() */ @Override public String toString() { return this.getId(); } /** * @see java.lang.Object#equals(java.lang.Object) */ @SuppressWarnings("unchecked") @Override public boolean equals(Object object) { if ((object == null) || !(object instanceof DatabaseCluster)) return false; String id = ((DatabaseCluster) object).getId(); return (id != null) && id.equals(this.id); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return this.id.hashCode(); } protected DatabaseClusterDecorator getDecorator() { return this.decorator; } protected void setDecorator(DatabaseClusterDecorator decorator) { this.decorator = decorator; } protected void add(Database database) { String id = database.getId(); synchronized (this.databaseMap) { if (this.databaseMap.containsKey(id)) { throw new IllegalArgumentException(Messages.getMessage(Messages.DATABASE_ALREADY_EXISTS, id, this)); } this.register(database, database.getInactiveMBean()); this.databaseMap.put(id, database); } } protected Iterator> getDatabases() { synchronized (this.databaseMap) { return this.databaseMap.values().iterator(); } } /** * @see net.sf.hajdbc.DatabaseCluster#getStateManager() */ @Override public StateManager getStateManager() { return this.stateManager; } /** * @see net.sf.hajdbc.DatabaseCluster#setStateManager(net.sf.hajdbc.StateManager) */ @Override public void setStateManager(StateManager stateManager) { this.stateManager = stateManager; } /** * @see net.sf.hajdbc.DatabaseCluster#setLockManager(net.sf.hajdbc.LockManager) */ @Override public void setLockManager(LockManager lockManager) { this.lockManager = lockManager; } /** * @see net.sf.hajdbc.DatabaseClusterMBean#getUrl() */ @Override public URL getUrl() { return this.url; } private boolean activate(Database database, SynchronizationStrategy strategy) throws SQLException, InterruptedException { Lock lock = this.lockManager.writeLock(LockManager.GLOBAL); lock.lockInterruptibly(); try { SynchronizationContext context = new SynchronizationContextImpl(this, database); if (context.getActiveDatabaseSet().contains(database)) { return false; } this.test(database); try { DatabaseEvent event = new DatabaseEvent(database); logger.info(Messages.getMessage(Messages.DATABASE_SYNC_START, database, this)); for (SynchronizationListener listener: this.synchronizationListenerList) { listener.beforeSynchronization(event); } strategy.synchronize(context); logger.info(Messages.getMessage(Messages.DATABASE_SYNC_END, database, this)); for (SynchronizationListener listener: this.synchronizationListenerList) { listener.afterSynchronization(event); } return this.activate(database, this.stateManager); } finally { context.close(); } } catch (NoSuchElementException e) { return this.activate(database, this.stateManager); } finally { lock.unlock(); } } /** * @see javax.management.MBeanRegistration#postDeregister() */ @Override public void postDeregister() { this.stop(); this.unregisterDatabases(); } private void unregisterDatabases() { synchronized (this.databaseMap) { Iterator> databases = this.databaseMap.values().iterator(); while (databases.hasNext()) { this.unregister(databases.next()); databases.remove(); } } } /** * @see javax.management.MBeanRegistration#postRegister(java.lang.Boolean) */ @Override public void postRegister(Boolean registered) { if (!registered) { this.postDeregister(); } } /** * @see javax.management.MBeanRegistration#preDeregister() */ @Override public void preDeregister() throws Exception { // Nothing to do } /** * @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer, javax.management.ObjectName) */ @Override public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { this.server = server; InputStream inputStream = null; logger.info(Messages.getMessage(Messages.HA_JDBC_INIT, this.getVersion(), this.url)); try { inputStream = this.url.openStream(); IUnmarshallingContext context = BindingDirectory.getFactory(this.getClass()).createUnmarshallingContext(); context.setDocument(inputStream, null); context.setUserContext(this); context.unmarshalElement(); if (this.decorator != null) { this.decorator.decorate(this); } this.start(); return name; } catch (IOException e) { logger.error(Messages.getMessage(Messages.CONFIG_NOT_FOUND, this.url), e); throw e; } catch (JiBXException e) { logger.error(Messages.getMessage(Messages.CONFIG_LOAD_FAILED, this.url), e); this.unregisterDatabases(); throw e; } catch (Exception e) { logger.error(Messages.getMessage(Messages.CLUSTER_START_FAILED, this), e); this.postDeregister(); throw e; } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { logger.warn(e.toString(), e); } } } } private void export() { File file = null; WritableByteChannel outputChannel = null; FileChannel fileChannel = null; try { file = File.createTempFile("ha-jdbc", ".xml"); //$NON-NLS-1$ //$NON-NLS-2$ IMarshallingContext context = BindingDirectory.getFactory(this.getClass()).createMarshallingContext(); context.setIndent(1, System.getProperty("line.separator"), '\t'); //$NON-NLS-1$ // This method closes the writer context.marshalDocument(this, null, null, new FileWriter(file)); fileChannel = new FileInputStream(file).getChannel(); outputChannel = this.getOutputChannel(this.url); fileChannel.transferTo(0, file.length(), outputChannel); } catch (Exception e) { logger.warn(Messages.getMessage(Messages.CONFIG_STORE_FAILED, this.url), e); } finally { if (outputChannel != null) { try { outputChannel.close(); } catch (IOException e) { logger.warn(e.getMessage(), e); } } if (fileChannel != null) { try { fileChannel.close(); } catch (IOException e) { logger.warn(e.getMessage(), e); } } if (file != null) { file.delete(); } } } /** * We cannot use URLConnection for files because Sun's implementation does not support output. */ private WritableByteChannel getOutputChannel(URL url) throws IOException { return this.isFile(url) ? new FileOutputStream(this.toFile(url)).getChannel() : Channels.newChannel(url.openConnection().getOutputStream()); } private boolean isFile(URL url) { return url.getProtocol().equals("file"); //$NON-NLS-1$ } private File toFile(URL url) { return new File(url.getPath()); } protected void addSynchronizationStrategyBuilder(SynchronizationStrategyBuilder builder) throws Exception { this.synchronizationStrategyMap.put(builder.getId(), builder.buildStrategy()); } protected Iterator getSynchronizationStrategyBuilders() throws Exception { List builderList = new ArrayList(this.synchronizationStrategyMap.size()); for (Map.Entry mapEntry: this.synchronizationStrategyMap.entrySet()) { builderList.add(SynchronizationStrategyBuilder.getBuilder(mapEntry.getKey(), mapEntry.getValue())); } return builderList.iterator(); } /** * @see net.sf.hajdbc.DatabaseClusterMBean#addActivationListener(net.sf.hajdbc.DatabaseActivationListener) */ @Override public void addActivationListener(DatabaseActivationListener listener) { this.activationListenerList.add(listener); } /** * @see net.sf.hajdbc.DatabaseClusterMBean#addDeactivationListener(net.sf.hajdbc.DatabaseDeactivationListener) */ @Override public void addDeactivationListener(DatabaseDeactivationListener listener) { this.deactivationListenerList.add(listener); } /** * @see net.sf.hajdbc.DatabaseClusterMBean#addSynchronizationListener(net.sf.hajdbc.SynchronizationListener) */ @Override public void addSynchronizationListener(SynchronizationListener listener) { this.synchronizationListenerList.add(listener); } /** * @see net.sf.hajdbc.DatabaseClusterMBean#removeActivationListener(net.sf.hajdbc.DatabaseActivationListener) */ @Override public void removeActivationListener(DatabaseActivationListener listener) { this.activationListenerList.remove(listener); } /** * @see net.sf.hajdbc.DatabaseClusterMBean#removeDeactivationListener(net.sf.hajdbc.DatabaseDeactivationListener) */ @Override public void removeDeactivationListener(DatabaseDeactivationListener listener) { this.deactivationListenerList.remove(listener); } /** * @see net.sf.hajdbc.DatabaseClusterMBean#removeSynchronizationListener(net.sf.hajdbc.SynchronizationListener) */ @Override public void removeSynchronizationListener(SynchronizationListener listener) { this.synchronizationListenerList.remove(listener); } class FailureDetectionTask implements Runnable { /** * @see java.lang.Runnable#run() */ @Override public void run() { Set> databaseSet = AbstractDatabaseCluster.this.getBalancer().all(); if (databaseSet.size() > 1) { Map>> aliveMap = AbstractDatabaseCluster.this.getAliveMap(databaseSet); // Deactivate the dead databases, so long as at least one is alive // Skip deactivation if membership is empty in case of cluster panic if (!aliveMap.get(true).isEmpty() && !AbstractDatabaseCluster.this.getStateManager().isMembershipEmpty()) { for (Database database: aliveMap.get(false)) { if (AbstractDatabaseCluster.this.deactivate(database, AbstractDatabaseCluster.this.getStateManager())) { logger.error(Messages.getMessage(Messages.DATABASE_DEACTIVATED, database, this)); } } } } } } class AutoActivationTask implements Runnable { /** * @see java.lang.Runnable#run() */ @Override public void run() { for (String databaseId: AbstractDatabaseCluster.this.getInactiveDatabases()) { AbstractDatabaseCluster.this.activate(databaseId); } } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/Invoker.java0000644000175000017500000000274511151703042021712 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import net.sf.hajdbc.Database; /** * Represents a method invocation on a SQL object against a database. * @author Paul Ferraro * @param Type of the root object (e.g. driver, datasource) * @param Target object type of the invocation * @param Return type of this invocation */ public interface Invoker { /** * Invokes an action against the specified database on the specified SQL object * @param database a database * @param object an SQL object * @return the invocation result * @throws Exception */ public R invoke(Database database, T object) throws Exception; }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DataSourceDatabaseClusterMBean.java0000644000175000017500000000307311151703042026214 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import javax.sql.DataSource; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseClusterMBean; /** * @author Paul Ferraro * */ public interface DataSourceDatabaseClusterMBean extends DatabaseClusterMBean, DatabaseCluster { /** * Adds a new DataSource to this cluster using the specified identifier and JNDI name. * @param databaseId a database identifier * @param name the JNDI name use to lookup the DataSource * @throws IllegalArgumentException if this database already exists, or no DataSource was found using the specified name. * @throws IllegalStateException if mbean registration fails. */ public void add(String databaseId, String name); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/BlobInvocationHandler.java0000644000175000017500000000356411216552731024514 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.sql.Blob; import java.util.Map; import java.util.Set; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * @param * @param

*/ @SuppressWarnings("nls") public class BlobInvocationHandler extends LocatorInvocationHandler { private static final Set DATABASE_READ_METHOD_SET = Methods.findMethods(Blob.class, "getBinaryStream", "getBytes", "length", "position"); /** * @param object * @param proxy * @param invoker * @param objectMap * @throws Exception */ protected BlobInvocationHandler(P object, SQLProxy proxy, Invoker invoker, Map, Blob> objectMap) throws Exception { super(object, proxy, invoker, Blob.class, objectMap); } /** * @see net.sf.hajdbc.sql.LocatorInvocationHandler#getDatabaseReadMethodSet() */ @Override protected Set getDatabaseReadMethodSet() { return DATABASE_READ_METHOD_SET; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DriverReadInvocationStrategy.java0000644000175000017500000000266111151703042026076 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.util.Map; import net.sf.hajdbc.Database; /** * @author Paul Ferraro * @param * @param * @param */ public class DriverReadInvocationStrategy implements InvocationStrategy { /** * @see net.sf.hajdbc.sql.InvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public R invoke(SQLProxy proxy, Invoker invoker) throws Exception { Map.Entry, T> entry = proxy.entry(); return invoker.invoke(entry.getKey(), entry.getValue()); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/InactiveDriverDatabaseMBean.java0000644000175000017500000000300411151703042025530 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import net.sf.hajdbc.InactiveDatabaseMBean; /** * @author Paul Ferraro * @since 1.1 */ public interface InactiveDriverDatabaseMBean extends ActiveDriverDatabaseMBean, InactiveDatabaseMBean { /** * Set the url for this database * @param url a database url * @throws IllegalArgumentException if url is not accepted by any driver */ public void setUrl(String url); /** * Set the driver class for this database. * @param driver the driver class name * @throws IllegalArgumentException if driver class could not be found or does not implement java.sql.Driver */ public void setDriver(String driver); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/PreparedStatementInvocationStrategy.java0000644000175000017500000000430311151703042027471 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.PreparedStatement; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * @param */ public class PreparedStatementInvocationStrategy extends DatabaseWriteInvocationStrategy { private Connection connection; private TransactionContext transactionContext; private String sql; /** * @param cluster * @param connection * @param transactionContext * @param sql */ public PreparedStatementInvocationStrategy(DatabaseCluster cluster, Connection connection, TransactionContext transactionContext, String sql) { super(cluster.getNonTransactionalExecutor()); this.connection = connection; this.transactionContext = transactionContext; this.sql = sql; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public PreparedStatement invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(PreparedStatement.class, new PreparedStatementInvocationHandler(this.connection, proxy, invoker, this.invokeAll(proxy, invoker), this.transactionContext, new FileSupportImpl(), this.sql)); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/0000755000175000017500000000000011674455606020417 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/PooledConnectionInvocationStrategy.java0000644000175000017500000000406311151703042030260 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro */ public class PooledConnectionInvocationStrategy extends DatabaseWriteInvocationStrategy { private ConnectionPoolDataSource dataSource; /** * @param cluster * @param dataSource */ public PooledConnectionInvocationStrategy(DatabaseCluster cluster, ConnectionPoolDataSource dataSource) { super(cluster.getNonTransactionalExecutor()); this.dataSource = dataSource; } @Override public PooledConnection invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(PooledConnection.class, new PooledConnectionInvocationHandler(this.dataSource, proxy, invoker, this.invokeAll(proxy, invoker))); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/ConnectionPoolDataSourceReference.java0000644000175000017500000000344611151703042027770 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import javax.sql.ConnectionPoolDataSource; import net.sf.hajdbc.sql.CommonDataSourceReference; /** * @author Paul Ferraro */ public class ConnectionPoolDataSourceReference extends CommonDataSourceReference { private static final long serialVersionUID = 2473805187473417008L; /** * Constructs a reference to a ConnectionPoolDataSource for the specified cluster * @param cluster a cluster identifier */ protected ConnectionPoolDataSourceReference(String cluster) { this(cluster, null); } /** * Constructs a reference to a ConnectionPoolDataSource for the specified cluster * @param cluster a cluster identifier * @param config the uri of the configuration file */ protected ConnectionPoolDataSourceReference(String cluster, String config) { super(ConnectionPoolDataSource.class, ConnectionPoolDataSourceFactory.class, cluster, config); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/ConnectionPoolDataSourceDatabase.java0000644000175000017500000000350711205604526027603 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.sql.Connection; import java.sql.SQLException; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import net.sf.hajdbc.sql.CommonDataSourceDatabase; /** * A database described by a {@link ConnectionPoolDataSource}. * @author Paul Ferraro */ public class ConnectionPoolDataSourceDatabase extends CommonDataSourceDatabase { /** * Constructs a new database described by a {@link ConnectionPoolDataSource}. */ public ConnectionPoolDataSourceDatabase() { super(ConnectionPoolDataSource.class); } /** * @see net.sf.hajdbc.Database#connect(java.lang.Object) */ @Override public Connection connect(ConnectionPoolDataSource dataSource) throws SQLException { String user = this.getUser(); PooledConnection connection = (user != null) ? dataSource.getPooledConnection(user, this.getPassword()) : dataSource.getPooledConnection(); return connection.getConnection(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/ConnectionPoolDataSourceDatabaseClusterMBean.java0000644000175000017500000000224211151703042032034 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import javax.sql.ConnectionPoolDataSource; import net.sf.hajdbc.sql.CommonDataSourceDatabaseClusterMBean; /** * @author Paul Ferraro * */ public interface ConnectionPoolDataSourceDatabaseClusterMBean extends CommonDataSourceDatabaseClusterMBean { } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/AbstractPooledConnectionInvocationHandler.java0000644000175000017500000001410511216552316031525 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.lang.reflect.Method; import java.sql.SQLException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.sql.ConnectionEventListener; import javax.sql.PooledConnection; import javax.sql.StatementEventListener; import net.sf.hajdbc.Database; import net.sf.hajdbc.sql.AbstractChildInvocationHandler; import net.sf.hajdbc.sql.ConnectionInvocationStrategy; import net.sf.hajdbc.sql.DriverWriteInvocationStrategy; import net.sf.hajdbc.sql.InvocationStrategy; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.sql.TransactionContext; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * @param * @param */ @SuppressWarnings("nls") public abstract class AbstractPooledConnectionInvocationHandler extends AbstractChildInvocationHandler { private static final Method addConnectionEventListenerMethod = Methods.getMethod(PooledConnection.class, "addConnectionEventListener", ConnectionEventListener.class); private static final Method addStatementEventListenerMethod = Methods.getMethod(PooledConnection.class, "addStatementEventListener", StatementEventListener.class); private static final Method removeConnectionEventListenerMethod = Methods.getMethod(PooledConnection.class, "removeConnectionEventListener", ConnectionEventListener.class); private static final Method removeStatementEventListenerMethod = Methods.getMethod(PooledConnection.class, "removeStatementEventListener", StatementEventListener.class); private static final Set eventListenerMethodSet = new HashSet(Arrays.asList(addConnectionEventListenerMethod, addStatementEventListenerMethod, removeConnectionEventListenerMethod, removeStatementEventListenerMethod)); private static final Method getConnectionMethod = Methods.getMethod(PooledConnection.class, "getConnection"); private static final Method closeMethod = Methods.getMethod(PooledConnection.class, "close"); private Map> connectionEventListenerInvokerMap = new HashMap>(); private Map> statementEventListenerInvokerMap = new HashMap>(); /** * @param dataSource * @param proxy * @param invoker * @param proxyClass * @param objectMap * @throws Exception */ protected AbstractPooledConnectionInvocationHandler(D dataSource, SQLProxy proxy, Invoker invoker, Class proxyClass, Map, C> objectMap) throws Exception { super(dataSource, proxy, invoker, proxyClass, objectMap); } @Override protected InvocationStrategy getInvocationStrategy(C connection, Method method, Object[] parameters) throws Exception { if (eventListenerMethodSet.contains(method)) { return new DriverWriteInvocationStrategy(); } if (method.equals(getConnectionMethod)) { return new ConnectionInvocationStrategy(this.cluster, connection, this.createTransactionContext()); } return super.getInvocationStrategy(connection, method, parameters); } @Override protected void postInvoke(C connection, Method method, Object[] parameters) { if (method.equals(closeMethod)) { this.getParentProxy().removeChild(this); } } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#close(java.lang.Object, java.lang.Object) */ @Override protected void close(D dataSource, C connection) throws SQLException { connection.close(); } protected abstract TransactionContext createTransactionContext(); /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#record(net.sf.hajdbc.sql.Invoker, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected void record(Invoker invoker, Method method, Object[] parameters) { if (method.equals(addConnectionEventListenerMethod)) { synchronized (this.connectionEventListenerInvokerMap) { this.connectionEventListenerInvokerMap.put(parameters[0], invoker); } } else if (method.equals(removeConnectionEventListenerMethod)) { synchronized (this.connectionEventListenerInvokerMap) { this.connectionEventListenerInvokerMap.remove(parameters[0]); } } else if (method.equals(addStatementEventListenerMethod)) { synchronized (this.statementEventListenerInvokerMap) { this.statementEventListenerInvokerMap.put(parameters[0], invoker); } } else if (method.equals(removeStatementEventListenerMethod)) { synchronized (this.statementEventListenerInvokerMap) { this.statementEventListenerInvokerMap.remove(parameters[0]); } } } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#replay(net.sf.hajdbc.Database, java.lang.Object) */ @Override protected void replay(Database database, C connection) throws Exception { synchronized (this.connectionEventListenerInvokerMap) { for (Invoker invoker: this.connectionEventListenerInvokerMap.values()) { invoker.invoke(database, connection); } } synchronized (this.statementEventListenerInvokerMap) { for (Invoker invoker: this.statementEventListenerInvokerMap.values()) { invoker.invoke(database, connection); } } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/ConnectionPoolDataSourceInvocationHandler.java0000644000175000017500000000415611151703042031500 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.lang.reflect.Method; import java.util.Set; import javax.sql.ConnectionPoolDataSource; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.sql.CommonDataSourceInvocationHandler; import net.sf.hajdbc.sql.InvocationStrategy; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") public class ConnectionPoolDataSourceInvocationHandler extends CommonDataSourceInvocationHandler { private static final Set getPooledConnectionMethodSet = Methods.findMethods(ConnectionPoolDataSource.class, "getPooledConnection"); /** * @param databaseCluster */ public ConnectionPoolDataSourceInvocationHandler(DatabaseCluster databaseCluster) { super(databaseCluster, ConnectionPoolDataSource.class); } @Override protected InvocationStrategy getInvocationStrategy(ConnectionPoolDataSource dataSource, Method method, Object[] parameters) throws Exception { if (getPooledConnectionMethodSet.contains(method)) { return new PooledConnectionInvocationStrategy(this.cluster, dataSource); } return super.getInvocationStrategy(dataSource, method, parameters); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/ConnectionPoolDataSource.java0000644000175000017500000000554011151703042026146 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.io.PrintWriter; import java.sql.SQLException; import javax.naming.NamingException; import javax.naming.Reference; import javax.sql.PooledConnection; import net.sf.hajdbc.sql.CommonDataSourceProxy; /** * @author Paul Ferraro * */ public class ConnectionPoolDataSource extends CommonDataSourceProxy implements javax.sql.ConnectionPoolDataSource { /** * Constructs a new ConnectionPoolDataSource */ public ConnectionPoolDataSource() { super(new ConnectionPoolDataSourceFactory()); } /** * @see javax.sql.ConnectionPoolDataSource#getPooledConnection() */ @Override public PooledConnection getPooledConnection() throws SQLException { return this.getProxy().getPooledConnection(); } /** * @see javax.sql.ConnectionPoolDataSource#getPooledConnection(java.lang.String, java.lang.String) */ @Override public PooledConnection getPooledConnection(String user, String password) throws SQLException { return this.getProxy().getPooledConnection(user, password); } /** * @see javax.sql.CommonDataSource#getLoginTimeout() */ @Override public int getLoginTimeout() throws SQLException { return this.getProxy().getLoginTimeout(); } /** * @see javax.sql.CommonDataSource#getLogWriter() */ @Override public PrintWriter getLogWriter() throws SQLException { return this.getProxy().getLogWriter(); } /** * @see javax.sql.CommonDataSource#setLoginTimeout(int) */ @Override public void setLoginTimeout(int timeout) throws SQLException { this.getProxy().setLoginTimeout(timeout); } /** * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter) */ @Override public void setLogWriter(PrintWriter writer) throws SQLException { this.getProxy().setLogWriter(writer); } /** * @see javax.naming.Referenceable#getReference() */ @Override public Reference getReference() throws NamingException { return new ConnectionPoolDataSourceReference(this.getCluster(), this.getConfig()); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/PooledConnectionInvocationHandler.java0000644000175000017500000000421211151703042030027 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.util.Map; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; import net.sf.hajdbc.Database; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.LocalTransactionContext; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.sql.TransactionContext; /** * @author Paul Ferraro * */ public class PooledConnectionInvocationHandler extends AbstractPooledConnectionInvocationHandler { /** * @param dataSource * @param proxy * @param invoker * @param objectMap * @throws Exception */ protected PooledConnectionInvocationHandler(ConnectionPoolDataSource dataSource, SQLProxy proxy, Invoker invoker, Map, PooledConnection> objectMap) throws Exception { super(dataSource, proxy, invoker, PooledConnection.class, objectMap); } /** * @see net.sf.hajdbc.sql.pool.AbstractPooledConnectionInvocationHandler#createTransactionContext() */ @Override protected TransactionContext createTransactionContext() { return new LocalTransactionContext(this.cluster); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/ConnectionPoolDataSourceDatabaseCluster.java0000644000175000017500000000403211151703042031130 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.net.URL; import javax.sql.ConnectionPoolDataSource; import net.sf.hajdbc.sql.CommonDataSourceDatabase; import net.sf.hajdbc.sql.CommonDataSourceDatabaseCluster; import org.jibx.runtime.IUnmarshallingContext; /** * @author Paul Ferraro * */ public class ConnectionPoolDataSourceDatabaseCluster extends CommonDataSourceDatabaseCluster implements ConnectionPoolDataSourceDatabaseClusterMBean { /** * Object factory for JiBX that pulls the cluster instance from the unmarshalling context * @param context unmarshalling context * @return a database cluster */ public static ConnectionPoolDataSourceDatabaseCluster extractDatabaseCluster(IUnmarshallingContext context) { return (ConnectionPoolDataSourceDatabaseCluster) context.getUserContext(); } /** * @param id * @param url */ public ConnectionPoolDataSourceDatabaseCluster(String id, URL url) { super(id, url); } /** * @see net.sf.hajdbc.sql.CommonDataSourceDatabaseCluster#createDatabase() */ @Override protected CommonDataSourceDatabase createDatabase() { return new ConnectionPoolDataSourceDatabase(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/pool/ConnectionPoolDataSourceFactory.java0000644000175000017500000000425311151703042027476 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.pool; import java.lang.reflect.InvocationHandler; import java.sql.SQLException; import javax.sql.ConnectionPoolDataSource; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseClusterFactory; import net.sf.hajdbc.sql.CommonDataSourceObjectFactory; /** * @author Paul Ferraro * */ public class ConnectionPoolDataSourceFactory extends CommonDataSourceObjectFactory { /** * Constructs a new factory for creating a ConnectionPoolDataSource. */ public ConnectionPoolDataSourceFactory() { super(ConnectionPoolDataSource.class); } /** * @see net.sf.hajdbc.sql.CommonDataSourceObjectFactory#getDatabaseCluster(java.lang.String, java.lang.String) */ @Override protected DatabaseCluster getDatabaseCluster(String id, String config) throws SQLException { return DatabaseClusterFactory.getDatabaseCluster(id, ConnectionPoolDataSourceDatabaseCluster.class, ConnectionPoolDataSourceDatabaseClusterMBean.class, config); } /** * @see net.sf.hajdbc.sql.CommonDataSourceObjectFactory#getInvocationHandler(net.sf.hajdbc.DatabaseCluster) */ @Override protected InvocationHandler getInvocationHandler(DatabaseCluster cluster) { return new ConnectionPoolDataSourceInvocationHandler(cluster); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/SavepointInvocationHandler.java0000644000175000017500000000457511151703042025600 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.SQLException; import java.sql.Savepoint; import java.util.Map; import net.sf.hajdbc.Database; /** * @author Paul Ferraro * @param */ public class SavepointInvocationHandler extends AbstractChildInvocationHandler { /** * @param connection the connection that created this savepoint * @param proxy the invocation handler of the connection that created this savepoint * @param invoker the invoker used to create this savepoint * @param savepointMap a map of database to underlying savepoint * @throws Exception */ protected SavepointInvocationHandler(Connection connection, SQLProxy proxy, Invoker invoker, Map, Savepoint> savepointMap) throws Exception { super(connection, proxy, invoker, Savepoint.class, savepointMap); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(Savepoint object, Method method, Object[] parameters) { return new DriverReadInvocationStrategy(); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#close(java.lang.Object, java.lang.Object) */ @Override protected void close(Connection connection, Savepoint savepoint) throws SQLException { connection.releaseSavepoint(savepoint); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/InvocationStrategy.java0000644000175000017500000000267711151703042024135 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; /** * Defines a strategy for invoking an invoker. * @author Paul Ferraro * @param Type of the root object (e.g. driver, datasource) * @param Target object type of the invocation * @param Return type of this invocation */ public interface InvocationStrategy { /** * Invoke the specified invoker against the specified proxy. * @param proxy a JDBC object proxy * @param invoker an invoker * @return a result * @throws Exception if the invocation fails */ R invoke(SQLProxy proxy, Invoker invoker) throws Exception; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/AbstractChildInvocationHandler.java0000644000175000017500000000466311151703042026335 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.SQLException; import java.util.Map; import net.sf.hajdbc.Database; /** * @author Paul Ferraro * @param * @param

* @param */ public abstract class AbstractChildInvocationHandler extends AbstractInvocationHandler { private P parentObject; private SQLProxy parentProxy; private Invoker parentInvoker; protected AbstractChildInvocationHandler(P parent, SQLProxy proxy, Invoker invoker, Class proxyClass, Map, T> objectMap) throws Exception { super(proxy.getDatabaseCluster(), proxyClass, objectMap); this.parentObject = parent; this.parentProxy = proxy; this.parentInvoker = invoker; this.parentProxy.addChild(this); } @Override protected T createObject(Database database) throws Exception { P object = this.parentProxy.getObject(database); if (object == null) { throw new IllegalStateException(); } return this.parentInvoker.invoke(database, object); } @Override protected void close(Database database, T object) { try { this.close(this.parentProxy.getObject(database), object); } catch (SQLException e) { this.logger.info(e.getMessage(), e); } } protected abstract void close(P parent, T object) throws SQLException; /** * @see net.sf.hajdbc.sql.SQLProxy#getRoot() */ @Override public final SQLProxy getRoot() { return this.parentProxy.getRoot(); } protected P getParent() { return this.parentObject; } protected SQLProxy getParentProxy() { return this.parentProxy; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/ActiveDriverDatabaseMBean.java0000644000175000017500000000245111151703042025206 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import net.sf.hajdbc.ActiveDatabaseMBean; /** * @author Paul Ferraro * */ public interface ActiveDriverDatabaseMBean extends ActiveDatabaseMBean { /** * Returns the url for this database * @return a database url */ public String getUrl(); /** * Returns the driver class name for this database. * @return a driver class name */ public String getDriver(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/LockingInvocationStrategy.java0000644000175000017500000000402311151703042025427 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.util.List; import java.util.concurrent.locks.Lock; /** * An invocation strategy decorator that acquires a list of locks before invocation, and releases them afterward. * @author Paul Ferraro * @param Type of the root object (e.g. driver, datasource) * @param Target object type of the invocation * @param Return type of this invocation */ public class LockingInvocationStrategy implements InvocationStrategy { private InvocationStrategy strategy; private List lockList; /** * @param strategy * @param lockList */ public LockingInvocationStrategy(InvocationStrategy strategy, List lockList) { this.strategy = strategy; this.lockList = lockList; } /** * @see net.sf.hajdbc.sql.InvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public R invoke(SQLProxy proxy, Invoker invoker) throws Exception { for (Lock lock: this.lockList) { lock.lock(); } try { return this.strategy.invoke(proxy, invoker); } finally { for (Lock lock: this.lockList) { lock.unlock(); } } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DriverDatabaseCluster.java0000644000175000017500000000371711151703042024517 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.net.URL; import java.sql.Driver; import org.jibx.runtime.IUnmarshallingContext; /** * @author Paul Ferraro * */ public class DriverDatabaseCluster extends AbstractDatabaseCluster implements DriverDatabaseClusterMBean { /** * Object factory for JiBX that pulls the cluster instance from the unmarshalling context * @param context unmarshalling context * @return a database cluster */ public static DriverDatabaseCluster extractDatabaseCluster(IUnmarshallingContext context) { return (DriverDatabaseCluster) context.getUserContext(); } /** * Constructs a new DriverDatabaseCluster * @param id * @param url */ public DriverDatabaseCluster(String id, URL url) { super(id, url); } /** * @see net.sf.hajdbc.sql.DriverDatabaseClusterMBean#add(java.lang.String, java.lang.String, java.lang.String) */ @Override public void add(String databaseId, String driver, String url) { DriverDatabase database = new DriverDatabase(); database.setId(databaseId); database.setDriver(driver); database.setUrl(url); this.add(database); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/StatementInvocationHandler.java0000644000175000017500000000356711151703042025574 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.Statement; import java.util.Map; import net.sf.hajdbc.Database; /** * @author Paul Ferraro * @param */ public class StatementInvocationHandler extends AbstractStatementInvocationHandler { /** * @param connection the connection that created this statement * @param proxy the invocation handler of the connection that created this statement * @param invoker the invoker used to create this statement * @param statementMap a map of database to underlying statement * @param transactionContext * @param fileSupport support for streams * @throws Exception */ public StatementInvocationHandler(Connection connection, SQLProxy proxy, Invoker invoker, Map, Statement> statementMap, TransactionContext transactionContext, FileSupport fileSupport) throws Exception { super(connection, proxy, invoker, Statement.class, statementMap, transactionContext, fileSupport); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CommonDataSourceDatabaseCluster.java0000644000175000017500000000321611151703042026461 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.net.URL; /** * @author Paul Ferraro * @param */ public abstract class CommonDataSourceDatabaseCluster extends AbstractDatabaseCluster implements CommonDataSourceDatabaseClusterMBean { /** * Constructs a new DataSourceDatabaseCluster * @param id * @param url */ public CommonDataSourceDatabaseCluster(String id, URL url) { super(id, url); } /** * @see net.sf.hajdbc.sql.DataSourceDatabaseClusterMBean#add(java.lang.String, java.lang.String) */ @Override public void add(String databaseId, String name) { CommonDataSourceDatabase database = this.createDatabase(); database.setId(databaseId); database.setName(name); this.add(database); } protected abstract CommonDataSourceDatabase createDatabase(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/CommonDataSourceDatabase.java0000644000175000017500000001062511210276430025123 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; import java.lang.reflect.InvocationTargetException; import java.util.Properties; import javax.management.DynamicMBean; import javax.management.NotCompliantMBeanException; import javax.management.StandardMBean; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import net.sf.hajdbc.Messages; /** * A database described by a data source. * @author Paul Ferraro * @param javax.sql data source interface */ public abstract class CommonDataSourceDatabase extends AbstractDatabase implements InactiveDataSourceDatabaseMBean { private String name; private Class targetClass; protected CommonDataSourceDatabase(Class targetClass) { this.targetClass = targetClass; } /** * @see net.sf.hajdbc.sql.ActiveDataSourceDatabaseMBean#getName() */ @Override public String getName() { return this.name; } /** * @see net.sf.hajdbc.sql.InactiveDataSourceDatabaseMBean#setName(java.lang.String) */ @Override public void setName(String name) { this.checkDirty(this.name, name); this.name = name; } /** * @see net.sf.hajdbc.Database#createConnectionFactory() */ @Override public D createConnectionFactory() { try { Class dataSourceClass = Class.forName(this.name); return this.createDataSource(dataSourceClass.asSubclass(this.targetClass)); } catch (ClassNotFoundException e) { return this.createDataSource(); } } private D createDataSource() { try { Context context = new InitialContext(this.getProperties()); return this.targetClass.cast(context.lookup(this.name)); } catch (NamingException e) { throw new IllegalArgumentException(Messages.getMessage(Messages.JNDI_LOOKUP_FAILED, this.name), e); } } private D createDataSource(Class dataSourceClass) { Properties properties = this.getProperties(); try { D dataSource = dataSourceClass.newInstance(); for (PropertyDescriptor descriptor: Introspector.getBeanInfo(dataSourceClass).getPropertyDescriptors()) { String value = properties.getProperty(descriptor.getName()); if (value != null) { PropertyEditor editor = PropertyEditorManager.findEditor(descriptor.getPropertyType()); editor.setAsText(value); descriptor.getWriteMethod().invoke(dataSource, editor.getValue()); } } return dataSource; } catch (InstantiationException e) { throw new IllegalArgumentException(e.toString(), e); } catch (IllegalAccessException e) { throw new IllegalArgumentException(e.toString(), e); } catch (IntrospectionException e) { throw new IllegalArgumentException(e.toString(), e); } catch (InvocationTargetException e) { throw new IllegalArgumentException(e.getTargetException().toString(), e); } } /** * @see net.sf.hajdbc.Database#getActiveMBean() */ @Override public DynamicMBean getActiveMBean() { try { return new StandardMBean(this, ActiveDataSourceDatabaseMBean.class); } catch (NotCompliantMBeanException e) { throw new IllegalStateException(e); } } /** * @see net.sf.hajdbc.Database#getInactiveMBean() */ @Override public DynamicMBean getInactiveMBean() { try { return new StandardMBean(this, InactiveDataSourceDatabaseMBean.class); } catch (NotCompliantMBeanException e) { throw new IllegalStateException(e); } } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/LocatorInvocationHandler.java0000644000175000017500000000722211216552707025237 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import net.sf.hajdbc.Database; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * @param * @param

* @param */ public abstract class LocatorInvocationHandler extends AbstractChildInvocationHandler { private final Method freeMethod; private final List> invokerList = new LinkedList>(); /** * @param parent * @param proxy * @param invoker * @param proxyClass * @param objectMap * @throws Exception */ protected LocatorInvocationHandler(P parent, SQLProxy proxy, Invoker invoker, Class proxyClass, Map, E> objectMap) throws Exception { super(parent, proxy, invoker, proxyClass, objectMap); this.freeMethod = Methods.findMethod(proxyClass, "free"); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(E object, Method method, Object[] parameters) throws Exception { if (this.getDatabaseReadMethodSet().contains(method)) { return new DatabaseReadInvocationStrategy(); } return super.getInvocationStrategy(object, method, parameters); } protected abstract Set getDatabaseReadMethodSet(); /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#postInvoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @SuppressWarnings("nls") @Override protected void postInvoke(E object, Method method, Object[] parameters) { if ((this.freeMethod != null) && method.equals(this.freeMethod)) { this.getParentProxy().removeChild(this); } } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#close(java.lang.Object, java.lang.Object) */ @SuppressWarnings("nls") @Override protected void close(P parent, E locator) { if (this.freeMethod != null) { try { // free() is a Java 1.6 method - so invoke reflectively this.freeMethod.invoke(locator); } catch (IllegalAccessException e) { this.logger.warn(e.getMessage(), e); } catch (InvocationTargetException e) { this.logger.warn(e.toString(), e.getTargetException()); } } } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#record(net.sf.hajdbc.sql.Invoker, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected void record(Invoker invoker, Method method, Object[] parameters) { if (this.isRecordable(method)) { synchronized (this.invokerList) { this.invokerList.add(invoker); } } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DriverInvocationHandler.java0000644000175000017500000000233311151703042025051 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Driver; import net.sf.hajdbc.DatabaseCluster; /** * @author Paul Ferraro * */ public class DriverInvocationHandler extends AbstractRootInvocationHandler { /** * @param databaseCluster */ public DriverInvocationHandler(DatabaseCluster databaseCluster) { super(databaseCluster, Driver.class); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/AbstractInvocationHandler.java0000644000175000017500000003625711216552617025411 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.sql.SQLException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.WeakHashMap; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.Messages; import net.sf.hajdbc.util.SQLExceptionFactory; import net.sf.hajdbc.util.reflect.Methods; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Paul Ferraro * @param * @param */ @SuppressWarnings("nls") public abstract class AbstractInvocationHandler implements InvocationHandler, SQLProxy { private static final Method equalsMethod = Methods.getMethod(Object.class, "equals", Object.class); private static final Method hashCodeMethod = Methods.getMethod(Object.class, "hashCode"); private static final Method toStringMethod = Methods.getMethod(Object.class, "toString"); /* JDBC 4.0 methods */ private static final Method isWrapperForMethod = Methods.findMethod("java.sql.Wrapper", "isWrapperFor", Class.class); private static final Method unwrapMethod = Methods.findMethod("java.sql.Wrapper", "unwrap", Class.class); protected Logger logger = LoggerFactory.getLogger(this.getClass()); protected DatabaseCluster cluster; private Class proxyClass; private Map, T> objectMap; private Map, Void> childMap = new WeakHashMap, Void>(); private Map> invokerMap = new HashMap>(); /** * @param cluster the database cluster * @param proxyClass the interface being proxied * @param objectMap a map of database to sql object. */ protected AbstractInvocationHandler(DatabaseCluster cluster, Class proxyClass, Map, T> objectMap) { this.cluster = cluster; this.proxyClass = proxyClass; this.objectMap = objectMap; } /** * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @SuppressWarnings("unchecked") @Override public final Object invoke(Object object, Method method, Object[] parameters) throws Exception { if (method.equals(toStringMethod)) return ""; if (!this.cluster.isActive()) { throw new SQLException(Messages.getMessage(Messages.CLUSTER_NOT_ACTIVE, this.cluster)); } T proxy = this.proxyClass.cast(object); InvocationStrategy strategy = this.getInvocationStrategy(proxy, method, parameters); Invoker invoker = this.getInvoker(proxy, method, parameters); Object result = strategy.invoke(this, invoker); this.record(invoker, method, parameters); this.postInvoke(proxy, method, parameters); return result; } /** * Returns the appropriate {@link InvocationStrategy} for the specified method. * This implementation detects {@link java.sql.Wrapper} methods; and {@link Object#equals}, {@link Object#hashCode()}, and {@link Object#toString()}. * Default invocation strategy is {@link DatabaseWriteInvocationStrategy}. * @param object the proxied object * @param method the method to invoke * @param parameters the method invocation parameters * @return an invocation strategy * @throws Exception */ protected InvocationStrategy getInvocationStrategy(final T object, Method method, final Object[] parameters) throws Exception { // Most Java 1.6 sql classes implement java.sql.Wrapper if (((isWrapperForMethod != null) && method.equals(isWrapperForMethod)) || ((unwrapMethod != null) && method.equals(unwrapMethod))) { return new DriverReadInvocationStrategy(); } if (method.equals(equalsMethod)) { return new InvocationStrategy() { public Boolean invoke(SQLProxy proxy, Invoker invoker) { return object == parameters[0]; } }; } if (method.equals(hashCodeMethod) || method.equals(toStringMethod)) { return new DriverReadInvocationStrategy(); } return new DatabaseWriteInvocationStrategy(this.cluster.getNonTransactionalExecutor()); } /** * Return the appropriate invoker for the specified method. * @param object * @param method * @param parameters * @return an invoker * @throws Exception */ protected Invoker getInvoker(T object, Method method, Object[] parameters) throws Exception { if (this.isSQLMethod(method)) { long now = System.currentTimeMillis(); if (this.cluster.isCurrentTimestampEvaluationEnabled()) { parameters[0] = this.cluster.getDialect().evaluateCurrentTimestamp((String) parameters[0], new java.sql.Timestamp(now)); } if (this.cluster.isCurrentDateEvaluationEnabled()) { parameters[0] = this.cluster.getDialect().evaluateCurrentDate((String) parameters[0], new java.sql.Date(now)); } if (this.cluster.isCurrentTimeEvaluationEnabled()) { parameters[0] = this.cluster.getDialect().evaluateCurrentTime((String) parameters[0], new java.sql.Time(now)); } if (this.cluster.isRandEvaluationEnabled()) { parameters[0] = this.cluster.getDialect().evaluateRand((String) parameters[0]); } } return new SimpleInvoker(method, parameters); } /** * Indicates whether or not the specified method accepts a SQL string as its first parameter. * @param method a method * @return true, if the specified method accepts a SQL string as its first parameter, false otherwise. */ protected boolean isSQLMethod(Method method) { return false; } /** * Called after method is invoked. * @param proxy the proxied object * @param method the method that was just invoked * @param parameters the parameters of the method that was just invoked */ protected void postInvoke(T proxy, Method method, Object[] parameters) { // Do nothing } /** * @see net.sf.hajdbc.sql.SQLProxy#entry() */ @Override public Map.Entry, T> entry() { synchronized (this.objectMap) { return this.objectMap.entrySet().iterator().next(); } } /** * @see net.sf.hajdbc.sql.SQLProxy#entries() */ @Override public Set, T>> entries() { synchronized (this.objectMap) { return this.objectMap.entrySet(); } } /** * @see net.sf.hajdbc.sql.SQLProxy#addChild(net.sf.hajdbc.sql.SQLProxy) */ @Override public final void addChild(SQLProxy child) { synchronized (this.childMap) { this.childMap.put(child, null); } } /** * @see net.sf.hajdbc.sql.SQLProxy#removeChildren() */ @Override public final void removeChildren() { synchronized (this.childMap) { this.childMap.clear(); } } /** * @see net.sf.hajdbc.sql.SQLProxy#removeChild(net.sf.hajdbc.sql.SQLProxy) */ @Override public final void removeChild(SQLProxy child) { child.removeChildren(); synchronized (this.childMap) { this.childMap.remove(child); } } /** * Returns the underlying SQL object for the specified database. * If the sql object does not exist (this might be the case if the database was newly activated), it will be created from the stored operation. * Any recorded operations are also executed. If the object could not be created, or if any of the executed operations failed, then the specified database is deactivated. * @param database a database descriptor. * @return an underlying SQL object */ @Override public T getObject(Database database) { synchronized (this.objectMap) { T object = this.objectMap.get(database); if (object == null) { try { object = this.createObject(database); this.replay(database, object); this.objectMap.put(database, object); } catch (Exception e) { if (!this.objectMap.isEmpty() && this.cluster.deactivate(database, this.cluster.getStateManager())) { this.logger.warn(Messages.getMessage(Messages.SQL_OBJECT_INIT_FAILED, this.getClass().getName(), database), e); } } } return object; } } protected abstract T createObject(Database database) throws Exception; protected void record(Invoker invoker, Method method, Object[] parameters) { // Record only the last invocation of a given recordable method if (this.isRecordable(method)) { synchronized (this.invokerMap) { this.invokerMap.put(method, invoker); } } } protected boolean isRecordable(Method method) { return false; } protected void replay(Database database, T object) throws Exception { synchronized (this.invokerMap) { for (Invoker invoker: this.invokerMap.values()) { invoker.invoke(database, object); } } } /** * @see net.sf.hajdbc.sql.SQLProxy#retain(java.util.Set) */ @Override public final void retain(Set> databaseSet) { synchronized (this.childMap) { for (SQLProxy child: this.childMap.keySet()) { child.retain(databaseSet); } } synchronized (this.objectMap) { Iterator, T>> mapEntries = this.objectMap.entrySet().iterator(); while (mapEntries.hasNext()) { Map.Entry, T> mapEntry = mapEntries.next(); Database database = mapEntry.getKey(); if (!databaseSet.contains(database)) { T object = mapEntry.getValue(); if (object != null) { this.close(database, object); } mapEntries.remove(); } } } } protected abstract void close(Database database, T object); /** * @see net.sf.hajdbc.sql.SQLProxy#getDatabaseCluster() */ @Override public final DatabaseCluster getDatabaseCluster() { return this.cluster; } /** * @see net.sf.hajdbc.sql.SQLProxy#handleFailure(net.sf.hajdbc.Database, java.lang.Exception) */ @Override public void handleFailure(Database database, Exception exception) throws Exception { Set> databaseSet = this.cluster.getBalancer().all(); // If cluster has only one database left, don't deactivate if (databaseSet.size() <= 1) { throw exception; } Map>> aliveMap = this.cluster.getAliveMap(databaseSet); this.detectClusterPanic(aliveMap); List> aliveList = aliveMap.get(true); // If all are dead, assume the worst and throw caught exception // If failed database is alive, then throw caught exception if (aliveList.isEmpty() || aliveList.contains(database)) { throw exception; } // Otherwise deactivate failed database if (this.cluster.deactivate(database, this.cluster.getStateManager())) { this.logger.error(Messages.getMessage(Messages.DATABASE_DEACTIVATED, database, this), exception); } } /** * @see net.sf.hajdbc.sql.SQLProxy#handleFailures(java.util.SortedMap) */ @Override public void handleFailures(SortedMap, Exception> exceptionMap) throws Exception { if (exceptionMap.size() == 1) { throw exceptionMap.get(exceptionMap.firstKey()); } Map>> aliveMap = this.cluster.getAliveMap(exceptionMap.keySet()); this.detectClusterPanic(aliveMap); List> aliveList = aliveMap.get(true); List> deadList = aliveMap.get(false); if (!aliveList.isEmpty()) { for (Database database: deadList) { if (this.cluster.deactivate(database, this.cluster.getStateManager())) { this.logger.error(Messages.getMessage(Messages.DATABASE_DEACTIVATED, database, this.cluster), exceptionMap.get(database)); } } } List> list = aliveList.isEmpty() ? deadList : aliveList; SQLException exception = SQLExceptionFactory.createSQLException(exceptionMap.get(list.get(0))); for (Database database: list.subList(1, list.size())) { exception.setNextException(SQLExceptionFactory.createSQLException(exceptionMap.get(database))); } throw exception; } /** * @see net.sf.hajdbc.sql.SQLProxy#handlePartialFailure(java.util.SortedMap, java.util.SortedMap) */ @Override public SortedMap, R> handlePartialFailure(SortedMap, R> resultMap, SortedMap, Exception> exceptionMap) throws Exception { Map>> aliveMap = this.cluster.getAliveMap(exceptionMap.keySet()); // Assume success databases are alive aliveMap.get(true).addAll(resultMap.keySet()); this.detectClusterPanic(aliveMap); for (Map.Entry, Exception> exceptionMapEntry: exceptionMap.entrySet()) { Database database = exceptionMapEntry.getKey(); Exception exception = exceptionMapEntry.getValue(); if (this.cluster.deactivate(database, this.cluster.getStateManager())) { this.logger.error(Messages.getMessage(Messages.DATABASE_DEACTIVATED, database, this.cluster), exception); } } return resultMap; } /** * Detect cluster panic if all conditions are met: *

    *
  • We're in distributable mode
  • *
  • We're the only group member
  • *
  • All alive databases are local
  • *
  • All dead databases are remote
  • *
* @param aliveMap * @throws Exception */ protected void detectClusterPanic(Map>> aliveMap) throws Exception { if (this.cluster.getStateManager().isMembershipEmpty()) { List> aliveList = aliveMap.get(true); List> deadList = aliveMap.get(false); if (!aliveList.isEmpty() && !deadList.isEmpty() && sameProximity(aliveList, true) && sameProximity(deadList, false)) { this.cluster.stop(); String message = Messages.getMessage(Messages.CLUSTER_PANIC_DETECTED, this.cluster); this.logger.error(message); throw new SQLException(message); } } } private boolean sameProximity(List> databaseList, boolean local) { boolean same = true; for (Database database: databaseList) { same &= (database.isLocal() == local); } return same; } protected class SimpleInvoker implements Invoker { private Method method; private Object[] parameters; /** * @param method * @param parameters */ public SimpleInvoker(Method method, Object[] parameters) { this.method = method; this.parameters = parameters; } /** * @see net.sf.hajdbc.sql.Invoker#invoke(net.sf.hajdbc.Database, java.lang.Object) */ @Override public Object invoke(Database database, T object) throws Exception { return Methods.invoke(this.method, object, this.parameters); } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DatabaseReadInvocationStrategy.java0000644000175000017500000000476711151703042026360 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.SQLException; import java.util.NoSuchElementException; import java.util.SortedMap; import java.util.TreeMap; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.Messages; /** * @author Paul Ferraro * @param * @param * @param */ public class DatabaseReadInvocationStrategy implements InvocationStrategy { /** * @see net.sf.hajdbc.sql.InvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public R invoke(SQLProxy proxy, Invoker invoker) throws Exception { SortedMap, R> map = this.invokeAll(proxy, invoker); return map.get(map.firstKey()); } protected SortedMap, R> invokeAll(SQLProxy proxy, Invoker invoker) throws Exception { DatabaseCluster cluster = proxy.getDatabaseCluster(); Balancer balancer = cluster.getBalancer(); try { while (true) { Database database = balancer.next(); T object = proxy.getObject(database); try { balancer.beforeInvocation(database); R result = invoker.invoke(database, object); SortedMap, R> resultMap = new TreeMap, R>(); resultMap.put(database, result); return resultMap; } catch (Exception e) { proxy.handleFailure(database, e); } finally { balancer.afterInvocation(database); } } } catch (NoSuchElementException e) { throw new SQLException(Messages.getMessage(Messages.NO_ACTIVE_DATABASES, cluster)); } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/0000755000175000017500000000000011674455606020056 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XADataSourceFactory.java0000644000175000017500000000405511151703042024514 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.lang.reflect.InvocationHandler; import java.sql.SQLException; import javax.sql.XADataSource; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseClusterFactory; import net.sf.hajdbc.sql.CommonDataSourceObjectFactory; /** * @author Paul Ferraro */ public class XADataSourceFactory extends CommonDataSourceObjectFactory { /** * Constructs a new factory for creating an XADataSource. */ public XADataSourceFactory() { super(XADataSource.class); } /** * @see net.sf.hajdbc.sql.CommonDataSourceObjectFactory#getDatabaseCluster(java.lang.String, java.lang.String) */ @Override protected DatabaseCluster getDatabaseCluster(String id, String config) throws SQLException { return DatabaseClusterFactory.getDatabaseCluster(id, XADataSourceDatabaseCluster.class, XADataSourceDatabaseClusterMBean.class, config); } /** * @see net.sf.hajdbc.sql.CommonDataSourceObjectFactory#getInvocationHandler(net.sf.hajdbc.DatabaseCluster) */ @Override protected InvocationHandler getInvocationHandler(DatabaseCluster cluster) { return new XADataSourceInvocationHandler(cluster); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XAConnectionInvocationStrategy.java0000644000175000017500000000363211151703042027006 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import javax.sql.XAConnection; import javax.sql.XADataSource; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * */ public class XAConnectionInvocationStrategy extends DatabaseWriteInvocationStrategy { private XADataSource dataSource; /** * @param cluster * @param dataSource */ public XAConnectionInvocationStrategy(DatabaseCluster cluster, XADataSource dataSource) { super(cluster.getNonTransactionalExecutor()); this.dataSource = dataSource; } @Override public XAConnection invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(XAConnection.class, new XAConnectionInvocationHandler(this.dataSource, proxy, invoker, this.invokeAll(proxy, invoker))); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XADataSource.java0000644000175000017500000000531311151703042023162 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.io.PrintWriter; import java.sql.SQLException; import javax.naming.NamingException; import javax.naming.Reference; import javax.sql.XAConnection; import net.sf.hajdbc.sql.CommonDataSourceProxy; /** * @author Paul Ferraro */ public class XADataSource extends CommonDataSourceProxy implements javax.sql.XADataSource { /** * Constructs a new XADataSource */ public XADataSource() { super(new XADataSourceFactory()); } /** * @see javax.sql.XADataSource#getXAConnection() */ @Override public XAConnection getXAConnection() throws SQLException { return this.getProxy().getXAConnection(); } /** * @see javax.sql.XADataSource#getXAConnection(java.lang.String, java.lang.String) */ @Override public XAConnection getXAConnection(String user, String password) throws SQLException { return this.getProxy().getXAConnection(user, password); } /** * @see javax.sql.CommonDataSource#getLoginTimeout() */ @Override public int getLoginTimeout() throws SQLException { return this.getProxy().getLoginTimeout(); } /** * @see javax.sql.CommonDataSource#getLogWriter() */ @Override public PrintWriter getLogWriter() throws SQLException { return this.getProxy().getLogWriter(); } /** * @see javax.sql.CommonDataSource#setLoginTimeout(int) */ @Override public void setLoginTimeout(int timeout) throws SQLException { this.getProxy().setLoginTimeout(timeout); } /** * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter) */ @Override public void setLogWriter(PrintWriter writer) throws SQLException { this.getProxy().setLogWriter(writer); } /** * @see javax.naming.Referenceable#getReference() */ @Override public Reference getReference() throws NamingException { return new XADataSourceReference(this.getCluster(), this.getConfig()); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XADataSourceDatabaseCluster.java0000644000175000017500000000365411151703042026157 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.net.URL; import javax.sql.XADataSource; import org.jibx.runtime.IUnmarshallingContext; import net.sf.hajdbc.sql.CommonDataSourceDatabase; import net.sf.hajdbc.sql.CommonDataSourceDatabaseCluster; /** * @author Paul Ferraro * */ public class XADataSourceDatabaseCluster extends CommonDataSourceDatabaseCluster implements XADataSourceDatabaseClusterMBean { /** * Object factory for JiBX that pulls the cluster instance from the unmarshalling context * @param context unmarshalling context * @return a database cluster */ public static XADataSourceDatabaseCluster extractDatabaseCluster(IUnmarshallingContext context) { return (XADataSourceDatabaseCluster) context.getUserContext(); } /** * @param id * @param url */ public XADataSourceDatabaseCluster(String id, URL url) { super(id, url); } /** * @see net.sf.hajdbc.sql.CommonDataSourceDatabaseCluster#createDatabase() */ @Override protected CommonDataSourceDatabase createDatabase() { return new XADataSourceDatabase(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XAResourceInvocationHandler.java0000644000175000017500000001312011211045264026244 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.lang.reflect.Method; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.Lock; import javax.sql.XAConnection; import javax.sql.XADataSource; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import net.sf.hajdbc.Database; import net.sf.hajdbc.LockManager; import net.sf.hajdbc.sql.AbstractChildInvocationHandler; import net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy; import net.sf.hajdbc.sql.DriverReadInvocationStrategy; import net.sf.hajdbc.sql.InvocationStrategy; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") public class XAResourceInvocationHandler extends AbstractChildInvocationHandler { private static final Set driverReadMethodSet = Methods.findMethods(XAResource.class, "getTransactionTimeout", "isSameRM"); private static final Set databaseWriteMethodSet = Methods.findMethods(XAResource.class, "setTransactionTimeout"); private static final Set intraTransactionMethodSet = Methods.findMethods(XAResource.class, "end", "prepare", "recover"); private static final Method startMethod = Methods.getMethod(XAResource.class, "start", Xid.class, Integer.TYPE); private static final Set endTransactionMethodSet = Methods.findMethods(XAResource.class, "commit", "rollback", "forget"); // Xids are global - so store in static variable private static ConcurrentMap lockMap = new ConcurrentHashMap(); /** * @param connection * @param proxy * @param invoker * @param objectMap * @throws Exception */ protected XAResourceInvocationHandler(XAConnection connection, SQLProxy proxy, Invoker invoker, Map, XAResource> objectMap) throws Exception { super(connection, proxy, invoker, XAResource.class, objectMap); } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#getInvocationStrategy(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override protected InvocationStrategy getInvocationStrategy(XAResource resource, Method method, Object[] parameters) throws Exception { if (driverReadMethodSet.contains(method)) { return new DriverReadInvocationStrategy(); } if (databaseWriteMethodSet.contains(method)) { return new DatabaseWriteInvocationStrategy(this.cluster.getNonTransactionalExecutor()); } if (method.equals(startMethod) || intraTransactionMethodSet.contains(method) || endTransactionMethodSet.contains(method)) { final InvocationStrategy strategy = new DatabaseWriteInvocationStrategy(this.cluster.getTransactionalExecutor()); if (method.equals(startMethod)) { Xid xid = (Xid) parameters[0]; final Lock lock = this.cluster.getLockManager().readLock(LockManager.GLOBAL); // Lock may already exist if we're resuming a suspended transaction Lock existingLock = lockMap.putIfAbsent(xid, lock); if (existingLock == null) { return new InvocationStrategy() { @Override public Object invoke(SQLProxy proxy, Invoker invoker) throws Exception { lock.lock(); return strategy.invoke(proxy, invoker); } }; } } if (endTransactionMethodSet.contains(method)) { final Lock lock = lockMap.remove(parameters[0]); return new InvocationStrategy() { @Override public Object invoke(SQLProxy proxy, Invoker invoker) throws Exception { try { return strategy.invoke(proxy, invoker); } finally { if (lock != null) { lock.unlock(); } } } }; } return strategy; } return super.getInvocationStrategy(resource, method, parameters); } /** * @see net.sf.hajdbc.sql.AbstractChildInvocationHandler#close(java.lang.Object, java.lang.Object) */ @Override protected void close(XAConnection connection, XAResource resource) { // Do nothing } /** * @see net.sf.hajdbc.sql.AbstractInvocationHandler#isRecordable(java.lang.reflect.Method) */ @Override protected boolean isRecordable(Method method) { return databaseWriteMethodSet.contains(method); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XADataSourceDatabase.java0000644000175000017500000000332711205607552024623 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.sql.Connection; import java.sql.SQLException; import javax.sql.XAConnection; import javax.sql.XADataSource; import net.sf.hajdbc.sql.CommonDataSourceDatabase; /** * A database described by an {@link XADataSource}. * @author Paul Ferraro */ public class XADataSourceDatabase extends CommonDataSourceDatabase { /** * Constructs a new database described by an {@link XADataSource}. */ public XADataSourceDatabase() { super(XADataSource.class); } /** * @see net.sf.hajdbc.Database#connect(java.lang.Object) */ @Override public Connection connect(XADataSource dataSource) throws SQLException { String user = this.getUser(); XAConnection connection = (user != null) ? dataSource.getXAConnection(user, this.getPassword()) : dataSource.getXAConnection(); return connection.getConnection(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XADataSourceInvocationHandler.java0000644000175000017500000000373411151703042026517 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.lang.reflect.Method; import java.util.Set; import javax.sql.XADataSource; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.sql.AbstractRootInvocationHandler; import net.sf.hajdbc.sql.InvocationStrategy; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro * */ @SuppressWarnings("nls") public class XADataSourceInvocationHandler extends AbstractRootInvocationHandler { private static final Set getXAConnectionMethodSet = Methods.findMethods(XADataSource.class, "getXAConnection"); /** * @param databaseCluster */ public XADataSourceInvocationHandler(DatabaseCluster databaseCluster) { super(databaseCluster, XADataSource.class); } @Override protected InvocationStrategy getInvocationStrategy(XADataSource dataSource, Method method, Object[] parameters) throws Exception { if (getXAConnectionMethodSet.contains(method)) { return new XAConnectionInvocationStrategy(this.cluster, dataSource); } return super.getInvocationStrategy(dataSource, method, parameters); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XAConnectionInvocationHandler.java0000644000175000017500000000612211151703042026556 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.SQLException; import java.util.Map; import javax.sql.XAConnection; import javax.sql.XADataSource; import net.sf.hajdbc.Database; import net.sf.hajdbc.sql.InvocationStrategy; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.sql.TransactionContext; import net.sf.hajdbc.sql.pool.AbstractPooledConnectionInvocationHandler; import net.sf.hajdbc.util.reflect.Methods; /** * @author Paul Ferraro */ @SuppressWarnings("nls") public class XAConnectionInvocationHandler extends AbstractPooledConnectionInvocationHandler { private static final Method getXAResource = Methods.getMethod(XAConnection.class, "getXAResource"); /** * @param dataSource * @param proxy * @param invoker * @param objectMap * @throws Exception */ public XAConnectionInvocationHandler(XADataSource dataSource, SQLProxy proxy, Invoker invoker, Map, XAConnection> objectMap) throws Exception { super(dataSource, proxy, invoker, XAConnection.class, objectMap); } @Override protected InvocationStrategy getInvocationStrategy(XAConnection connection, Method method, Object[] parameters) throws Exception { if (method.equals(getXAResource)) { return new XAResourceInvocationStrategy(this.cluster, connection); } return super.getInvocationStrategy(connection, method, parameters); } /** * @see net.sf.hajdbc.sql.pool.AbstractPooledConnectionInvocationHandler#createTransactionContext() */ @Override protected TransactionContext createTransactionContext() { return new TransactionContext() { @Override public void close() { // Do nothing } @Override public InvocationStrategy end(InvocationStrategy strategy) throws SQLException { return strategy; } @Override public InvocationStrategy start(InvocationStrategy strategy, Connection connection) throws SQLException { return strategy; } }; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XADataSourceDatabaseClusterMBean.java0000644000175000017500000000217411151703042027056 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import javax.sql.XADataSource; import net.sf.hajdbc.sql.CommonDataSourceDatabaseClusterMBean; /** * @author Paul Ferraro * */ public interface XADataSourceDatabaseClusterMBean extends CommonDataSourceDatabaseClusterMBean { } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XAResourceInvocationStrategy.java0000644000175000017500000000406711151703042026501 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import javax.sql.XAConnection; import javax.sql.XADataSource; import javax.transaction.xa.XAResource; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy; import net.sf.hajdbc.sql.Invoker; import net.sf.hajdbc.sql.SQLProxy; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * */ public class XAResourceInvocationStrategy extends DatabaseWriteInvocationStrategy { private XAConnection connection; /** * @param cluster * @param connection */ public XAResourceInvocationStrategy(DatabaseCluster cluster, XAConnection connection) { super(cluster.getNonTransactionalExecutor()); this.connection = connection; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public XAResource invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(XAResource.class, new XAResourceInvocationHandler(this.connection, proxy, invoker, this.invokeAll(proxy, invoker))); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/xa/XADataSourceReference.java0000644000175000017500000000327511151703042025006 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql.xa; import javax.sql.XADataSource; import net.sf.hajdbc.sql.CommonDataSourceReference; /** * @author Paul Ferraro * */ public class XADataSourceReference extends CommonDataSourceReference { private static final long serialVersionUID = -1333879245815171042L; /** * Constructs a reference to an XADataSource for the specified cluster * @param cluster a cluster identifier */ protected XADataSourceReference(String cluster) { this(cluster, null); } /** * Constructs a reference to an XADataSource for the specified cluster * @param cluster a cluster identifier * @param config the uri of the configuration file */ protected XADataSourceReference(String cluster, String config) { super(XADataSource.class, XADataSourceFactory.class, cluster, config); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/SavepointInvocationStrategy.java0000644000175000017500000000361111151703042026013 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.Savepoint; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.util.reflect.ProxyFactory; /** * @author Paul Ferraro * @param */ public class SavepointInvocationStrategy extends DatabaseWriteInvocationStrategy { private Connection connection; /** * @param cluster * @param connection the connection from which to create savepoints */ public SavepointInvocationStrategy(DatabaseCluster cluster, Connection connection) { super(cluster.getTransactionalExecutor()); this.connection = connection; } /** * @see net.sf.hajdbc.sql.DatabaseWriteInvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, net.sf.hajdbc.sql.Invoker) */ @Override public Savepoint invoke(SQLProxy proxy, Invoker invoker) throws Exception { return ProxyFactory.createProxy(Savepoint.class, new SavepointInvocationHandler(this.connection, proxy, invoker, this.invokeAll(proxy, invoker))); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sql/DataSourceDatabase.java0000644000175000017500000000326411205604467023764 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sql; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; /** * A database described by a {@link DataSource}. * @author Paul Ferraro */ public class DataSourceDatabase extends CommonDataSourceDatabase { /** * Constructs a new database described by a {@link DataSource}. */ public DataSourceDatabase() { super(DataSource.class); } /** * @param dataSource A DataSource * @return a database connection * @throws SQLException if a database connection could not be made * @see net.sf.hajdbc.Database#connect(Object) */ @Override public Connection connect(DataSource dataSource) throws SQLException { String user = this.getUser(); return (user != null) ? dataSource.getConnection(user, this.getPassword()) : dataSource.getConnection(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Messages_es.properties0000644000175000017500000001137611151703042023207 0ustar moellermoeller#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) # # HA-JDBC: High-Availability JDBC # Copyright (c) 2004-2007 Paul Ferraro # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation; either version 2.1 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Contact: ferraro@users.sourceforge.net # cluster-not-active = El cl\u00FAster {0} de bases de datos no est\u00E1 activo. cluster-panic-detected = P\u00E1nico detectado en el cl\u00FAster {0} de bases de datos. cluster-start-failed = Fallo al arrancar el cl\u00FAster {0} de bases de datos. cluster-state-load-failed = Fallo al cargar el estado del cl\u00FAster de bases de datos {0}. cluster-state-store-failed = Fallo al almacenar el estado del cl\u00FAster de bases de datos {0}. command-received = Comando recibido: {0}. config-load-failed = Fallo al cargar la configuraci\u00F3n de HA-JDBC a partir de {0}. config-not-found = No podido localizar el archivo de configuraci\u00F3n del racimo de la base de datos: {0}. config-store-failed = Fallo al guardar la configuraci\u00F3n de HA-JDBC a {0}. database-activate-failed = Fallo al activar la base de datos {0} del cl\u00FAster {1}. database-activated = Base de datos {0} del cl\u00FAster {1} activada. database-already-exists = El cl\u00FAster {1} contiene ya la base de datos {0}. database-deactivated = Base de datos {0} del cl\u00FAster {1} desactivada. database-not-active = La base de datos no estaba activa cuando {0} se cre\u00F3. database-not-alive = La base de datos {0} del cl\u00FAster {1} no est\u00E1 respondiendo. database-still-active = La base de datos {0} del cl\u00FAster {1} no pudo quitarse porque sigue activa. database-sync-end = Finalizada sincronizaci\u00F3n de la base de datos {0} del cl\u00FAster {1}. database-sync-start = Inicio de la sincronizaci\u00F3n de la base de datos {0} del cl\u00FAster {1}. delete-count = Borradas {0} filas de {1}. driver-not-found = Driver {0} no encontrado. driver-register-failed = Fallo al registrar el driver {0}. group-member-joined = {0} se ha unido al canal {1}. group-member-left = {0} ha abandonado el canal {1}. ha-jdbc-init = Incializando HA-JDBC {0} desde {1}. initial-cluster-state-local = Usar el estado local para inicializar el cl\u00FAster {0}. initial-cluster-state-none = Estado inicial del cl\u00FAster no encontrado. initial-cluster-state-remote = Usar el estado remoto de {1} para inicializar el cl\u00FAster {0}. insert-count = Insertadas {0} filas en {1}. invalid-balancer = {0} no es un balanceador v\u00E1lido. invalid-database = El cl\u00FAster de bases de datos {1} no contiene la base de datos {0}. invalid-database-cluster = {0} no es un cl\u00FAster v\u00E1lido de bases de datos. invalid-meta-data-cache = {0} no es una cache de metadatos v\u00E1lida. invalid-property = {0} no es una propiedad v\u00E1lida de {1}. invalid-property-value = {0} no es valor {1} v\u00E1lido para {2}. invalid-sync-strategy = {0} no es una estrategia v\u00E1lida de sincronizaci\u00F3n para el cl\u00FAster. jdbc-url-rejected = Ning\u00FAn driver registrado aceptar\u00E1 la URL {0}. jndi-lookup-failed = Fallo al realizar la b\u00FAsqueda por nombres de {0}. mbean-server-not-found = Ning\u00FAn servidor de mbean encontr\u00F3. no-active-databases = Ninguna base de datos activa en el cl\u00FAster {0}. primary-key-required = La tabla {1} no contiene una clave primaria - Requerida por la estrategia de la sincronizaci\u00F3n {0}. schema-lookup-failed = Fallo al localizar {0} entre los esquemas siguientes: {1}. Verifique la implementaci\u00F3n de {2}. sequence-out-of-sync = El siguiente valor ({2}) para la secuencia {0} de la base de datos {1} no concuerda con el siguiente valor ({4}) de la base de datos {3}. shut-down = Cerrando HA-JDBC. sql-object-init-failed = No pudo inicializarse {0} para la base de datos {1}. statement-failed = Fallo al ejecutar la instrucci\u00F3n: {0}. table-lock-acquire = Adquiriendo los cerrojos de las tablas en las bases de datos activas. table-lock-release = Liberando los cerrojos de las tablas en las bases de datos activas. update-count = Actualizadas {0} filas en {1}. write-lock-failed = Fallo al adquirir el cerrojo exclusivo en el cl\u00FAster {0} de bases de datos. ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseDeactivationListener.java0000644000175000017500000000234611151703042025240 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.EventListener; /** * Event listener for database activations. * @author Paul Ferraro */ public interface DatabaseDeactivationListener extends EventListener { /** * Triggered after database is successfully deactivated. * @param event indicates the database that was deactivated */ public void deactivated(DatabaseEvent event); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/ActiveDatabaseMBean.java0000644000175000017500000000414611151703042023236 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.Properties; /** * @author Paul Ferraro * */ public interface ActiveDatabaseMBean { /** * Returns the unique idenfier for this database * @return a unique identifier */ public String getId(); /** * Returns the relative "weight" of this cluster node. * In general, when choosing a node to service read requests, a cluster will favor the node with the highest weight. * A weight of 0 is somewhat special, depending on the type of balancer used by the cluster. * In most cases, a weight of 0 means that this node will never service read requests unless it is the only node in the cluster. * @return a positive integer */ public int getWeight(); /** * @return the database user */ public String getUser(); /** * @return the password of the database user */ public String getPassword(); /** * Returns a collection of additional properties of this database. * @return additional properties of this database */ public Properties getProperties(); /** * Indicates whether or not this database is local to the machine on which the JVM resides. * @return true if local, false if remote */ public boolean isLocal(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/balancer/0000755000175000017500000000000011674455606020416 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/balancer/BalancerClass.java0000644000175000017500000000553711151703042023744 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Messages; import net.sf.hajdbc.util.ClassEnum; import net.sf.hajdbc.util.Enums; /** * @author Paul Ferraro * @since 1.1 */ public enum BalancerClass implements ClassEnum> { SIMPLE(SimpleBalancer.class), RANDOM(RandomBalancer.class), ROUND_ROBIN(RoundRobinBalancer.class), LOAD(LoadBalancer.class); @SuppressWarnings("unchecked") private Class balancerClass; @SuppressWarnings("unchecked") private BalancerClass(Class balancerClass) { this.balancerClass = balancerClass; } /** * @see net.sf.hajdbc.util.ClassEnum#isInstance(java.lang.Object) */ @Override public boolean isInstance(Balancer balancer) { return this.balancerClass.equals(balancer.getClass()); } /** * @see net.sf.hajdbc.util.ClassEnum#newInstance() */ @Override public Balancer newInstance() throws Exception { return this.balancerClass.newInstance(); } /** * Creates a new instance of the Balancer implementation identified by the specified identifier * @param id an enumerated balancer identifier * @return a new Balancer instance * @throws Exception if specified balancer identifier is invalid */ public static Balancer deserialize(String id) throws Exception { try { return Enums.valueOf(BalancerClass.class, id).newInstance(); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_BALANCER, id)); } } /** * Return the identifier of the specified Balancer. * @param balancer a Balancer implementation * @return the class name of this balancer */ public static String serialize(Balancer balancer) { for (BalancerClass balancerClass: BalancerClass.values()) { if (balancerClass.isInstance(balancer)) { return Enums.id(balancerClass); } } throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_BALANCER, balancer.getClass())); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/balancer/AbstractBalancer.java0000644000175000017500000000743411151703042024440 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import java.util.Collections; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; /** * Thread-safe abstract balancer implementation that implements most of the Balancer interface, except {@link Balancer#next()}. * Uses A copy-on-write algorithm for {@link #add(Database)}, {@link #remove(Database)}, and {@link #clear()}. * Calls to {@link #all()} are non-blocking. * * @author Paul Ferraro * @param either java.sql.Driver or javax.sql.DataSource */ public abstract class AbstractBalancer implements Balancer { protected Lock lock = new ReentrantLock(); protected volatile SortedSet> databaseSet = new TreeSet>(); /** * @see net.sf.hajdbc.Balancer#beforeInvocation(net.sf.hajdbc.Database) */ @Override public void beforeInvocation(Database database) { // Do nothing } /** * @see net.sf.hajdbc.Balancer#afterInvocation(net.sf.hajdbc.Database) */ @Override public void afterInvocation(Database database) { // Do nothing } /** * @see net.sf.hajdbc.Balancer#remove(net.sf.hajdbc.Database) */ @Override public boolean remove(Database database) { this.lock.lock(); try { boolean exists = this.databaseSet.contains(database); if (exists) { SortedSet> set = new TreeSet>(this.databaseSet); set.remove(database); this.databaseSet = set; this.removed(database); } return exists; } finally { this.lock.unlock(); } } /** * Called when a database was removed from the set. * @param database a database descriptor */ protected abstract void removed(Database database); /** * @see net.sf.hajdbc.Balancer#add(net.sf.hajdbc.Database) */ @Override public boolean add(Database database) { this.lock.lock(); try { boolean exists = this.databaseSet.contains(database); if (!exists) { SortedSet> set = new TreeSet>(this.databaseSet); set.add(database); this.databaseSet = set; this.added(database); } return !exists; } finally { this.lock.unlock(); } } /** * Called when a database was added to the set. * @param database a database descriptor */ protected abstract void added(Database database); /** * @see net.sf.hajdbc.Balancer#all() */ @Override public Set> all() { return Collections.unmodifiableSet(this.databaseSet); } /** * @see net.sf.hajdbc.Balancer#clear() */ @Override public void clear() { this.lock.lock(); try { this.databaseSet = new TreeSet>(); this.cleared(); } finally { this.lock.unlock(); } } /** * Called when the set was cleared. */ protected abstract void cleared(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/balancer/LoadBalancer.java0000644000175000017500000001100411151703042023540 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import java.util.Collections; import java.util.Comparator; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; /** * Balancer implementation whose {@link #next()} implementation returns the database with the least load. * * @author Paul Ferraro * @param either java.sql.Driver or javax.sql.DataSource */ public class LoadBalancer implements Balancer { private volatile Map, AtomicInteger> databaseMap = Collections.emptyMap(); private Lock lock = new ReentrantLock(); private Comparator, AtomicInteger>> comparator = new Comparator, AtomicInteger>>() { public int compare(Map.Entry, AtomicInteger> mapEntry1, Map.Entry, AtomicInteger> mapEntry2) { Database database1 = mapEntry1.getKey(); Database database2 = mapEntry2.getKey(); float load1 = mapEntry1.getValue().get(); float load2 = mapEntry2.getValue().get(); int weight1 = database1.getWeight(); int weight2 = database2.getWeight(); // If weights are the same, we can simply compare the loads if (weight1 == weight2) { return Float.compare(load1, load2); } float weightedLoad1 = (weight1 != 0) ? (load1 / weight1) : Float.POSITIVE_INFINITY; float weightedLoad2 = (weight2 != 0) ? (load2 / weight2) : Float.POSITIVE_INFINITY; return Float.compare(weightedLoad1, weightedLoad2); } }; /** * @see net.sf.hajdbc.Balancer#all() */ @Override public Set> all() { return Collections.unmodifiableSet(this.databaseMap.keySet()); } /** * @see net.sf.hajdbc.Balancer#clear() */ @Override public void clear() { this.lock.lock(); try { this.databaseMap = Collections.emptyMap(); } finally { this.lock.unlock(); } } /** * @see net.sf.hajdbc.Balancer#remove(net.sf.hajdbc.Database) */ @Override public boolean remove(Database database) { this.lock.lock(); try { boolean exists = this.databaseMap.containsKey(database); if (exists) { Map, AtomicInteger> map = new TreeMap, AtomicInteger>(this.databaseMap); map.remove(database); this.databaseMap = map; } return exists; } finally { this.lock.unlock(); } } /** * @see net.sf.hajdbc.Balancer#next() */ @Override public Database next() { return Collections.min(this.databaseMap.entrySet(), this.comparator).getKey(); } /** * @see net.sf.hajdbc.Balancer#add(net.sf.hajdbc.Database) */ @Override public boolean add(Database database) { this.lock.lock(); try { boolean exists = this.databaseMap.containsKey(database); if (!exists) { Map, AtomicInteger> map = new TreeMap, AtomicInteger>(this.databaseMap); map.put(database, new AtomicInteger(1)); this.databaseMap = map; } return !exists; } finally { this.lock.unlock(); } } /** * @see net.sf.hajdbc.Balancer#beforeInvocation(net.sf.hajdbc.Database) */ @Override public void beforeInvocation(Database database) { AtomicInteger load = this.databaseMap.get(database); if (load != null) { load.incrementAndGet(); } } /** * @see net.sf.hajdbc.Balancer#afterInvocation(net.sf.hajdbc.Database) */ @Override public void afterInvocation(Database database) { AtomicInteger load = this.databaseMap.get(database); if (load != null) { load.decrementAndGet(); } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/balancer/RandomBalancer.java0000644000175000017500000000561011151703042024107 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import net.sf.hajdbc.Database; /** * Balancer implementation whose {@link #next()} implementation returns a random database. * The probability that a given database will be returned is: weight / total-weight. * * @author Paul Ferraro * @param either java.sql.Driver or javax.sql.DataSource */ public class RandomBalancer extends AbstractBalancer { private volatile List> databaseList = Collections.emptyList(); private Random random = new Random(); /** * @see net.sf.hajdbc.Balancer#next() */ @Override public Database next() { List> list = this.databaseList; if (list.isEmpty()) { return this.databaseSet.first(); } int index = this.random.nextInt(list.size()); return list.get(index); } /** * @see net.sf.hajdbc.balancer.AbstractBalancer#added(net.sf.hajdbc.Database) */ @Override protected void added(Database database) { int weight = database.getWeight(); if (weight > 0) { List> list = new ArrayList>(this.databaseList.size() + weight); list.addAll(this.databaseList); for (int i = 0; i < weight; ++i) { list.add(database); } this.databaseList = list; } } /** * @see net.sf.hajdbc.balancer.AbstractBalancer#removed(net.sf.hajdbc.Database) */ @Override protected void removed(Database database) { int weight = database.getWeight(); if (weight > 0) { List> list = new ArrayList>(this.databaseList.size() - weight); int index = this.databaseList.indexOf(database); list.addAll(this.databaseList.subList(0, index)); list.addAll(this.databaseList.subList(index + weight, this.databaseList.size())); this.databaseList = list; } } /** * @see net.sf.hajdbc.balancer.AbstractBalancer#cleared() */ @Override protected void cleared() { this.databaseList = Collections.emptyList(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/balancer/RoundRobinBalancer.java0000644000175000017500000000467311151703042024760 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import java.util.LinkedList; import java.util.Queue; import net.sf.hajdbc.Database; /** * Balancer implementation whose {@link #next()} implementation uses a circular FIFO queue. * * @author Paul Ferraro * @param either java.sql.Driver or javax.sql.DataSource */ public class RoundRobinBalancer extends AbstractBalancer { private Queue> databaseQueue = new LinkedList>(); /** * @see net.sf.hajdbc.balancer.AbstractBalancer#added(net.sf.hajdbc.Database) */ @Override protected void added(Database database) { int weight = database.getWeight(); for (int i = 0; i < weight; ++i) { this.databaseQueue.add(database); } } /** * @see net.sf.hajdbc.balancer.AbstractBalancer#removed(net.sf.hajdbc.Database) */ @Override protected void removed(Database database) { int weight = database.getWeight(); for (int i = 0; i < weight; ++i) { this.databaseQueue.remove(database); } } /** * @see net.sf.hajdbc.Balancer#next() */ @Override public Database next() { this.lock.lock(); try { if (this.databaseQueue.isEmpty()) { return this.databaseSet.first(); } if (this.databaseQueue.size() == 1) { return this.databaseQueue.element(); } Database database = this.databaseQueue.remove(); this.databaseQueue.add(database); return database; } finally { this.lock.unlock(); } } /** * @see net.sf.hajdbc.balancer.AbstractBalancer#cleared() */ @Override protected void cleared() { this.databaseQueue.clear(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/balancer/SimpleBalancer.java0000644000175000017500000000461411151703042024123 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.balancer; import java.util.Collections; import java.util.Comparator; import java.util.NoSuchElementException; import net.sf.hajdbc.Database; /** * Trivial balancer implementation whose {@link #next} implementation always returns the database with the highest weight. * * @author Paul Ferraro * @param either java.sql.Driver or javax.sql.DataSource */ public class SimpleBalancer extends AbstractBalancer { private volatile Database nextDatabase = null; private Comparator> comparator = new Comparator>() { @Override public int compare(Database database1, Database database2) { return database1.getWeight() - database2.getWeight(); } }; /** * @see net.sf.hajdbc.Balancer#next() */ @Override public Database next() { Database next = this.nextDatabase; if (next == null) { throw new NoSuchElementException(); } return next; } /** * @see net.sf.hajdbc.balancer.AbstractBalancer#added(net.sf.hajdbc.Database) */ @Override protected void added(Database database) { this.reset(); } /** * @see net.sf.hajdbc.balancer.AbstractBalancer#removed(net.sf.hajdbc.Database) */ @Override protected void removed(Database database) { this.reset(); } private void reset() { this.nextDatabase = this.databaseSet.isEmpty() ? null : Collections.max(this.databaseSet, this.comparator); } /** * @see net.sf.hajdbc.balancer.AbstractBalancer#cleared() */ @Override protected void cleared() { this.nextDatabase = null; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Messages_de.properties0000644000175000017500000001056711151703042023171 0ustar moellermoeller#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) # # HA-JDBC: High-Availability JDBC # Copyright (c) 2004-2007 Paul Ferraro # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation; either version 2.1 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Contact: ferraro@users.sourceforge.net # cluster-not-active = Datenbankblock {0} ist nicht aktiv. cluster-panic-detected = Blockpanik ermittelt auf Datenbankblock {0}. cluster-start-failed = Konnte Datenbankblock {0} beginnen nicht. cluster-state-load-failed = Konnte den Zustand von Cluster {0} nicht laden cluster-state-store-failed = Konnte den Zustand von Cluster {0} nicht speichern command-received = Empfing befehl: {0} config-load-failed = Konnte HA-JDBC Konfiguration von {0} nicht laden config-not-found = Konnte Cluster-Konfigurations-File nicht finden: {0} config-store-failed = Konnte HA-JDBC Konfiguration nicht nach {0} speichern database-activate-failed = Konnte Datenbank {0} vom Cluster {1} nicht aktivieren database-activated = Datenbank {0} von Cluster {1} wurde aktiviert database-already-exists = Cluster {1} enth\\u00E4lt bereits Datenbank {0}. database-deactivated = Datenbank {0} von Cluster {1} wurde deaktiviert database-not-active = Datenbank war zur Zeit der Erzeugung von {0} nicht aktiv database-not-alive = Datenbank {0} von Cluster {1} antwortet nicht. database-still-active = Datenbank {0} von Cluster {1} konnte nicht entfernt werden, weil sie noch aktiv ist. database-sync-end = Synchronisierung der Datenbank {0} von Cluster {1} fertig. database-sync-start = Beginn der Synchronisierung von Datenbank {0} von Cluster {1}. delete-count = {0} Zeilen aus {1} gel\u00F6scht driver-not-found = Konnte Treiber {0} nicht finden driver-register-failed = Konnte Treiber {0} nicht registrieren group-member-joined = {0} trat ein in Gruppe {1} group-member-left = {0} verlie\u00DF die Gruppe {1} ha-jdbc-init = Initialisierung HA-JDBC {0} von {1} initial-cluster-state-local = Verwenden des lokalen Ausgangsblockzustandes {0}. initial-cluster-state-none = Kein Ausgangsblockzustand gefunden. initial-cluster-state-remote = Verwenden des Remoteausgangsblockzustandes {0} von {1}. insert-count = {0} Zeilen in {1} eingef\u00FCgt invalid-balancer = {0} ist kein g\u00FCltiger Balancer. invalid-database = Cluster {1} enth\\u00E4lt nicht die Datenbank {0} invalid-database-cluster = {0} ist nicht ein g\\u00FCltiger Datenbankcluster. invalid-meta-data-cache = {0} ist nicht ein g\\u00FCltiger Metadaten-Cache. invalid-property = {0} ist keine g\u00FCltige Property von {1} invalid-property-value = {0} ist kein g\u00FCltiger {1}-Wert f\u00FCr {2} invalid-sync-strategy = {0} ist keine g\u00FCltige Synchronisations-Strategie. jdbc-url-rejected = Kein eingetragener Treiber erkennt URL {0} jndi-lookup-failed = JNDI-Namensaufl\u00F6sung von {0} fehlgeschlagen mbean-server-not-found = Keinen MBean-Server gefunden. no-active-databases = Keine aktiven Datenbanken im Cluster {0} primary-key-required = Tabelle {1} enth\u00E4lt keinen Prim\u00E4rschl\u00FCssel - dies wird durch Synchronisations-Strategie {0} gefordert schema-lookup-failed = Konnte {0} in den folgenden Schemata nicht lokalisieren: {1}. \\u00DCberpr\\u00FCfen Sie die Umsetzung von {2}. sequence-out-of-sync = Der Folgewert ({2}) der Reihenfolge {0} von der Datenbank {1} pass nicht zum Folgewert ({4}) von der Datenbank {3}. shut-down = Beende HA-JDBC. sql-object-init-failed = Konnte {0} f\u00FCr Datenbank {1} nicht initialisieren statement-failed = Scheitern der Ausf\u00FChrung von: {0} table-lock-acquire = Erhalte Tabellen-Sperren auf aktiven Datenbanken. table-lock-release = Gebe Tabellen-Sperren auf aktiven Datenbanken frei. update-count = {0} Zeilen in {1} aktualisiert write-lock-failed = Konnte exklusive Sperrung auf Cluster {0} nicht erwerben. ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseActivationListener.java0000644000175000017500000000233611151703042024726 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.EventListener; /** * Event listener for database activations. * @author Paul Ferraro */ public interface DatabaseActivationListener extends EventListener { /** * Triggered after database is successfully activated. * @param event indicates the database that was activated */ public void activated(DatabaseEvent event); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/0000755000175000017500000000000011674455606021504 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/Command.java0000644000175000017500000000272211151703042023704 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import java.io.Serializable; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.StateManager; /** * @author Paul Ferraro */ public interface Command extends Serializable { /** * Execute this command on the specified database cluster. * @param either java.sql.Driver or javax.sql.DataSource * @param databaseCluster a database cluster * @param stateManager a state manager */ public R execute(DatabaseCluster databaseCluster, StateManager stateManager); public R unmarshalResult(Object object); public Object marshalResult(R result); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/DistributableStateManager.java0000644000175000017500000001404011151703042027413 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import java.text.MessageFormat; import java.util.Collection; import java.util.Set; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseEvent; import net.sf.hajdbc.Messages; import net.sf.hajdbc.StateManager; import org.jgroups.Address; import org.jgroups.Channel; import org.jgroups.Message; import org.jgroups.MessageListener; import org.jgroups.blocks.GroupRequest; import org.jgroups.blocks.MessageDispatcher; import org.jgroups.blocks.RequestHandler; import org.jgroups.util.Rsp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * StateManager implementation that broadcasts database activations and deactivations to other group members * and retrieves initial state from another group member. * * @author Paul Ferraro */ public class DistributableStateManager extends AbstractMembershipListener implements StateManager, MessageListener, RequestHandler { private static final String CHANNEL = "{0}-state"; //$NON-NLS-1$ private static Logger logger = LoggerFactory.getLogger(DistributableStateManager.class); private int timeout; private MessageDispatcher dispatcher; private DatabaseCluster databaseCluster; private StateManager stateManager; /** * @param databaseCluster * @param decorator * @throws Exception */ public DistributableStateManager(DatabaseCluster databaseCluster, DistributableDatabaseClusterDecorator decorator) throws Exception { super(decorator.createChannel(MessageFormat.format(CHANNEL, databaseCluster.getId()))); this.databaseCluster = databaseCluster; this.dispatcher = new MessageDispatcher(this.channel, this, this, this); this.timeout = decorator.getTimeout(); this.stateManager = databaseCluster.getStateManager(); } /** * @see org.jgroups.blocks.RequestHandler#handle(org.jgroups.Message) */ @SuppressWarnings("unchecked") @Override public Object handle(Message message) { try { Command command = (Command) message.getObject(); logger.info(Messages.getMessage(Messages.COMMAND_RECEIVED, command)); return command.marshalResult(command.execute(this.databaseCluster, this.stateManager)); } catch (Throwable e) { logger.error(e.getMessage(), e); return e; } } /** * @see net.sf.hajdbc.StateManager#getInitialState() */ @Override public Set getInitialState() { Command> command = new QueryInitialStateCommand(); Collection responses = this.send(command, GroupRequest.GET_FIRST, this.timeout); for (Rsp response: responses) { Object result = response.getValue(); if (result != null) { Set state = command.unmarshalResult(result); logger.info(Messages.getMessage(Messages.INITIAL_CLUSTER_STATE_REMOTE, state, response.getSender())); return state; } } return this.stateManager.getInitialState(); } /** * @see net.sf.hajdbc.DatabaseActivationListener#activated(net.sf.hajdbc.DatabaseEvent) */ @Override public void activated(DatabaseEvent event) { if (this.databaseCluster.isActive()) { // Send synchronous notification this.send(new ActivateCommand(event.getId()), GroupRequest.GET_ALL, 0); } this.stateManager.activated(event); } /** * @see net.sf.hajdbc.DatabaseDeactivationListener#deactivated(net.sf.hajdbc.DatabaseEvent) */ @Override public void deactivated(DatabaseEvent event) { // Send asynchronous notification this.send(new DeactivateCommand(event.getId()), GroupRequest.GET_NONE, this.timeout); this.stateManager.deactivated(event); } private Collection send(Command command, int mode, long timeout) { return this.dispatcher.castMessage(null, this.createMessage(command), mode, timeout).values(); } private Message createMessage(Command command) { return new Message(null, this.dispatcher.getChannel().getLocalAddress(), command); } /** * @see net.sf.hajdbc.Lifecycle#start() */ @Override public void start() throws Exception { Channel channel = this.dispatcher.getChannel(); channel.connect(channel.getClusterName()); this.dispatcher.start(); this.stateManager.start(); } /** * @see net.sf.hajdbc.Lifecycle#stop() */ @Override public void stop() { this.dispatcher.stop(); this.dispatcher.getChannel().close(); this.stateManager.stop(); } /** * @see net.sf.hajdbc.distributable.AbstractMembershipListener#memberJoined(org.jgroups.Address) */ @Override protected void memberJoined(Address address) { logger.info(Messages.getMessage(Messages.GROUP_MEMBER_JOINED, address, this.databaseCluster)); } /** * @see net.sf.hajdbc.distributable.AbstractMembershipListener#memberLeft(org.jgroups.Address) */ @Override protected void memberLeft(Address address) { logger.info(Messages.getMessage(Messages.GROUP_MEMBER_LEFT, address, this.databaseCluster)); } /** * @see org.jgroups.MessageListener#getState() */ @Override public byte[] getState() { return null; } /** * @see org.jgroups.MessageListener#setState(byte[]) */ @Override public void setState(byte[] state) { // Do nothing } /** * @see org.jgroups.MessageListener#receive(org.jgroups.Message) */ @Override public void receive(Message message) { // Do nothing } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/AbstractMembershipListener.java0000644000175000017500000000534511151703042027617 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.jgroups.Address; import org.jgroups.Channel; import org.jgroups.MembershipListener; import org.jgroups.View; /** * @author Paul Ferraro */ public abstract class AbstractMembershipListener implements MembershipListener { protected Channel channel; private Set
addressSet = new HashSet
(); protected AbstractMembershipListener(Channel channel) { this.channel = channel; this.channel.setOpt(Channel.LOCAL, false); } /** * @see org.jgroups.MembershipListener#block() */ @Override public final void block() { // Do nothing } /** * @see org.jgroups.MembershipListener#suspect(org.jgroups.Address) */ @Override public final void suspect(Address address) { // Do nothing } /** * @see org.jgroups.MembershipListener#viewAccepted(org.jgroups.View) */ @Override public final void viewAccepted(View view) { synchronized (this.addressSet) { Iterator
addresses = this.addressSet.iterator(); while (addresses.hasNext()) { Address address = addresses.next(); if (!view.containsMember(address)) { addresses.remove(); this.memberLeft(address); } } Address localAddress = this.channel.getLocalAddress(); for (Address address: view.getMembers()) { // Track remote members only if (!address.equals(localAddress) && this.addressSet.add(address)) { this.memberJoined(address); } } } } public int getMembershipSize() { synchronized (this.addressSet) { return this.addressSet.size(); } } public boolean isMembershipEmpty() { synchronized (this.addressSet) { return this.addressSet.isEmpty(); } } protected abstract void memberJoined(Address address); protected abstract void memberLeft(Address address); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/AbstractCommand.java0000644000175000017500000000467411151703042025400 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; /** * Represents a database command to be executed on a given database cluster. * @author Paul Ferraro * @since 1.0 */ public abstract class AbstractCommand implements Command, Externalizable { protected String databaseId; /** * Constructs a new AbstractDatabaseCommand. */ protected AbstractCommand() { // Do nothing } /** * Constructs a new AbstractDatabaseCommand. * @param databaseId a database identifier */ public AbstractCommand(String databaseId) { this.databaseId = databaseId; } /** * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput) */ @Override public void writeExternal(ObjectOutput output) throws IOException { output.writeUTF(this.databaseId); } /** * @see java.io.Externalizable#readExternal(java.io.ObjectInput) */ @Override public void readExternal(ObjectInput input) throws IOException { this.databaseId = input.readUTF(); } /** * @see java.lang.Object#toString() */ @Override public String toString() { return this.getClass().getName() + " [" + this.databaseId + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } /** * @see net.sf.hajdbc.distributable.Command#marshalResult(java.lang.Object) */ @Override public Object marshalResult(Boolean result) { return result; } /** * @see net.sf.hajdbc.distributable.Command#unmarshalResult(java.lang.Object) */ @Override public Boolean unmarshalResult(Object result) { return (Boolean) result; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/DistributableDatabaseClusterDecorator.java0000644000175000017500000000445311151703042031760 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseClusterDecorator; import org.jgroups.Channel; import org.jgroups.JChannelFactory; /** * @author Paul Ferraro * */ public class DistributableDatabaseClusterDecorator implements DatabaseClusterDecorator { private JChannelFactory factory; private String config = "stacks.xml"; //$NON-NLS-1$ private String stack = "udp-sync"; //$NON-NLS-1$ private int timeout = 1000; public Channel createChannel(String name) throws Exception { return this.factory.createMultiplexerChannel(this.stack, name); } /** * Returns the number of milliseconds to allow for jgroups cluster operations * @return a number of milliseconds */ public int getTimeout() { return this.timeout; } /** * @see net.sf.hajdbc.DatabaseClusterDecorator#decorate(net.sf.hajdbc.DatabaseCluster) */ @Override public void decorate(DatabaseCluster databaseCluster) throws Exception { if (this.factory == null) { this.factory = new JChannelFactory(); this.factory.setDomain(JChannelFactory.class.getPackage().getName()); this.factory.setMultiplexerConfig(this.config); this.factory.create(); } databaseCluster.setLockManager(new DistributableLockManager(databaseCluster, this)); databaseCluster.setStateManager(new DistributableStateManager(databaseCluster, this)); } @Override protected void finalize() { this.factory.destroy(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/DeactivateCommand.java0000644000175000017500000000347011151703042025677 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.StateManager; /** * Command pattern object indicating that a database is to be deactivated. * @author Paul Ferraro * @since 1.0 */ public class DeactivateCommand extends AbstractCommand { private static final long serialVersionUID = 3257006574802647092L; /** * Constructs a new DatabaseDeactivationCommand. */ public DeactivateCommand() { super(); } /** * Constructs a new DatabaseDeactivationCommand. * @param databaseId a database identifier */ public DeactivateCommand(String databaseId) { super(databaseId); } /** * @see net.sf.hajdbc.distributable.Command#execute(net.sf.hajdbc.DatabaseCluster, net.sf.hajdbc.StateManager) */ @Override public Boolean execute(DatabaseCluster databaseCluster, StateManager stateManager) { return databaseCluster.deactivate(databaseCluster.getDatabase(this.databaseId), stateManager); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/AbstractLockDecree.java0000644000175000017500000000375611151703042026022 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import org.jgroups.Address; /** * @author Paul Ferraro * @since 2.0 */ public abstract class AbstractLockDecree implements LockDecree, Externalizable { protected String id; private Address address; protected AbstractLockDecree(String id, Address address) { this.id = id; this.address = address; } protected AbstractLockDecree() { // Required for deserialization } /** * @see net.sf.hajdbc.distributable.LockDecree#getAddress() */ public Address getAddress() { return this.address; } /** * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput) */ @Override public void writeExternal(ObjectOutput output) throws IOException { output.writeUTF(this.id); output.writeObject(this.address); } /** * @see java.io.Externalizable#readExternal(java.io.ObjectInput) */ @Override public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException { this.id = input.readUTF(); this.address = (Address) input.readObject(); } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/AcquireLockDecree.java0000644000175000017500000000352311151703042025640 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import org.jgroups.Address; import net.sf.hajdbc.LockManager; /** * @author Paul Ferraro * @since 2.0 */ public class AcquireLockDecree extends AbstractLockDecree { private static final long serialVersionUID = 9016576896686385467L; public AcquireLockDecree() { super(); } public AcquireLockDecree(String id, Address address) { super(id, address); } /** * @see net.sf.hajdbc.distributable.LockDecree#vote(net.sf.hajdbc.LockManager, java.util.Map) */ @Override public boolean vote(LockManager lockManager, Map lockMap) { Lock lock = lockManager.writeLock(this.id); try { boolean locked = lock.tryLock(0, TimeUnit.SECONDS); if (locked) { synchronized (lockMap) { lockMap.put(this.id, lock); } } return locked; } catch (InterruptedException e) { return false; } } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/ActivateCommand.java0000644000175000017500000000346011151703042025365 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.StateManager; /** * Command pattern object indicating that a database is to be activated. * @author Paul Ferraro * @since 1.0 */ public class ActivateCommand extends AbstractCommand { private static final long serialVersionUID = 3618141143175673655L; /** * Constructs a new DatabaseActivationCommand. */ public ActivateCommand() { // Do nothing } /** * Constructs a new DatabaseActivationCommand. * @param databaseId a database identifier */ public ActivateCommand(String databaseId) { super(databaseId); } /** * @see net.sf.hajdbc.distributable.Command#execute(net.sf.hajdbc.DatabaseCluster, net.sf.hajdbc.StateManager) */ @Override public Boolean execute(DatabaseCluster databaseCluster, StateManager stateManager) { return databaseCluster.activate(databaseCluster.getDatabase(this.databaseId), stateManager); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/LockDecree.java0000644000175000017500000000120111151703042024315 0ustar moellermoellerpackage net.sf.hajdbc.distributable; import java.io.Serializable; import java.util.Map; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.LockManager; import org.jgroups.Address; public interface LockDecree extends Serializable { /** * Returns the address of the node that requested the lock * @return a node address */ public Address getAddress(); /** * Execute lock operation. * @param lockManager a lock manager * @param lockMap a map of object identifier to lock * @return true if operation was successful, false otherwise. */ public boolean vote(LockManager lockManager, Map lockMap); }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/QueryInitialStateCommand.java0000644000175000017500000000462311151703042027247 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import java.util.Arrays; import java.util.Collections; import java.util.Set; import java.util.TreeSet; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.StateManager; import net.sf.hajdbc.util.Strings; /** * @author Paul Ferraro */ public class QueryInitialStateCommand implements Command> { private static final long serialVersionUID = -8409746321944635265L; /** * @see net.sf.hajdbc.distributable.Command#execute(net.sf.hajdbc.DatabaseCluster, net.sf.hajdbc.StateManager) */ @Override public Set execute(DatabaseCluster databaseCluster, StateManager stateManager) { return databaseCluster.isActive() ? stateManager.getInitialState() : null; } /** * Optimize transfer of result by marshalling set of strings into a string. * @see net.sf.hajdbc.distributable.Command#marshalResult(java.lang.Object) */ @Override public Object marshalResult(Set set) { return (set != null) ? Strings.join(set, Strings.COMMA) : null; } /** * Restore marshalled string into a set of strings * @see net.sf.hajdbc.distributable.Command#unmarshalResult(java.lang.Object) */ @Override public Set unmarshalResult(Object object) { String state = (String) object; if (state == null) return null; if (state.length() == 0) return Collections.emptySet(); return new TreeSet(Arrays.asList(state.split(Strings.COMMA))); } /** * @see java.lang.Object#toString() */ @Override public String toString() { return this.getClass().getName(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/DistributableLockManager.java0000644000175000017500000002277311151703042027237 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.LockManager; import org.jgroups.Address; import org.jgroups.Message; import org.jgroups.MessageListener; import org.jgroups.blocks.GroupRequest; import org.jgroups.blocks.MethodCall; import org.jgroups.blocks.RpcDispatcher; import org.jgroups.util.Rsp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * LockManager implementation that leverages a JGroups 2-phase voting adapter for obtain remote write locks. * * @author Paul Ferraro */ public class DistributableLockManager extends AbstractMembershipListener implements LockManager, MessageListener { private static final String CHANNEL = "{0}-lock"; //$NON-NLS-1$ static Logger logger = LoggerFactory.getLogger(DistributableLockManager.class); protected RpcDispatcher dispatcher; protected int timeout; private LockManager lockManager; private Map> addressMap = new ConcurrentHashMap>(); /** * Constructs a new DistributableLock. * @param either java.sql.Driver or javax.sql.Datasource * @param databaseCluster a database cluster * @param decorator a decorator * @throws Exception */ public DistributableLockManager(DatabaseCluster databaseCluster, DistributableDatabaseClusterDecorator decorator) throws Exception { super(decorator.createChannel(MessageFormat.format(CHANNEL, databaseCluster.getId()))); this.lockManager = databaseCluster.getLockManager(); this.timeout = decorator.getTimeout(); this.dispatcher = new RpcDispatcher(this.channel, this, this, this); } /** * @see net.sf.hajdbc.Lifecycle#start() */ @Override public void start() throws Exception { this.channel.connect(this.channel.getClusterName()); this.lockManager.start(); } /** * @see net.sf.hajdbc.Lifecycle#stop() */ @Override public void stop() { this.channel.close(); this.lockManager.stop(); } /** * Read locks are local. * @see net.sf.hajdbc.LockManager#readLock(java.lang.String) */ @Override public Lock readLock(String object) { return this.lockManager.readLock(object); } /** * Write locks are distributed. * @see net.sf.hajdbc.LockManager#writeLock(java.lang.String) */ @Override public Lock writeLock(String object) { return new DistributableLock(object, this.lockManager.writeLock(object)); } /** * Votes on the specified decree. * @param decree a lock decree * @return true, if success, false if failure */ public boolean vote(LockDecree decree) { Map lockMap = this.addressMap.get(decree.getAddress()); // Vote negatively for decrees from non-members if (lockMap == null) { return false; } return decree.vote(this.lockManager, lockMap); } /** * @see net.sf.hajdbc.distributable.AbstractMembershipListener#memberJoined(org.jgroups.Address) */ @Override protected void memberJoined(Address address) { this.addressMap.put(address, new HashMap()); } /** * @see net.sf.hajdbc.distributable.AbstractMembershipListener#memberLeft(org.jgroups.Address) */ @Override protected void memberLeft(Address address) { Map lockMap = this.addressMap.remove(address); for (Lock lock: lockMap.values()) { lock.unlock(); } } /** * @see org.jgroups.MessageListener#getState() */ @Override public byte[] getState() { return null; } /** * @see org.jgroups.MessageListener#receive(org.jgroups.Message) */ @Override public void receive(Message message) { // Do nothing } /** * @see org.jgroups.MessageListener#setState(byte[]) */ @Override public void setState(byte[] arg0) { // Do nothing } private class DistributableLock implements Lock { private LockDecree acquireDecree; private LockDecree releaseDecree; private Lock lock; /** * @param object * @param lock */ public DistributableLock(String object, Lock lock) { Address address = DistributableLockManager.this.channel.getLocalAddress(); this.acquireDecree = new AcquireLockDecree(object, address); this.releaseDecree = new ReleaseLockDecree(object, address); this.lock = lock; } /** * @see java.util.concurrent.locks.Lock#lock() */ @Override public void lock() { while (!DistributableLockManager.this.isMembershipEmpty()) { if (this.tryLockFairly()) return; Thread.yield(); } this.lock.lock(); } /** * @see java.util.concurrent.locks.Lock#lockInterruptibly() */ @Override public void lockInterruptibly() throws InterruptedException { while (!DistributableLockManager.this.isMembershipEmpty()) { if (this.tryLockFairly()) return; if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); } Thread.yield(); } this.lock.lockInterruptibly(); } /** * @see java.util.concurrent.locks.Lock#tryLock() */ @Override public boolean tryLock() { if (this.lock.tryLock()) { if (this.tryRemoteLock()) { return true; } this.lock.unlock(); } return false; } /** * Like {@link #tryLock()}, but do not barge on other waiting threads * @return true, if lock acquired, false otherwise * @throws InterruptedException */ private boolean tryLockFairly() { try { if (this.lock.tryLock(0, TimeUnit.SECONDS)) { if (this.tryRemoteLock()) { return true; } this.lock.unlock(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return false; } /** * @see java.util.concurrent.locks.Lock#tryLock(long, java.util.concurrent.TimeUnit) */ @Override public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { // Convert timeout to milliseconds long ms = unit.toMillis(timeout); long stopTime = System.currentTimeMillis() + ms; do { if (DistributableLockManager.this.isMembershipEmpty()) { return this.lock.tryLock(ms, TimeUnit.MILLISECONDS); } if (this.tryLockFairly()) { return true; } if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); } ms = stopTime - System.currentTimeMillis(); } while (ms >= 0); return false; } /** * @see java.util.concurrent.locks.Lock#unlock() */ @Override public void unlock() { this.remoteUnlock(); this.lock.unlock(); } private boolean tryRemoteLock() { Map> map = null; try { map = this.remoteLock(); return map.get(false).isEmpty(); } finally { if (map != null) { this.remoteUnlock(map.get(true)); } } } private Map> remoteLock() { return DistributableLockManager.this.remoteVote(this.acquireDecree, null, DistributableLockManager.this.timeout); } private Map> remoteUnlock() { return this.remoteUnlock(null); } private Map> remoteUnlock(Vector
address) { return DistributableLockManager.this.remoteVote(this.releaseDecree, address, 0); } /** * @see java.util.concurrent.locks.Lock#newCondition() */ @Override public Condition newCondition() { throw new UnsupportedOperationException(); } } Map> remoteVote(LockDecree decree, Vector
addresses, long timeout) { Map> map = new TreeMap>(); int size = (addresses != null) ? addresses.size() : this.getMembershipSize(); map.put(true, new Vector
(size)); map.put(false, new Vector
(size)); if (size > 0) { try { Method method = this.getClass().getMethod("vote", LockDecree.class); //$NON-NLS-1$ MethodCall call = new MethodCall(method, new Object[] { decree }); Collection responses = this.dispatcher.callRemoteMethods(addresses, call, GroupRequest.GET_ALL, timeout).values(); for (Rsp response: responses) { Object value = response.wasReceived() ? response.getValue() : false; map.get((value != null) ? value : false).add(response.getSender()); } } catch (NoSuchMethodException e) { throw new IllegalStateException(e); } } return map; } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/distributable/ReleaseLockDecree.java0000644000175000017500000000324111151703042025624 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.distributable; import java.util.Map; import java.util.concurrent.locks.Lock; import org.jgroups.Address; import net.sf.hajdbc.LockManager; /** * @author Paul Ferraro * @since 2.0 */ public class ReleaseLockDecree extends AbstractLockDecree { private static final long serialVersionUID = -2410005124267913965L; public ReleaseLockDecree() { super(); } public ReleaseLockDecree(String id, Address address) { super(id, address); } /** * @see net.sf.hajdbc.distributable.LockDecree#vote(net.sf.hajdbc.LockManager, java.util.Map) */ @Override public boolean vote(LockManager lockManager, Map lockMap) { Lock lock = null; synchronized (lockMap) { lock = lockMap.remove(this.id); } if (lock != null) { lock.unlock(); } return true; } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/QualifiedName.java0000644000175000017500000000252111151703042022172 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; /** * Tuple that stores the schema name and object name of a schema qualified object. * @author Paul Ferraro */ public class QualifiedName { private String schema; private String name; public QualifiedName(String schema, String name) { this(name); this.schema = schema; } public QualifiedName(String name) { this.name = name; } public String getSchema() { return this.schema; } public String getName() { return this.name; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseMetaDataCacheFactory.java0000644000175000017500000000176711151703042025062 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; public interface DatabaseMetaDataCacheFactory { DatabaseMetaDataCache createCache(DatabaseCluster cluster); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/SynchronizationContext.java0000644000175000017500000000504611151703042024241 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.sql.Connection; import java.sql.SQLException; import java.util.Set; import java.util.concurrent.ExecutorService; /** * @author Paul Ferraro * @param Driver or DataSource * @since 2.0 */ public interface SynchronizationContext { /** * Returns a connection to the specified database. * @param database a database to which to connect * @return a database connection * @throws SQLException if connection could not be obtained */ public Connection getConnection(Database database) throws SQLException; /** * Returns the database from which to synchronize. * @return a database */ public Database getSourceDatabase(); /** * Returns the database to synchronize. * @return a database */ public Database getTargetDatabase(); /** * Returns a snapshot of the activate databases in the cluster at the time synchronization started. * @return a collection of databases */ public Set> getActiveDatabaseSet(); /** * Returns a cache of database meta data for the source database. * @return a cache of database meta data */ public DatabaseProperties getSourceDatabaseProperties(); /** * Returns a cache of database meta data for the target database. * @return a cache of database meta data */ public DatabaseProperties getTargetDatabaseProperties(); /** * Returns the dialect of the cluster. * @return a dialect */ public Dialect getDialect(); /** * An executor service for executing tasks asynchronously. * @return an executor service */ public ExecutorService getExecutor(); /** * Closes any open database connections and shuts down the executor service. */ public void close(); }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseMetaDataCache.java0000644000175000017500000000274711151703042023531 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.sql.Connection; import java.sql.SQLException; /** * Interface for retrieving pre-processed, cached, database meta data. * * @author Paul Ferraro * @since 2.0 */ public interface DatabaseMetaDataCache { /** * Flushes this cache. * @throws SQLException if flush fails */ public void flush() throws SQLException; /** * Retrieves processed meta data for this database. * @return a DatabaseProperties implementation * @throws SQLException if database properties could not be fetched. */ public DatabaseProperties getDatabaseProperties(Connection connection) throws SQLException; }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseProperties.java0000644000175000017500000000256111216551757023273 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.sql.SQLException; import java.util.Collection; /** * @author Paul Ferraro * */ public interface DatabaseProperties { public Collection getTables() throws SQLException; public boolean supportsSelectForUpdate() throws SQLException; public TableProperties findTable(String table) throws SQLException; public Collection getSequences() throws SQLException; public SequenceProperties findSequence(String sequence) throws SQLException; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/SequenceProperties.java0000644000175000017500000000174311151703042023320 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; /** * @author Paul Ferraro */ public interface SequenceProperties { public String getName(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Messages_it.properties0000644000175000017500000001212711151703042023207 0ustar moellermoeller#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) # # HA-JDBC: High-Availability JDBC # Copyright (c) 2004-2007 Paul Ferraro # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation; either version 2.1 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Contact: ferraro@users.sourceforge.net # cluster-not-active = La serie di ingranaggi {0} della base di dati non \u00E8 attiva. cluster-panic-detected = Panico della serie di ingranaggi rilevato sulla serie di ingranaggi {0} della base di dati. cluster-start-failed = Non \u00E8 riuscito ad iniziare la serie di ingranaggi {0} della base di dati. cluster-state-load-failed = Non \u00E8 riuscito a caricare dichiarano della serie di ingranaggi della base di dati {0}. cluster-state-store-failed = Non \u00E8 riuscito ad immagazzinare dichiarano della serie di ingranaggi della base di dati {0}. command-received = Ordine ricevuto: {0} config-load-failed = Non \u00E8 riuscito a caricare la configurazione di HA-JDBC da {0} config-not-found = Non riuscito ad individuare la lima di configurazione del mazzo della base di dati: {0} config-store-failed = Non \u00E8 riuscito a conservare la configurazione di HA-JDBC a {0} database-activate-failed = Non \u00E8 riuscito ad attivare la base di dati {0} dalla serie di ingranaggi {1} database-activated = La base di dati {0} dalla serie di ingranaggi {1} \u00E8 stata attivata database-already-exists = La serie di ingranaggi {1} gi\u00E0 contiene la base di dati {0}. database-deactivated = La base di dati {0} dalla serie di ingranaggi {1} \u00E8 stata disattivata database-not-active = La base di dati non era attiva allora {0} \u00E8 stata generata database-not-alive = La base di dati {0} dalla serie di ingranaggi {1} non sta rispondendo. database-still-active = La base di dati {0} dalla serie di ingranaggi {1} non potrebbe essere rimossa perch\u00E9 \u00E8 ancora attiva. database-sync-end = Sincronizzazione rifinita di base di dati {0} dalla serie di ingranaggi {1}. database-sync-start = Iniziare sincronizzazione di base di dati {0} dalla serie di ingranaggi {1}. delete-count = Cancellato {0} rema da {1} driver-not-found = Non \u00E8 riuscito ad individuare il driver {0} driver-register-failed = Non \u00E8 riuscito a registrare il driver {0} group-member-joined = {0} ha unito la scanalatura {1} group-member-left = {0} ha lasciato la scanalatura {1} ha-jdbc-init = Inizializzazione HA-JDBC {0} de {1} initial-cluster-state-local = Usando la serie di ingranaggi iniziale locale dichiari {0}. initial-cluster-state-none = Nessuna serie di ingranaggi iniziale dichiara trovato. initial-cluster-state-remote = Usando la serie di ingranaggi iniziale a distanza dichiari {0} da {1}. insert-count = Inserito {0} rema in {1} invalid-balancer = {0} non \u00E8 un compensatore valido. invalid-database = La serie di ingranaggi della base di dati {1} non contiene la base di dati {0} invalid-database-cluster = {0} non \u00E8 una serie di ingranaggi valida della base di dati. invalid-meta-data-cache = {0} non \u00E8 un nascondiglio valido di meta dati. invalid-property = {0} non \u00E8 una propriet\u00E0 valida di {1} invalid-property-value = {0} non \u00E8 { un 1 } valore valido per {2} invalid-sync-strategy = {0} non \u00E8 una strategia valida di sincronizzazione per la serie di ingranaggi. jdbc-url-rejected = Nessun driver registrato accetter\u00E0 il URL {0} jndi-lookup-failed = Non \u00E8 riuscito a realizzare chiamare l'occhiata di {0} mbean-server-not-found = Nessun mbean server trovato. no-active-databases = Nessun basi di dati attive in serie di ingranaggi {0} primary-key-required = La Tabella {1} non contiene una chiave primaria - questa \u00E8 richiesta da strategia di sincronizzazione {0}. schema-lookup-failed = Non \u00E8 riuscito ad individuare {0} nei seguenti schemi: {1}. Verifichi l'esecuzione di {2}. sequence-out-of-sync = Il valore seguente ({2}) per la sequenza {0} da base di dati {1} non abbina il valore seguente ({4}) da base di dati {3}. shut-down = Chiudendo gi\u00F9 HA-JDBC. sql-object-init-failed = Non \u00E8 riuscito a inizializzarsi {0} per base di dati {1} statement-failed = \u00C8 venuto a mancare a eseguono la dichiarazione: {0} table-lock-acquire = Acquisizione delle serrature della tabella sulle basi di dati attive. table-lock-release = Liberare le serrature della tabella sulle basi di dati attive. update-count = Aggiornato {0} rema dentro {1} write-lock-failed = Non \u00E8 riuscito ad acquistare la serratura esclusiva sulla serie di ingranaggi {0} della base di dati. ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/TableProperties.java0000644000175000017500000000274611151703042022603 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.sql.SQLException; import java.util.Collection; /** * @author Paul Ferraro * */ public interface TableProperties { public String getName(); public Collection getColumns() throws SQLException; public ColumnProperties getColumnProperties(String column) throws SQLException; public UniqueConstraint getPrimaryKey() throws SQLException; public Collection getForeignKeyConstraints() throws SQLException; public Collection getUniqueConstraints() throws SQLException; public Collection getIdentityColumns() throws SQLException; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Messages_pt.properties0000644000175000017500000001135211151703042023215 0ustar moellermoeller#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) # # HA-JDBC: High-Availability JDBC # Copyright (c) 2004-2007 Paul Ferraro # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation; either version 2.1 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Contact: ferraro@users.sourceforge.net # cluster-not-active = O conjunto {0} da base de dados n\u00E3o \u00E9 ativo. cluster-panic-detected = P\u00E2nico do conjunto detectado no conjunto {0} da base de dados. cluster-start-failed = N\u00E3o come\u00E7ou o conjunto {0} da base de dados. cluster-state-load-failed = N\u00E3o carregou o estado do conjunto da base de dados {0}. cluster-state-store-failed = N\u00E3o armazenou o estado do conjunto da base de dados {0}. command-received = O comando recebeu: {0} config-load-failed = N\u00E3o carregou a configura\u00E7\u00E3o de HA-JDBC de {0} config-not-found = N\u00E3o encontram a lima de configura\u00E7\u00E3o do conjunto da base de dados: {0} config-store-failed = N\u00E3o conservou a configura\u00E7\u00E3o de HA-JDBC a {0} database-activate-failed = N\u00E3o ativou a base de dados {0} do conjunto {1} database-activated = A base de dados {0} do conjunto {1} foi ativada database-already-exists = O conjunto {1} contem j\u00E1 a base de dados {0}. database-deactivated = A base de dados {0} do conjunto {1} foi desativada database-not-active = A base de dados n\u00E3o era ativa {0} foi criada naquele tempo database-not-alive = A base de dados {0} do conjunto {1} n\u00E3o est\u00E1 respondendo. database-still-active = A base de dados {0} do conjunto {1} n\u00E3o poderia ser removida porque \u00E9 ainda ativa. database-sync-end = Sincroniza\u00E7\u00E3o terminada da base de dados {0} do conjunto {1}. database-sync-start = Come\u00E7ando a sincroniza\u00E7\u00E3o da base de dados {0} do conjunto {1}. delete-count = Suprimido {0} enfileira de {1} driver-not-found = N\u00E3o encontrou o excitador {0} driver-register-failed = N\u00E3o registou o excitador {0} group-member-joined = {0} juntou a canaleta {1} group-member-left = {0} deixou a canaleta {1} ha-jdbc-init = Inicializando HA-JDBC {0} de {1} initial-cluster-state-local = Usando o estado inicial local do conjunto {0}. initial-cluster-state-none = Nenhum estado inicial do conjunto encontrou. initial-cluster-state-remote = Usando o estado inicial remoto do conjunto {0} de {1}. insert-count = Introduzido {0} enfileira em {1} invalid-balancer = {0} n\u00E3o \u00E9 um equilibrador v\u00E1lido. invalid-database = O conjunto da base de dados {1} n\u00E3o contem a base de dados {0} invalid-database-cluster = {0} n\u00E3o s\u00E3o um conjunto v\u00E1lido da base de dados. invalid-meta-data-cache = {0} n\u00E3o s\u00E3o um esconderijo v\u00E1lido dos meta-data. invalid-property = {0} n\u00E3o \u00E9 uma propriedade v\u00E1lida de {1} invalid-property-value = {0} n\u00E3o \u00E9 { um 1 } valor v\u00E1lido para {2} invalid-sync-strategy = {0} n\u00E3o \u00E9 uma estrat\u00E9gia v\u00E1lida da sincroniza\u00E7\u00E3o para o conjunto. jdbc-url-rejected = Nenhum excitador registado aceitar\u00E1 URL {0} jndi-lookup-failed = N\u00E3o executou nomear o lookup de {0} mbean-server-not-found = Nenhum mbean server encontrado. no-active-databases = Nenhumas bases de dados ativas no conjunto {0} primary-key-required = A tabela {1} n\u00E3o contem uma chave preliminar - esta \u00E9 requerida pela estrat\u00E9gia da sincroniza\u00E7\u00E3o {0}. schema-lookup-failed = N\u00E3o encontrou a {0} nos seguintes schemas: {1}. Verifique a execu\u00E7\u00E3o de {2}. sequence-out-of-sync = O valor seguinte ({2}) para a seq\u00FC\u00EAncia {0} da base de dados {1} n\u00E3o combina o valor seguinte ({4}) da base de dados {3}. shut-down = Fechar abaixo HA-JDBC. sql-object-init-failed = N\u00E3o inicializou {0} para a base de dados {1} statement-failed = Falhou a executam a indica\u00E7\u00E3o: {0} table-lock-acquire = Adquirindo fechamentos da tabela em bases de dados ativas. table-lock-release = Liberando fechamentos da tabela em bases de dados ativas. update-count = Updated {0} enfileira dentro {1} write-lock-failed = N\u00E3o adquiriu o fechamento exclusivo no conjunto {0} da base de dados. ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Dialect.java0000644000175000017500000001644511175406125021055 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Collection; import java.util.List; import java.util.regex.Pattern; /** * Encapsulates database vendor specific SQL syntax. * * @author Paul Ferraro * @since 1.1 */ public interface Dialect { /** * Returns a simple SQL statement used to validate whether a database is alive or not. * @return a SQL statement * @throws SQLException */ public String getSimpleSQL() throws SQLException; /** * Returns a SQL statement used to truncate a table. * @param properties table meta data * @return a SQL statement * @throws SQLException if there was an error fetching meta data. */ public String getTruncateTableSQL(TableProperties properties) throws SQLException; /** * Returns a SQL statement used to create a foreign key constraint. * @param constraint foreign key constraint meta data * @return a SQL statement * @throws SQLException if there was an error fetching meta data. */ public String getCreateForeignKeyConstraintSQL(ForeignKeyConstraint constraint) throws SQLException; /** * Returns a SQL statement used to drop a foreign key constraint. * @param constraint foreign key constraint meta data * @return a SQL statement * @throws SQLException if there was an error fetching meta data. */ public String getDropForeignKeyConstraintSQL(ForeignKeyConstraint constraint) throws SQLException; /** * Returns a SQL statement used to create a unique constraint. * @param constraint unique constraint meta data * @return a SQL statement * @throws SQLException if there was an error fetching meta data. */ public String getCreateUniqueConstraintSQL(UniqueConstraint constraint) throws SQLException; /** * Returns a SQL statement used to drop a unique constraint. * @param constraint unique constraint meta data * @return a SQL statement * @throws SQLException if there was an error fetching meta data. */ public String getDropUniqueConstraintSQL(UniqueConstraint constraint) throws SQLException; /** * Determines whether the specified SQL is a SELECT ... FOR UPDATE statement * @param sql a SQL statement * @return true if this is a SELECT ... FOR UPDATE statement, false if it is not * @throws SQLException if there was an error fetching meta data. */ public boolean isSelectForUpdate(String sql) throws SQLException; /** * Returns the data type of the specified column of the specified schema and table. * This method is intended to correct JDBC driver type mapping quirks. * @param properties table column meta data * @return the JDBC data type of this column * @throws SQLException */ public int getColumnType(ColumnProperties properties) throws SQLException; /** * Parses a table name from the specified INSERT SQL statement that may contain identity columns. * @param sql a SQL statement * @return the name of a table, or null if this SQL statement is not an INSERT statement or this dialect does not support identity columns * @throws SQLException * @since 2.0 */ public String parseInsertTable(String sql) throws SQLException; /** * Parses a sequence name from the specified SQL statement. * @param sql a SQL statement * @return the name of a sequence, or null if this SQL statement does not reference a sequence or this dialect does not support sequences * @throws SQLException * @since 2.0 */ public String parseSequence(String sql) throws SQLException; /** * Returns a collection of all sequences in this database. * @param metaData database meta data * @return a collection of sequence names * @throws SQLException * @since 2.0 */ public Collection getSequences(DatabaseMetaData metaData) throws SQLException; /** * Returns a SQL statement for obtaining the next value the specified sequence * @param sequence a sequence name * @return a SQL statement * @throws SQLException * @since 2.0 */ public String getNextSequenceValueSQL(SequenceProperties sequence) throws SQLException; /** * Returns a SQL statement used reset the current value of a sequence. * @param sequence a sequence name * @param value a sequence value * @return a SQL statement * @throws SQLException * @since 2.0 */ public String getAlterSequenceSQL(SequenceProperties sequence, long value) throws SQLException; /** * Returns a SQL statement used reset the current value of an identity column. * @param table a sequence name * @param column a sequence name * @param value a sequence value * @return a SQL statement * @throws SQLException * @since 2.0.2 */ public String getAlterIdentityColumnSQL(TableProperties table, ColumnProperties column, long value) throws SQLException; /** * Returns a search path of schemas * @param metaData * @return a list of schema names * @throws SQLException * @since 2.0 */ public List getDefaultSchemas(DatabaseMetaData metaData) throws SQLException; /** * Returns a pattern for identifiers that do not require quoting * @param metaData * @return a regular expression pattern * @throws SQLException * @since 2.0.2 */ public Pattern getIdentifierPattern(DatabaseMetaData metaData) throws SQLException; /** * Replaces non-deterministic CURRENT_DATE functions with deterministic static values. * @param sql an SQL statement * @param date the replacement date * @return an equivalent deterministic SQL statement * @throws SQLException * @since 2.0.2 */ public String evaluateCurrentDate(String sql, java.sql.Date date); /** * Replaces non-deterministic CURRENT_TIME functions with deterministic static values. * @param sql an SQL statement * @param time the replacement time * @return an equivalent deterministic SQL statement * @throws SQLException * @since 2.0.2 */ public String evaluateCurrentTime(String sql, java.sql.Time time); /** * Replaces non-deterministic CURRENT_TIMESTAMP functions with deterministic static values. * @param sql an SQL statement * @param timestamp the replacement timestamp * @return an equivalent deterministic SQL statement * @throws SQLException * @since 2.0.2 */ public String evaluateCurrentTimestamp(String sql, java.sql.Timestamp timestamp); /** * Replaces non-deterministic RAND() functions with deterministic static values. * @param sql an SQL statement * @return an equivalent deterministic SQL statement * @throws SQLException * @since 2.0.2 */ public String evaluateRand(String sql); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/SynchronizationStrategy.java0000644000175000017500000000244211151703042024414 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.sql.SQLException; /** * @author Paul Ferraro */ public interface SynchronizationStrategy { /** * Synchronizes a target database with a source database as defined by the synchronization context. * @param * @param context a synchronization context * @throws SQLException if synchronization fails */ public void synchronize(SynchronizationContext context) throws SQLException; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/ColumnProperties.java0000644000175000017500000000210411175404664023013 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; /** * @author Paul Ferraro * */ public interface ColumnProperties { public String getName(); public int getType(); public String getNativeType(); public boolean isAutoIncrement(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseEvent.java0000644000175000017500000000256511151703042022204 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.EventObject; /** * Identifies the target database of an event. * @author Paul Ferraro */ public class DatabaseEvent extends EventObject { private static final long serialVersionUID = -6709361835865578668L; /** * @param database */ public DatabaseEvent(Database database) { super(database.getId()); } /** * Returns the identifier of the target database. * @return a database identifier */ public String getId() { return (String) super.getSource(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseClusterDecorator.java0000644000175000017500000000203711151703042024401 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; /** * @author Paul Ferraro */ public interface DatabaseClusterDecorator { public void decorate(DatabaseCluster databaseCluster) throws Exception; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/ForeignKeyConstraint.java0000644000175000017500000000364111151703042023601 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.List; /** * Represents a foreign key constraint on a table. * * @author Paul Ferraro * @since 1.1 */ public interface ForeignKeyConstraint extends UniqueConstraint { /** * @return the foreign table of this foreign key */ public String getForeignTable(); /** * @return the foreign column of this foreign key */ public List getForeignColumnList(); /** * @return Returns the deleteRule. */ public int getDeleteRule(); /** * @return Returns the updateRule. */ public int getUpdateRule(); /** * @return Returns the deferrability. */ public int getDeferrability(); /** * @param deferrability The deferrability to set. */ public void setDeferrability(int deferrability); /** * @param deleteRule The deleteRule to set. */ public void setDeleteRule(int deleteRule); /** * @param foreignTable The foreignTable to set. */ public void setForeignTable(String foreignTable); /** * @param updateRule The updateRule to set. */ public void setUpdateRule(int updateRule); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseClusterMBean.java0000644000175000017500000001077511151703042023451 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.net.URL; import java.util.Set; /** * @author Paul Ferraro * @version $Revision: 2038 $ * @since 1.0 */ public interface DatabaseClusterMBean { /** * Determines whether or not the specified database is responsive * @param databaseId a database identifier * @return true, if the database is alive, false otherwise * @throws IllegalArgumentException if no database exists with the specified identifier. */ public boolean isAlive(String databaseId); /** * Deactivates the specified database. * @param databaseId a database identifier * @throws IllegalArgumentException if no database exists with the specified identifier. * @throws IllegalStateException if mbean could not be re-registered using inactive database interface. */ public void deactivate(String databaseId); /** * Synchronizes, using the default strategy, and reactivates the specified database. * @param databaseId a database identifier * @throws IllegalArgumentException if no database exists with the specified identifier. * @throws IllegalStateException if synchronization fails, or if mbean could not be re-registered using active database interface. */ public void activate(String databaseId); /** * Synchronizes, using the specified strategy, and reactivates the specified database. * @param databaseId a database identifier * @param syncId the class name of a synchronization strategy * @throws IllegalArgumentException if no database exists with the specified identifier, or no synchronization strategy exists with the specified identifier. * @throws IllegalStateException if synchronization fails, or if mbean could not be re-registered using active database interface. */ public void activate(String databaseId, String syncId); /** * Returns a collection of active databases in this cluster. * @return a list of database identifiers */ public Set getActiveDatabases(); /** * Returns a collection of inactive databases in this cluster. * @return a collection of database identifiers */ public Set getInactiveDatabases(); /** * Return the current HA-JDBC version * @return the current version */ public String getVersion(); /** * Removes the specified database/DataSource from the cluster. * @param databaseId a database identifier * @throws IllegalStateException if database is still active, or if mbean unregistration fails. */ public void remove(String databaseId); /** * Flushes this cluster's cache of DatabaseMetaData. */ public void flushMetaDataCache(); /** * Returns the set of synchronization strategies available to this cluster. * @return a set of synchronization strategy identifiers */ public Set getSynchronizationStrategies(); /** * Returns the default synchronization strategy used by this cluster. * @return a synchronization strategy identifier */ public String getDefaultSynchronizationStrategy(); /** * Returns the URL of the configuration file for this cluster. * @return a URL */ public URL getUrl(); /** * Provided so that mbean proxies will use mbean toString() implementation * @return string representation of this cluster */ public String toString(); public void addActivationListener(DatabaseActivationListener listener); public void removeActivationListener(DatabaseActivationListener listener); public void addDeactivationListener(DatabaseDeactivationListener listener); public void removeDeactivationListener(DatabaseDeactivationListener listener); public void addSynchronizationListener(SynchronizationListener listener); public void removeSynchronizationListener(SynchronizationListener listener); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Database.java0000644000175000017500000000356211205302071021175 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.sql.Connection; import java.sql.SQLException; import javax.management.DynamicMBean; /** * @author Paul Ferraro * @version $Revision: 1536 $ * @param either java.sql.Driver or javax.sql.DataSource * @since 1.0 */ public interface Database extends InactiveDatabaseMBean, Comparable> { /** * Connects to the database using the specified connection factory. * @param connectionFactory a factory object for creating connections * @return a database connection * @throws SQLException if connection fails */ public Connection connect(D connectionFactory) throws SQLException; /** * Factory method for creating a connection factory object for this database. * @return a connection factory object * @throws IllegalArgumentException if connection factory could not be created */ public D createConnectionFactory(); public DynamicMBean getActiveMBean(); public DynamicMBean getInactiveMBean(); public boolean isDirty(); public void clean(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/0000755000175000017500000000000011674455606017624 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/ClassEnum.java0000644000175000017500000000303211151703042022333 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util; /** * Interface for enumerated implementation classes. * @author Paul Ferraro * @param the implemented interface for each enumerated class */ public interface ClassEnum { /** * Creates a new instance of the enumerated class. * @return a new instance of the enumerated class * @throws Exception if a new instance could not be instantiated. */ public T newInstance() throws Exception; /** * Indicates whether the specified object is an instance of this enumerated class. * @param object an instance * @return true, if this object is an instance of this enumerated class, false otherwise */ public boolean isInstance(T object); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/PropertiesMapper.java0000644000175000017500000000632211151703042023747 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util; import java.util.Properties; import org.jibx.runtime.JiBXException; import org.jibx.runtime.impl.MarshallingContext; import org.jibx.runtime.impl.UnmarshallingContext; /** * Customer JiBX unmarshaller for unmarshalling a {@link java.util.Properties} object. * * @author Paul Ferraro * @since 1.0 */ public class PropertiesMapper extends AbstractMapper { private static final String ELEMENT = "property"; //$NON-NLS-1$ private static final String ATTRIBUTE = "name"; //$NON-NLS-1$ /** * Constructs a new PropertiesMapper. */ public PropertiesMapper() { super(Properties.class); } /** * Constructs a new PropertiesMapper. * @param uri * @param index * @param name */ public PropertiesMapper(String uri, int index, String name) { super(Properties.class, uri, index, name); } /** * @see net.sf.hajdbc.util.AbstractMapper#marshal(java.lang.Object, org.jibx.runtime.impl.MarshallingContext) */ @Override protected void marshal(Properties properties, MarshallingContext context) throws JiBXException { if (properties != null) { if (this.name != null) { context.startTag(this.index, this.name); } for (Object key: properties.keySet()) { String name = (String) key; context.startTagAttributes(this.index, ELEMENT).attribute(this.index, ATTRIBUTE, name).closeStartContent().content(properties.getProperty(name)).endTag(this.index, ELEMENT); } if (this.name != null) { context.endTag(this.index, this.name); } } } /** * @see net.sf.hajdbc.util.AbstractMapper#unmarshal(java.lang.Object, org.jibx.runtime.impl.UnmarshallingContext) */ @Override protected Properties unmarshal(Properties existingProperties, UnmarshallingContext context) throws JiBXException { Properties properties = (existingProperties != null) ? existingProperties : new Properties(); if (this.name != null) { context.parsePastStartTag(this.uri, this.name); } while (context.isAt(this.uri, ELEMENT)) { String name = context.attributeText(this.uri, ATTRIBUTE); context.parsePastStartTag(this.uri, ELEMENT); String value = context.parseContentText(); properties.put(name, value); context.parsePastEndTag(this.uri, ELEMENT); } if (this.name != null) { context.parsePastEndTag(this.uri, this.name); } return properties; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/AbstractMapper.java0000644000175000017500000000601111217563434023365 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util; import org.jibx.runtime.IAliasable; import org.jibx.runtime.IMarshaller; import org.jibx.runtime.IMarshallingContext; import org.jibx.runtime.IUnmarshaller; import org.jibx.runtime.IUnmarshallingContext; import org.jibx.runtime.JiBXException; import org.jibx.runtime.impl.MarshallingContext; import org.jibx.runtime.impl.UnmarshallingContext; /** * @author Paul Ferraro * */ public abstract class AbstractMapper implements IMarshaller, IUnmarshaller, IAliasable { protected String uri; protected String name; protected int index; private Class targetClass; /** * Constructs a new PropertiesMapper. */ protected AbstractMapper(Class targetClass) { this.targetClass = targetClass; } /** * Constructs a new PropertiesMapper. * @param uri * @param index * @param name */ protected AbstractMapper(Class targetClass, String uri, int index, String name) { this(targetClass); this.uri = uri; this.index = index; this.name = name; } /** * @see org.jibx.runtime.IMarshaller#isExtension(java.lang.String) */ @Override public boolean isExtension(String arg0) { return false; } /** * @see org.jibx.runtime.IMarshaller#marshal(java.lang.Object, org.jibx.runtime.IMarshallingContext) */ @Override public void marshal(Object object, IMarshallingContext context) throws JiBXException { this.marshal(this.targetClass.cast(object), (MarshallingContext) context); } protected abstract void marshal(T object, MarshallingContext context) throws JiBXException; /** * @see org.jibx.runtime.IUnmarshaller#isPresent(org.jibx.runtime.IUnmarshallingContext) */ @Override public boolean isPresent(IUnmarshallingContext context) throws JiBXException { return context.isAt(this.uri, this.name); } /** * @see org.jibx.runtime.IUnmarshaller#unmarshal(java.lang.Object, org.jibx.runtime.IUnmarshallingContext) */ @Override public Object unmarshal(Object object, IUnmarshallingContext context) throws JiBXException { return this.unmarshal(this.targetClass.cast(object), (UnmarshallingContext) context); } protected abstract T unmarshal(T object, UnmarshallingContext context) throws JiBXException; } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/servlet/0000755000175000017500000000000011674455606021310 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/servlet/DatabaseClusterShutdownContextListener.java0000644000175000017500000000507611151703042032014 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.servlet; import java.lang.management.ManagementFactory; import javax.management.JMException; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import net.sf.hajdbc.DatabaseClusterFactory; /** * Utility to automatically shutdown a list of database clusters scoped to a servlet context. * The clusters to shutdown are defined in a comma delimited init parameter: ha-jdbc.clusters * * @author Paul Ferraro */ public class DatabaseClusterShutdownContextListener implements ServletContextListener { private static final String CLUSTERS = "ha-jdbc.clusters"; private static final String DELIMITER = ","; /** * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) */ @Override public void contextDestroyed(ServletContextEvent event) { ServletContext context = event.getServletContext(); String clusters = context.getInitParameter(CLUSTERS); if (clusters != null) { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); for (String cluster: clusters.split(DELIMITER)) { try { ObjectName name = DatabaseClusterFactory.getObjectName(cluster.trim()); if (server.isRegistered(name)) { server.unregisterMBean(name); } } catch (JMException e) { event.getServletContext().log(e.getMessage(), e); } } } } /** * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) */ @Override public void contextInitialized(ServletContextEvent event) { // Do nothing } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/Enums.java0000644000175000017500000000345511151703042021541 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util; /** * Helper methods for Enums * @author Paul Ferraro */ public final class Enums { /** * Like {@link Enum#valueOf(Class, String)}, but converts id to upper-case and swaps dashes for underscores. * Used for deserializing configuration file enums. * @param * @param targetEnum * @param id * @return an enum value */ public static > T valueOf(Class targetEnum, String id) { return Enum.valueOf(targetEnum, id.toUpperCase().replace(Strings.DASH, Strings.UNDERSCORE)); } /** * Like {@link Enum#name()}, but returns in lower-case, swapping underscores for dashes. * Used for serializing configuration file enums. * @param * @param value * @return the id of the specified enum value */ public static > String id(T value) { return value.name().toLowerCase().replace(Strings.UNDERSCORE, Strings.DASH); } private Enums() { // Hide constructor } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/Strings.java0000644000175000017500000000510211151703042022072 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; /** * A set of String utilities. * @author Paul Ferraro * @since 2.0 */ public final class Strings { public static final String ANY = "%"; //$NON-NLS-1$ public static final String COMMA = ","; //$NON-NLS-1$ public static final String DASH = "-"; //$NON-NLS-1$ public static final String DOT = "."; //$NON-NLS-1$ public static final String EMPTY = ""; //$NON-NLS-1$ public static final String PADDED_COMMA = ", "; //$NON-NLS-1$ public static final String QUESTION = "?"; //$NON-NLS-1$ public static final String UNDERSCORE = "_"; //$NON-NLS-1$ /** * Performs the reverse of a split operation, joining the elements of the specified collection using the specified delimiter. * @param collection a collection of strings * @param delimiter a string to insert between each collection element * @return a new String */ public static String join(Collection collection, String delimiter) { StringBuilder builder = new StringBuilder(); Iterator elements = collection.iterator(); while (elements.hasNext()) { builder.append(elements.next()); if (elements.hasNext()) { builder.append(delimiter); } } return builder.toString(); } /** * Performs the reverse of a split operation, joining the elements of the specified collection using the specified delimiter. * @param strings an array of strings * @param delimiter a string to insert between each array element * @return a new String */ public static String join(String[] strings, String delimiter) { return join(Arrays.asList(strings), delimiter); } private Strings() { // Hide constructor } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/reflect/0000755000175000017500000000000011674455606021250 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/reflect/SimpleInvocationHandler.java0000644000175000017500000000335511151703042026656 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.reflect; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * A trivial invocation handler implementation. * @author Paul Ferraro */ public class SimpleInvocationHandler implements InvocationHandler { private Object object; /** * Constructs a new invocation handler that proxies the specified object. * @param object */ public SimpleInvocationHandler(Object object) { this.object = object; } /** * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override public Object invoke(Object proxy, Method method, Object[] parameters) throws Throwable { try { return method.invoke(this.object, parameters); } catch (InvocationTargetException e) { throw e.getTargetException(); } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/reflect/ProxyFactory.java0000644000175000017500000000312311151703042024537 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.reflect; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; /** * @author Paul Ferraro */ public final class ProxyFactory { /** * Helper method to simplify creation and casting of a proxy instance for a single interface. * @param target interface * @param targetInterface interface to proxy * @param handler an invocation handler * @return a proxy instance for the given target interface */ public static T createProxy(Class targetInterface, InvocationHandler handler) { return targetInterface.cast(Proxy.newProxyInstance(targetInterface.getClassLoader(), new Class[] { targetInterface }, handler)); } private ProxyFactory() { // Hide constructor } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/reflect/Methods.java0000644000175000017500000001105211151703042023471 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.reflect; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.SQLException; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.regex.Pattern; import net.sf.hajdbc.util.SQLExceptionFactory; /** * @author Paul Ferraro */ public final class Methods { /** * Helper method for Method.invoke(Object, Object...) that performs the necessary exception handling. * @param method a method to invoke * @param object the object on which to invoke the given method * @param parameters the method parameters * @return the return value of the method invocation * @throws SQLException the target exception of the method invocation * @throws IllegalArgumentException if the the underlying method is inaccessible */ public static Object invoke(Method method, Object object, Object... parameters) throws SQLException { try { return method.invoke(object, parameters); } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } catch (InvocationTargetException e) { throw SQLExceptionFactory.createSQLException(e.getTargetException()); } } /** * Returns a set of methods for the specified class whose names match the specified regular expression patterns. * @param sourceClass the class from which to find methods * @param patterns regular expression patterns * @return a set of methods */ public static Set findMethods(Class sourceClass, String... patterns) { List list = new LinkedList(); Method[] methods = sourceClass.getMethods(); for (String regex: patterns) { Pattern pattern = Pattern.compile(regex); for (Method method: methods) { if (pattern.matcher(method.getName()).matches()) { list.add(method); } } } return new HashSet(list); } /** * Helper method for {@link Class#getMethod(String, Class...)} where method is known to exist. * @param sourceClass the class from which to find methods * @param name the method name * @param types the parameter types * @return the method with the specified name and parameter types * @throws IllegalArgumentException if no such method exists */ public static Method getMethod(Class sourceClass, String name, Class... types) { try { return sourceClass.getMethod(name, types); } catch (NoSuchMethodException e) { throw new IllegalArgumentException(e); } } /** * Helper method for {@link Class#getMethod(String, Class...)} that returns null if the method does not exist. * @param sourceClass the class from which to find methods * @param name the method name * @param types the parameter types * @return the method with the specified name and parameter types, or null if the method does not exist */ public static Method findMethod(Class sourceClass, String name, Class... types) { try { return sourceClass.getMethod(name, types); } catch (NoSuchMethodException e) { return null; } } /** * Helper method for {@link Class#getMethod(String, Class...)} that returns null if the class or method does not exist. * @param className the name of the class containing the method * @param name the method name * @param types the parameter types * @return the method with the specified name and parameter types, or null if the class or method does not exist */ public static Method findMethod(String className, String name, Class... types) { try { return findMethod(Class.forName(className), name, types); } catch (ClassNotFoundException e) { return null; } } private Methods() { // Hide constructor } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/concurrent/0000755000175000017500000000000011674455606022006 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/concurrent/CronExecutorService.java0000644000175000017500000000302511151703042026566 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.concurrent; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import org.quartz.CronExpression; /** * Executor service that schedules a runnable task for execution via a cron expression. * * @author Paul Ferraro */ public interface CronExecutorService extends Executor, ExecutorService { /** * Schedules the specified task to execute according to the specified cron expression. * @see org.quartz.CronExpression * @param task the Runnable task to schedule * @param expression a cron expression */ public void schedule(Runnable task, CronExpression expression); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/concurrent/SemaphoreLock.java0000644000175000017500000000502511151703042025363 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.concurrent; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; /** * An implementation of {@link java.util.concurrent.locks.Lock} using a binary semaphore. * Unlike the {@link java.util.concurrent.locks.ReentrantLock} this lock can be locked and unlocked by different threads. * Conditions are not supported. * * @author Paul Ferraro */ public class SemaphoreLock implements Lock { private final Semaphore semaphore; public SemaphoreLock(boolean fair) { this(new Semaphore(1, fair)); } SemaphoreLock(Semaphore semaphore) { this.semaphore = semaphore; } /** * @see java.util.concurrent.locks.Lock#lock() */ @Override public void lock() { this.semaphore.acquireUninterruptibly(); } /** * @see java.util.concurrent.locks.Lock#lockInterruptibly() */ @Override public void lockInterruptibly() throws InterruptedException { this.semaphore.acquire(); } /** * @see java.util.concurrent.locks.Lock#newCondition() */ @Override public Condition newCondition() { throw new UnsupportedOperationException(); } /** * @see java.util.concurrent.locks.Lock#tryLock() */ @Override public boolean tryLock() { return this.semaphore.tryAcquire(); } /** * @see java.util.concurrent.locks.Lock#tryLock(long, java.util.concurrent.TimeUnit) */ @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return this.semaphore.tryAcquire(time, unit); } /** * @see java.util.concurrent.locks.Lock#unlock() */ @Override public void unlock() { this.semaphore.release(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/concurrent/DaemonThreadFactory.java0000644000175000017500000000325311151703042026513 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.concurrent; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; /** * ThreadFactory implementation that creates daemon threads. * * @author Paul Ferraro * @since 1.1 */ public class DaemonThreadFactory implements ThreadFactory { private static ThreadFactory instance = new DaemonThreadFactory(); private ThreadFactory factory = Executors.defaultThreadFactory(); /** * Returns single shared instance * @return a ThreadFactory instance */ public static ThreadFactory getInstance() { return instance; } /** * @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable) */ @Override public Thread newThread(Runnable runnable) { Thread thread = this.factory.newThread(runnable); thread.setDaemon(true); return thread; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/concurrent/SynchronousExecutor.java0000644000175000017500000000422611151703042026702 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.concurrent; import java.util.Collections; import java.util.List; import java.util.concurrent.AbstractExecutorService; import java.util.concurrent.TimeUnit; /** * Executor service that executes tasks in the caller thread. * * @author Paul Ferraro */ public class SynchronousExecutor extends AbstractExecutorService { private boolean shutdown; /** * @see java.util.concurrent.ExecutorService#awaitTermination(long, java.util.concurrent.TimeUnit) */ @Override public boolean awaitTermination(long time, TimeUnit unit) { return true; } /** * @see java.util.concurrent.ExecutorService#isShutdown() */ @Override public boolean isShutdown() { return this.shutdown; } /** * @see java.util.concurrent.ExecutorService#isTerminated() */ @Override public boolean isTerminated() { return this.shutdown; } /** * @see java.util.concurrent.ExecutorService#shutdown() */ @Override public void shutdown() { this.shutdown = true; } /** * @see java.util.concurrent.ExecutorService#shutdownNow() */ @Override public List shutdownNow() { this.shutdown(); return Collections.emptyList(); } /** * @see java.util.concurrent.Executor#execute(java.lang.Runnable) */ @Override public void execute(Runnable task) { task.run(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/concurrent/SemaphoreReadWriteLock.java0000644000175000017500000001071511151703042027174 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.concurrent; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; /** * Simple {@link java.util.concurrent.locks.ReadWriteLock} implementation that uses a semaphore. * A read lock requires 1 permit, while a write lock requires all the permits. * Lock upgrading and downgrading is not supported; nor are conditions. * * @author Paul Ferraro */ public class SemaphoreReadWriteLock implements ReadWriteLock { private static final int DEFAULT_PERMITS = Integer.MAX_VALUE; private final Lock readLock; private final Lock writeLock; public SemaphoreReadWriteLock(boolean fair) { this(DEFAULT_PERMITS, fair); } public SemaphoreReadWriteLock(int permits, boolean fair) { Semaphore semaphore = new Semaphore(permits, fair); this.readLock = new SemaphoreLock(semaphore); this.writeLock = new SemaphoreWriteLock(semaphore, permits); } /** * @see java.util.concurrent.locks.ReadWriteLock#readLock() */ @Override public Lock readLock() { return this.readLock; } /** * @see java.util.concurrent.locks.ReadWriteLock#writeLock() */ @Override public Lock writeLock() { return this.writeLock; } private static class SemaphoreWriteLock implements Lock { private final Semaphore semaphore; private final int permits; SemaphoreWriteLock(Semaphore semaphore, int permits) { this.semaphore = semaphore; this.permits = permits; } /** * Helps avoid write lock starvation, when using an unfair acquisition policy by draining all available permits. * @return the number of drained permits */ private int drainPermits() { return this.semaphore.isFair() ? 0 : this.semaphore.drainPermits(); } /** * @see java.util.concurrent.locks.Lock#lock() */ @Override public void lock() { int drained = this.drainPermits(); if (drained < this.permits) { this.semaphore.acquireUninterruptibly(this.permits - drained); } } /** * @see java.util.concurrent.locks.Lock#lockInterruptibly() */ @Override public void lockInterruptibly() throws InterruptedException { int drained = this.drainPermits(); if (drained < this.permits) { try { this.semaphore.acquire(this.permits - drained); } catch (InterruptedException e) { if (drained > 0) { this.semaphore.release(drained); } throw e; } } } /** * @see java.util.concurrent.locks.Lock#tryLock() */ @Override public boolean tryLock() { // This will barge the fairness queue, so there's no need to drain permits return this.semaphore.tryAcquire(this.permits); } /** * @see java.util.concurrent.locks.Lock#tryLock(long, java.util.concurrent.TimeUnit) */ @Override public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { int drained = this.drainPermits(); if (drained == this.permits) return true; boolean acquired = false; try { acquired = this.semaphore.tryAcquire(this.permits - drained, timeout, unit); } finally { if (!acquired && (drained > 0)) { this.semaphore.release(drained); } } return acquired; } /** * @see java.util.concurrent.locks.Lock#unlock() */ @Override public void unlock() { this.semaphore.release(this.permits); } /** * @see java.util.concurrent.locks.Lock#newCondition() */ @Override public Condition newCondition() { throw new UnsupportedOperationException(); } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/concurrent/CronThreadPoolExecutor.java0000644000175000017500000000676311151703042027243 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.concurrent; import java.util.Date; import java.util.concurrent.CancellationException; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.quartz.CronExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Scheduled thread-pool executor implementation that leverages a Quartz CronExpression to calculate future execution times for scheduled tasks. * * @author Paul Ferraro * @since 1.1 */ public class CronThreadPoolExecutor extends ScheduledThreadPoolExecutor implements CronExecutorService { protected static Logger logger = LoggerFactory.getLogger(CronThreadPoolExecutor.class); /** * Constructs a new CronThreadPoolExecutor. * @param corePoolSize * @param handler */ public CronThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) { super(corePoolSize, DaemonThreadFactory.getInstance(), handler); } /** * Constructs a new CronThreadPoolExecutor. * @param corePoolSize */ public CronThreadPoolExecutor(int corePoolSize) { super(corePoolSize, DaemonThreadFactory.getInstance()); } /** * @see net.sf.hajdbc.util.concurrent.CronExecutorService#schedule(java.lang.Runnable, org.quartz.CronExpression) */ @Override public void schedule(final Runnable task, final CronExpression expression) { if (task == null) throw new NullPointerException(); this.setCorePoolSize(this.getCorePoolSize() + 1); Runnable scheduleTask = new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { Date now = new Date(); Date time = expression.getNextValidTimeAfter(now); try { while (time != null) { CronThreadPoolExecutor.this.schedule(task, time.getTime() - now.getTime(), TimeUnit.MILLISECONDS); while (now.before(time)) { Thread.sleep(time.getTime() - now.getTime()); now = new Date(); } time = expression.getNextValidTimeAfter(now); } } catch (RejectedExecutionException e) { // Occurs if executor was already shutdown when schedule() is called } catch (CancellationException e) { // Occurs when scheduled, but not yet executed tasks are canceled during shutdown } catch (InterruptedException e) { // Occurs when executing tasks are interrupted during shutdownNow() } } }; this.execute(scheduleTask); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/Formatter.java0000644000175000017500000000405611151703042022413 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util; import java.text.ParseException; import java.util.Date; import org.quartz.CronExpression; /** * @author Paul Ferraro * */ public final class Formatter { public static String serializeCronExpression(CronExpression expression) { return (expression != null) ? expression.getCronExpression() : null; } public static CronExpression deserializeCronExpression(String schedule) throws ParseException { if (schedule == null) { return null; } CronExpression expression = new CronExpression(schedule); // Quartz inappropriately throws an UnsupportedOperationException if both day-of-week // and day-of-month are specified - so we preemptively test the expression here. try { expression.getNextValidTimeAfter(new Date()); return expression; } catch (UnsupportedOperationException e) { throw new ParseException(e.getMessage(), schedule.length()); } } public static String serializeClass(Class targetClass) { return (targetClass != null) ? targetClass.getName() : null; } public static Class deserializeClass(String className) throws ClassNotFoundException { return (className != null) ? Class.forName(className) : null; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/ref/0000755000175000017500000000000011674455606020400 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/ref/VolatileReference.java0000644000175000017500000000240311151703042024614 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2008 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util.ref; /** * A synchronizable wrapper around a nullable object. * @author Paul Ferraro */ public class VolatileReference { private volatile T object; public VolatileReference() { // Do nothing } public VolatileReference(T object) { this.object = object; } public T get() { return this.object; } public void set(T object) { this.object = object; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/util/SQLExceptionFactory.java0000644000175000017500000000353611151703042024320 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.util; import java.sql.SQLException; /** * @author Paul Ferraro * */ public final class SQLExceptionFactory { /** * Helper method for missing SQLException(String, Throwable) constructor in Java < 1.6 * @param message the description of the exception * @param cause the exception to wrap * @return an SQLException wrapping the given cause */ public static SQLException createSQLException(String message, Throwable cause) { SQLException exception = new SQLException(message); exception.initCause(cause); return exception; } /** * Helper method for missing SQLException(Throwable) constructor in Java < 1.6 * @param cause the exception to wrap * @return an SQLException wrapping the given cause */ public static SQLException createSQLException(Throwable cause) { if (cause instanceof SQLException) { return (SQLException) cause; } SQLException exception = new SQLException(); exception.initCause(cause); return exception; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseCluster.java0000644000175000017500000001317311151703042022541 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; /** * @author Paul Ferraro * @param either java.sql.Driver or javax.sql.DataSource */ public interface DatabaseCluster extends Lifecycle { /** * Returns the identifier of this cluster. * @return an identifier */ public String getId(); /** * Activates the specified database * @param database a database descriptor * @param manager a state manager * @return true, if the database was activated, false it was already active */ public boolean activate(Database database, StateManager manager); /** * Deactivates the specified database * @param database a database descriptor * @param manager a state manager * @return true, if the database was deactivated, false it was already inactive */ public boolean deactivate(Database database, StateManager manager); /** * Returns the database identified by the specified id * @param id a database identifier * @return a database descriptor * @throws IllegalArgumentException if no database exists with the specified identifier */ public Database getDatabase(String id); /** * Returns the Balancer implementation used by this database cluster. * @return an implementation of Balancer */ public Balancer getBalancer(); /** * Returns an executor service used to execute transactional database writes. * @return an implementation of ExecutorService */ public ExecutorService getTransactionalExecutor(); /** * Returns an executor service used to execute non-transactional database writes. * @return an implementation of ExecutorService */ public ExecutorService getNonTransactionalExecutor(); /** * Returns a dialect capable of returning database vendor specific values. * @return an implementation of Dialect */ public Dialect getDialect(); /** * Returns a LockManager capable of acquiring named read/write locks on the specific objects in this database cluster. * @return a LockManager implementation */ public LockManager getLockManager(); /** * Sets the LockManager implementation capable of acquiring named read/write locks on the specific objects in this database cluster. * @param lockManager a lock manager */ public void setLockManager(LockManager lockManager); /** * Returns a StateManager for persisting database cluster state. * @return a StateManager implementation */ public StateManager getStateManager(); /** * Sets the StateManager implementation for persisting database cluster state. * @param stateManager a state manager */ public void setStateManager(StateManager stateManager); /** * Returns a DatabaseMetaData cache. * @return a DatabaseMetaDataCache implementation */ public DatabaseMetaDataCache getDatabaseMetaDataCache(); /** * Indicates whether or not sequence detection is enabled for this cluster. * @return true, if sequence detection is enabled, false otherwise. */ public boolean isSequenceDetectionEnabled(); /** * Indicates whether or not identity column detection is enabled for this cluster. * @return true, if identity column detection is enabled, false otherwise. */ public boolean isIdentityColumnDetectionEnabled(); /** * Indicates whether or not non-deterministic CURRENT_DATE SQL functions will be evaluated to deterministic static values. * @return true, if temporal SQL replacement is enabled, false otherwise. */ public boolean isCurrentDateEvaluationEnabled(); /** * Indicates whether or not non-deterministic CURRENT_TIME functions will be evaluated to deterministic static values. * @return true, if temporal SQL replacement is enabled, false otherwise. */ public boolean isCurrentTimeEvaluationEnabled(); /** * Indicates whether or not non-deterministic CURRENT_TIMESTAMP functions will be evaluated to deterministic static values. * @return true, if temporal SQL replacement is enabled, false otherwise. */ public boolean isCurrentTimestampEvaluationEnabled(); /** * Indicates whether or not non-deterministic RAND() functions will be replaced by evaluated to static values. * @return true, if temporal SQL replacement is enabled, false otherwise. */ public boolean isRandEvaluationEnabled(); /** * Determines whether the specified databases are alive. * @param databases a collection of database descriptors * @return a map of alive status to set of database descriptors */ public Map>> getAliveMap(Collection> databases); /** * Indicates whether or not this cluster is active, i.e. started, but not yet stopped. * @return true, if this cluster is active, false otherwise. */ public boolean isActive(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/0000755000175000017500000000000011674455606020254 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/MckoiDialect.java0000644000175000017500000000315711151703042023431 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; /** * Dialect for Mckoi. * * @author Paul Ferraro */ @SuppressWarnings("nls") public class MckoiDialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#parseInsertTable(java.lang.String) */ @Override public String parseInsertTable(String sql) { return null; } /** * @see net.sf.hajdbc.dialect.StandardDialect#sequencePattern() */ @Override protected String sequencePattern() { return "(?:CURR|NEXT)VAL\\s*\\(\\s*'([^']+)'\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampPattern() */ @Override protected String currentTimestampPattern() { return super.currentTimestampPattern() + "|(?<=\\W)DATEOB\\s*\\(\\s*\\)"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/OracleDialect.java0000644000175000017500000000601711151703042023572 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.LinkedList; import java.util.List; import net.sf.hajdbc.QualifiedName; /** * Dialect for Oracle (commercial). * @author Paul Ferraro */ @SuppressWarnings("nls") public class OracleDialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#dummyTable() */ @Override protected String dummyTable() { return "DUAL"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { List sequenceList = new LinkedList(); Statement statement = metaData.getConnection().createStatement(); ResultSet resultSet = statement.executeQuery("SELECT SEQUENCE_NAME FROM USER_SEQUENCES"); while (resultSet.next()) { sequenceList.add(new QualifiedName(resultSet.getString(1))); } statement.close(); return sequenceList; } /** * @see net.sf.hajdbc.dialect.StandardDialect#parseInsertTable(java.lang.String) */ @Override public String parseInsertTable(String sql) { return null; } /** * @see net.sf.hajdbc.dialect.StandardDialect#truncateTableFormat() */ @Override protected String truncateTableFormat() { return "TRUNCATE TABLE {0}"; } /** * ON UPDATE and deferrability clauses are not supported. * @see net.sf.hajdbc.dialect.StandardDialect#createForeignKeyConstraintFormat() */ @Override protected String createForeignKeyConstraintFormat() { return "ALTER TABLE {1} ADD CONSTRAINT {0} FOREIGN KEY ({2}) REFERENCES {3} ({4}) ON DELETE {5,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#sequencePattern() */ @Override protected String sequencePattern() { return "'?(\\w+)'?\\.(?:CURR|NEXT)VAL"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#nextSequenceValueFormat() */ @Override protected String nextSequenceValueFormat() { return "{0}.NEXTVAL"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/H2Dialect.java0000644000175000017500000000666611151703042022650 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.LinkedList; import java.util.List; import net.sf.hajdbc.QualifiedName; /** * Dialect for H2 Database Engine. * @author Paul Ferraro */ @SuppressWarnings("nls") public class H2Dialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#executeFunctionFormat() */ @Override protected String executeFunctionFormat() { return "CALL {0}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { List sequenceList = new LinkedList(); Statement statement = metaData.getConnection().createStatement(); ResultSet resultSet = statement.executeQuery("SELECT SEQUENCE_SCHEMA, SEQUENCE_NAME FROM INFORMATION_SCHEMA.SYSTEM_SEQUENCES"); while (resultSet.next()) { sequenceList.add(new QualifiedName(resultSet.getString(1), resultSet.getString(2))); } statement.close(); return sequenceList; } /** * Deferrability clause is not supported. * @see net.sf.hajdbc.dialect.StandardDialect#createForeignKeyConstraintFormat() */ @Override protected String createForeignKeyConstraintFormat() { return "ALTER TABLE {1} ADD CONSTRAINT {0} FOREIGN KEY ({2}) REFERENCES {3} ({4}) ON DELETE {5,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT} ON UPDATE {6,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentDatePattern() */ @Override protected String currentDatePattern() { return "(?<=\\W)CURRENT_DATE(?:\\s*\\(\\s*\\))?(?=\\W)|(?<=\\W)CURDATE\\s*\\(\\s*\\)|(?<=\\W)SYSDATE(?=\\W)|(?<=\\W)TODAY(?=\\W)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimePattern() */ @Override protected String currentTimePattern() { return "(?<=\\W)CURRENT_TIME(?:\\s*\\(\\s*\\))?(?=\\W)|(?<=\\W)CURTIME\\s*\\(\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampPattern() */ @Override protected String currentTimestampPattern() { return "(?<=\\W)CURRENT_TIMESTAMP(?:\\s*\\(\\s*\\d*\\s*\\))?(?=\\W)|(?<=\\W)NOW\\s*\\(\\s*\\d*\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#randomPattern() */ @Override protected String randomPattern() { return "(?<=\\W)RAND\\s*\\(\\s*\\d*\\s*\\)"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/PostgreSQLDialect.java0000644000175000017500000001130511175404404024372 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.util.Strings; /** * Dialect for PostgreSQL. * @author Paul Ferraro * @since 1.1 */ @SuppressWarnings("nls") public class PostgreSQLDialect extends StandardDialect { /** * PostgreSQL uses a schema search path to locate unqualified table names. * The default search path is [$user,public], where $user is the current user. * @see net.sf.hajdbc.dialect.StandardDialect#getDefaultSchemas(java.sql.DatabaseMetaData) */ @Override public List getDefaultSchemas(DatabaseMetaData metaData) throws SQLException { Connection connection = metaData.getConnection(); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SHOW search_path"); resultSet.next(); String[] schemas = resultSet.getString(1).split(Strings.COMMA); resultSet.close(); statement.close(); List schemaList = new ArrayList(schemas.length); for (String schema: schemas) { schemaList.add(schema.equals("$user") ? metaData.getUserName() : schema); } return schemaList; } /** * PostgreSQL uses the native type OID to identify BLOBs. * However the JDBC driver incomprehensibly maps OIDs to INTEGERs. * The PostgreSQL JDBC folks claim this intentional. * @see net.sf.hajdbc.dialect.StandardDialect#getColumnType(net.sf.hajdbc.ColumnProperties) */ @Override public int getColumnType(ColumnProperties properties) { return properties.getNativeType().equalsIgnoreCase("oid") ? Types.BLOB : properties.getType(); } /** * Versions >=8.1 of the PostgreSQL JDBC driver return incorrect values for DatabaseMetaData.getExtraNameCharacters(). * @see net.sf.hajdbc.dialect.StandardDialect#getIdentifierPattern(java.sql.DatabaseMetaData) */ @Override public Pattern getIdentifierPattern(DatabaseMetaData metaData) throws SQLException { if ((metaData.getDriverMajorVersion() >= 8) && (metaData.getDriverMinorVersion() >= 1)) { return Pattern.compile("[A-Za-z\\0200-\\0377_][A-Za-z\\0200-\\0377_0-9\\$]*"); } return super.getIdentifierPattern(metaData); } /** * @see net.sf.hajdbc.dialect.StandardDialect#truncateTableFormat() */ @Override protected String truncateTableFormat() { return "TRUNCATE TABLE {0}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#sequencePattern() */ @Override protected String sequencePattern() { return "(?:CURR|NEXT)VAL\\s*\\(\\s*'([^']+)'\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#nextSequenceValueFormat() */ @Override protected String nextSequenceValueFormat() { return "NEXTVAL(''{0}'')"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#alterIdentityColumnFormat() */ @Override protected String alterIdentityColumnFormat() { return "ALTER SEQUENCE {0}_{1}_seq RESTART WITH {2}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampPattern() */ @Override protected String currentTimestampPattern() { return super.currentTimestampPattern() + "|(?<=\\W)NOW\\s*\\(\\s*\\)|(?<=\\W)TRANSACTION_TIMESTAMP\\s*\\(\\s*\\)|(?<=\\W)STATEMENT_TIMESTAMP\\s*\\(\\s*\\)|(?<=\\W)CLOCK_TIMESTAMP\\s*\\(\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#randomPattern() */ @Override protected String randomPattern() { return "(?<=\\W)RANDOM\\s*\\(\\s*\\)"; } /** * Recognizes FOR SHARE and FOR UPDATE. * @see net.sf.hajdbc.dialect.StandardDialect#selectForUpdatePattern() */ @Override protected String selectForUpdatePattern() { return "SELECT\\s+.+\\s+FOR\\s+(SHARE|UPDATE)"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/FirebirdDialect.java0000644000175000017500000000600511151703042024110 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.LinkedList; import java.util.List; import net.sf.hajdbc.QualifiedName; /** * Dialect for Firebird. * @author Paul Ferraro */ @SuppressWarnings("nls") public class FirebirdDialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#dummyTable() */ @Override protected String dummyTable() { return "RDB$DATABASE"; } /** * Firebird 2.0 will support standard syntax. Until then... * @see net.sf.hajdbc.dialect.StandardDialect#alterSequenceFormat() */ @Override protected String alterSequenceFormat() { return "SET GENERATOR {0} TO {1}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { List sequenceList = new LinkedList(); Statement statement = metaData.getConnection().createStatement(); ResultSet resultSet = statement.executeQuery("SELECT RDB$GENERATOR_NAME FROM RDB$GENERATORS"); while (resultSet.next()) { sequenceList.add(new QualifiedName(resultSet.getString(1))); } statement.close(); return sequenceList; } /** * @see net.sf.hajdbc.dialect.StandardDialect#parseInsertTable(java.lang.String) */ @Override public String parseInsertTable(String sql) { return null; } /** * Firebird 2.0 will support standard syntax. Until then... * @see net.sf.hajdbc.dialect.StandardDialect#sequencePattern() */ @Override protected String sequencePattern() { return "GEN_ID\\s*\\(\\s*([^\\s,]+)\\s*,\\s*\\d+\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#selectForUpdatePattern() */ @Override protected String selectForUpdatePattern() { return "SELECT\\s+.+\\s+WITH\\s+LOCK"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#nextSequenceValueFormat() */ @Override protected String nextSequenceValueFormat() { return "GEN_ID({0}, 1)"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/MySQLDialect.java0000644000175000017500000001050111175404327023335 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Collection; import java.util.Collections; import java.util.List; import net.sf.hajdbc.QualifiedName; /** * Dialect for MySQL * @author Paul Ferraro */ @SuppressWarnings("nls") public class MySQLDialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#getDefaultSchemas(java.sql.DatabaseMetaData) */ @Override public List getDefaultSchemas(DatabaseMetaData metaData) throws SQLException { return Collections.singletonList(this.executeFunction(metaData.getConnection(), "DATABASE()")); } /** * @see net.sf.hajdbc.dialect.StandardDialect#parseSequence(java.lang.String) */ @Override public String parseSequence(String sql) { return null; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { return Collections.emptyList(); } /** * Deferrability clause is not supported. * @see net.sf.hajdbc.dialect.StandardDialect#createForeignKeyConstraintFormat() */ @Override protected String createForeignKeyConstraintFormat() { return "ALTER TABLE {1} ADD CONSTRAINT {0} FOREIGN KEY ({2}) REFERENCES {3} ({4}) ON DELETE {5,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT} ON UPDATE {6,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#createUniqueConstraintFormat() */ @Override protected String createUniqueConstraintFormat() { return "ALTER TABLE {1} ADD UNIQUE {0} ({2})"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#dropForeignKeyConstraintFormat() */ @Override protected String dropForeignKeyConstraintFormat() { return "ALTER TABLE {1} DROP FOREIGN KEY {0}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#dropUniqueConstraintFormat() */ @Override protected String dropUniqueConstraintFormat() { return "ALTER TABLE {1} DROP INDEX {0}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#alterIdentityColumnFormat() */ @Override protected String alterIdentityColumnFormat() { return "ALTER TABLE {0} AUTO_INCREMENT = {2}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentDatePattern() */ @Override protected String currentDatePattern() { return super.currentDatePattern() + "|(?<=\\W)CURDATE\\s*\\(\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimePattern() */ @Override protected String currentTimePattern() { return super.currentTimePattern() + "|(?<=\\W)CURTIME\\s*\\(\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampPattern() */ @Override protected String currentTimestampPattern() { return super.currentTimestampPattern() + "|(?<=\\W)NOW\\s*\\(\\s*\\)|(?<=\\W)SYSDATE\\s*\\(\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#dateLiteralFormat() */ @Override protected String dateLiteralFormat() { return this.timestampLiteralFormat(); } /** * @see net.sf.hajdbc.dialect.StandardDialect#timeLiteralFormat() */ @Override protected String timeLiteralFormat() { return this.timestampLiteralFormat(); } /** * @see net.sf.hajdbc.dialect.StandardDialect#timestampLiteralFormat() */ @Override protected String timestampLiteralFormat() { return "''{0}''"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/SybaseDialect.java0000644000175000017500000000730011175404424023617 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Collection; import java.util.Collections; import net.sf.hajdbc.QualifiedName; /** * Dialect for Sybase (commercial). * @author Paul Ferraro */ @SuppressWarnings("nls") public class SybaseDialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampFunction() */ @Override protected String currentTimestampFunction() { return "GETDATE()"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#truncateTableFormat() */ @Override protected String truncateTableFormat() { return "TRUNCATE TABLE {0}"; } /** * Deferrability clause is not supported. * @see net.sf.hajdbc.dialect.StandardDialect#createForeignKeyConstraintFormat() */ @Override protected String createForeignKeyConstraintFormat() { return "ALTER TABLE {1} ADD CONSTRAINT {0} FOREIGN KEY ({2}) REFERENCES {3} ({4}) ON DELETE {5,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT} ON UPDATE {6,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT}"; } /** * Sybase does not support sequences. * @see net.sf.hajdbc.dialect.StandardDialect#parseSequence(java.lang.String) */ @Override public String parseSequence(String sql) { return null; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { return Collections.emptyList(); } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentDatePattern() */ @Override protected String currentDatePattern() { return "(?<=\\W)CURRENT\\s+DATE(?=\\W)|(?<=\\W)TODAY\\s*\\(\\s*\\*\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimePattern() */ @Override protected String currentTimePattern() { return "(?<=\\W)CURRENT\\s+TIME(?=\\W)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampPattern() */ @Override protected String currentTimestampPattern() { return "(?<=\\W)CURRENT\\s+TIMESTAMP(?=\\W)|(?<=\\W)GETDATE\\s*\\(\\s*\\)|(?<=\\W)NOW\\s*\\(\\s*\\*\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#dateLiteralFormat() */ @Override protected String dateLiteralFormat() { return this.timestampLiteralFormat(); } /** * @see net.sf.hajdbc.dialect.StandardDialect#timeLiteralFormat() */ @Override protected String timeLiteralFormat() { return this.timestampLiteralFormat(); } /** * @see net.sf.hajdbc.dialect.StandardDialect#timestampLiteralFormat() */ @Override protected String timestampLiteralFormat() { return "''{0}''"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#randomPattern() */ @Override protected String randomPattern() { return "(?<=\\W)RAND\\s*\\(\\s*\\d*\\s*\\)"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/StandardDialect.java0000644000175000017500000002770511214204044024132 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.MessageFormat; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sf.hajdbc.ColumnProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.QualifiedName; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.UniqueConstraint; import net.sf.hajdbc.util.Strings; /** * @author Paul Ferraro * @since 1.1 */ @SuppressWarnings("nls") public class StandardDialect implements Dialect { private Pattern selectForUpdatePattern = this.compile(this.selectForUpdatePattern()); private Pattern insertIntoTablePattern = this.compile(this.insertIntoTablePattern()); private Pattern sequencePattern = this.compile(this.sequencePattern()); private Pattern currentTimestampPattern = this.compile(this.currentTimestampPattern()); private Pattern currentDatePattern = this.compile(this.currentDatePattern()); private Pattern currentTimePattern = this.compile(this.currentTimePattern()); private Pattern randomPattern = this.compile(this.randomPattern()); private Pattern compile(String pattern) { return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); } protected String selectForUpdatePattern() { return "SELECT\\s+.+\\s+FOR\\s+UPDATE"; } protected String insertIntoTablePattern() { return "INSERT\\s+(?:INTO\\s+)?'?([^'\\s\\(]+)"; } protected String sequencePattern() { return "NEXT\\s+VALUE\\s+FOR\\s+'?([^',\\s\\(\\)]+)"; } protected String currentDatePattern() { return "(?<=\\W)CURRENT_DATE(?=\\W)"; } protected String currentTimePattern() { return "(?<=\\W)CURRENT_TIME(?:\\s*\\(\\s*\\d+\\s*\\))?(?=\\W)|(?<=\\W)LOCALTIME(?:\\s*\\(\\s*\\d+\\s*\\))?(?=\\W)"; } protected String currentTimestampPattern() { return "(?<=\\W)CURRENT_TIMESTAMP(?:\\s*\\(\\s*\\d+\\s*\\))?(?=\\W)|(?<=\\W)LOCALTIMESTAMP(?:\\s*\\(\\s*\\d+\\s*\\))?(?=\\W)"; } protected String randomPattern() { return "(?<=\\W)RAND\\s*\\(\\s*\\)"; } /** * @see net.sf.hajdbc.Dialect#getSimpleSQL() */ @Override public String getSimpleSQL() { return this.executeFunctionSQL(this.currentTimestampFunction()); } protected String executeFunctionFormat() { StringBuilder builder = new StringBuilder("SELECT {0}"); String dummyTable = this.dummyTable(); if (dummyTable != null) { builder.append(" FROM ").append(dummyTable); } return builder.toString(); } protected String executeFunctionSQL(String function) { return MessageFormat.format(this.executeFunctionFormat(), function); } protected String currentTimestampFunction() { return "CURRENT_TIMESTAMP"; } protected String dummyTable() { return null; } /** * @see net.sf.hajdbc.Dialect#getTruncateTableSQL(net.sf.hajdbc.TableProperties) */ @Override public String getTruncateTableSQL(TableProperties properties) { return MessageFormat.format(this.truncateTableFormat(), properties.getName()); } protected String truncateTableFormat() { return "DELETE FROM {0}"; } /** * @see net.sf.hajdbc.Dialect#getCreateForeignKeyConstraintSQL(net.sf.hajdbc.ForeignKeyConstraint) */ @Override public String getCreateForeignKeyConstraintSQL(ForeignKeyConstraint key) { return MessageFormat.format(this.createForeignKeyConstraintFormat(), key.getName(), key.getTable(), Strings.join(key.getColumnList(), Strings.PADDED_COMMA), key.getForeignTable(), Strings.join(key.getForeignColumnList(), Strings.PADDED_COMMA), key.getDeleteRule(), key.getUpdateRule(), key.getDeferrability()); } protected String createForeignKeyConstraintFormat() { return "ALTER TABLE {1} ADD CONSTRAINT {0} FOREIGN KEY ({2}) REFERENCES {3} ({4}) ON DELETE {5,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT} ON UPDATE {6,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT} {7,choice,5#DEFERRABLE INITIALLY DEFERRED|6#DEFERRABLE INITIALLY IMMEDIATE|7#NOT DEFERRABLE}"; } /** * @see net.sf.hajdbc.Dialect#getDropForeignKeyConstraintSQL(net.sf.hajdbc.ForeignKeyConstraint) */ @Override public String getDropForeignKeyConstraintSQL(ForeignKeyConstraint key) { return MessageFormat.format(this.dropForeignKeyConstraintFormat(), key.getName(), key.getTable()); } protected String dropForeignKeyConstraintFormat() { return this.dropConstraintFormat(); } protected String dropConstraintFormat() { return "ALTER TABLE {1} DROP CONSTRAINT {0}"; } /** * @see net.sf.hajdbc.Dialect#getCreateUniqueConstraintSQL(net.sf.hajdbc.UniqueConstraint) */ @Override public String getCreateUniqueConstraintSQL(UniqueConstraint constraint) { return MessageFormat.format(this.createUniqueConstraintFormat(), constraint.getName(), constraint.getTable(), Strings.join(constraint.getColumnList(), Strings.PADDED_COMMA)); } protected String createUniqueConstraintFormat() { return "ALTER TABLE {1} ADD CONSTRAINT {0} UNIQUE ({2})"; } /** * @see net.sf.hajdbc.Dialect#getDropUniqueConstraintSQL(net.sf.hajdbc.UniqueConstraint) */ @Override public String getDropUniqueConstraintSQL(UniqueConstraint constraint) { return MessageFormat.format(this.dropUniqueConstraintFormat(), constraint.getName(), constraint.getTable()); } protected String dropUniqueConstraintFormat() { return this.dropConstraintFormat(); } /** * @see net.sf.hajdbc.Dialect#isSelectForUpdate(java.lang.String) */ @Override public boolean isSelectForUpdate(String sql) { return this.selectForUpdatePattern.matcher(sql).find(); } /** * @see net.sf.hajdbc.Dialect#parseInsertTable(java.lang.String) */ @Override public String parseInsertTable(String sql) { return this.parse(this.insertIntoTablePattern, sql); } /** * @see net.sf.hajdbc.Dialect#getDefaultSchemas(java.sql.DatabaseMetaData) */ @Override public List getDefaultSchemas(DatabaseMetaData metaData) throws SQLException { return Collections.singletonList(metaData.getUserName()); } protected String executeFunction(Connection connection, String function) throws SQLException { Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(this.executeFunctionSQL(function)); resultSet.next(); String value = resultSet.getString(1); resultSet.close(); statement.close(); return value; } protected List executeQuery(Connection connection, String sql) throws SQLException { List resultList = new LinkedList(); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(sql); while (resultSet.next()) { resultList.add(resultSet.getString(1)); } resultSet.close(); statement.close(); return resultList; } /** * @see net.sf.hajdbc.Dialect#parseSequence(java.lang.String) */ @Override public String parseSequence(String sql) { return this.parse(this.sequencePattern, sql); } /** * @see net.sf.hajdbc.Dialect#getColumnType(net.sf.hajdbc.ColumnProperties) */ @Override public int getColumnType(ColumnProperties properties) { return properties.getType(); } /** * @see net.sf.hajdbc.Dialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { List sequenceList = new LinkedList(); ResultSet resultSet = metaData.getTables(Strings.EMPTY, null, Strings.ANY, new String[] { this.sequenceTableType() }); while (resultSet.next()) { sequenceList.add(new QualifiedName(resultSet.getString("TABLE_SCHEM"), resultSet.getString("TABLE_NAME"))); } resultSet.close(); return sequenceList; } protected String sequenceTableType() { return "SEQUENCE"; } /** * @see net.sf.hajdbc.Dialect#getNextSequenceValueSQL(net.sf.hajdbc.SequenceProperties) */ @Override public String getNextSequenceValueSQL(SequenceProperties sequence) { return this.executeFunctionSQL(MessageFormat.format(this.nextSequenceValueFormat(), sequence.getName())); } protected String nextSequenceValueFormat() { return "NEXT VALUE FOR {0}"; } /** * @see net.sf.hajdbc.Dialect#getAlterSequenceSQL(net.sf.hajdbc.SequenceProperties, long) */ @Override public String getAlterSequenceSQL(SequenceProperties sequence, long value) { return MessageFormat.format(this.alterSequenceFormat(), sequence.getName(), String.valueOf(value)); } protected String alterSequenceFormat() { return "ALTER SEQUENCE {0} RESTART WITH {1}"; } @Override public String getAlterIdentityColumnSQL(TableProperties table, ColumnProperties column, long value) throws SQLException { return MessageFormat.format(this.alterIdentityColumnFormat(), table.getName(), column.getName(), String.valueOf(value)); } protected String alterIdentityColumnFormat() { return "ALTER TABLE {0} ALTER COLUMN {1} RESTART WITH {2}"; } /** * @see net.sf.hajdbc.Dialect#getIdentifierPattern(java.sql.DatabaseMetaData) */ @Override public Pattern getIdentifierPattern(DatabaseMetaData metaData) throws SQLException { return Pattern.compile(MessageFormat.format("[a-zA-Z][\\w{0}]*", Pattern.quote(metaData.getExtraNameCharacters()))); } protected String parse(Pattern pattern, String string) { Matcher matcher = pattern.matcher(string); return matcher.find() ? matcher.group(1) : null; } /** * @see net.sf.hajdbc.Dialect#evaluateCurrentDate(java.lang.String, java.sql.Date) */ @Override public String evaluateCurrentDate(String sql, java.sql.Date date) { return this.evaluateTemporal(sql, this.currentDatePattern, date, this.dateLiteralFormat()); } protected String dateLiteralFormat() { return "DATE ''{0}''"; } /** * @see net.sf.hajdbc.Dialect#evaluateCurrentTime(java.lang.String, java.sql.Time) */ @Override public String evaluateCurrentTime(String sql, java.sql.Time time) { return this.evaluateTemporal(sql, this.currentTimePattern, time, this.timeLiteralFormat()); } protected String timeLiteralFormat() { return "TIME ''{0}''"; } /** * @see net.sf.hajdbc.Dialect#evaluateCurrentTimestamp(java.lang.String, java.sql.Timestamp) */ @Override public String evaluateCurrentTimestamp(String sql, java.sql.Timestamp timestamp) { return this.evaluateTemporal(sql, this.currentTimestampPattern, timestamp, this.timestampLiteralFormat()); } protected String timestampLiteralFormat() { return "TIMESTAMP ''{0}''"; } private String evaluateTemporal(String sql, Pattern pattern, java.util.Date date, String format) { return pattern.matcher(sql).replaceAll(MessageFormat.format(format, date.toString())); } /** * @see net.sf.hajdbc.Dialect#evaluateRand(java.lang.String) */ @Override public String evaluateRand(String sql) { StringBuffer buffer = new StringBuffer(); Matcher matcher = this.randomPattern.matcher(sql); while (matcher.find()) { matcher.appendReplacement(buffer, Double.toString(Math.random())); } return matcher.appendTail(buffer).toString(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/HSQLDBDialect.java0000644000175000017500000000623611151703042023345 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.LinkedList; import java.util.List; import net.sf.hajdbc.QualifiedName; /** * Dialect for HSQLDB. * * @author Paul Ferraro * @since 1.1 */ @SuppressWarnings("nls") public class HSQLDBDialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#executeFunctionFormat() */ @Override protected String executeFunctionFormat() { return "CALL {0}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { List sequenceList = new LinkedList(); Statement statement = metaData.getConnection().createStatement(); ResultSet resultSet = statement.executeQuery("SELECT SEQUENCE_SCHEMA, SEQUENCE_NAME FROM INFORMATION_SCHEMA.SYSTEM_SEQUENCES"); while (resultSet.next()) { sequenceList.add(new QualifiedName(resultSet.getString(1), resultSet.getString(2))); } statement.close(); return sequenceList; } /** * Deferrability clause is not supported. * @see net.sf.hajdbc.dialect.StandardDialect#createForeignKeyConstraintFormat() */ @Override protected String createForeignKeyConstraintFormat() { return "ALTER TABLE {1} ADD CONSTRAINT {0} FOREIGN KEY ({2}) REFERENCES {3} ({4}) ON DELETE {5,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT} ON UPDATE {6,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentDatePattern() */ @Override protected String currentDatePattern() { return "(?<=\\W)CURRENT_DATE(?=\\W)|(?<=\\W)CURDATE\\s*\\(\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimePattern() */ @Override protected String currentTimePattern() { return "(?<=\\W)CURRENT_TIME(?=\\W)|(?<=\\W)CURTIME\\s*\\(\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampPattern() */ @Override protected String currentTimestampPattern() { return "(?<=\\W)CURRENT_TIMESTAMP(?=\\W)|(?<=\\W)NOW\\s*\\(\\s*\\)"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/DerbyDialect.java0000644000175000017500000000654011175404314023441 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Collection; import java.util.Collections; import net.sf.hajdbc.QualifiedName; /** * Dialect for Apache Derby. * * @author Paul Ferraro * @since 1.1 */ @SuppressWarnings("nls") public class DerbyDialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#executeFunctionFormat() */ @Override protected String executeFunctionFormat() { return "VALUES {0}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#parseSequence(java.lang.String) */ @Override public String parseSequence(String sql) { return null; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { return Collections.emptyList(); } /** * Deferrability clause is not supported. * @see net.sf.hajdbc.dialect.StandardDialect#createForeignKeyConstraintFormat() */ @Override protected String createForeignKeyConstraintFormat() { return "ALTER TABLE {1} ADD CONSTRAINT {0} FOREIGN KEY ({2}) REFERENCES {3} ({4}) ON DELETE {5,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT} ON UPDATE {6,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentDatePattern() */ @Override protected String currentDatePattern() { return super.currentDatePattern() + "|(?<=\\W)CURRENT\\s+DATE(?=\\W)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimePattern() */ @Override protected String currentTimePattern() { return super.currentTimePattern() + "|(?<=\\W)CURRENT\\s+TIME(?=\\W)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampPattern() */ @Override protected String currentTimestampPattern() { return super.currentTimestampPattern() + "|(?<=\\W)CURRENT\\s+TIMESTAMP(?=\\W)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#dateLiteralFormat() */ @Override protected String dateLiteralFormat() { return "DATE(''{0}'')"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#timeLiteralFormat() */ @Override protected String timeLiteralFormat() { return "TIME(''{0}'')"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#timestampLiteralFormat() */ @Override protected String timestampLiteralFormat() { return "TIMESTAMP(''{0}'')"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/DialectClass.java0000644000175000017500000000576411151703042023442 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.util.ClassEnum; import net.sf.hajdbc.util.Enums; /** * @author Paul Ferraro * @since 1.1 */ public enum DialectClass implements ClassEnum { DB2(DB2Dialect.class), DERBY(DerbyDialect.class), FIREBIRD(FirebirdDialect.class), H2(H2Dialect.class), HSQLDB(HSQLDBDialect.class), INGRES(IngresDialect.class), MAXDB(MaxDBDialect.class), MCKOI(MckoiDialect.class), MYSQL(MySQLDialect.class), ORACLE(OracleDialect.class), POSTGRESQL(PostgreSQLDialect.class), STANDARD(StandardDialect.class), SYBASE(SybaseDialect.class); private Class dialectClass; private DialectClass(Class dialectClass) { this.dialectClass = dialectClass; } /** * @see net.sf.hajdbc.util.ClassEnum#isInstance(java.lang.Object) */ @Override public boolean isInstance(Dialect dialect) { return this.dialectClass.equals(dialect.getClass()); } /** * @see net.sf.hajdbc.util.ClassEnum#newInstance() */ @Override public Dialect newInstance() throws Exception { return this.dialectClass.newInstance(); } /** * Creates a new instance of the Dialect implementation from the specified class name. * @param id the class name of a Dialect instance. * @return a new Dialect instance * @throws Exception if a Dialect instance could not be instantiated from the specified class name. */ public static Dialect deserialize(String id) throws Exception { try { DialectClass dialectClass = (id != null) ? Enums.valueOf(DialectClass.class, id) : STANDARD; return dialectClass.newInstance(); } catch (IllegalArgumentException e) { return Class.forName(id).asSubclass(Dialect.class).newInstance(); } } /** * Return a String representation that identifies the specified Dialect. * @param dialect a Dialect implementation * @return the class name of this dialect */ public static String serialize(Dialect dialect) { for (DialectClass dialectClass: DialectClass.values()) { if (dialectClass.isInstance(dialect)) { return Enums.id(dialectClass); } } return dialect.getClass().getName(); } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/MaxDBDialect.java0000644000175000017500000000637211151703042023324 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.LinkedList; import java.util.List; import net.sf.hajdbc.QualifiedName; /** * Dialect for MySQL MaxDB. * @author Paul Ferraro * @since 1.1 */ @SuppressWarnings("nls") public class MaxDBDialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#dummyTable() */ @Override protected String dummyTable() { return "DUAL"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampFunction() */ @Override protected String currentTimestampFunction() { return "SYSDATE"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { List sequenceList = new LinkedList(); Statement statement = metaData.getConnection().createStatement(); ResultSet resultSet = statement.executeQuery("SELECT SEQUENCE_NAME FROM USER_SEQUENCES"); while (resultSet.next()) { sequenceList.add(new QualifiedName(resultSet.getString(1))); } statement.close(); return sequenceList; } /** * @see net.sf.hajdbc.dialect.StandardDialect#parseInsertTable(java.lang.String) */ @Override public String parseInsertTable(String sql) { return null; } /** * @see net.sf.hajdbc.dialect.StandardDialect#truncateTableFormat() */ @Override protected String truncateTableFormat() { return "TRUNCATE TABLE {0}"; } /** * ON UPDATE and deferrability clauses are not supported. * @see net.sf.hajdbc.dialect.StandardDialect#createForeignKeyConstraintFormat() */ @Override protected String createForeignKeyConstraintFormat() { return "ALTER TABLE {1} ADD CONSTRAINT {0} FOREIGN KEY ({2}) REFERENCES {3} ({4}) ON DELETE {5,choice,0#CASCADE|1#RESTRICT|2#SET NULL|3#NO ACTION|4#SET DEFAULT}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#sequencePattern() */ @Override protected String sequencePattern() { return "'?(\\w+)'?\\.(?:CURR|NEXT)VAL"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#nextSequenceValueFormat() */ @Override protected String nextSequenceValueFormat() { return "{0}.NEXTVAL"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/DB2Dialect.java0000644000175000017500000000562211151703042022735 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.LinkedList; import java.util.List; import net.sf.hajdbc.QualifiedName; /** * Dialect for DB2 (commercial). * @author Paul Ferraro * @since 1.1 */ @SuppressWarnings("nls") public class DB2Dialect extends StandardDialect { /** * @see net.sf.hajdbc.dialect.StandardDialect#executeFunctionFormat() */ @Override protected String executeFunctionFormat() { return "VALUES {0}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { List sequenceList = new LinkedList(); Statement statement = metaData.getConnection().createStatement(); ResultSet resultSet = statement.executeQuery("SELECT SEQSCHEMA, SEQNAME FROM SYSCAT.SEQUENCES"); while (resultSet.next()) { sequenceList.add(new QualifiedName(resultSet.getString(1), resultSet.getString(2))); } statement.close(); return sequenceList; } /** * @see net.sf.hajdbc.dialect.StandardDialect#sequencePattern() */ @Override protected String sequencePattern() { return "(?:NEXT|PREV)VAL\\s+FOR\\s+'?([^',\\s\\(\\)]+)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#nextSequenceValueFormat() */ @Override protected String nextSequenceValueFormat() { return "NEXTVAL FOR {0}"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#dateLiteralFormat() */ @Override protected String dateLiteralFormat() { return this.timestampLiteralFormat(); } /** * @see net.sf.hajdbc.dialect.StandardDialect#timeLiteralFormat() */ @Override protected String timeLiteralFormat() { return this.timestampLiteralFormat(); } /** * @see net.sf.hajdbc.dialect.StandardDialect#timestampLiteralFormat() */ @Override protected String timestampLiteralFormat() { return "''{0}''"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/dialect/IngresDialect.java0000644000175000017500000000676611151703042023627 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.dialect; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.regex.Pattern; import net.sf.hajdbc.QualifiedName; /** * Dialect for Ingres. * * @author Paul Ferraro */ @SuppressWarnings("nls") public class IngresDialect extends StandardDialect { private Pattern legacySequencePattern = Pattern.compile("'?(\\w+)'?\\.(?:(?:CURR)|(?:NEXT))VAL", Pattern.CASE_INSENSITIVE); /** * @see net.sf.hajdbc.dialect.StandardDialect#parseInsertTable(java.lang.String) */ @Override public String parseInsertTable(String sql) { return null; } /** * @see net.sf.hajdbc.dialect.StandardDialect#getSequences(java.sql.DatabaseMetaData) */ @Override public Collection getSequences(DatabaseMetaData metaData) throws SQLException { List sequenceList = new LinkedList(); Statement statement = metaData.getConnection().createStatement(); ResultSet resultSet = statement.executeQuery("SELECT seq_name FROM iisequence"); while (resultSet.next()) { sequenceList.add(new QualifiedName(resultSet.getString(1))); } statement.close(); return sequenceList; } /** * @see net.sf.hajdbc.dialect.StandardDialect#parseSequence(java.lang.String) */ @Override public String parseSequence(String sql) { String sequence = super.parseSequence(sql); return (sequence != null) ? sequence : this.parse(this.legacySequencePattern, sql); } /** * @see net.sf.hajdbc.dialect.StandardDialect#sequencePattern() */ @Override protected String sequencePattern() { return "(?:NEXT|CURRENT)\\s+VALUE\\s+FOR\\s+'?([^',\\s\\(\\)]+)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentDatePattern() */ @Override protected String currentDatePattern() { return "(?<=\\W)CURRENT_DATE(?=\\W)|(?<=\\W)DATE\\s*\\(\\s*'TODAY'\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimePattern() */ @Override protected String currentTimePattern() { return "(?<=\\W)CURRENT_TIME(?=\\W)|(?<=\\W)LOCAL_TIME(?=\\W)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#currentTimestampPattern() */ @Override protected String currentTimestampPattern() { return "(?<=\\W)CURRENT_TIMESTAMP(?=\\W)|(?<=\\W)LOCAL_TIMESTAMP(?=\\W)|(?<=\\W)DATE\\s*\\(\\s*'NOW'\\s*\\)"; } /** * @see net.sf.hajdbc.dialect.StandardDialect#randomPattern() */ @Override protected String randomPattern() { return "(?<=\\W)RANDOMF\\s*\\(\\s*\\)"; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/DatabaseClusterFactory.properties0000644000175000017500000000154111217570127025351 0ustar moellermoeller# # HA-JDBC: High-Availability JDBC # Copyright (c) 2004-2007 Paul Ferraro # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation; either version 2.1 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Contact: ferraro@users.sourceforge.net # version = 2.0.16-rc-1 ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/Messages.java0000644000175000017500000001225411151703042021241 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.text.MessageFormat; import java.util.ResourceBundle; /** * Provides localized access to log/error messages. * * @author Paul Ferraro * @version $Revision: 1908 $ * @since 1.0 */ @SuppressWarnings("nls") public final class Messages { public static final String CLUSTER_NOT_ACTIVE = "cluster-not-active"; public static final String CLUSTER_PANIC_DETECTED = "cluster-panic-detected"; public static final String CLUSTER_START_FAILED = "cluster-start-failed"; public static final String CLUSTER_STATE_LOAD_FAILED = "cluster-state-load-failed"; public static final String CLUSTER_STATE_STORE_FAILED = "cluster-state-store-failed"; public static final String COMMAND_RECEIVED = "command-received"; public static final String CONFIG_LOAD_FAILED = "config-load-failed"; public static final String CONFIG_STORE_FAILED = "config-store-failed"; public static final String CONFIG_NOT_FOUND = "config-not-found"; public static final String DATABASE_ACTIVATE_FAILED = "database-activate-failed"; public static final String DATABASE_ACTIVATED = "database-activated"; public static final String DATABASE_ALREADY_EXISTS = "database-already-exists"; public static final String DATABASE_DEACTIVATED = "database-deactivated"; public static final String DATABASE_NOT_ACTIVE = "database-not-active"; public static final String DATABASE_NOT_ALIVE = "database-not-alive"; public static final String DATABASE_STILL_ACTIVE = "database-still-active"; public static final String DATABASE_SYNC_END = "database-sync-end"; public static final String DATABASE_SYNC_START = "database-sync-start"; public static final String DELETE_COUNT = "delete-count"; public static final String DRIVER_NOT_FOUND = "driver-not-found"; public static final String DRIVER_REGISTER_FAILED = "driver-register-failed"; public static final String GROUP_MEMBER_JOINED = "group-member-joined"; public static final String GROUP_MEMBER_LEFT = "group-member-left"; public static final String HA_JDBC_INIT = "ha-jdbc-init"; public static final String INITIAL_CLUSTER_STATE_LOCAL = "initial-cluster-state-local"; public static final String INITIAL_CLUSTER_STATE_NONE = "initial-cluster-state-none"; public static final String INITIAL_CLUSTER_STATE_REMOTE = "initial-cluster-state-remote"; public static final String INSERT_COUNT = "insert-count"; public static final String INVALID_BALANCER = "invalid-balancer"; public static final String INVALID_DATABASE = "invalid-database"; public static final String INVALID_DATABASE_CLUSTER = "invalid-database-cluster"; public static final String INVALID_META_DATA_CACHE = "invalid-meta-data-cache"; public static final String INVALID_PROPERTY = "invalid-property"; public static final String INVALID_PROPERTY_VALUE = "invalid-property-value"; public static final String INVALID_SYNC_STRATEGY = "invalid-sync-strategy"; public static final String JDBC_URL_REJECTED = "jdbc-url-rejected"; public static final String JNDI_LOOKUP_FAILED = "jndi-lookup-failed"; public static final String MBEAN_SERVER_NOT_FOUND = "mbean-server-not-found"; public static final String NO_ACTIVE_DATABASES = "no-active-databases"; public static final String PRIMARY_KEY_REQUIRED = "primary-key-required"; public static final String SCHEMA_LOOKUP_FAILED = "schema-lookup-failed"; public static final String SEQUENCE_OUT_OF_SYNC = "sequence-out-of-sync"; public static final String SHUT_DOWN = "shut-down"; public static final String SQL_OBJECT_INIT_FAILED = "sql-object-init-failed"; public static final String STATEMENT_FAILED = "statement-failed"; public static final String TABLE_LOCK_ACQUIRE = "table-lock-acquire"; public static final String TABLE_LOCK_RELEASE = "table-lock-release"; public static final String UPDATE_COUNT = "update-count"; public static final String WRITE_LOCK_FAILED = "write-lock-failed"; private static ResourceBundle resource = ResourceBundle.getBundle(Messages.class.getName()); /** * Returns the localized message using the specified resource key and potential arguments. * @param key a resource key * @param args a variable number of arguments * @return a localized message */ public static String getMessage(String key, Object... args) { String message = resource.getString(key); return (args.length == 0) ? message : MessageFormat.format(message, args); } private Messages() { // Hide constructor } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sync/0000755000175000017500000000000011674455606017623 5ustar moellermoellerha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sync/SynchronizationContextImpl.java0000644000175000017500000001172411206340365026045 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import java.sql.Connection; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import net.sf.hajdbc.Balancer; import net.sf.hajdbc.Database; import net.sf.hajdbc.DatabaseCluster; import net.sf.hajdbc.DatabaseMetaDataCache; import net.sf.hajdbc.DatabaseProperties; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.SynchronizationContext; import net.sf.hajdbc.util.concurrent.DaemonThreadFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Paul Ferraro * @param Driver or DataSource */ public class SynchronizationContextImpl implements SynchronizationContext { private static Logger logger = LoggerFactory.getLogger(SynchronizationContextImpl.class); private Set> activeDatabaseSet; private Database sourceDatabase; private Database targetDatabase; private DatabaseCluster cluster; private DatabaseProperties sourceDatabaseProperties; private DatabaseProperties targetDatabaseProperties; private Map, Connection> connectionMap = new HashMap, Connection>(); private ExecutorService executor; /** * @param cluster * @param database * @throws SQLException */ public SynchronizationContextImpl(DatabaseCluster cluster, Database database) throws SQLException { this.cluster = cluster; Balancer balancer = cluster.getBalancer(); this.sourceDatabase = balancer.next(); this.activeDatabaseSet = balancer.all(); this.targetDatabase = database; this.executor = Executors.newFixedThreadPool(this.activeDatabaseSet.size(), DaemonThreadFactory.getInstance()); DatabaseMetaDataCache cache = cluster.getDatabaseMetaDataCache(); this.targetDatabaseProperties = cache.getDatabaseProperties(this.getConnection(this.targetDatabase)); this.sourceDatabaseProperties = cache.getDatabaseProperties(this.getConnection(this.sourceDatabase)); } /** * @see net.sf.hajdbc.SynchronizationContext#getConnection(net.sf.hajdbc.Database) */ @Override public Connection getConnection(Database database) throws SQLException { synchronized (this.connectionMap) { Connection connection = this.connectionMap.get(database); if (connection == null) { connection = database.connect(database.createConnectionFactory()); this.connectionMap.put(database, connection); } return connection; } } /** * @see net.sf.hajdbc.SynchronizationContext#getSourceDatabase() */ @Override public Database getSourceDatabase() { return this.sourceDatabase; } /** * @see net.sf.hajdbc.SynchronizationContext#getTargetDatabase() */ @Override public Database getTargetDatabase() { return this.targetDatabase; } /** * @see net.sf.hajdbc.SynchronizationContext#getActiveDatabaseSet() */ @Override public Set> getActiveDatabaseSet() { return this.activeDatabaseSet; } /** * @see net.sf.hajdbc.SynchronizationContext#getSourceDatabaseProperties() */ @Override public DatabaseProperties getSourceDatabaseProperties() { return this.sourceDatabaseProperties; } /** * @see net.sf.hajdbc.SynchronizationContext#getTargetDatabaseProperties() */ @Override public DatabaseProperties getTargetDatabaseProperties() { return this.targetDatabaseProperties; } /** * @see net.sf.hajdbc.SynchronizationContext#getDialect() */ @Override public Dialect getDialect() { return this.cluster.getDialect(); } /** * @see net.sf.hajdbc.SynchronizationContext#getExecutor() */ @Override public ExecutorService getExecutor() { return this.executor; } /** * @see net.sf.hajdbc.SynchronizationContext#close() */ @Override public void close() { synchronized (this.connectionMap) { for (Connection connection: this.connectionMap.values()) { if (connection != null) { try { if (!connection.isClosed()) { connection.close(); } } catch (SQLException e) { logger.warn(e.toString(), e); } } } } this.executor.shutdown(); } }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sync/SynchronizationSupport.java0000644000175000017500000002405311151703042025244 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.text.MessageFormat; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import net.sf.hajdbc.Database; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.ForeignKeyConstraint; import net.sf.hajdbc.Messages; import net.sf.hajdbc.SequenceProperties; import net.sf.hajdbc.SynchronizationContext; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.UniqueConstraint; import net.sf.hajdbc.util.SQLExceptionFactory; import net.sf.hajdbc.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Paul Ferraro * */ public final class SynchronizationSupport { private static Logger logger = LoggerFactory.getLogger(SynchronizationSupport.class); private SynchronizationSupport() { // Hide } /** * Drop all foreign key constraints on the target database * @param * @param context a synchronization context * @throws SQLException if database error occurs */ public static void dropForeignKeys(SynchronizationContext context) throws SQLException { Dialect dialect = context.getDialect(); Connection connection = context.getConnection(context.getTargetDatabase()); Statement statement = connection.createStatement(); for (TableProperties table: context.getTargetDatabaseProperties().getTables()) { for (ForeignKeyConstraint constraint: table.getForeignKeyConstraints()) { String sql = dialect.getDropForeignKeyConstraintSQL(constraint); logger.debug(sql); statement.addBatch(sql); } } statement.executeBatch(); statement.close(); } /** * Restores all foreign key constraints on the target database * @param * @param context a synchronization context * @throws SQLException if database error occurs */ public static void restoreForeignKeys(SynchronizationContext context) throws SQLException { Dialect dialect = context.getDialect(); Connection connection = context.getConnection(context.getTargetDatabase()); Statement statement = connection.createStatement(); for (TableProperties table: context.getSourceDatabaseProperties().getTables()) { for (ForeignKeyConstraint constraint: table.getForeignKeyConstraints()) { String sql = dialect.getCreateForeignKeyConstraintSQL(constraint); logger.debug(sql); statement.addBatch(sql); } } statement.executeBatch(); statement.close(); } /** * Synchronizes the sequences on the target database with the source database. * @param * @param context a synchronization context * @throws SQLException if database error occurs */ public static void synchronizeSequences(final SynchronizationContext context) throws SQLException { Collection sequences = context.getSourceDatabaseProperties().getSequences(); if (!sequences.isEmpty()) { Database sourceDatabase = context.getSourceDatabase(); Set> databases = context.getActiveDatabaseSet(); ExecutorService executor = context.getExecutor(); Dialect dialect = context.getDialect(); Map sequenceMap = new HashMap(); Map, Future> futureMap = new HashMap, Future>(); for (SequenceProperties sequence: sequences) { final String sql = dialect.getNextSequenceValueSQL(sequence); logger.debug(sql); for (final Database database: databases) { Callable task = new Callable() { public Long call() throws SQLException { Statement statement = context.getConnection(database).createStatement(); ResultSet resultSet = statement.executeQuery(sql); resultSet.next(); long value = resultSet.getLong(1); statement.close(); return value; } }; futureMap.put(database, executor.submit(task)); } try { Long sourceValue = futureMap.get(sourceDatabase).get(); sequenceMap.put(sequence, sourceValue); for (Database database: databases) { if (!database.equals(sourceDatabase)) { Long value = futureMap.get(database).get(); if (!value.equals(sourceValue)) { throw new SQLException(Messages.getMessage(Messages.SEQUENCE_OUT_OF_SYNC, sequence, database, value, sourceDatabase, sourceValue)); } } } } catch (InterruptedException e) { throw SQLExceptionFactory.createSQLException(e); } catch (ExecutionException e) { throw SQLExceptionFactory.createSQLException(e.getCause()); } } Connection targetConnection = context.getConnection(context.getTargetDatabase()); Statement targetStatement = targetConnection.createStatement(); for (SequenceProperties sequence: sequences) { String sql = dialect.getAlterSequenceSQL(sequence, sequenceMap.get(sequence) + 1); logger.debug(sql); targetStatement.addBatch(sql); } targetStatement.executeBatch(); targetStatement.close(); } } /** * @param * @param context * @throws SQLException */ public static void synchronizeIdentityColumns(SynchronizationContext context) throws SQLException { Statement sourceStatement = context.getConnection(context.getSourceDatabase()).createStatement(); Statement targetStatement = context.getConnection(context.getTargetDatabase()).createStatement(); Dialect dialect = context.getDialect(); for (TableProperties table: context.getSourceDatabaseProperties().getTables()) { Collection columns = table.getIdentityColumns(); if (!columns.isEmpty()) { String selectSQL = MessageFormat.format("SELECT max({0}) FROM {1}", Strings.join(columns, "), max("), table.getName()); //$NON-NLS-1$ //$NON-NLS-2$ logger.debug(selectSQL); Map map = new HashMap(); ResultSet resultSet = sourceStatement.executeQuery(selectSQL); if (resultSet.next()) { int i = 0; for (String column: columns) { map.put(column, resultSet.getLong(++i)); } } resultSet.close(); if (!map.isEmpty()) { for (Map.Entry mapEntry: map.entrySet()) { String alterSQL = dialect.getAlterIdentityColumnSQL(table, table.getColumnProperties(mapEntry.getKey()), mapEntry.getValue() + 1); if (alterSQL != null) { logger.debug(alterSQL); targetStatement.addBatch(alterSQL); } } targetStatement.executeBatch(); } } } sourceStatement.close(); targetStatement.close(); } /** * @param * @param context * @throws SQLException */ public static void dropUniqueConstraints(SynchronizationContext context) throws SQLException { Dialect dialect = context.getDialect(); Connection connection = context.getConnection(context.getTargetDatabase()); Statement statement = connection.createStatement(); for (TableProperties table: context.getTargetDatabaseProperties().getTables()) { for (UniqueConstraint constraint: table.getUniqueConstraints()) { String sql = dialect.getDropUniqueConstraintSQL(constraint); logger.debug(sql); statement.addBatch(sql); } } statement.executeBatch(); statement.close(); } /** * @param * @param context * @throws SQLException */ public static void restoreUniqueConstraints(SynchronizationContext context) throws SQLException { Dialect dialect = context.getDialect(); Connection connection = context.getConnection(context.getTargetDatabase()); Statement statement = connection.createStatement(); for (TableProperties table: context.getSourceDatabaseProperties().getTables()) { // Drop unique constraints on the current table for (UniqueConstraint constraint: table.getUniqueConstraints()) { String sql = dialect.getCreateUniqueConstraintSQL(constraint); logger.debug(sql); statement.addBatch(sql); } } statement.executeBatch(); statement.close(); } /** * @param connection */ public static void rollback(Connection connection) { try { connection.rollback(); connection.setAutoCommit(true); } catch (SQLException e) { logger.warn(e.toString(), e); } } /** * Helper method for {@link java.sql.ResultSet#getObject(int)} with special handling for large objects. * @param resultSet * @param index * @param type * @return the object of the specified type at the specified index from the specified result set * @throws SQLException */ public static Object getObject(ResultSet resultSet, int index, int type) throws SQLException { switch (type) { case Types.BLOB: { return resultSet.getBlob(index); } case Types.CLOB: { return resultSet.getClob(index); } default: { return resultSet.getObject(index); } } } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sync/FullSynchronizationStrategy.java0000644000175000017500000001603111151703042026212 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Collection; import java.util.Collections; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.Messages; import net.sf.hajdbc.SynchronizationContext; import net.sf.hajdbc.SynchronizationStrategy; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.util.SQLExceptionFactory; import net.sf.hajdbc.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Database-independent synchronization strategy that does full record transfer between two databases. * This strategy is best used when there are many differences between the active database and the inactive database (i.e. very much out of sync). * The following algorithm is used: *
    *
  1. Drop the foreign keys on the inactive database (to avoid integrity constraint violations)
  2. *
  3. For each database table: *
      *
    1. Delete all rows in the inactive database table
    2. *
    3. Query all rows on the active database table
    4. *
    5. For each row in active database table: *
        *
      1. Insert new row into inactive database table
      2. *
      *
    6. *
    *
  4. *
  5. Re-create the foreign keys on the inactive database
  6. *
  7. Synchronize sequences
  8. *
* @author Paul Ferraro */ public class FullSynchronizationStrategy implements SynchronizationStrategy { private static Logger logger = LoggerFactory.getLogger(FullSynchronizationStrategy.class); private int maxBatchSize = 100; private int fetchSize = 0; /** * @see net.sf.hajdbc.SynchronizationStrategy#synchronize(net.sf.hajdbc.SynchronizationContext) */ @Override public void synchronize(SynchronizationContext context) throws SQLException { Connection sourceConnection = context.getConnection(context.getSourceDatabase()); Connection targetConnection = context.getConnection(context.getTargetDatabase()); Dialect dialect = context.getDialect(); ExecutorService executor = context.getExecutor(); boolean autoCommit = targetConnection.getAutoCommit(); targetConnection.setAutoCommit(true); SynchronizationSupport.dropForeignKeys(context); targetConnection.setAutoCommit(false); try { for (TableProperties table: context.getSourceDatabaseProperties().getTables()) { String tableName = table.getName(); Collection columns = table.getColumns(); String commaDelimitedColumns = Strings.join(columns, Strings.PADDED_COMMA); final String selectSQL = "SELECT " + commaDelimitedColumns + " FROM " + tableName; //$NON-NLS-1$ //$NON-NLS-2$ final Statement selectStatement = sourceConnection.createStatement(); selectStatement.setFetchSize(this.fetchSize); Callable callable = new Callable() { public ResultSet call() throws SQLException { return selectStatement.executeQuery(selectSQL); } }; Future future = executor.submit(callable); String deleteSQL = dialect.getTruncateTableSQL(table); logger.debug(deleteSQL); Statement deleteStatement = targetConnection.createStatement(); int deletedRows = deleteStatement.executeUpdate(deleteSQL); logger.info(Messages.getMessage(Messages.DELETE_COUNT, deletedRows, tableName)); deleteStatement.close(); ResultSet resultSet = future.get(); String insertSQL = "INSERT INTO " + tableName + " (" + commaDelimitedColumns + ") VALUES (" + Strings.join(Collections.nCopies(columns.size(), Strings.QUESTION), Strings.PADDED_COMMA) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ logger.debug(insertSQL); PreparedStatement insertStatement = targetConnection.prepareStatement(insertSQL); int statementCount = 0; while (resultSet.next()) { int index = 0; for (String column: columns) { index += 1; int type = dialect.getColumnType(table.getColumnProperties(column)); Object object = SynchronizationSupport.getObject(resultSet, index, type); if (resultSet.wasNull()) { insertStatement.setNull(index, type); } else { insertStatement.setObject(index, object, type); } } insertStatement.addBatch(); statementCount += 1; if ((statementCount % this.maxBatchSize) == 0) { insertStatement.executeBatch(); insertStatement.clearBatch(); } insertStatement.clearParameters(); } if ((statementCount % this.maxBatchSize) > 0) { insertStatement.executeBatch(); } logger.info(Messages.getMessage(Messages.INSERT_COUNT, statementCount, tableName)); insertStatement.close(); selectStatement.close(); targetConnection.commit(); } } catch (InterruptedException e) { SynchronizationSupport.rollback(targetConnection); throw SQLExceptionFactory.createSQLException(e); } catch (ExecutionException e) { SynchronizationSupport.rollback(targetConnection); throw SQLExceptionFactory.createSQLException(e.getCause()); } catch (SQLException e) { SynchronizationSupport.rollback(targetConnection); throw e; } targetConnection.setAutoCommit(true); SynchronizationSupport.restoreForeignKeys(context); SynchronizationSupport.synchronizeIdentityColumns(context); SynchronizationSupport.synchronizeSequences(context); targetConnection.setAutoCommit(autoCommit); } /** * @return the fetchSize. */ public int getFetchSize() { return this.fetchSize; } /** * @param fetchSize the fetchSize to set. */ public void setFetchSize(int fetchSize) { this.fetchSize = fetchSize; } /** * @return the maxBatchSize. */ public int getMaxBatchSize() { return this.maxBatchSize; } /** * @param maxBatchSize the maxBatchSize to set. */ public void setMaxBatchSize(int maxBatchSize) { this.maxBatchSize = maxBatchSize; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sync/SynchronizationStrategyBuilder.java0000644000175000017500000001047211151703042026701 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; import java.util.HashMap; import java.util.Map; import java.util.Properties; import net.sf.hajdbc.Messages; import net.sf.hajdbc.SynchronizationStrategy; /** * @author Paul Ferraro * @since 1.1 */ public class SynchronizationStrategyBuilder { private static final String CLASS = "class"; //$NON-NLS-1$ private String id; private Class targetClass; private Properties properties; /** * Constructs a new SynchronizationStrategyBuilder. */ public SynchronizationStrategyBuilder() { // Do nothing } /** * @return the unique identifier for this synchronization strategy */ public String getId() { return this.id; } /** * @return a SynchronizationStrategy instance * @throws Exception */ public SynchronizationStrategy buildStrategy() throws Exception { SynchronizationStrategy strategy = this.targetClass.asSubclass(SynchronizationStrategy.class).newInstance(); PropertyDescriptor[] descriptors = Introspector.getBeanInfo(this.targetClass).getPropertyDescriptors(); Map propertyDescriptorMap = new HashMap(); for (PropertyDescriptor descriptor: descriptors) { // Prevent Object.getClass() from being read as a property if (descriptor.getName().equals(CLASS)) continue; propertyDescriptorMap.put(descriptor.getName(), descriptor); } for (Object key: this.properties.keySet()) { String name = (String) key; PropertyDescriptor descriptor = propertyDescriptorMap.get(name); if (descriptor == null) { throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_PROPERTY, name, this.getClass().getName())); } PropertyEditor editor = PropertyEditorManager.findEditor(descriptor.getPropertyType()); String textValue = this.properties.getProperty(name); try { if (editor == null) { throw new Exception(); } editor.setAsText(textValue); } catch (Exception e) { throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_PROPERTY_VALUE, textValue, name, this.targetClass.getName())); } descriptor.getWriteMethod().invoke(strategy, editor.getValue()); } return strategy; } /** * @param id * @param strategy * @return a builder for this strategy * @throws Exception */ public static SynchronizationStrategyBuilder getBuilder(String id, SynchronizationStrategy strategy) throws Exception { SynchronizationStrategyBuilder builder = new SynchronizationStrategyBuilder(); builder.id = id; Class strategyClass = strategy.getClass(); builder.targetClass = strategyClass; builder.properties = new Properties(); PropertyDescriptor[] descriptors = Introspector.getBeanInfo(strategyClass).getPropertyDescriptors(); for (PropertyDescriptor descriptor: descriptors) { // Prevent Object.getClass() from being written as a property if (descriptor.getName().equals(CLASS)) continue; PropertyEditor editor = PropertyEditorManager.findEditor(descriptor.getPropertyType()); if (editor == null) continue; editor.setValue(descriptor.getReadMethod().invoke(strategy)); builder.properties.setProperty(descriptor.getName(), editor.getAsText()); } return builder; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sync/PassiveSynchronizationStrategy.java0000644000175000017500000000265411151703042026730 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import net.sf.hajdbc.SynchronizationContext; import net.sf.hajdbc.SynchronizationStrategy; /** * Trivial {@link SynchronizationStrategy} implementation that assumes that the inactive database is already in sync. * * @author Paul Ferraro * @since 1.0 */ public class PassiveSynchronizationStrategy implements SynchronizationStrategy { /** * @see net.sf.hajdbc.SynchronizationStrategy#synchronize(net.sf.hajdbc.SynchronizationContext) */ @Override public void synchronize(SynchronizationContext context) { // Do nothing } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/sync/DifferentialSynchronizationStrategy.java0000644000175000017500000003266711173413255027731 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc.sync; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import net.sf.hajdbc.Dialect; import net.sf.hajdbc.Messages; import net.sf.hajdbc.SynchronizationContext; import net.sf.hajdbc.SynchronizationStrategy; import net.sf.hajdbc.TableProperties; import net.sf.hajdbc.UniqueConstraint; import net.sf.hajdbc.util.SQLExceptionFactory; import net.sf.hajdbc.util.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Database-independent synchronization strategy that only updates differences between two databases. * This strategy is best used when there are few differences between the active database and the inactive database (i.e. barely out of sync). * The following algorithm is used: *
    *
  1. Drop the foreign keys on the inactive database (to avoid integrity constraint violations)
  2. *
  3. For each database table: *
      *
    1. Drop the unique constraints on the table (to avoid integrity constraint violations)
    2. *
    3. Find the primary key(s) of the table
    4. *
    5. Query all rows in the inactive database table, sorting by the primary key(s)
    6. *
    7. Query all rows on the active database table
    8. *
    9. For each row in table: *
        *
      1. If primary key of the rows are the same, determine whether or not row needs to be updated
      2. *
      3. Otherwise, determine whether row should be deleted, or a new row is to be inserted
      4. *
      *
    10. *
    11. Re-create the unique constraints on the table (to avoid integrity constraint violations)
    12. *
    *
  4. *
  5. Re-create the foreign keys on the inactive database
  6. *
  7. Synchronize sequences
  8. *
* @author Paul Ferraro */ public class DifferentialSynchronizationStrategy implements SynchronizationStrategy { private static Logger logger = LoggerFactory.getLogger(DifferentialSynchronizationStrategy.class); private int fetchSize = 0; private int maxBatchSize = 100; /** * @see net.sf.hajdbc.SynchronizationStrategy#synchronize(net.sf.hajdbc.SynchronizationContext) */ @Override public void synchronize(SynchronizationContext context) throws SQLException { Connection sourceConnection = context.getConnection(context.getSourceDatabase()); Connection targetConnection = context.getConnection(context.getTargetDatabase()); Dialect dialect = context.getDialect(); ExecutorService executor = context.getExecutor(); boolean autoCommit = targetConnection.getAutoCommit(); targetConnection.setAutoCommit(true); SynchronizationSupport.dropForeignKeys(context); SynchronizationSupport.dropUniqueConstraints(context); targetConnection.setAutoCommit(false); try { for (TableProperties table: context.getSourceDatabaseProperties().getTables()) { String tableName = table.getName(); UniqueConstraint primaryKey = table.getPrimaryKey(); if (primaryKey == null) { throw new SQLException(Messages.getMessage(Messages.PRIMARY_KEY_REQUIRED, this.getClass().getName(), tableName)); } List primaryKeyColumnList = primaryKey.getColumnList(); Collection columns = table.getColumns(); // List of colums for select statement - starting with primary key List columnList = new ArrayList(columns.size()); columnList.addAll(primaryKeyColumnList); for (String column: columns) { if (!primaryKeyColumnList.contains(column)) { columnList.add(column); } } List nonPrimaryKeyColumnList = columnList.subList(primaryKeyColumnList.size(), columnList.size()); String commaDelimitedColumns = Strings.join(columnList, Strings.PADDED_COMMA); // Retrieve table rows in primary key order final String selectSQL = "SELECT " + commaDelimitedColumns + " FROM " + tableName + " ORDER BY " + Strings.join(primaryKeyColumnList, Strings.PADDED_COMMA); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ final Statement targetStatement = targetConnection.createStatement(); targetStatement.setFetchSize(this.fetchSize); logger.debug(selectSQL); Callable callable = new Callable() { public ResultSet call() throws SQLException { return targetStatement.executeQuery(selectSQL); } }; Future future = executor.submit(callable); Statement sourceStatement = sourceConnection.createStatement(); sourceStatement.setFetchSize(this.fetchSize); ResultSet sourceResultSet = sourceStatement.executeQuery(selectSQL); ResultSet inactiveResultSet = future.get(); String primaryKeyWhereClause = " WHERE " + Strings.join(primaryKeyColumnList, " = ? AND ") + " = ?"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // Construct DELETE SQL String deleteSQL = "DELETE FROM " + tableName + primaryKeyWhereClause; //$NON-NLS-1$ logger.debug(deleteSQL); PreparedStatement deleteStatement = targetConnection.prepareStatement(deleteSQL); // Construct INSERT SQL String insertSQL = "INSERT INTO " + tableName + " (" + commaDelimitedColumns + ") VALUES (" + Strings.join(Collections.nCopies(columnList.size(), Strings.QUESTION), Strings.PADDED_COMMA) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ logger.debug(insertSQL); PreparedStatement insertStatement = targetConnection.prepareStatement(insertSQL); // Construct UPDATE SQL PreparedStatement updateStatement = null; if (!nonPrimaryKeyColumnList.isEmpty()) { String updateSQL = "UPDATE " + tableName + " SET " + Strings.join(nonPrimaryKeyColumnList, " = ?, ") + " = ?" + primaryKeyWhereClause; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ logger.debug(updateSQL); updateStatement = targetConnection.prepareStatement(updateSQL); } boolean hasMoreActiveResults = sourceResultSet.next(); boolean hasMoreInactiveResults = inactiveResultSet.next(); int insertCount = 0; int updateCount = 0; int deleteCount = 0; while (hasMoreActiveResults || hasMoreInactiveResults) { int compare = 0; if (!hasMoreActiveResults) { compare = 1; } else if (!hasMoreInactiveResults) { compare = -1; } else { for (int i = 1; i <= primaryKeyColumnList.size(); ++i) { Object activeObject = sourceResultSet.getObject(i); Object inactiveObject = inactiveResultSet.getObject(i); // We assume that the primary keys column types are Comparable compare = this.compare(activeObject, inactiveObject); if (compare != 0) { break; } } } if (compare > 0) { deleteStatement.clearParameters(); for (int i = 1; i <= primaryKeyColumnList.size(); ++i) { int type = dialect.getColumnType(table.getColumnProperties(columnList.get(i - 1))); deleteStatement.setObject(i, inactiveResultSet.getObject(i), type); } deleteStatement.addBatch(); deleteCount += 1; if ((deleteCount % this.maxBatchSize) == 0) { deleteStatement.executeBatch(); deleteStatement.clearBatch(); } } else if (compare < 0) { insertStatement.clearParameters(); for (int i = 1; i <= columnList.size(); ++i) { int type = dialect.getColumnType(table.getColumnProperties(columnList.get(i - 1))); Object object = SynchronizationSupport.getObject(sourceResultSet, i, type); if (sourceResultSet.wasNull()) { insertStatement.setNull(i, type); } else { insertStatement.setObject(i, object, type); } } insertStatement.addBatch(); insertCount += 1; if ((insertCount % this.maxBatchSize) == 0) { insertStatement.executeBatch(); insertStatement.clearBatch(); } } else if (updateStatement != null) // if (compare == 0) { updateStatement.clearParameters(); boolean updated = false; for (int i = primaryKeyColumnList.size() + 1; i <= columnList.size(); ++i) { int type = dialect.getColumnType(table.getColumnProperties(columnList.get(i - 1))); Object activeObject = SynchronizationSupport.getObject(sourceResultSet, i, type); Object inactiveObject = SynchronizationSupport.getObject(inactiveResultSet, i, type); int index = i - primaryKeyColumnList.size(); if (sourceResultSet.wasNull()) { updateStatement.setNull(index, type); updated |= !inactiveResultSet.wasNull(); } else { updateStatement.setObject(index, activeObject, type); updated |= inactiveResultSet.wasNull(); updated |= !equals(activeObject, inactiveObject); } } if (updated) { for (int i = 1; i <= primaryKeyColumnList.size(); ++i) { int type = dialect.getColumnType(table.getColumnProperties(columnList.get(i - 1))); updateStatement.setObject(i + nonPrimaryKeyColumnList.size(), inactiveResultSet.getObject(i), type); } updateStatement.addBatch(); updateCount += 1; if ((updateCount % this.maxBatchSize) == 0) { updateStatement.executeBatch(); updateStatement.clearBatch(); } } } if (hasMoreActiveResults && (compare <= 0)) { hasMoreActiveResults = sourceResultSet.next(); } if (hasMoreInactiveResults && (compare >= 0)) { hasMoreInactiveResults = inactiveResultSet.next(); } } if ((deleteCount % this.maxBatchSize) > 0) { deleteStatement.executeBatch(); } deleteStatement.close(); if ((insertCount % this.maxBatchSize) > 0) { insertStatement.executeBatch(); } insertStatement.close(); if (updateStatement != null) { if ((updateCount % this.maxBatchSize) > 0) { updateStatement.executeBatch(); } updateStatement.close(); } targetStatement.close(); sourceStatement.close(); targetConnection.commit(); logger.info(Messages.getMessage(Messages.INSERT_COUNT, insertCount, tableName)); logger.info(Messages.getMessage(Messages.UPDATE_COUNT, updateCount, tableName)); logger.info(Messages.getMessage(Messages.DELETE_COUNT, deleteCount, tableName)); } } catch (ExecutionException e) { SynchronizationSupport.rollback(targetConnection); throw SQLExceptionFactory.createSQLException(e.getCause()); } catch (InterruptedException e) { SynchronizationSupport.rollback(targetConnection); throw SQLExceptionFactory.createSQLException(e.getCause()); } catch (SQLException e) { SynchronizationSupport.rollback(targetConnection); throw e; } targetConnection.setAutoCommit(true); SynchronizationSupport.restoreUniqueConstraints(context); SynchronizationSupport.restoreForeignKeys(context); SynchronizationSupport.synchronizeIdentityColumns(context); SynchronizationSupport.synchronizeSequences(context); targetConnection.setAutoCommit(autoCommit); } private boolean equals(Object object1, Object object2) { if ((object1 instanceof byte[]) && (object2 instanceof byte[])) { byte[] bytes1 = (byte[]) object1; byte[] bytes2 = (byte[]) object2; if (bytes1.length != bytes2.length) { return false; } return Arrays.equals(bytes1, bytes2); } return object1.equals(object2); } @SuppressWarnings("unchecked") private int compare(Object object1, Object object2) { return ((Comparable) object1).compareTo(object2); } /** * @return the fetchSize. */ public int getFetchSize() { return this.fetchSize; } /** * @param fetchSize the fetchSize to set. */ public void setFetchSize(int fetchSize) { this.fetchSize = fetchSize; } /** * @return Returns the maxBatchSize. */ public int getMaxBatchSize() { return this.maxBatchSize; } /** * @param maxBatchSize The maxBatchSize to set. */ public void setMaxBatchSize(int maxBatchSize) { this.maxBatchSize = maxBatchSize; } } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/StateManager.java0000644000175000017500000000270111151703042022041 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.Set; /** * @author Paul Ferraro * */ public interface StateManager extends DatabaseActivationListener, DatabaseDeactivationListener, Lifecycle { /** * Returns the initial state of the cluster. * @return a set of database identifiers, or null, if no initial cluster state was found. */ public Set getInitialState(); /** * Detects whether or not the membership of this state manager is empty. * Used during cluster panic detection. * @return true, if membership is empty, false otherwise */ public boolean isMembershipEmpty(); } ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/LockManager.java0000644000175000017500000000317311151703042021655 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; import java.util.concurrent.locks.Lock; import net.sf.hajdbc.util.Strings; /** * Manages a set of named read/write locks. A global lock is represented by an empty name (i.e ""). * Obtaining a named read or write lock should implicitly obtain a global read lock. * Consequently, all named locks are blocked if a global write lock is obtained. * @author Paul Ferraro */ public interface LockManager extends Lifecycle { public static final String GLOBAL = Strings.EMPTY; /** * Obtains a named read lock. * @param object an object to lock * @return a read lock */ public Lock readLock(String object); /** * Obtains a named write lock. * @param object an object to lock * @return a write lock */ public Lock writeLock(String object); }ha-jdbc-2.0.16+rc1/src/net/sf/hajdbc/InactiveDatabaseMBean.java0000644000175000017500000000356311151703042023567 0ustar moellermoeller/* * HA-JDBC: High-Availability JDBC * Copyright (c) 2004-2007 Paul Ferraro * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: ferraro@users.sourceforge.net */ package net.sf.hajdbc; /** * @author Paul Ferraro * @since 1.1 */ public interface InactiveDatabaseMBean extends ActiveDatabaseMBean { /** * Set the weight for this database * @param weight a weight * @exception IllegalArgumentException if weight is less than 0 */ public void setWeight(int weight); /** * Set the user for this database. * @param user a user */ public void setUser(String user); /** * Set the password for this database * @param password a password */ public void setPassword(String password); /** * Set the value of the specified property. * @param name a property name * @param value a property value */ public void setProperty(String name, String value); /** * Removes the specified property. * @param name a property name */ public void removeProperty(String name); /** * Sets whether or not this database is local to the machine on which the JVM resides. * @param local true if local, false if remote */ public void setLocal(boolean local); } ha-jdbc-2.0.16+rc1/lib-1.5/0000775000175000017500000000000011674455666014526 5ustar moellermoellerha-jdbc-2.0.16+rc1/lib-1.5/runtime/0000755000175000017500000000000011674455666016207 5ustar moellermoellerha-jdbc-2.0.16+rc1/lib/0000775000175000017500000000000011674455666014225 5ustar moellermoellerha-jdbc-2.0.16+rc1/lib/runtime/0000755000175000017500000000000011674455666015706 5ustar moellermoellerha-jdbc-2.0.16+rc1/lib/compile/0000755000175000017500000000000011674455666015653 5ustar moellermoellerha-jdbc-2.0.16+rc1/lib/test/0000755000175000017500000000000011674455666015202 5ustar moellermoellerha-jdbc-2.0.16+rc1/LICENSE.txt0000644000175000017500000005747411151703035015271 0ustar moellermoeller GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONSha-jdbc-2.0.16+rc1/conf/0000775000175000017500000000000011674455606014376 5ustar moellermoellerha-jdbc-2.0.16+rc1/conf/jibx/0000755000175000017500000000000011674455606015330 5ustar moellermoellerha-jdbc-2.0.16+rc1/conf/jibx/binding-pool-datasource.xml0000644000175000017500000000231511151703041022537 0ustar moellermoeller ha-jdbc-2.0.16+rc1/conf/jibx/binding-datasource.xml0000644000175000017500000000217411151703041021573 0ustar moellermoeller ha-jdbc-2.0.16+rc1/conf/jibx/binding-driver.xml0000644000175000017500000000221311151703041020726 0ustar moellermoeller ha-jdbc-2.0.16+rc1/conf/jibx/binding.xml0000644000175000017500000000760011151703041017442 0ustar moellermoeller ha-jdbc-2.0.16+rc1/conf/jibx/binding-xa-datasource.xml0000644000175000017500000000222311151703041022174 0ustar moellermoeller ha-jdbc-2.0.16+rc1/conf/jibx/binding.dtd0000644000175000017500000004317711151703041017426 0ustar moellermoeller ha-jdbc-2.0.16+rc1/conf/services/0000755000175000017500000000000011674455606016217 5ustar moellermoellerha-jdbc-2.0.16+rc1/conf/services/java.sql.Driver0000644000175000017500000000003011151703041021057 0ustar moellermoellernet.sf.hajdbc.sql.Driverha-jdbc-2.0.16+rc1/doc/0000775000175000017500000000000011674455606014216 5ustar moellermoellerha-jdbc-2.0.16+rc1/doc/build.xml0000644000175000017500000000030211151703035016006 0ustar moellermoeller ha-jdbc-2.0.16+rc1/doc/src/0000755000175000017500000000000011674455606015003 5ustar moellermoellerha-jdbc-2.0.16+rc1/doc/src/content/0000755000175000017500000000000011217570222016436 5ustar moellermoellerha-jdbc-2.0.16+rc1/doc/src/content/xdocs/0000755000175000017500000000000011674455606017575 5ustar moellermoellerha-jdbc-2.0.16+rc1/doc/src/content/xdocs/xsd.xml0000644000175000017500000000074311151703037021101 0ustar moellermoeller
XML Schema Definition
Version Schema URL
2.0 http://ha-jdbc.sourceforge.net/xsd/ha-jdbc-2.0.xsd
ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/index.xml0000644000175000017500000000473311151703037021415 0ustar moellermoeller
HA-JDBC: High-Availability JDBC
Overview

HA-JDBC is a JDBC proxy that provides light-weight, transparent, fault tolerant clustering capability to any underlying JDBC driver.

Features
  • Supports any database accessible via JDBC.
  • High-availability/Fault Tolerance - An HA-JDBC database cluster can lose a node without failing/corrupting open transactions.
  • Live activation/deactivation allows for maintenance/upgrading of a database node without loss of service.
  • Improves performance of concurrent read-access by distributing load across individual nodes.
  • Supports full JDBC 3.0 and 4.0 feature set.
  • Out-of-the-box database-independent strategies for synchronizing a failed cluster node.
  • Exposes JMX management interface to allow administration of databases and clusters.
  • Ability to add/subtract database nodes to/from a cluster at runtime.
  • Can be configured to auto-activate failed database nodes during scheduled off-peak times.
  • Open source (LGPL).
Dependent Libraries
  • JGroups - reliable multicast communication framework
  • Quartz - enterprise job scheduler
  • JiBX - an XML binding framework
  • SLF4J - a simple facade for various logging APIs.
Related Software
  • Sequoia - Database-independent clustering middleware
  • PGCluster - Multi-master replication system for PostgreSQL.
  • MySQL Cluster - Fault tolerant database architecture using NDB storage engine
  • H2 Clustering - a simple clustering / high availability mechanism for H2
ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/dtd.xml0000644000175000017500000000162611151703037021057 0ustar moellermoeller
Document Type Definition
Version Public ID System ID
2.0 -//HA-JDBC//DTD HA-JDBC 2.0//EN http://ha-jdbc.sourceforge.net/dtd/ha-jdbc-2.0.dtd
1.1 -//HA-JDBC//DTD HA-JDBC 1.1//EN http://ha-jdbc.sourceforge.net/dtd/ha-jdbc-1.1.dtd
1.0 -//HA-JDBC//DTD HA-JDBC 1.0//EN http://ha-jdbc.sourceforge.net/dtd/ha-jdbc-1.0.dtd
ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/performance.xml0000644000175000017500000000240711151703037022603 0ustar moellermoeller
Performance

The following graphs compare the performance of a single database accessed via normal JDBC vs. a cluster of two identical databases accessed via HA-JDBC.

Read Operations

By distributing read operations to each node in the cluster, HA-JDBC is able to achieve better performance under load than normal JDBC access.

Write Operations

By performing write operations in parallel to each node in the cluster, HA-JDBC is only slightly slower than normal JDBC access. The slight performance loss is largely due increased network traffic and parallel processing overhead.

ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/site.xml0000644000175000017500000000423111151703037021243 0ustar moellermoeller ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/faq.xml0000644000175000017500000004003411213217111021037 0ustar moellermoeller Frequently Asked Questions Dependency FAQs JGroups FAQ http://www.jgroups.org/javagroupsnew/docs/faq.html SLF4J FAQ http://slf4j.org/faq.html Quartz FAQ http://www.opensymphony.com/quartz/wikidocs/FAQ.html Configuring HA-JDBC How do I configure HA-JDBC to notify me when a database is deactivated? Use your logging facility. HA-JDBC generates an ERROR level log message when it automatically deactivates a database. If you use Log4J, configure an SMTP appender for the "net.sf.hajdbc" logger.
If you use java.util.logging, configure an SMTPHandler for the "net.sf.hajdbc" package.
I need to pass additional parameters to my JDBC driver. How can I specify these in my HA-JDBC configuration?

The database element may contain any number of property elements. HA-JDBC will pass these properties through to the Driver.connect(String url, Properties info) method of the underlying JDBC driver.

e.g.

org.postgresql.Driver jdbc:postgresql:database true postgres XXXX ]]>

Alternatively, many JDBC drivers accept properties appended directly to the url.

e.g.

org.postgresql.Driver jdbc:postgresql:database?ssl=true postgres XXXX ]]>
How can I specify JNDI environment properties to my HA-JDBC DataSource configuration?

The datasource element may contain any number of property elements. HA-JDBC will pass these properties into the InitialContext(Hashtable env) constructor.

e.g.

jdbc/database org.jnp.interfaces.NamingContextFactory org.jboss.naming:org.jnp.interfaces ]]>

Alternatively, these properties may be specified in an jndi.properties application resource file. Details here.

Using HA-JDBC I get a java.lang.OutOfMemoryError when synchronizing a failed cluster node. Why?

This can occur if your database contains a table with more rows than can be fetched into memory at once. Both the differential and full synchronization strategies have a fetchSize property that control the number of rows that are fetched at a time.

e.g.

1000 ]]>

Each strategy also has a maxBatchSize property to control the number of statements to execute at a time.

e.g.

50 ]]>
How can HA-JDBC be leveraged to improve database-driven HTTP Session failover?

Several session replication methods are described in an article posted to TheServerSide.com. Figure 7 illustrates the database persistence approach. When describing the disadvantages of this approach, the article fails to mention that the session database is a single point of failure in this design. HTTP sessions will survive the failure of an application server node, but failure of the session database spells doom for the application.

However, this can easily remedied with redundant session databases using the HA-JDBC driver in distributable mode.

e.g.

For Tomcat, following the configuration instructions for setting up a Persistent Manager using a JDBC store here. Simply use HA-JDBC's driver and url in place of your database's JDBC driver and url for the driverName and connectionURL properties of your store configuration.

Can I use HA-JDBC with Tomcat 5.0? Yes, but first you will need to upgrade the JMX implementation used by Tomcat (found in $CATALINA_HOME/bin/jmx.jar). Tomcat 5.0 ships with MX4J 1.1.1 which only implements JMX 1.1. Because HA-JDBC requires JMX 1.2, you will need to upgrade this file to MX4J 2.0 or greater. HA-JDBC remembers which databases were inactive even after I restart my JVM. Where is this state recorded and how do I clear it?

HA-JDBC uses the Java preferences API to persist the local database cluster state. The default storage mechanism varies depending on your operating system.

On Unix-like systems, the cluster state will be stored on the file system within the user's home directory:

~/.java/.userPrefs/net/sf/hajdbc/local/prefs.xml

On Windows systems, the cluster state will be stored in the registry:

HKEY_CURRENT_USER\Software\JavaSoft\Prefs\net\sf\hajdbc\local\cluster-name

Why does my application need to specify a username and password when making database connections through HA-JDBC when the necessary authentication information is already specified in its configuration file?

The username and password set in the configuration file are only used by HA-JDBC when it needs to connect to a database independently of your application. e.g. during synchronization, DatabaseCluster.isAlive() calls, etc. When your application connects to the database, the authentication information specified is passed through to the underlying driver.

The purpose of this authentication pass-through is to retain the flexibility your application had without HA-JDBC to use an appropriate database user (with an appropriate set of permissions) for a given task. Traditionally, applications will use a database user with select/insert/update/delete privileges only. Some application may not need to write information to a database and can use a database user with select privileges only. The database user that is used by HA-JDBC should be more of a root/superuser, with specific abilities to drop and create indexes and foreign keys (used during synchronization).

Since the same password will be passed through to each database, the user used by your application must exist and have the same password on each database in your cluster. The usernames/passwords used by HA-JDBC (as specified in the configuration file), however, do not need to be the same on each database.

Using version 1.4 or 1.5 of Sun's Java implementation, HA-JDBC mysteriously deadlocks the first time DriverManager.getConnection() is called. Why?

In Java 1.5 and earlier, all of the methods on java.sql.DriverManager are synchronized. Your initial call to DriverManager.getConnection(...) triggers the startup of HA-JDBC. As HA-JDBC initializes, it will eventually call DriverManager.getDriver(...) for each database url in your cluster. The calls to DriverManager.getDriver(...) occur in a different thread from your application thread, hence the deadlock.

There are at least 2 known workarounds for this problem:

  1. Upgrade to Java 1.6. After forever insisting that the blanket synchronization of java.sql.DriverManager was not a defect, Sun silently fixed this in Java 1.6.
  2. Rather than use DriverManager.getConnection(...) to obtain connections, use DriverManager.getDriver(...).connect(...) instead. This will circumvent the deadlock since DriverManager.getDriver(...) will not trigger HA-JDBC startup and Driver.connect(...) is not synchronized.
About HA-JDBC How does HA-JDBC compare to Sequoia?

Both HA-JDBC and Sequoia attempt to solve the same problem (i.e. eliminating the database as a single point of failure), but have different approaches.

Feature comparison
HA-JDBC Sequoia
Architecture
  1. HA-JDBC driver delegates JDBC methods directly to the underlying JDBC drivers.
  2. Cluster details are stored in distributed cache on client.
  3. Leverages underlying database for request scheduling.
  4. High-availability is inherent in symmetric design.
  1. Sequoia's JDBC driver delegates query execution to a remote controller process. Controller then delegates queries to the underlying JDBC driver.
  2. Cluster details are known only to controller.
  3. The controller's request scheduler strategy is responsible for determining execution order.
  4. Controller introduces new single point-of-failure. Workaround is to set up a failover controller process. Details here.
Cluster topography
  1. Databases within a cluster must be homogenous.
  2. Supports "mirroring" only.
  1. Supports heterogenous database clusters - requires that SQL queries be translated to appropriate SQL dialect.
  2. Supports RAIDb-0, RAIDb-1, and RAIDb-2 configurations (i.e. mirroring (replication), striping (partitioning), and partial mirroring/striping, respectively).
Failed node recovery
  1. No recovery log is maintained.
  2. Synchronization achieved through various brute force strategies.
  3. Inefficient hot synchronization capability tolerated at the savings of performance during normal usage.
  4. Includes the ability to automatically reactivate failed database nodes according to a schedule.
  1. Controller uses internal database recovery log to restore state of a reactivated database.
  2. Synchronization is done by executing SQL statements since last checkpoint.
  3. Efficient hot synchronization capability achieved at the cost of recovery log overhead.
  4. Failed database nodes can only be re-activated manually.
Performance

Faster reads under load, slightly slower writes than standard JDBC. Details here.

Qualitatively slower than HA-JDBC since each request requires an additional network hop (i.e. driver to controller, controller to database). Details here.

Cluster administration

Leverages JConsole from Sun's JDK 1.5+ or any other 3rd party JMX console for cluster administration.

Provides custom JMX-based command-line administration console.

Provides connection pooling

No - many open source solutions already exist and can be used in conjunction with HA-JDBC:

Yes - implemented in controller

ResultSet caching ability

No - Transparent result set caching is available through IronEye Cache.

Yes - implemented in controller

JDBC 2.0 feature support

Full support

Lacks support for:

  • Database-compiled PreparedStatements
  • CallableStatements with OUT parameters
  • True large object support - Blob and Clob are simulated with encoded byte[] and String, respectively
  • True binary/character stream support - simulated with encoded byte[] and String, respectively
  • Array and Ref types
  • Custom type mapping
  • Block fetched scrollable ResultSets
  • Statement execution cancellation
JDBC 3.0 support

Full support

Lacks support for:

  • Transactional Savepoints
  • XADataSource and XAConnection
  • PreparedStatement pooling
  • Retrieval of auto-generated keys
  • ParameterMetaData
  • ResultSet holdability support
  • Queries/Store procedures that return multiple ResultSets
  • Updatable Blobs and Clobs
JDBC 4.0 support

Full support

None

ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/xsd/0000755000175000017500000000000011674455606020373 5ustar moellermoellerha-jdbc-2.0.16+rc1/doc/src/content/xdocs/xsd/ha-jdbc-2.0.xsd0000644000175000017500000001612411151703037022664 0ustar moellermoeller ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/dtd/0000755000175000017500000000000011674455606020350 5ustar moellermoellerha-jdbc-2.0.16+rc1/doc/src/content/xdocs/dtd/ha-jdbc-1.1.dtd0000644000175000017500000000423311151703037022614 0ustar moellermoeller ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/dtd/ha-jdbc-2.0.dtd0000644000175000017500000000526711151703037022624 0ustar moellermoeller ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/dtd/ha-jdbc-1.0.dtd0000644000175000017500000000465011151703037022616 0ustar moellermoeller ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/tabs.xml0000644000175000017500000000163411151703037021234 0ustar moellermoeller ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/images/0000755000175000017500000000000011674455606021042 5ustar moellermoellerha-jdbc-2.0.16+rc1/doc/src/content/xdocs/images/graph_update.png0000644000175000017500000001644611151703037024206 0ustar moellermoeller‰PNG  IHDRî Ý4S;sRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<¤IDATx^íݹ%¥@of`>úf&¢ø8Of`f`7š¹=—#Ã@7Õü°æóÏ9ÃO±€ÕµÙ½ûüç?ü |æ ,Kàã2´lü@ŸQ9‹€ÀòPùòSÈ  rÖ å  òå§@@å¬@Ë@åËO!€ €ÊY®¥pËÂÿüöóa•b¨ý´ÇÌG4®ºù}šÈ¨V°dúŸÈHê6)3=€&£ ‘®PyW¼+5.Qy:ž°Öm ùf3’º}-Ð|#BE ‹ÕÆ&/?=y¨”œE•Ï"o®_Ê]²ìSl!͈»ª¼P‘Âbýftzý†FË­ òV$—oG-¾¢ÊSËsùÛ C­ÑòåÃ?yéóÅn/N®Š¿¼…ߦeZpCZ~ý1€wPù;~ÕÞOå™ ·/#"O—¨§ëP¤ìôÛÐãO_߯¹òÕ^Þ6Z° 娜ñA@§rI~Ý0+STÿu~ 3ÅòÁߪ<¥$1~H@Þ‚¯%„ÌR>™*?yöã«ú-‹ô¬àöÌ!Ÿ ¥™ž6äR5y©Ó3W¯0§ÿ”ÔG¯PyÕ¬QXH• Aí_L—• UÙ0M®S¾彜ŒL}kpaðr•? ÿiÈiËÂW$/AQ}!¨|¡Éêê•{ñƒ|¯òb_Štû©Íü!Rþ€¥8dy§}—­&€Ê OÎØÐªÄ—?Љþ5oÌèü¡è59•ª Ï=„Å2f—·àAåòI?¶$*?vêožO„3ByÒqd´| ùŠTŽ’™“èöãv\OW&áK†‰ä€¥HI‚…2û@åûÍé«EǸa[•GÕ«¼S,œ6î’s~Dî_½²ÃÓŸ‡¯ŠEãß&éŬ<ç«ù¦ò.Pù.3É8 ƒ  òƒ'Ÿ¡C»@å»Ì$ã€&€Êž|†ìB•ï2“Œ8˜*?xò: ° T¾ËL2@à`¨üàÉgè€À.Pù.3É8 ƒ  òƒ'Ÿ¡C»¡òèÓÕÑç•Ó/ï–q@D`ÊýhÂçZ\?Œ¾4hº °î*OSrÐI•ﵜ  0‡À•gÜÊçL;½B{è®òèhE~ÀâÓy¾€ PK`/Q—GÓ]åywWeåWáÿò€€€@Y~{•è®rw *;ómž-*,`Š@_ì%êòhF¨¼…¬*gBB2©ìS • Å •ì#iÙHPùJ«“X!!™÷)…Ê… ƒb€ÀJö‘´l$¨|¥ÕI¬€€€L€û”BåÂ…A1@`%ûHZ6T¾Òê$V@@H@&À}J¡rá  °}$- *_iu+ $ à>¥P¹paP X†À§ÝGÒ²‘ òeV'B—ǯb2îSjœÊóa‘åƒû’uLœLÀy•KŒª)=BË7Á“OÞuŒ \÷GåMë8_û¿oµîži¬¼áº§)ìD ”8YyÑÉš<¯|§ ÃX `@êq²r¬óu>ãÿý_t´’9`‰*ò- ”Àåñ[,í]f»ÅÑo{æ“ôâUÁ`F@H€À,·ù8,}/:Ñ,®39•ôÍYù¬ C¿0H ãqX$FV•ÜN„)òGåÓ4-é•OÙ3t kŠGå£N+ƒÊ­í(âÀx£òiš–tŒÊÇoz„€ч€òI”²S™qw°¼§†Êíl*"À`ÂdÜGõ^8kµ€Ê/Hºƒª ÔzœÓ×!²òê@¬O@áqTŽÊ×_øŒ»¨:mÚe‚ã€e—UÏ8 ° gp]2ÎYy‡ËDë&9`Ùe«2ÜhbpTÞÚ»ÚCå›ðú~™ƒ§X:Èt“ãXnŸÁâÃ"„Ê7ÛÆ çXmð[Œ¥ìTfÊ]7NÜßí·y²¨üØÏÀ÷ 0Àà°t¼>…ÖFå{ìIFq,ðH¤öë‘Ð:ÍdÓš¬ûÎüëí,>þ5•Ý #Pû«ë£òÃâ\¥£OŸV7suü*÷oZFÈ]\Ý·Pù*‰8«ì}wŠ—…/ƒ»ÿ8+É6:†ÕiQ•¿\èT7H¿Ÿ”ÐàÜÁÒµÛ@åï=-˜"€ÇÕÓáõírðôOg™k¾î€enø¨\½î©hÀ Ÿ·ìÁü6Gå_?²3×ÑÂÞQy½A›ã Œ×2—œ¡NgCåµ€ò àñªIñocVÕâmÏ™¦.öÊkW3å­ÀãòQKÜuQôÉf4gåþw@3Œ*—oJ$€Ç…“òRâ¨\ääèãš#mŽÊ…;b àqɤ4‘8*Gå’ÅFTÀãdO·Jê¦eD:Û¨Põ Y¹naQëXx¼8õ “qß×F– ¥Zå_o`ü÷ȼØOæ,O¸m“–â– €5xTäÜöD%êNc«•ëh²rÝxÓófÏ·LV^Ü0B€d|V2ÎK…Ÿ£ÇiIîG|:aOž‰•ña<õ㯠z"ÐïD…¬ü‹™å"¯*6[›•§ ~û®|Ü~S"tÖµÜi{”¬>`©U9gå$hçà\åv®‡eâaï{Z>Šî*îQñ×dbô-gåçXo¿‘âñhNÏÀj¸*äÜ£dµÊÓ›kót58ÎÊ.tšjK{žs ÎÛžRÁw*okZkE_$•£òVûšvÎ"p¸Ç­•KUÞ^Q§EQ²ò³¹Âhõ¸Yƒ£r©koï%’V~W•¯ ·ƒb<ÓãSnGQ¬ªw²Y¯¶æmÏY£DåŠM•Nôø*w3>KS³ú­P¹ÿŒOš˜‰•w²ÍV8ðá*kI•²¾T^e ÷ pZ2¾¢ÄQyA²oCôŸ'ê±9iBz\HÆ`1uÎ8ìÑŠŽ2ƒª>`Qz_‘¬Üà†9'¤£<¾n2þþ³žÉ'Ó¨ü1R=s<¾Ä_°¡ò§WÅg§„דÛǰHrv³ˆõ† æ Žòø "ŠQ¢”Û2Þ3]3†h ßšœ•ûîÓ/ÂOIâQ¹bú©ò’À!ß&o{ÀbÊæ“Uî¯{ѽŒþÌè‹ü¹þËmIuT8ÁãûI¼íKÑæ>Åôç üñ‡‹Áýä§Ÿ~rß^_\ß~ÿý÷ÿýwÕ:ô­ÍÛó)7¿MÕŸÂ%+WL?UÔ¶÷ø®o«ò«µ¼ÍC•_…/G?q*ÿùçŸûí·ë‹?ÿüó²¹bY6ËÊÕgO·mñIúSVþt.ÏÏ!0€ÀÞ¿ hð/ô0_ij_ݦŒ›GâvÉx˜•ÿòË/áoœ•¿A³x¹“•«ç•ŠlüaNûÏÀj8§o|uÆ“Íó*÷¯“Xth«¥OÀCƒ»’Æ9`i¸Ði*%°«Ä2¸ŸV‰Ròw°Ü¬OŸÃ^Fú矊,ß}÷]xÀrÀüðÊ hâ€E5¬ˆÊÓO ý$îõ]|×NÂgÅ2jçä=ò¼NN®ÂîüÄeßîOô¶§+pIßÊÛžá!It2¥¦VU•¯¸£ìǼÓÛ›g&à·k¬Ê-K¤Œ³ráaˆš#7#Úwß6n“ŒcðtMªd6eDåÛ˜‡4#°‡Ä1xfA ò²òf:¡¡I–>Qá\¸jPyYåÑAù0¹›}á#\[›N`Ñd}+V*Wè^•+4Uå$޾_.]µ¼g¬½zk|V®ô¾"*¹¸Ï¬¾ÄÑwÃ%ªNèS6o¯ò)w"ºˆ6œišÚžÀ*çÝËK±‰ÊÝë¹LxÑ烮’î,þÖò°nXøöôüƒ·«­ŽXò8  •§½ð“£xƒ¯2êKâ«„zBœ¨\Mà±bôžg(w²ò‘Wõ%úZ(y’Œ[[]j‘…ï:šT³¬<ʯÃ[Pò§">ß2õ­¹•p7‹ØÔ|¯Ì*7¢<±ÅãWD)·eÌz¦™Ê3/ÊÔÔª*šElp/Ò¢ xÄÛ\lUn [>}*'Íòa 3hyƒò’¨Üæž©jƒ»QãñÚÙV^.–=J~\– *¶ :u´ÄçéåcÇãrVãK.á´†AV«üöÕGÀò¯ Æ/zlEÀø2k‡‰Çk‰ .?FJvz©VyúÈó²òÁ›¡aw;yœ›Ç.Œ~MÙ‘ì˜HÞªÜÝ”2,Ö~OËýlæñ~ h¹!1R²Ó *o¸xhêžÀ6*çPe¡%nG²c"©VyzV>&P—þ/´’Õ˜ëñ†‡!x|­%=ÌKF:ªVùĸQùZ{É‚Ç?.'ÿ4Ê¿©»Ü¬íðDSMé•ï±n-Žbz>žBÑýâîùñ×)A’AOÁn¹S…¦–®2Zå–“xFå>ëç‹U\)ù”Pùõ=S°ïti/+‚ר<þttÎ,—þ›®ñøzÔíA`i/+‚¤rEddå=Öw6ñxª´ù’@ç,Ô*¹`N¯ŽÇO_VÇ¿…›„Z­rÝ͈­bµºlkŠÇ:tzÎvç,ÔˆF峆ÇÛžÖöæx•ó&§µ5`6žYššÕoµÊÓ[V„7±¼!*7µmð¸©é ˜ˆÀ{á¬ÕBµÊýKøÅ˜1£r;ÛÛ™ "¹%0FJvzѨÜE?,ïbdÕ¦ܯ±üŸn"ÂçÖ~­ë‘Zǰ#Ù1‘hTîê•ÏÝ$ÞÝsÃ÷Î1·œ%ß#P;½T«œ³ò÷‹ìM ËÜ ¿™tê*Ø‘ì˜HªU>&¬Û^Ž=+Okzz<>}  `¢©¦t]¡ò0úºëNSù¢ xh î?СF†ÜÕE¤òHý™o3ŒQùçPňÎNàm»†4BåþmÒð¾ÿÆ©ü~˜½U¾ÁñøÉµ3ö®Þ4Øø•§÷?ñé¹äÖÆýT¾ú!øÓ¾åpÜŽÑŽÄ m»†„ÊG/õ]õí9âñÑKŠþîtõ¦ÁÆëTþQ:ù_q`iö]<`yêkÅŸ‡ú^1~yÌüB9+Jv%P”Òf*Tþfä •§Ý­uÀ²}öfBäãäÇv¼ñÕŠu'¨þqQc¶Yøä“ðtû¥Óñø˜é£9&ÎY¨T~³66óø­¾o·„/)ß0/¯òŽ( * Y¸I¨¨|O•ËõýÆé$ãUr¡ðHMü¸P#¨<^]ë¦ä/õ]ët<>RLôUK`! 7 •³BVô¸âT¤vW\å£^ð¸‚!UFhâÇ…Aå_W×Zcðtïq8>ÒGô¥&°…›„ŠÊ×S92Uoo*žC ‰j•¬mû)ù¬4üœÍÏHw"°…›„ŠÊ¿¬^ËÇà;ù…± #ÐÄ 5‚Êízœƒ”aÛžŽö#°…›„zºÊ æã¤áûi…'ÐÄ 52AåþqhÓÜg°ØQ9¿Ûéqc Y¸I¨sT>VÅ ½8žæÏ`™îñêÙxs24È }²YÑ*OSòY*Ÿåqô-ß”„€šÀf¦.g‚ÊCw§Ï1ÏDÜ0+ìqô­ÞT„€Ž@Ñ}›­òèh%£ò~¿aäòx¿Æ}Ë¡¾tG€@H`3S‡3Zå‘»§då]SrÞ½ÔåPÔ‚@[E÷mV`´Ê£[V¢£ó<Ü&,=<ÎùIÛMHkxO`3S‡3AåŘž ¼WyC£ï÷› ЀÚ3‹V²Ý.REfL瀿þ‡£º-æ“…ð ×~ø÷ׄ"øõ;@˜öF½øv¢Hü·i¶ž6ѸMöàn_LØ]‘D¦%€Êµä¶¨—I*o³ÝHd·²Ž ¹8|1U+æ; eý4Uñ§ç$OÕ‹Cö;÷ÅÄ‹—A|C•½ *O5ZLí3ÊÎx¿¶£h"ó.Ž.ù¾RÑgÊ ûÍ?zE2x-T®%·E=#*÷G ·Ò”˜4 ¡Ró¯!¢3ÌEKyô2§o±“æ•ÏŸƒ‰HÜT•ÀæÏLnFn]VqÚÑÓÑGUü™ËF$ýâIK±ß[]/M•/=} ‚:´-Ê4s¾,¯ûò€å©ººYarý~윕7X»4@å,‡ïH n ñ)§[Ål:*æLš9ˆ2ñ¨dþÐãö,% Œ!f€Oã tÕ£F$ÜÒQ³! &€ÊÕè¨@À Tne&ˆ€€š*W££" +P¹•™ @j¨\ŽŠ€¬@åVf‚8 ¨  r5:*B°B•[™ † &~’ƒ¯!@`Uÿ6ŽÞþqyÆþIEND®B`‚ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/images/jdbc.png0000644000175000017500000000755311151703037022444 0ustar moellermoeller‰PNG  IHDRVêv²únsBITÛáOà#IDATxœíÝ[LeÇñ]Xhº-r†¦  ÖFˆÐF¹¢˜1F½€(¨•‹Ö¨5öƆ<õNmMêRRô²i©Ñ^xalƒµJ šš4˜Fˆœ)[X ì¼óvÞ}X¶Ëæ™ÿ÷sÃ2<;ûÌ<ÿçÇÌìÉ®iš €T›Íf·ÛcÝ ¬O¹°¦®”àÐ(W^Ò(:¨+“³Ûíq±î€X"ш@4"D#ш@4"D#ш@4"D“¾ï´ Ë»î}ëÂËuzØï coV599ét:§¦¦ÂµÂßÁê»±¼ 6B¨«0u'X¡G€¦iÑénww÷üü|www 1G]E›¾»µPùÞ·  `óæÍ %%%?ýô“¦i‹‹‹eee¾íëëëûûûWm¼–={ö?~|ïÞ½~ûé§ŸæççoÚ´éé§Ÿ¾uëÖºËWö¹¯¯¯ªªêþûïOHH¨¨¨8{öìZ¢ýQú­paa¡¹¹Ùét:Îæææ……ã.EEE <òÈÏ?ÿÔ>]ÍFÆ(V¨+%ê*œ×æççgffšššl6[BBÂã?ÞÛÛ«7p¹\ãããEEE«6^U¿Íf{ýõ×—––ôÛ†™™™Ë—/ONN>üðÃGŽYwùJo¼ñF}}ýàà Ûíþè£Îž=»Ö†ØþxüÖÓÒÒRXX8<<<<<¼sçΖ–ßþŸ;wnvvöàÁƒ¼±*ê*²u¥…/­ v»]¿}íÚµC‡é·OžÿüsMÓN:uøðáUw||<+++øåÆí-[¶ÌÌÌØ:¿¾­ºMÓòòòŒ SSSyyy+ÛÌÏÏÇÇÇx¬À62F±B]­ÅTu¶øçŸ>ÞXÏÒÒÒªºò×{"6¨+ýväêjC''.î¿k¨®®ÎÌÌ«¸-ÁPq»¬Ôg·%| ˆ¦j¬uTfÉ£5DÀºR5„ˆF¢€hD ˆF¢€hD ˆF¢9ô|1"º2¿ÿF€…ßa ŠÎ%êÊäø¼@:"D#ш@4"D#ш@4"D#ш@45"À~—﯇#77·±±qhhheãøøø;wž?ÞoUýýýµµµÛ¶mKJJªªªúì³Ï¢´ 0êÊf»ûvοŸ<šŒ~ê7<Ï7>þøãüüüááa¿f^¯÷üùóyyy¾køë¯¿222NŸ>ír¹fff¾ÿþûÊÊÊ(nAèT#_ªôYx]Ù5MSå»Ó~úuø½÷Þû÷ßO:å×ÌãñlݺunnÎhÙÐÐPZZúöÛoG·ãa ÊùR¥ÏÂëJá£ÃÍ›7·oßî×Ìëõ~ñÅ ¾-³³³‡††"ßÓðSeŒ|©Ògáu¥Æµ€ÀrrrFGG}—ègt¯¾újRRÒä䤱|bb"+++ê„’„Ô•"`dd$##Ãw‰žpn·ûÑG}æ™gŒå©©©~ƒ ¬EH])'.nõÞvvvÖÕÕ­\~ß}÷8pàêÕ«Æ’}ûöuwwGª‹Pu¥Æµ€ÙÙÙO>ùä±Çӵݽr;00ðî»ïîØ±cllÌhllÎôôt[[[EE…ñ§ßÿ=55µ½½Ýår¹Ýî~øaÿþýQ܎ЙŒV2Ÿ©+" ===...%%¥¦¦f``@_¨‡—þümSSÓàà ï]ŒtKNN®©©ñûë/¿üòä“OnÙ²ÅápðÁÑÛ˜ 0ó­ÅÌ}¦®t6µž”LÅ1R±ÏÒð!â€tD ˆF¢€hD ˆF¢€hD ˆF¢€hD ˆæÐߦ„ue~–ýP½ø¬ºuˆ2 —“e#@gá‘CtX¾„,:>Á !°üä×I™B†á"§`¤D€Nθ"dÒŠDVè¤1‚$³0$¾.@»û5²±îLDæü·É< 0ˆuø^¢#@'¼$cèm2Oüp^ ó_ÇQÀÿPB0оˆÔ‡…1¸+q"àó«bþ¯Š£€5Q1–ÁP@¬ƒêQ÷."`}”‘е Á¢¤Â`¸7Ô–É1@÷Џg™91.¡!BDÁ™ Ã2"`C¨¼˜c6ˆØ(J0VØóaA„åeìðp!‰ºŒvrxaFFû6ˆ€ˆ XÃŽ]!D@QµaÁnŒ(" ²(ß`ïE ”ò½bE =”uØQÑDDÅû'úˆ€ ÐWbŸÄ 3½]CD@,Qúì˜#bOæ4¹Õ&D˜…¨)!jcMŽ0 CÂ6ª…0«N«n—ꈓ²Ø„±ØæX `^Ö˜6ÖØ #ÌNÝ)¤nÏE!Ô ÖtR«·ÂñÍÂjPèûŽ™ÿjá(@1fž`fîÖB(Él“ÍlýAð8P’©Î ˜ÿJã(@m±~L~ ¬ úS‘ÉoœXAçAž8¹æ¿58bÝ„‡o ˜œvû:Ç}ç?“ßzˆK 2BÀä·*®X–ß?|ßïk úZm˜ÿÆQ€eiš¶ñ©Ëä·<ެoÕÓû•ãd3X  ÅʾÖiÂÊ¿ÂÂ8°¾Ð^DÈ)€XÙº“?ÈP$ÆKƒ,+Œï 0É› üL¦*ä ¬oƒÿékãr ¥Dâ‰=ž,´6Ž”ç7E£0 ÑDD *cÆ|ÍÓ„€PiŸ±7mÇ %昄×(C•©eªÏ5ĺˆ5¨2ÿu¤€Bˆe¨2ÿujõV2"P†ZÇÕjõV2"@%ªÌ+Uú  U®±©uå¼G@%‘û€à°0mÇ ¿Ã˜O9óô! TeÌ7Þ&„ ”ç÷) aÿ PÞ,lmD€¥¬:3ùÈ@Xs𤠈F¢€hD ˆF¢€hD ˆF¢€hD ˆF¢€hD ˆF¢€hD ˆF¢€hD ˆF¢€hD ˆF¢€hD ˆF¢€hD ˆF¢€hD ˆF¢ˆ»Ýë. (D"EÓ´Xwë#Ô išBÿWív;ó_ •Jô0󙿇ðC¨ÇœÓÌœ½ÂºˆU™gÊ™§' 6ãAôÇ1†0","ðÅÂÐF9ë„Ù"„ölµ!ˆÆëш@4"¼ž_4"@ v»Ýn·;ŽÜÜÜÆÆÆ¡¡¡àïÑŽAuD€24M[XXøñÇKJJöíÛ722ëÁ ˆ•8ŽxàÍ7ßljjjmmõýSaaaRRRbbbiiéåË—õ…ú!€~ ™Ífûî»ïÊÊÊ’’’jkkoݺxµ½½½eee‰‰‰™™™/½ô’¾pyy¹¥¥%'''))©®®njj*b»áD(éÅ_ìééñ]2000???33ÓÐÐÐÔÔ¤/ÔŸñÕ4ÍxêwÕf6›í·ß~;wîÜôôtEEÅ;ï¼xµÏ?ÿ|kkëììì•+WvíÚ¥/AXp9@4"D#ш@4"D#Ñþ-HR±o8IEND®B`‚ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/images/project.svg0000644000175000017500000000243511151703037023215 0ustar moellermoeller HA-JDBC logo ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/images/graph_delete.png0000644000175000017500000001625011151703037024157 0ustar moellermoeller‰PNG  IHDRîh€žsRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<&IDATx^íÝ™%¥@À ŒÀGߌÀD4#0çÉ ŒÀ ŒàFã-‡d  6 6°æ»Ÿ·û4?›¬ÚÍ©®óÍ7üƒ üÃ?@X–ÀÇehÙø €þAå,@Ë@åËO!€ €ÊY€–'€Ê—ŸB@•³ ,O•/?…p{[mÔ~æÖ[Wò*ðR¾nËO…=†Å2q*Šuœ…ø{Óò6Pù6SÙa ·v‹^,0¯ra”i#Å~Ó–óŽKQlzŠ˜©2ž*ÏÜnOÖ_/šÅˆÊ‹c)¤øKƘ‰Æ9&z1K•›š I,\4‹¤‘âØÚ³ò|œáaŽ&}1_,=‡ñåýeÀ½’ž™¤¯»bQŠ<)°=T¾ýW PbáUTî´˜|ôÓ§o3Å¢_Vò߆Œ§¯oûŠšM¯LÑ}  ò}ç¶~dB•‡©b”‡æz[ñ¶ÓL&5’e^Q©Ñ¹JƤá`u†L þGùê'™{@å{ΫnTB•íùT ˜Ñßz6r«zhÑ™ÆS0‘ýQ¹8µ@僛înc•§‰4]ïš›ÜþZ ÏÊÓ_Mž®U®Í§8å×EÓkŽà:@å@nÑÌN*Ï$Ý©:oÏs$Åž~x2»„pÔfU•-–!ƒÐ@åj»Ö)ê/MS]Ô“q«~q,Š“¡ñoSé|ê} ö6+‡Ob.\ 'Cå'̲tŒ·jȘUyFŽÅtûö¤%_KxÀE%¹œdÊ réÊ> *?`’ÅCLqoóÐÛb¾d¦‘§Š’\^7Ê[Ê·?òŽö%Cá†/F%3 rÑìáÕ"Ÿ°G< G<ÉÜ“*ßs^ pT~Ôt3X@`O¨|ÏyeT€ÀQPùQÓÍ`!=  ò=ç•QAG@åGM7ƒ…ö$€Ê÷œWFE•5Ý Ø“*ßs^ pT~Ôt3X@`O¨|ÏyeT€ÀQÆ©<}F‡>Œâ¨ `°€Ú RyèëðIC¡ßÛC €Î$0BåÎ×þ¿·ZOŸwæ|0j@ ¯«<Ê»óß*@@¡òÛ',‡©ºÏÙÃùkñ5 *§Éýu•{ ·î®:+¿ ÿ€Pù[¢;X\7þ2+é• 0E  H”²S™qYy;5TÎ…„Ú…³V ¨\¸0(¬D`-·G‹ÊWZÄ  ´Ëq­P¹paP X‰ÀZ"n•¯´:‰h—ãZ- rá  °µDÜ-*_iu+ $Ð.ǵZ@åÂ…A1@`%k‰¸=ZT¾Òê$V@@H ]Žkµ€Ê… ƒb€ÀJÖq{´¨|¥ÕI¬€€@»×j• Å •¬%âöhQùJ«“X!!v9®ÕÂ8•ß>Ñ?QBÇi 1Å ‰Rv*3Hå®'n‡ïöÛsÑ7f$㨕Ï^§ô<&㨕³ ‹ª’qTŽÊ-.bb‚Àáj“qTŽÊß2 ¶è’qTŽÊm­c¢ÀÉÔÉ8*Gå'oÆ+“qTŽÊ­,eâ€À™zIÜÑ[Àh]CÔü‰ÐíCk»Fuß÷•Ÿ¹Ãõ ÚOT"JŒdª‹:•‡5 Ÿ^›´aT+z ðm›·ŒPù [š1žF o2ÎKùSôõ“Ýë¾zØÎí‹O¡ òÓ69ãÝž@÷d•—UÞXÂôDô¼òHô™^Pùö›žCà¥d•Wˆ:L¥åŸq››“•Ÿ³u)·%ÎÛž"›§ò­µyèôŒÊ£7WùØ€@øñ›¯G¤³ Õ½íy{ä-†¥¢N¢ÜÁ‚^ 0ŒÀ¢É8*—ºööafÒÊmåPù°mLG‡X7Gåm–R•î†?†À¿@ q’¡N*Þö>Ì6\æÉˆþoG%HPù˜L/ÇXýP%œ8‰Rv*S¡ò'íæŸR=C1ÿmž,*?V1 |=’qX*®Oº°8‰£ò{’. PE`§d•W¨\Q42¸wzúz¦q²òªýIaHl–Œ£r…ŸëªÔfå··Êð" Ћ€KÆ{µf­:=­_ºî¬\1^ÎÊ%™e 0’À–'*@…¬–®òºÊ£7Ký¥ÛQ‹¾åmÏ‘û™¾N#`ÿÉ´½fäÓ§¥µ¬ ~„Ê5qÝÕᬼ×B§£œcp7­—ǯÿöÒÎ*íhT¦Òù›ÍûR@åG ˆÁ¶ðúÞõ]Í'8Î㨼ìÞ§{QÊ5›K ò–½MÝœ–€Gsê=ŽÊ˺Eå'1®Eàpƒ‡ç*~âÊ.Û«Dõ *_k“íÆ0¸ŸÜ0ç€Ez‘Òýµ§´õçr°ll%†&'€Á3ç*dåí¦}½T.ßí”Ü¿Ó4'+ÝÅ òýôĈò޽E¸0ž<ÎÛž"Ù¦¡+ªÖ\• ×7ÅV'@.™ÁŒÇQyY·#o$¢Aå’õM™u `pùÜå=ŽÊQ¹|-Q}`ðZŽE£rT^»¨(% ®'ñ8*/«<|VÕðDMg qÀ¢[úÔ²Fà„¾Ä\èqT^ö­â¬Üß7}ûpÄrÇŸ£øÒú Y @ÞYîqT^6j­Êóšþ4*oÜ TŸBƒwÁ^åqT^V¹;`•ûº«•¦ä®”¤MTÞeKÐÈ0¤ôB]ëqT^VtzS¹Ð‘²½ÙQy¯åN;F†÷…ÇQyY庩î‹*¿½fð",ØûÓ2Ç“¿$~ýOׯÎTëÖú $@tBòÍWÞó ÓpÎÊûæ/´6‘Àiòðjgp]28m§2*× ;5¾{Å =ü¶xIxoõÐ2Zàñz®nƒ£ò²¨%gâåVJð¶gûn¡…7àq5U¯ïÆ< @mÝyΘZùüþË‘‹I±šN—Ѝ\½a¨ø<®`Û7¿ @í³žÉ'Ó,dåŠ%K•½ àñªù`ðö¯òî¿(T±J ÷TùÓ/ê `UE³WËÆ¢ú¢Îôxx$Rûõȉ®rKX8ôŒ)›÷T¹šN—Ѝ|äN ¯<=Þ~WÉÈE¥vN䙢Í}yŸéþþûïn¤î•üÑ}{}q}ûÝwßýõ×_ ¨\*È8Óãk­‰^*¿F·y¨ò«ðåñè§òŸ~úé×_½¾øã?.›+`¢r4ª@à‘Ài_+÷ÓÖQåy›GâvÉx˜•ÿüóÏá‹ê­ÕMåj4½*rÀ¢^TìEà(/*q7×jí rß~ÕÚ1ë™þY¹¿øø/ÔÔª*šEÜw Òš5‡x|düí¬|ââì¬ò|sUj®-ŒÊ'.£c»>Áã›IÜ­ÕZ½øòf=3_å.yIe¾Í?/æX¡0ð)ñø¶owŠÊ j³r_Þ}‘ÿ6ß·Ù«åÛ‹’ö§ØÞã[&ã°H¯aéA¹Pî¨|ŠèTA`¡Ïä¬} Ê{•Up~µŠÔhI9Ÿ2Z»–w>`ÑŠ’qŸž§¯sÀòêú¦ñ µ>“s}¡êLåÔä{7eóUU~›þó"ºðïÞò{ ª?ñò½¬µÜEå—Óó6÷Þ÷_¸g°ø[ËÃkRXØáªzðV•GsVDFÀYy{ºA í¼¾M¥]’q‘ŒK(õ½ƒ%³HR•_ͺþèúogT¸öÁ[Už6'êà³þÝ//Dßò¶§p™RLG`­#”tŒÅ®ê°lY«˜b>ð ±<Ù<Ìk]ùëÏô¯?ìt¬ýK½åéùo‰L+v­Êå-KÞ"Þr2¨¾V7ø¿¿æ7}_¤ö[+ú¤JåO'-‘ÿüóO/÷ðk‡+¯r_ ]øà-TnÕá+60¸ãB2®XÝU~kóÈÎWZýÛo¿]%¯ÿúg³8G·?x«³ÊÃS‘ð¨D N^‘¬\± ¬²ÁñxËê•‹%*™÷LtÒ©üúL‰KÙWØ×ÃÏ—èòà­þ*W3j¬ˆÊ[Vö uº\2ªH(=•QÛÆ¬gPyËz î6KÃIÆ»¬9TþH º%|ëVM­ª¢Ù«e—•G#µ¶4¸;çp¼v1¤å«Ü6ë²òöUA ¶lvÂEâ½–*/àfÄ^Kvj 욆û<^»$2åQyî€%¯wäýÊ-ïyl+¡D£ãÖoùtÏ*iİáòHֽ֑ЋcFå³vE¯~—ÎÁ=’ñ^ëáÕvŠ>Ù¬@µÊÓ³r ¯ï4%Gå¯.h;/÷!):’q;Ë©‰ÄK;•©V¹nð¡ÊCw§¯ûö§ßÂI \ïØÚ”¦ø ¶)ØÕêLµn­Ñ*Mž³ Ü‹—b $°z>N2npQCZWʺÈ5*¿=ìÎw¯ÈÊÓ9+/._ƒ6ð¸Aª„T$ ⺵ªUž¦Ï„::9 o_‘´àRøâüQÀ¥=N2nj-Õ³®”u‘R¹.¸¨*¯]ÍsË[ð8E™»&öÞÅ9 5R­r—‡ÿ†•Oܵ]O÷89uí”mV~˜—Œt¤Qù¬ÐQù*›Í‚ÇWaEœ/˜¥©Yý¢ò—Ò¹ÍÎõ8Éø¹+ïë‘ÏRê¬~5*÷§+áÝ„@Vn—N÷¸}DD8†À#™ê¢ZåO·*³Ô½Lô8ɸzÖv­8ÀH¦º@å»®äò¸ú>Öj®ÇË£¥ÄaLyv@0¨ü°~} {òhÙö§\áñã–‘ù°§©.ªUÎ͈æ×ð}€Å¼Xàià³<ΡʢKqLئ<; Ê„uÛgåµ{@÷éZå:ƒ[¸Ÿ¤ûº§AlF@íÄE+ž¨òFƒo¶â¶$°¨‘Õa¤r ¾åŽeP¸% vâ¢÷W9g«Cà@‹Yö¶*Çàî^† O@íÄE+î¦r Îf†.‹Yö*÷ú®ýãLngÏC`Wj'.Zqa•ëðï"ÿôâ£v]ñŒ [XÔÈê°×S9ßrã1(ô% vâ¢WRù‡Ä¿äÔµO8é»Ph °L`Q#«Ã^IåžÁbyi ' vâ¢ç«\þpaT._Ç”„Àá5²:ìÉ*7þ¼òÃ7ÇÀºÔN\´"*_w­9 ðH`Q#«ÃFål@`Cj'.ZÑ®ÊùˆB@j‹Y¶]•§Còëµ£ÕUÔÕºbÛ¾âöTO"džöæBdjõb¤ü|•WÝÁ¢£¦[FºZj ,T2kð$î®e7é$3½Öd•WðjÜ]Ëâêàî “Ù&«ÌÅ*qVÉTaTþ8 -¾Á¡î•£r…4Õ«TÑ—…*¨•W¯Cõ&Ù¾âöT_V"S½lT@娼z%.´-‡:¸;µXÇW\ˆLõ~°Qa%•Û F€Ì@忦„€ Ô@åµÄ(@ÀTnnJ€@-T^KŒò€ÌXFåºwÀ?†÷Í7rðaGòꮤï%ú6ÓûmEÉ`÷¨îÎݨiTQ2Qµ=ÖN¢n}Tµ|ª¸ÓšQ Íì>ùf”¬.³eÖP¹z2$ë;œ›t If.Ü‘¶òÕ£ŠaݪŠi;OÕu=ªè=.04iúµdB£2’*é¬ ÖñŒ–\ÕšÑ1Qð66 RõšQ ·­º_ÉN·\f •Ë—zY²ìÒ­åz¬½„¸¾„¸ÝÏÆ{T 0¬"G•”#M+ ‘êzTw—þ²½"¿–ËvQ…4ª(éQ­Ô´¢¢;¿ åô¬iIlÕ¶’4úF™Z#딪ÎAN¨¨K—zéChºŽ‘ô¨î®£Ê%qú2ŠIôiÍSÌ·û]MFWñi\¨ü 7µ©P¹ï¯ªnZXX]·InáöØ’zD]{tÅäÛÃ'­Qb%ìnä{¤J¬é•¹-S¬¨`fº%=úy—¯å¨Z¢¨üc¯5YvHåâºI£¨Z=™M%é:,SÕ¯®b¯m) UÝ]DUØ]ª³[Èè¦>ºöïGF‡•ï¬òèCá'Ú`Bpü’´úd$ß©¯.DIéï¼ÂS&Ša±p°µT…Ý ºÇhDU /uºŠU‹\=‰º1Žì.ÚAOß —ëŠÅ–QùŠp‰€À¨| gz ð"Tþ"\š† 0†*Ù^ ¼H•¿—¦!Œ!€ÊÇp¦@/@å/Â¥i@c ò1œé€À‹Pù‹pi€À¨| gz ð"Tþ"\š† 0†*Ù^ ¼H•¿—¦!Œ!€ÊÇp6Ý‹âI‡SÆóôÌȉñ‡Oà›Â„N!à òÓWBèÇ'WatÞÜø32q„1€*Ùn©‰"3¦ªö×ÿpT·Å|²~áÚÿû_BñùGQáüƒ§»ÄZ»MöцÜ&þ2awE™–*×’Û¢^&©¼Ív#‘ÝÊÚ›:ýiäå¨@X1ßQdüÛ©¨Š?='yª^²°ß¹¿Ll±xÄWPùÑ B¡òT£ÅÔ8£ìŒ÷k;Š&2ïâ貑ï+}¦¼°ß ù£W$ƒ×@åZr[Ô3¢rÔp+M‰IÓÙ*5ÿ;Dt’¹hÉ#~5Áé[ì¤ùƒ@åóç`b7U%°ù3“Ûƒ‘[—EœvôtôQæ²I¿xÒRì÷–ÆÄÅ@×K@åKO_‡àŸm‹2Íœ/Ëë6°¤²F¹®iIEND®B`‚ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/images/graph_select.png0000644000175000017500000001647711151703037024207 0ustar moellermoeller‰PNG  IHDRîh€žsRGB®ÎégAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<½IDATx^íÛ•§@3pþ¼ŽÀ‰øFàœ?ýå 3p7ß!aÝPP o¡ØT>ÔhÈÝ W5˜AZÕ…Ï&€ÊÏžßêÑ¥âRÔJ^å’hò„Ž.¶Ö8–âÅ©@—Eæ]z¡‘Ý  òÝg°güOÖð?/j¥QåÅä*/6U *ï¹¶hk0T>ðVÍíÖR ¥nJ±±µð¬æö4Æ{Ü—L‹¥ç0Qá´nÔl¦7À4ÎÛÈ·Ze;„*‚ußFóŠlhK]…Ê3ýïÓ·™bá¹éþö5DT쩊ÿ©|q€û.B"W@å h‡WyÊ%£$ñ)±}¢–¯­«Syp¾…Túþ'“†2Õ]2-HT~øBdx5Py ­—•½=[È3È$ÂöYyª|,QITþ²U¿ëpQù®3g÷mŠzÀ²*OÏ:Ò<:<$yÊÊÓ×®eyV.lá6+^Y®úZœ*_|‚LÃ{ñŽ*¯‹ú€%½BäÍ^u©s…«ª˜.:[‰*_i6fÇR¥¿îYyF[Õ>1«‹ZåO¹§$]ØQx=@å³·Åý£ò=æÉ,ʼ4[λ‹uoóÙ'¿KZ“åö°¥xrÖ°DÃÉ´p{À’ïÅl‘ÐÑ‚Pù‚“29¤è07Œ&=çõ?ñâKËdþËŽœ àé@#“›‡­ÝŽ% /n4@÷_iØr• [Uv÷4œÉ‹†îg@å³g€þ!4@åÍi€Àl¨|ö Ð? f¨¼! @˜M•Ïžú‡ ÐL•7#¤@³  òÙ3@ÿ€š  òf„4@`6T>{è€@3TÞŒ Ì&€ÊgÏýCh&`¡òü$nŸhÑ<.€ ð"ÃUî3ôô¼¡ôiJ/ÂÏP!ô 0\å>ÈPÙ¡ßÓ‡Ìõm@x#•Srró-:† ô&0Aå·ÖN>—™¯!Tè­ÊÕÛ³PùSJ~±y:I¿Åvþ ¬®ÞÞñ Wyx!uÁ§fž® rÁ¦ ðA ·*Woo¸Ê;@åìQ@@H £y¶h • Å láߎA¢òV'±BB-¹ES¨\¸0(L ðûïÿèþnáߎA¢ò «“.!"gðb±§-¹ES¨\½T¨ !Ð(qÓþí$*²iPè"qTÞñ 1¤)nFTì ª@` %ŽÊ‡ø·c£¨|‹=I¨"Ð]⨼£u¿i*zö¡ÿü§ÿð'Ÿö¬Zú†ÀI•Qyú”•PÜ<ƒåŒ=É( PE`¨ÄQù•ûFµÓ”üöÁ,·¡pÀRµ[(  H•TùSnNV¾àf#$Œ `&qTn¡ò4IÊÊ«žMLa@`e—Çè³%›¶¸¯"ý¡M,E åC›ê,éÛA Wyx)NoY‰ŽÎóå¬\½¬©Y¦xüì@k.Ùôp•w5*Ÿµé:³<ŽÊ;Š·S¨\·¨)&z•÷÷oÇQù” I§P˜ëqTÞQ¼ý›BåŠEL!€Êû0Û"gåSÖ9BàdÓ=NVn|!©ëެüäÝÏØN!°‚ÇQy[K£òS6;ã8–À"GåÆr®ë•+vu<ŽÊëÜj\•±ßÄ™–ò8*"g÷Öjøô•ôÛð'OA ò3À¨ö'°šÇQy•GOYIº"‘¸ÿÄÿþkž@à4 z•÷Wy˜Œ‡­;ƒó –Ó¶5ãy5=ŽÊG©k—Ñ/Æx•ÇQyYåþc>òOiŠâ€eì^§õs ¼Íã¨\ ÔyEPù¹ªad ¼Ðã¨|ˆ§£å¿ÍD€Ênwš>”À;=ŽÊE*ON–÷ox½kÊã´ÃZ‚Àk=ŽÊË*WßHî*¢ò%¶8A¼€À›=ŽÊG©üéF²ò(…!Î!€ÊË:;¨Dõ§=uY¹Båé1?„Vþ¥Â!4;ÈÒ¢¡T«Üߌ‚ÎwÚŸ–9½¾‰ÀËóq7Õ"ÿT¨ZåµYyd|ÿ­/4º¡…;XÞäÆÚŸGå¢+T­ÊEÊ q3bÿ}O‹gÀã~>eR9§TuVÞ…bŒ•Ÿ¥FÓ™ÛizwÕ*¿}/Âf¨¼óÖ§¹ƒàñh2m¤´N/Õ*Ÿ:*?È< ¥'<žÒœhª)]W¨<Jnp†ŽÊ{î~Ú:…¿É)>Øi…ÊýmˆQ¸ò[PljÊO‘㈠äÓæñ¿‡sÄ‚h´ÍvÕëTÝAh&qßïˆ)§ML$à4=1€S»ÞÎÅkTÞØ¥º:Yù©»îãBâCç]í™M+¢ò¡Ë‰Æ!pC‰,‹M¬ÛHåáçõÕø$+7Øt1šÇ)£ »öÕNÜ´¢…ÊoÔC¹ Ù¡r›=@/ƒŒË,þž”'‰ýݪ˜&é’ÞQ¹åN ¯ŽxG˜Â¦$J9©Œ&+OH„·“gTîïN)bEåÂEL±¥p¢2e:Š>9¬@µÊÓƒ‰ÍÃ2·åÓú _@`S.ß4øÝÃ>ÌÔÅáLVyÕ‰9Yù”ì†N8QQ@ë[¥è¾Ã LV¹?­—`Eå}×:­ €ÄGP}jó÷ÿü÷é¯D)'•©Vù¿o•~}f†•[núª%€Äk‰IÊgd}ýW¦3/-Ò‘Få³BGå’¥O{H|ó¼¬óÎÒÔ¬~Qù EH³¯ €ÄÇMs‹Ç¯¨f)uV¿•§omÛDOV>nÛÐr-$^K¬ª|£ÇQyÙÉ’[Ë­¨J òªÍ@áAø °¾Ùv£ò²bQùèuLûË@âSÓÅ㨕¬UºØ·™³^Gåe•§7#šåé°Øl'z q³õÐÑ㨼¬r3q§¡ r³MEG$n¹ úz•Ryô wŒ–ðò€Ê-·ÖËûÚåXÝ Xœ÷=Žh³ì²³J(oF¬‚ŠÛÏøê<ƒ¥¸s(`L`—dÜ} òãÕÃ×/FƒÔã“•—ÞT.É©£<5¸°‘Ñ‹•ößL`;‰s¦?Rè·W‹.—AGåe•ëJ<¹›¬üÍê\gì[K|¨Ð‹¾.ÈÌò8£òœ¨v³òèh%£òÛŽø!úØå‘âΘ±W~j³ª‘ªÂ®Gùp„£ŽŠé’Î}kiÎÊ£%+_'%Gà˜LüiBÕùrKEáêš»šÚºJ…Ê%ÇÙO,¢·:ŸŽÎó(¯ZÂ…B1ä^×þå>ë#R+U}äÒÞ£¤·¨\÷"À¦VÆF*ïr¹CåëÛgñÏÄÕºDÁòÉÍ´fãñF•ËGjY2ŸL£r˹ ¯i^+ñb†ÞWâùîÌ<ÞE嫽të©ò§]’îb#dåÓD¸sÇH<š½A·‡_Xz¼‹ÊÝ*ë¬ýž*/ÚvhT¾Îª2ŽÄéX÷×8T]wÆšûTö·©éF‘{¶»^*—ØÜ{Égº¿ýö›Cá~òã?ºo¯/®o¿ÿþû¿þúKA•+ Qe!KeF#¸[uÄlSV¦)c~†*¿8\~âTþÓO?ýòË/×üñÇes1T®€F•UàñUfb·8:ª<Ÿ›GâvÉx˜•ÿüóÏáÕ »©\¦WEXÔ‹`ÓŠx|Ó‰[!lµvž<ó´ó*÷›|À¢FÓ«"*_a‡˜Å€ÇÍPÙ‘Z;ÏDkò*ù÷ßX¾ûî»ð€å:ùá‡ÌÉÊШ2™Ÿ<ûw?BåÑIËurréÕŸ¸ìÛý‰Þöt.é¯ò¶§M¯Šdåûï/éP¹”娵³¬gúgåþâã¿(R ƒpµÂçjE?É|úŸuûxü ³ì¢¸o›Š îüîÿ ¿ÈÇzØj;u8HüÔ™Ýh\r§Q²Zåºa£òö@K¨H¼…u;ЙjßZÕ*×ÝÁ¢Pù /gˆANÀI\^¾½¤{c³½Z8’À¾RÖE^­ò¨áy‹Båéx8+tlŠL¼#LšêE@'Ä}kµª\~ÌíßÞ oYñ逄 *ïµÊ{µƒÄ{‘¤î$J9©Œ‘Ê» CåÝ—»ºA$®FGE]œ³Q#Õ*OÕÌF‹Êmö€ëÅÉúé¯e$Áðacâûwgæ¥E:ªVùĸQyßýµ”¬3CÃã}çý%­M4Õ”®QùKö7ô?QSÆãjt/¯8ŧ;Õ¨<¼kExK—’•·oÎ$ιJût¿¹….ÎÙ¨‘j•§î6³9*oÙ™{I·Ì5u/Y¸K¨¨üüe¿Äñøù‹rü»øq£FªUîn$ÿ˜–¬¼výï(q<^;Ë”¿%`æ¥E:Ò¨|Vè¨\¾i7•8—O1%ófijV¿Ö*OÓyù>Q¹d÷î+q<.™_Ê ÌRê¬~5*å«~ÏÓW”·€Êó‹xk‰ãq¡¡(&$0K©³ú­Vyª`¹‹ý ÃF\’ñ£ò§E¬–ø:wm¯‰Ð[œ€D)'•™¯rGSbsTžnµÄ}¼ˆC cq=žœÀIš–Œe‚Êo­þ0ºO†o#ÏŸô=ý©ßÓ`uG@¢¿“ÊT«¼ýfÄÐÚU'ædå.%iÉÄ¿´DÞ‘@çlÔHµÊ9+ï¸Úžšê+ñ*KÎaZàñzÔ•ØÈÂ]B­Vy—^u¼!+ï.q…ÇÇÙËMDÉF:Éì[«Bå·÷ƒ»7?mƼÊ;‹WßڽZëÛ`ã>§úñl¤´N/¨|‰%="Wçãí—)_b…½/ˆu$k *Ÿ¼ÆI¼ÝãíÇ,H|òÚzw÷6]§T>m½“x/·Øœã”i ‹Ž?XG²6‘LP¹p¿?]xÚ~ÌYùP‰÷õ¸Âæ$ã¸t6]§—:•{ G_TçöíS‰ÍPùh‰+Ì+Üu’,‰ aRÌ€@•”(\¡ò.£MSrùgG·V¹ÄG¤äÂwA%®7ØÀtG ‹¯6jd‚ÊCwûdüà¬ÜLâC=žiœd{.H`# w ÕZå>hçîŒÊŸs6úyão‡¨©Á/pˆºp¯“ò0 ÐÅ5b­òÈݧfå–™ø¸óñÛTˤ‰/˜‡RH`# w ÕZå. ~›’ñY¹Ó±î¯å¦²·*Çâ–óK_:]ü¸Q#T®¦c©òŸ¡×­ÈL-{‰w B`µg6­ˆÊoÒúGâƒö?ÍC`S#«ÃFåñÒ]ÜãHü×0¡ÔNÜ´"*ßFåH|èΧñÃljduبü›¼fJŽÄ³ Ã1  vâ¦Qù¿‹jA#qƒ=OGØÔÈê°Qù—e¼šÇ‘ø‘~aPfÔNÜ´"*ÿXZKy‰›ív::˜À¦FV‡Ê­=îLù{ðîbh0# vâ¦'¨<úx§C‘àˆeòñ¢suÌ–2AàÍŠ>9¬€µÊÓ‡®øŸÉš©œ#Ž7+€±ŸA è“à X«Üãs—§ä®pßE–¦äH¼/aZƒÀ,‡™º8œ9*×åæ}Uy‰ÏÚrô Šî;¬Àd•GIz×'ì#¾¸<î›å¡Û#Ó&æ8ÌÔÅáLPyx8ž¦ç™ˆ{eåa>ÎóZG$D´ éŠî;¬€µÊà µCÝÐ2ZåÞ㜨Lßlq3uq8Ö*/4TåÎãH|Üþ¡e,B E5;Ö}™Ê?6g‘¥F€À8;ê¸%æ·¨œL|Üž¡e,H E‹;Ö}…Ê?<þùh…?€ÀKì¨ã–˜Wù—ÏÖãñ—l_† ¯Z´¸cÝcUŽÄÙÔx3uÜó*GâoÞÀŒŽ@‹w¬{”Ê‘8Û@å«_Š2ŸöDâl`@ $°ºÎzÇ7?+oü´'gC)Þª\½½É*oy gCOVWoïø¶T9gCy½U¹z{›©‰³! ÕÕÛ;¾uUž>ìØ}hsîC騂@oU®ÞÞº*OÉ…:¯âª«¨«uv|Å㨞DȪÚ>U…z{‚q{($o! FRKhù|ú¿îJ"²QPù(Ò[õSTùmêOroþÕÿ|ëMÃÁKjób0¾ë0˜0#N/WÑ#ò¬<êëI÷”RôÈVkŠ`û@å}ùÒ: PùÈt@ /TÞ—/­C@•€L€ú@å}ùÒ: PùÈt@ /TÞ—/­C@•€L€ú@å}ùÒ: PùÈt@ /*¿}´ïEî;ô¼€@w•‡jqñŒ~ ym†@  î*³ïpÎé¤ä]f•F!—¤òô£òç4I† @ É*ÊÙÄýöÃQy€@†@;nÕÄ•?¥äÚ¬üjç¿üƒ °•‡Û]åáe3ʵýKäú§a¡rÁ¦ ðA ·j¢»ÊÒ@åìQ@@H ¡y¶h • Å lá߆A¢òV'±BB -¹ES¨\¸0(lCà÷ïÞ¿ ƒDåÛ¬N…„PyËDû¦xÙS¸Ž)7¸<Î,íýÛ°ETþæýÉØ! $€ÊZ·KS¨\¸”)×p'+ï¢àV¢ò×îO!TÞÊ·ÛAåÂÕL1¼“€÷8YyG×7Êß¹?5„PùÇG‡¯ÿ• 4Å ðB¡ÇÉÊ—ö9*áþdÈ@åïêªp÷6$ßEþ×L$¨\¸¦)·ˆ Qþረ|§mG¬hJ@åq²ò\ò~ìøí]ùCœŒÜ…);*oº5h ;@åyO:+.á7NH’zŸÑï´ôˆhD@ëq²rQ~‰XR'£r¯éb;dåöÍ@`3¨\¢GÅYùÕ\èq•…}(·5éƒÑ‹«ü ¼“ÀÓ·wæiÝwXõK[•§­å_¢Ý,— \@ š€!%瀥|¡j«r—æç_P ÓùêUA€ÀNlGåe•GòZXÔn©gå;mAb=‘€Y¬fæK:9íïê–‰P¹y?PõœU¯ÿšõªŠ¡²£‰¦šÒ5*W­. Cà½Bƒ÷¶y}ûS|:±S‹ÊÓŽÇ €¬ü½aä³ ¤n­ÌšŸÔªÙ1RZ§µÊGާo½žéo$É‘[™·ùÑÍ:’ *ãÎdÌœuHÊä{¬o!jŒ@×é•Ë—4%!ðFBÉšÓssÅüd¬#Ù1‘¨UîoF ȮÅúÆÄ˜!0€Ðã>ÀÞåå$ÆHi^Ô*ç¬\¾˜( ­ h½ì+̲…ÅÌבì˜HP¹y©P‡°©¼(ôÞwŒè:½¨UîX¦ €›7Ã[‰@Ç3ç-Mš•pšâ¨‰ªU~ûidc€Ê%+˜2¨'ÐP¸>“Œû±‘Ò:½¨U>1tT^¿EiE =žIÏ‹a|Ôüþ°dTl¢©¦t­Pyþ\EþWŸ×»»_%ƒGå¶5M-¨ôP¹*€¯€/ÿÝds‰RN*£Pù“v‹.Ž „âö?KlŽÊmûZXÇã¡Ä 6?IÓ’±èTæÑQrï,TvhvT.ßc”„@okzÜ–˜KôwR‹Ê ãO•íAå½7'íC@H`)§úÖ&æMm]e´Ê=¬¢Êoo•áA@ KåZ64{‰;­uûàSã[{Ùüh•Gi8Y¹0c¢ºX<%^• 0Øpë*£U½vª=p—L!e ]<®:4ßÚˆà©ÜYZ…;XTû“ÂØHår›7qÎFXT¦Ò’›[á@åÂI1È ìåq7.ÉK ­´³K;j•?Ý‹2`À¨\¾?)  Õ<.Ô´¤Ø#-Õ*—,xÊ@à@ûz•ßž?Ø\~y!+?pO3¤WØZåE›ËvFIuVîoAQÝ|Ò,¯ƒÎp7hûßjd%'àQÌ™*Mœ³Q#•Ï*_mïÏDƒ?3vÀH *Ïäæ³45«_T>`‰ÒXðl¤r„6£òðýóº³òô€EuÔ^sÉ"+¯Ü-T?€Àyɸ›³ÊŸêÖ¨fǺê¬|˜¸y‹ÐÞa œ*ñJ?] vÔqM̨¼á^£)ô"pÞ‰JHª&%÷íDÔhqǺ¨¼×Þ£]4!pp2^´’¹ì¨ãš˜Õ*笼Éþ¤HœŒ·UytPS£ÅëªUn;+k¹.ã^oSâeOÉæ§ÌŽOÆ›{î~•4ŽÊ+7Õ;8[âÑM~MÎFz{œ³òœQ…•HÙV•w2Íš ÀÉÁkÒó•U¾òIWÆœŠ¬•›7<Ï#p¼Äo“ñt Bàñš¬|Ù”1o`T~ždQwo8QQ ·_aó\Úžú»×íÌv­ØRåOO=ÌÔT—EÜuþh|)$ãOÓ!LÏUÒ¯™z•[ÂÂÞ3ÃB³¥ÊÍtšTDåÂ)§X'$ãE°Eý »0;'ô̰h%ƒBåJ”@ŽÉ¸|}ä_)•·SY²‰Ê%/xõûC‹ß~ûÍïùá‡ܯ×ׯß~ûí_ýe*7@£ > ¼DâÍÓÏ[¡7ï%³L[©¼hóPåWáËãÑ#Nå?þøã/¿ürýðÇ\67l°f*7£iU‘ÃôS¥†Àñ'*EOÕЋéñ«k³vn=“ >·KÆÃ¬ü§Ÿ~ 4#EåftT|/’ñVs¾M´U›’vÚª`1£iU‘¬\²‚)#$ÿ¼a#Ó‹9QÚþ72øÁ)yó¬Ü±ŠFqéï¿ÿ.°|óÍ7W]ÀrÀ|÷ÝwødåhTéB`üyEÆ×]F8°QáÍ#Z«+s™OC›_''Waw~â²o÷/zÙÓ¸¤¿ÊËžØÿ`¦¦ªHV¾Ö^ÑGãŪ¯ª®qö Éø$W=³+¨Ür{_ùìÄý7ÎÊóÍ™ñI*¢òÕÖ–*ž0%ïž÷n_5ð¶…IÆ…<%J¹-³¬g–Py„Ëå£_Â}Yĵõòb‘^;eÍš]dîHÆå!Q *×Q Ýí%î~ˆ~Í·‹Êåëxµ’OirCó6lj5zW<$ãÚIÑI*(½¬gÚg决òTÙ¨\»4·.Ÿ?ñ¨?©oae¼$ã†ÙAåf¹Š¨Ü°OªRT­9§6WÜ/·Í”Yd>+/.Z[`æZ³r ƒÊÓÜŸG6%pm aäò’®Amya‹s‡*‹³]6S¹S_oÛ¥lÞ^åѤJTž6»ì–ù2û’Šªý ̲…Åö%L2^9w/I^ö̯^/%ÿƒû ky8а°³¨êƒ·«Å“ªüzWçõV ë¿i•¨°öƒ·–P¹kX‘¬¼~}oÁàñÌÓÛšÖÆÝÐ#7@»­bvέgž^xDá¸ަ½±Ó½Y?ú—z?ÊÓó¼…Ê[­ Ú±¨”¯ÏÁIÆ-ô_\§­ÊŸróÈÎþù§—{ø³›‡¼Ê}ðZ~ðVc•»Ó’🙶"Yùv³Òã™ô|;.È~îÕŽ#Z9f­^|ùŒgÒõÙùJ«ýõ× Ëõ_ÿÙ,ÎÑõ¼Õ^åfF•QùÊ;ç6¶V*ßeàÈz™2Û&ï™hIG*¿¾SâRöáúoøýM>x •¯³º^É{Tλ1W[ÜT>q˜ÍTîŠNWä÷Ÿ˜ÉJžøLäK×O^åq–ÁjÌÂYöÙ3•›Ñ´ª¸,âÕñ"ñ¼Aå$ã‹,¶4 ³v–õLc•§Íå;0å-BËnI`Ç{‰K–ÁÄ2fóœ¯òÛ£X&.Ö•»>[åÜý½òÚs±Õ¨<㺹Ê ê30ù°‡åàdåëï–L„§ªœd|—e)wÚ%Õ*Ÿ8ìeŸøì²¸‡Åy°Ç‡1¤£JM5¥kµÊ¹ƒ¥r…½¡úy*'ßnÝNñéÄNÕ*byÞBV¾Åv:ÌãH|‹U×ð–‰:®éºVåîNsyaRïjùGŠ ò-6ÕI*çåÍ-–ÜmEŸV`´ÊÃ÷ûx• ™¢ò-öÕ*'ßb±e‚Zå˜bj•§gå>‘—§ä.ß}y­sí6oÐ˶I¿®6SÄ£%`ðÒÖUÔ*o2ÚPåòÜ•kWsþfA§Ý¶òmÛš—xÃÓÔK41ÕFLPùíÙzúàÜ[ñÏîý®`øsý¨·Æ7[ÖOÉ[[ØÈÂMBµ¨<Ô®ê5Ï4OÓǫ́ÈÊëó©Û/ph•J·j‡d¼~¢i¡‰7jD­òÛôY5ਤT^³?óßÂÓÄÂmùòý 5#¥..¥œTf‚ÊÍøP¹y‹J$+)“?|7‡ç+"ñz†´à˜=³iEµÊÃ;Áå u:¨Ü°Kå_‰9WåÜüg˜\ªd4qÎFXT>kx¨\»uµvÖ–㩪ˉŠvj)_"0KS³úE奱çßåÉx4>›‘mµxysÏŵGÔ³”:«_‹ÊýÝMî°eXèdå’=d–ø×ë/÷›«þTÎ‰ŠŠ0…µ†yi‘ŽÔ*OofsT^\Í¥¦mjÑ–wÉxq,€@ E ;, T^³Zª[ŸŒ›¾U*'_hÑÊ0‡.Ò*?a9«dú/e?gÇò6%IÆOXn{Œaà C­rnF\j!›“qŸgÎ:$Ž–”qÄ8TYjåÌ0‡.Ò‘Eå³Bç¬<Ú~rƃìxŒÊñøñê\m€³45«_µÊë߸o**÷»¥>orÌ"¿– òÕLw|Zådåù´¨æD¥&WÝ›HJþžÜvß‘NwëàF«<ºe%::Ï~—³r§cÛÿÌ;Gr»¡ªqù¡¹ü2  €Â¨!0ؤӻ› ró˜×WyeNm^¸=^`´µi«e8!ðDÀì™M+êTþt 7fð‹«¼xìÐc×5OÆ…wšßŽ÷˜bÚ´#¥uzQ¨|zÐ˪ü¤d¼æ´•Û¤C­¦ûjp¨¼v—ŒÛlŽÇkWõ›lÒéÝ¡rûò™’Œw=Q1›àqû2¢fÓÝ:8Tn\G³’qc¸uÕ ïâ»êðR»Á&Þ*·¬¢ñŸŒËYHÉ-kˆ: LwëàP¹nAÍ:TÑEÙ¡ô“¯ñxØ4Ù€À`“Nï•+Í “ñNjm<®X=K`º[€ÊEëk|2>ýD¥ø(- M"0ؤӻCåå…6%/‡5©„78*Ÿ4t+"0Ý­ƒ@å¹e‘IÆ]Ölø_~®™Œ§Ç,x\¤ Í#0ؤӻCåkíÃãϲ6/ѼýÍÍŽ¬ˆÇGÒ¦/énÀ•GŸ&,ÿpÄaoÜ2n[¬Ô‚ž 6éôîF«<ú¼òküþ‘"‹1*2În„š(úä°£Uîñ9ƒËSrW¸ù|ÿë¸î;غÆF ŠÀa¦.gŽÊm¹yW•“Œ«ö …!°8¢û+0YåQ’Â}úlô滓ñæÍÒ  0‘Àa¦.g‚ÊÃÃñ4=ÏDÜ#+'_<·"<ØÝwXÑ*¯ÒetCË0•s›Šm‡P [8ÌÔÅáŒVy1 1*'ßb7$ÌjT³cÝשœdܼ7¨ì¨ãš˜ß¥r’ñ¶"¡B †@w¬û•“Œ×ì êB`;;ê¸&æW¨œd|»}HÀ¨$P£Åë®r’ñÊý@ulJ`G×Ä|²ÊIÆ7Ý„„ z5Zܱî™*'¯ß ´­ ì¨ãš˜T9ÉøÖ;à!Є@w¬{”ÊIÆ›ìÀvÔqMÌ稜dü€íÇ Њ@w¬{ˆÊñx« @;8ƒÀŽ:®‰y{•s¨rÆÆchK F‹;Ö¯òšOF$o»úi ÇØQÇ51OV¹ùóÊIÆÙr =ÔhqǺ[ªœd¼ÇÒ§MœD`G×ļ™ÊIÆOÚlŒýÔhqǺëª<ýV@¾sâ7%Ò5ö"°£Žkb^Wåé¨Â/UÙVÑVë ìøŠ ðiùAæ2*·¬Sx¾ÊUw°ØÀÙ6˜­*ÏÌÑ.Hw‰süb{›d¦×š¬rÕø/£ÁÝß–æ'sü™z•y¶(ŒÊ§‰ý|À“eÛ$Új™ý¸QÅ7ÙBÜ·çÏ6ß"zsœ¶Š¶ZmKs¨Ç“9~€LýÆSIVNV®Z0…7Ýñ4OâȨ÷ÃvRùĈ€ÀrPùrSB@€´P¹–å!,G•/7%@@K`•Û^oùžæ°#yuWÒÓ~ÍÌÊmEÉ`÷hîÎÝH‹4ª(YßQÂÍ´Í J;À§ŠýÖŒm€nÒ‡mŠLGòÍ(Y]Ë–ÙCåæÉ¬ïpnÒÅ'™¹p7FÚÊW*†uUÓvžªÛz4Ð{\ax9L–LhTFUÅ–Gkã-9U6&iÂ1šh^3†ÃmkîW²ÓW.³‡ÊåŽK½,ÙÉéÖò9…ªºVѶüœ ýsá¶¼5ˆê2i`XE>À¨¤|€iEÉw—ѱp½…@$l¥rÕ ú ¹êZ•ºX2À§ €|嬬iIl‡«<\L·kΰ»TýÒ¨}ízµõh¨eN‘WÜ][•Ë[èDùš1×j¥rÉQùÉ*¿}ª^z*îa*7lH“o7†jŒZ ¤©œ°;e•÷øÄ0ßc+•«f0 I5ÀÛ±‘ÚÆøX±»èy­v€áõ•­õ•¶¤èÜ2’¥E¨Z=•‰R“m)ض->Ë–ì®p:´—œ]hŽ3œ Õùƒ¹¢-T[-óJ3W$+?<+O¯íÅ R$eÉ%Äg^XÂ~£ŠþÒZ 2*éÛÑV”÷ŽHÕ]$}!™H5À0°U”Ï iÍCê¨Ý†OÖªd-Xf•/ÈŽ ,B•/2„@ÀN•ÛÙQ€À"Pù"A€ìP¹5!,B•/2„@ÀN•ÛÙQ€À"Pù"A€ìP¹5!,B•/2„@ÀN•ÛÙQ€À"Pù"A€ìP¹5!,B•/2„@ÀN•ÛÙTs—Ï ?ût.ÿðSUçFB︠r–Á×o%v be"ë„·N$+ϱ #€Ê‡¡^´£TIé§þGø Rúþ¯Që~ ÿû5§.$¾@X=êÅu‘>˜>ÉH[ cˆ Ü>G { Ôàâz°è®Ø0,T¾á¤5 9c“Ôà‘7ÓC†Ûc‡ÈÅ© =]'¢'O]gbx ÆW)þÆ]¢ºë? jºÖh¬#TÞîMTžÑhú§ÈkùÅÂùçQæ]Óoñê%ÁµÅR!È•  ò•ggDl‹¨ÜYÈÍ˜Š»•ÊóÁh³ò§«×íaш)§  ògU3¦LžkËdµ>}:d(öÞOå)? ¥bÀ·WMŽË5«•²P9‹ãñ¹›2‡æÅ³‹H忬\^±¦¤áåü *g6!€Ê›`ܾ¤$}üÖïNÇ‘•„g&>¹ŽZxºÜ&ÈO]?ndž:ø±Ü¶6è DqJFñÔÅöˈÌ#€Êç±§g@ òF i€À<¨|{z† Ј*o’f Ì#€Êç±§g@ òF i€À<¨|{z† Ј*o’f Ì#¾ƒŸ!@`Wÿ¼·¢¢e"íIEND®B`‚ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/images/ha-jdbc.png0000644000175000017500000001500411151703037023020 0ustar moellermoeller‰PNG  IHDRÎûx¢³sBITÛáOà¼IDATxœíÝ[L×ÇñYX60˜b0Á44 «q*±§µdÙ+Œ£ÞòªqRR§ªzsT%E‚–¦i9–#œ´X¡îKU98Q#Õ•¢Úu}QÛRZYTÄvƒ æâÅ»ööašétwf—=3çœý~ž–áìÌÿ?sÎewY±Ẍð»ÈŽÆ.¬&Ì+h°–0?â#%,%$rü®ôGÔ€pD-GÔ€pD-GÔ€pD-GÔ€pD-GÔ€pD-GÔ€pD-GÔ.ÌþéVù¤+>. Y(Ëב?Qøˆè_»v-S;LûSòìÍòQ{ÈÖQ†Êñ‚?Q‹Å¼9Mƒƒƒ7oÞôàX€ÇXG ‘å „ººº‚‚‚P(ôàƒ9rÄ0ŒH$ò™Ï|Æ>¦­­íìÙ³IÏg``à¿øÅÀÀ€}c ؽ{wmmm~~~KKËÄÄ„óö¸ûš7þþ÷¿þóŸ/++ …BMMMÖ,LZ›y/ëˆý'óÜÜ\gggIIIIIIggçÜÜœu—×^{­¡¡! Õ××?~ÜÕyDvcI»Žd‰Úááá›7oNMMµµµmß¾Ý0Œ¼¼¼µk×;vÌ099yåÊ•úúú¤ƒ“:sæŒaßúÖ·nß¾mÞ¶LMM9rd||üþûïßµkׂÛ}ûÛßnmm½páÂÌÌÌóÏ?ÿÆoÌ׈ñÑo:IƒtuuÕÕÕŽŽŽŽŽÖÔÔtuuÙëÿýï?==½sçÎ;v8Ÿ@À`I¾Žb>Izèp8ÌÛ'Ož|úé§ÍÛ{÷î}ã7'úÎw¾óÊ+¯Äb±—_~ù»ßýnÒã^¹reùòåî·[·—,Y255åÐ]\mIw‹ÅV¬Xqýúuóöµk×V¬X‘8ææÍ›¹¹¹ÇÇÇé¡¿Îë(¦Â:’"jÏŸ?¿sçÎÆÆÆŠŠŠP(d/©©©)‰Äb±/|á sss΃í"‘ÈÊ•+§§§c±Ø7êêêÌýÄþÿìG£Ñ`0è~»u;''çÎ;qu¨m¾Û¹¹¹Ö~nß¾ô ‰_z†¨uÏ÷kÄ:2o˹Ž|{!‰ääü÷è›7o®¨¨xýõ×ßÿý™™û°Í›7¿óÎ;gÏž5ŸmqlwèСsçÎâââááá·Þz+qØäääòåËÝo·TWW߸q#n£sm±d¯`TVVZOfMLL8ˆÃ:2É¿Žü‰Ú™™™½{÷®Y³Æürtttݺu«V­ŠF£û÷ï·lkk;pà@ÿ7¾ñÛõ÷÷ Y?U†††úûû­ïž:u*NNNîÛ·oݺu nOÔÑѱÿþéééÛ·oŸËî~{6㜸—mçŠuä^ åÍ^ 1¢„ËÆ¨ï·~ëÜc¥$£>~ÿý÷ïÚµËÜøÕ¯~µ»»{zzúèÑ£Ÿüä'ßàF6þsr¸—ñ4mí0///çææºö±ŽŽš·_1KtéÒ%+KJJ._¾ìþX¥¥¥ãããæíÁÁÁ_ÿú×eee ‡J«v eD-¼‰Drrþ;å>÷¹Ï8pÀ¼÷ŠYR•••Öó­Ë—/7oçääXO2ÌgrrÒßÔÔtìØ±ÉÉÉ]»vµ··§Õ2¢™™™Ù»wïš5kÌ/»ººžþù¾¾¾ÉÉÉH$röìYç»·¶¶öõõÍÎÎÎÎÎöõõµ¶¶šÛxàþþþH$2<<üƒüÀ~—S§NE£ÑÉÉÉ}ûö­[·Îܸ{÷î‘‘‘P(TUUUXX˜é.ùÅ€yddz,[¶,''§¨¨¨¹¹yxxØÚ~êÔ©Í›7/Y²$ }êSŸzæ™gއ;::Š‹‹‹‹‹;::Âá°¹ý¯ýk}}}0\µjU¿a{ŒÜÔÔt×]w•——wuuYãŸxâ‰òòò`0¸zõê£G.¾;‡š“ÁËbp¦îK=ÞW®î¹‚h¼,† à#i€)µ‰+ø½ï}omÉ%éI¶©èäIÂ+úŸuäÿNÁ/¾‰’XyÜ–Ó§O¯^½:‹566ž>}Úýãö322R]]7,¾úê«mmmö‘•••/^L¡éÙOEâò±0_8ŸEOëȆêO þ_ÜwûûûŸzê)Ã0:::\Þ+Ñ=÷Ü÷·Iæ3P_ÿú× ¬?C2 ãêÕ«Ö[åu’µ¿8/H3Ã:òˆß‰Ÿ¦ÄÊí["‘ÈÊ•+§§§c±Ø7êêê"‘ˆËÆíùƒ>¨ªªJ633³gÏžÏ~ö³Ö·ÊËËõûi ÷ü¾\éH,Û`eš¡ú£Z‡:wî\QQQ (..~ë­·ÆÛÿf4ÎÀÀÀÖ­[·ß}÷Ý;vì8~ü¸µeýúõ ¾t œØüë÷öšóysú}Æ:Ê$§oÚ+·oÙºuëÐÐõåÐÐÐc=6ß®¦§§_|ñŇzȾóo=Ÿ}öÙ{ï½wll,ñ(===<òˆõ­÷Þ{¯´´ÔücÓ™™™Ã‡oܸ1ý%`ð\­óPô„°Ž< ö‚q˜"ccceeeÖßbÆb±p8\VVf¿Ò¦¤3jžóý€Û·o¿páBÜQL………ÍÍÍqß=qâÄ£>ºdÉ’`0ØÐÐÐÛÛ›‘fý’ô$ggÚ.ظ¢gƒuäCé7{Áó½Éz${&Ï‚-+úf/x Àæ"=ÿûY­þëïnX¯A˜"=A¿ €Â¬´Õ>€´o¢ñ¨‹E  "j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„ËŠOÀÃbði2.eÉçI"=AC͵¤â÷)Z³ß%¨DÅëKÍà£ÁÀ D-GÔ€pD-GÔ€pD-GÔ€pD-GÔ€pD-GÔ€pD-GÔ€pD-—ZÔ>bÿ2 VUUµ··_¼x1qpnnnMMÍÁƒãvuæÌ™–––¥K—lÚ´iÏž=‹iƒš}¯î©x}©95ÇRdÝż‰DÎ;÷Ë_þò¾ûîF<¸bÅ ûþñ”——ïÛ·orrrjjêøCSSSz5P³T5g³l¸¾Ôœv͈ZKOOOgggâ°[·nØG¶¶¶¾ð ©7i ©Ž§æôjÀ‚²áúRsz2µ###ÕÕÕqâÑ諯¾ÚÖÖfYYYyñâÅtJN¨!ÕñÔœ^ XP6\_jNO†£vnn.///~ï†aÆŽ;®^½j}+ F"‘tËNrh÷ã©9½° l¸¾Ôœ#³ï@¸téRyy¹}‹y˜™™™OúÓ=ö˜µ½´´ôòåË|xãÆ)<Oå—jö¦fè}}©y‘5»ÚeË–åää577Ûïo¾Omûöí.\H²wÃ(,,lnnŽûî‰'}ôÑ%K–ƒÁ†††ÞÞÞTK§fIj†I×ëKÍ©9`(øÏë eÿ<5kLÅsEÍÞüa.GÔ€pD-GÔ€pD-GÔ€pD-GÔ€pD-GÔ€pD-GÔ€pD-GÔ€p¿ €ì”ûÀ:¿¬&ÌKø'?ZóO­k–­b͆je#)E¯& gÞ£xsR˜7žQôTâèd±,p,/OÒsÈ lˆ¤èõ¢l·Gôþ)zm 5n*Ÿðl îÕQz9ø{~)f˜÷Ô­\?ªÏCÙÊ}K<Ï—ê—Í r¤HÝó¯zå>g$gM†s‘Õ+7Ô,^9JŸmÕ'¹ •˵&yÎKªÔ­ÜP<$§ô¹Õ xy*—+jM²#÷4˜š†šÅKHéó©Añ²U.cÔšä<_.iP¼¡lýþRýìi0uå,^Þ¨5É|î¤Çª3”­ßKªŸ+=ê—¹xÙ£Ö$ÿyt Ç$6”­_( NŽÒ‹ËP§~5¢Ö¤Ê9õ*·Aœ =&¤*õ«µ&µÎo"m–¨¡r iÓ wmZP«~õ¢Ö¤â¹¶Ó`ºê_÷¸^’P·U£Ö¤îy·hÓ‚¡xóÑ£;m¦™º-¨µ&Õ¯¡×z6ï¤G/:u¡t †QkÒàzè±0 •¯—@*ztaÒ'jMz\º0ThD¡RiÖˆê]Øéµ&=®“fËÆ²™kK‰f¨ÞE"=£Ö¤Ç5Óf 2õ"O%‹§Ç<74j$)£Ö¤ÍõÓ¬×OÂ×.a zÑ úG­I›k©ß3¼ù'zœ7)i³0”-QkÒæºê´Ø ‘íhy¢4èE³ëâFvE­I›ùjèØ‹‘‰v4[É:µ£S/)ÉÆ¨5RÒJ»Í΃Á,ÕHöF­‰©,3÷éÚ»íèwuÒíQkÒiZÚµcÌß‘~kX³Ž4kg1ˆÚÿÑ,¡ô›åVGmZ3˜~º#jã1ãe—¶:5¥G/†vS.SˆÚä4›ý†âÍ·z•^ÕJŸ”~eQëDéxJJ­Åà²Zµš2ôW:u”qDíÂô›F’g“®oö’¼¼ôè·:!jÝÒrJÉÖT¦ÂH¶P“­žŒmòHލM–ÓË÷ T€ï}ZOÍš¨M‡–SÍû`ò숷æ1-g¾7ˆÚôé:í<è˯$òค,’"jK×)("2ä‰!WMï™ __#j3C×阑p”'aãèÝÝâé:«}AÔf’ÆS3ÖÊ ôJårÃ=¢6ó4ž¦ºþMÅåµÓþkÙš¿ˆZQ4ž²Zþ™¬ö &¥ñŒ•Q+–ÞÓW˱ӾA“Þ³TD­tÊÙDz÷¨ëÌ”Qëm¦uÒߣ5ûåZûµ™ª j½¦îOé514¹©_éÌUý)Ѝõ‡BÓ}1o„Jõ^>ʆ6šuú!jý$ùÔÏà;ü¥íÑÈD›ò®üWA{D­ÿd[¨âþ$W’-¯J¶KiÈzæ³Q+‹Wi öbIõQ,i7ëæŽRuºÈ£8쟕 Q+‡%šÞÊ‘$z’1ã1ár·iì9mîIõ§‹Ãž Y µ2ÊÔ;œ—œï¿í.ó}×aoÎ;ô·SçRªPû÷¢é'èwHÂ\*@`1÷ÞûÄí¾/H«Mû—q\>Ö“¼Yë肞&’¤M8àQ­ì’†HÏ È¿ã~®Øwù.×Ä»KÞ¬±è~]Þ¾#jÕ¸ºÜ<#i“?dí¬ˆtù±‰Ã$Y;û¥I¯_‡‘ Q«÷dôXŠ.ûÕæñ]¶õ›…rü. [ð‰Hç‘óÝ]Z‹,X¹~]r? !¢Vvî’ÃHUV£õJà|ßuøÒý~d³ø U¨Ù¬EÔJmÁ%d p?RZn*t߯Ë1¾s.R§ë›åx®V ™ZHª\îEö›%mZTé7›µÒñÒ‡Ì/§Ð¯¡u¿0µRpùF¥èïÑéWôጨõ“<ïxõìãQ<8Š<•d[¿p@ÔúCÚ·Ù *Œ~%!maÚ#j½¦Ä\Ï`‘ô+!%ŠÔ oöò”*S<îƒ`ÒF¿rÊT¿p¨õŽ*ëдøÕH¿2#m=FÔzJ•uhZ|µô+3µªUQ µžRë÷µL=w© ú…8D­×T™ß™ª“~å¤JÚ j=¥Êk™z…‡~å¤Ö+xzà‹y;%œë/Œ~¥"maÚ#jýáæ?zIt%ô+â(îÉSIÖ"jý”ô_øž¬_>Ž„~=;:7#¢V ö•ô?hö!{ôë0 ²õ‹DD­t\þsÆÅïSôkhÝ/LD­²m-Ñ/4Û½@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢„#j@8¢ó ~—à)ú…8D-œÄb1¿KðýB¢Ö;±XL¡Ç@`‘ë~e¶ø~‘N·×ÌÕ(óiÏl…ô+ù+ÔQë9§»¸ªèWrV•%ˆZ?É3õ½©„~ý"O%Y‹¨õŸõŸ÷×—CÓo6qˆZ‰8¿¨’Þ•±ÏL¡_;ýú…Q«Œô^ÝV÷úÒ¯êö›mˆZŽ÷Õ€pD-GÔjB¡¿SÊú…ZˆZï@  «ªªÚÛÛ/^¼èþŽB „~ÝßQhaQë©X,‡ß}÷ÝÆÆÆõë×_ºtÉïŠÄ¢_¿+‚4bðJÜÙîéééìì´o©­­ÍÏÏÏËËkllüóŸÿlÝ+îbÍ7ìí·ß^»vm~~þ–-[®]»æ¼Û¿üå/k×®ÍËË+//ÿÚ×¾fn¼}ûö~ô£ÊÊÊüüü–––ññqú¥_dQ븥822R]]8,¿ð +W®œïŽI‡†ÑÛÛûᇆÃáŸÿüçO>ù¤óøüão¿ýöÜÜܹsçz{{ͽ½½Ï<óÌøøøôôôÓO?½mÛ¶4[MV6ý&-,ñŽI‡IØ/RBÔz'nEÍÍÍååå%‡ÍϸKzǤÃìc&&&***œÇWVVöõõMLLØ|⟸~ýºyûêÕ«eeeÎ9£_½ûEJˆZïÄ­¨>ø ªªÊúòüùó;wîlll¬¨¨…BöÁöÛó ³¹sçN0tøðá‡~877·¾¾~hhÈÜ 3øüýêÝ/R¹öNÜÌîîî~ê©§¬/xàîîîÓ§OG"‘¸¥xçÎçaöñSSSÖ¯®»ÅbÓÓÓ¯¿þú²eËÌ/«««¯\¹B¿ô‹Œã^‹F£ÿú׿ž{î¹_ýêWÝÝÝÖöÑÑÑuëÖ­Zµ*îß¿ß~—ŠŠŠcÇŽ-8ìøñãÑhôÖ­[ï¼óÎÆÇïÞ½{dd$ UUUšŸ|òÉþþþË—/G"‘¿ýío_üâé—~‘~g}1O¸ù¾ËíÛ·_¸pÁþÝ7ß|³®®.77·¶¶¶§§Ç~i^zé¥ÂÂÂÒÒR‡a¹¹¹›6mÊÏÏ/++{î¹ç"‘ˆónŸxâ‰òòò`0¸zõê£Gš£ÑèOúÓšššP(´aÆßüæ7ôK¿È>n„ã ލáˆZލáˆZލáˆZލáþþ”rmü“Ú©IEND®B`‚ha-jdbc-2.0.16+rc1/doc/src/content/xdocs/doc.xml0000644000175000017500000014502311151703037021051 0ustar moellermoeller
Documentation
Introduction

HA-JDBC is a JDBC proxy that enables a Java application to transparently access a cluster of identical databases through the JDBC API.

Normal database access via JDBC Database cluster access via HA-JDBC

HA-JDBC has the following advantages over normal JDBC:

  • High-Availability: The database cluster is available to service requests so long as at least one database node is active.
  • Fault Tolerance: Because HA-JDBC operates via the JDBC API, it is transaction-aware and can survive a database node failure without failing or corrupting current transactions.
  • Scalability: By balancing read requests across databases, HA-JDBC can meet increasing load by scaling horizontally (i.e. adding database nodes).
Requirements
  • Java Runtime Environment 1.4 or greater
  • Type IV JDBC driver for underlying databases
  • An XML configuration file for each database cluster.
  • ha-jdbc-*.jar and its dependencies must exist in the classpath.
Dependencies
/lib : Required dependencies
Library Description Notes
jgroups-*.jar JGroups
jibx-run-*.jar JiBX
quartz-*.jar Quartz
slf4j-api-*.jar SLF4J API
Additional dependencies for Java 1.4 and 1.5 only.
stax-api-*.jar Streaming API for XML. Required dependency of JiBX.
Additional dependencies for Java 1.4 only.
backport-util-concurrent-*.jar JDK 1.4 backport of java.util.concurrent package. Required dependency of Retrotranslator.
jdbc-rowset-*.jar JDBC RowSet API and implementations
retrotranslator-runtime-*.jar Retrotranslator runtime.
/lib/runtime : Optional runtime dependencies
Library Description Notes
jcl104-over-slf4j-*.jar An implementation of the commons-logging api that delegates to SLF4J. Provides gradual migration from commons-logging to SLF4J. Commons-logging is a required dependency of JGroups and Quartz.
slf4j-jcl-*.jar Commons-logging provider for SLF4J. Used only in conjunction with commons-logging.jar.
slf4j-jdk14-*.jar JDK logging provider for SLF4J.
slf4j-log4j12-*.jar Log4J provider for SLF4J.
slf4j-simple-*.jar System.err logging provider for SLF4J.
Additional runtime dependencies for Java 1.4 and 1.5 only.:
stax-*.jar StAX reference implementation Any StAX implementation will suffice.
Additional runtime dependencies for Java 1.4 only:
jmx-*.jar JMX API and reference implementation Needed if your runtime environment does not provide a JMX implementation. Any JMX implementation will suffice.
You must include exactly one SLF4J implementation library (i.e. slf4j-*-*.jar) in your classpath. Never use jcl104-over-slf4j-*.jar in conjunction with slf4j-jcl-*.jar; this will cause a StackOverflowError.
<ha-jdbc> Configuration

Configuration for an HA-JDBC managed database cluster is contained in an XML file. The algorithm used to locate the configuration file resource at runtime is as follows:

  1. Determine the resource name from one of the following sources:

    1. A config property passed to DriverManager.getConnection(String, Properties), or the getConfig() property of the DataSource
    2. The ha-jdbc.cluster-id.configuration system property
    3. The ha-jdbc.configuration system property
    4. Use default value of ha-jdbc-{0}.xml
  2. Format the parameterized resource name using the identifier of the cluster.

  3. Attempt to interpret the resource name as a URL.

  4. If the resource name cannot be converted to a URL, then search for the resource in the classpath using the following class loaders:

    1. Search for resource using the thread context class loader.
    2. Search for resource using the class loader of the current class.
    3. Search for resource using the system class loader.
  5. If still not found, throw an exception back to the caller.

The root element of the configuration file has the following definition:

<!ELEMENT ha-jdbc (distributable?,sync+,cluster)>
<distributable>

Indicates that database clusters defined in this file will be accessed by multiple JVMs. HA-JDBC leverages JGroups to handle communication between database clusters across servers.

]]>
config
Defines one of the following:
  • Name of a system resource containing the JGroups XML configuration.
  • URL of the JGroups XML configuration file.
  • Path of the JGroups XML configuration on the local file system.
The jgroups config file is expected to use the new (as of 2.3) muliplexing format. See the JGroup's Wiki for assistance with customizing the protocol stack.
stack
The stack name from the jgroups configuration file.
timeout
Indicates the number of milliseconds allowed for JGroups operations.
<sync>

Defines a strategy for synchronizing a database before activation. If the strategy contains JavaBean properties, you can override their default values.

<!ELEMENT sync (property*)> ]]>
id
Uniquely identifies this synchronization strategy. Used when invoking activation methods.
class
Class name of an implementation of the net.sf.hajdbc.SynchronizationStrategy interface. Details here.
<property> ]]>
name
The name of the property. The value of the property is defined inside this element's contents.
<cluster>

Defines the nodes and behavior of a database cluster.

<!ELEMENT cluster (database+|datasource+)> ]]>
balancer
Defines the balancer implementation used to distribute read operations among the active nodes of this cluster.
default-sync
Defines the unique identifier of the synchronization strategy to use by default when activating nodes of this cluster.
dialect
The value of this attribute defines either: HA-JDBC references the configured dialect for any vendor specific SQL.
meta-data-cache
Defines the strategy to use for caching database meta data.
none
Meta data is loaded when requested and not cached.
lazy
Meta data is loaded and cached as it is requested.
eager
All necessary meta data is loaded and cached during HA-JDBC initialization.
transaction-mode
Indicates whether transactional writes should execute in serial or parallel. If your application uses distributed transactions coordinated via a transaction manager (typically provided by an application server) using the X/Open XA protocol then you should use serial mode. In serial mode, database writes execute in consistent order across databases in the cluster thereby avoiding deadlocks. If your application uses normal database transactions then you may use parallel mode. Parallel mode is obviously more efficient than serial mode. If you find that your application suffers unacceptably from SQLExceptions due to concurrent updates of the same data then you might want to use serial mode to improve fault tolerance.
parallel
Transactional writes are executed in parallel, for efficiency.
serial
Transactional writes are executed in serial, for improved fault tolerance.
auto-activate-schedule
Defines a cron schedule for an asynchronous task that will automatically activate any database nodes that are alive, but inactive. Schedule should be defined in accordance with the documentation for Quartz CronTrigger.
failure-detect-schedule
Defines a cron schedule for an asynchronous task that will proactively detect failed database nodes and deactivate them. Schedule should be defined in accordance with the documentation for Quartz CronTrigger.
min-threads
Defines the minimum size of the thread pool used for executing write operations.
max-threads
Defines the maximum size of the thread pool used for executing write operations.
max-idle
Defines the amount of time for which a non-core idle thread will remain in the thread pool before it is discarded.
detect-identity-columns
Indicates whether or not identity columns should be detected (if the configured dialect supports them) and measures taken to ensure that they are replicated correctly. If enabled, you should also use an eager meta-data-cache since identity column detection requires several database meta-data queries.
detect-sequences
Indicates whether or not sequence operations should be detected (if the configured dialect supports them) and measures taken to ensure that they are replicated correctly.
eval-current-date
Indicates whether or not SQL statements containing non-deterministic CURRENT_DATE functions should be replaced with deterministic client-generated values.
eval-current-time
Indicates whether or not SQL statements containing non-deterministic CURRENT_TIME functions should be replaced with deterministic client-generated values.
eval-current-timestamp
Indicates whether or not SQL statements containing non-deterministic CURRENT_TIMESTAMP functions should be replaced with deterministic client-generated values.
eval-rand
Indicates whether or not SQL statements containing non-deterministic RAND() functions should be replaced with deterministic client-generated values.
<database>

Defines the databases in this cluster that will be referenced via the java.sql.DriverManager facility.

]]>
driver
Defines the class name of the JDBC driver used to access this database.
url
Defines the JDBC url used to access this database.
property
Defines a property to be passed to the java.sql.Driver.connect() method.
user
Defines the user, if any, that HA-JDBC should use to connect to the database during synchronization and database failure detection.
password
Defines the password, if any, that HA-JDBC should use to connect to the database during synchronization and database failure detection.
]]>
id
Unique identifier for this database node.
weight
Defines the relative weight of this database node. The weight is used by the balancer implementation to determine which node will service a read request.
local
Indicates that this database resides on the local machine.
<datasource>, <pool-datasource>, <xa-datasource>

Defines the databases in this cluster that will be referenced via a javax.sql.DataSource.

]]>
name
Defines one of the following:
  • The JNDI name of this DataSource.
  • The class name of the DataSource.
property
Depending on the value of <name>, properties are interpreted as:
  • A JNDI environment property used when creating an InitialContext from which to lookup this data source.
  • A JavaBean property with which to initialize the data source.
user
Defines the user, if any, that HA-JDBC should use to connect to the database during synchronization and database failure detection.
password
Defines the password, if any, that HA-JDBC should use to connect to the database during synchronization and database failure detection.
]]>
id
Unique identifier for this database node.
weight
Defines the relative weight of this database node. The weight is used by the balancer implementation to determine which node will service a read request.
local
Indicates that this database resides on the local machine.
Dialect

The dialect attribute of a cluster determines the SQL syntax used for a given task. The value specified for this attribute is either the name of a class that implements net.sf.hajdbc.Dialect (custom implementations are allowed), or, more conveniently, a pre-defined, case-insensitive alias.

The HA-JDBC distribution contains the following dialect implementations:
Vendor(s) Dialect Alias
Apache Derby net.sf.hajdbc.dialect.DerbyDialect derby
Firebird, InterBase net.sf.hajdbc.dialect.FirebirdDialect firebird
H2 net.sf.hajdbc.dialect.H2Dialect h2
HSQLDB net.sf.hajdbc.dialect.HSQLDBDialect hsqldb
IBM DB2 net.sf.hajdbc.dialect.DB2Dialect db2
Ingres net.sf.hajdbc.dialect.IngresDialect ingres
Mckoi net.sf.hajdbc.dialect.MckoiDialect mckoi
MySQL net.sf.hajdbc.dialect.MySQLDialect mysql
MySQL MaxDB net.sf.hajdbc.dialect.MaxDBDialect maxdb
Oracle net.sf.hajdbc.dialect.OracleDialect oracle
PostgreSQL net.sf.hajdbc.dialect.PostgreSQLDialect postgresql
Sybase net.sf.hajdbc.dialect.SybaseDialect sybase
Standard (SQL-92 compliant) net.sf.hajdbc.dialect.StandardDialect standard
Dialect contributions are more than welcome. Please submit any additions/updates here.
Balancer

When executing a read request from the cluster, HA-JDBC uses the configured balancer strategy to determine which database should service the request. Each database can define a weight to affect how it is prioritized by the balancer. If no weight is specified for a given database, it is assumed to be 1.

HA-JDBC supports four types of balancers:

simple
Requests are always sent to the node with the highest weight.
random
Requests are sent to a random node. Node weights affect the probability that a given node will be chosen. The probability that a node will be chosen = weight / total-weight.
round-robin
Requests are sent to each node in succession. A node of weight n will receive n requests before the balancer moves on to the next node.
load
Requests are sent to the node with the smallest load. Node weights affect the calculated load of a given node. The load of a node = concurrent-requests / weight.
In general, a node with a weight of 0 will never service a request unless it is the last node in the cluster.
Synchronization Strategy

Synchronization is performed before a database node is activated.

HA-JDBC provides several out-of-the-box database independent strategies for synchronizing a failed database:

net.sf.hajdbc.sync.FullSynchronizationStrategy
Each table in the inactive database is truncated and data is reinserted from an active database. This strategy is fastest if the database is way out of sync.
net.sf.hajdbc.sync.DifferentialSynchronizationStrategy
For each table in the inactive database is compared, row by row, with an active database and only changes are updated. This strategy is fastest if the database is more in sync than not.
net.sf.hajdbc.sync.PassiveSynchronizationStrategy
Does nothing. Should only be used if databases are known to be in sync.

Each synchronization strategy must be defined in the HA-JDBC configuration file. A strategy may contain any number of JavaBean properties that can be set in the config file.

e.g.

1000 100 1000 100 ]]>

Although the build-in strategies should be sufficient for most small databases, they are probably not feasible for large databases. Synchronizing a large database will typically require vendor specific functionality. Custom synchronization strategies may be written by implementing the net.sf.hajdbc.SynchronizationStrategy interface or by extending the functionality of one of the existing strategies. For example, I may want to improve the efficiency of the FullSynchronizationStrategy by dropping and re-creating indexes on my database tables.

e.g.

Any custom strategies that you plan to use should also be defined in the configuration file.

Using HA-JDBC
DriverManager-based Access

Just like your database's JDBC driver, the HA-JDBC driver must first be loaded. As of Java 1.6, the DriverManager uses the service provider mechanism to auto-load JDBC drivers on startup. Java versions prior to 1.6 must load the HA-JDBC driver manually. This can be accomplished in one of two ways:

  • Add net.sf.hajdbc.sql.Driver to your jdbc.drivers system property.

    The JVM will automatically load and register each driver upon startup.

  • Explicitly load the net.sf.hajdbc.sql.Driver class using Class.forName(...).

    Per the JDBC specification, loading the HA-JDBC driver class automatically registers the driver with the DriverManager. The HA-JDBC driver will automatically load all underlying JDBC drivers defined within a given cluster. This means that you do not need to perform an additional Class.forName(...) to load your database's driver.

e.g.

The following is a sample HA-JDBC configuration that uses the DriverManager facility to obtain connections.

org.postgresql.Driver jdbc:postgresql://server1/database postgres password org.postgresql.Driver jdbc:postgresql://server2/database postgres password ]]>

The URL specified in subsequent calls to DriverManager.getConnection(...) has the following format:

jdbc:ha-jdbc:cluster-id

e.g.

The following is a sample Tomcat configuration that sets up a connection pool for the above HA-JDBC database cluster.

server.xml

]]>

web.xml

jdbc/cluster javax.sql.DataSource ]]>

Pooled connections to the HA-JDBC cluster are now available via a DataSource at java:comp/env/jdbc/cluster.

DataSource-based Access

An HA-JDBC cluster can also wrap one or more DataSources.

Connections are made to the HA-JDBC cluster via the following code:

You can define underlying data sources either by JNDI names to which they are already bound, or explicitly in your configuration file.

JNDI-based Configuration

e.g.

The following is a sample HA-JDBC configuration that uses JNDI-bound DataSource facilities to obtain connections.

java:comp/env/jdbc/database1 java:comp/env/jdbc/database2 ]]>

The corresponding Tomcat configuration might look like the following:

server.xml:

]]>

web.xml:

jdbc/database1 javax.sql.DataSource jdbc/database2 javax.sql.DataSource jdbc/cluster javax.sql.DataSource ]]>
Explicit Configuration

e.g.

The following is a sample HA-JDBC configuration that uses explicitly defines DataSource facilities to obtain connections. This setup has the advantage of not exposing underlying data sources to your application and is less verbose.

org.postgresql.ds.PGSimpleDataSource server1 5432 database org.postgresql.ds.PGSimpleDataSource server2 5432 database ]]>

The corresponding Tomcat configuration might look like the following:

server.xml:

]]>

web.xml:

jdbc/cluster javax.sql.DataSource ]]>
XADataSource-based access

An HA-JDBC cluster can also wrap one or more XADataSources. You can define underlying data sources either by JNDI names to which they are already bound, or explicitly in your configuration file.

Typically, when configuring an XADataSource for your application server, only the DataSource exposed to the application is bound to JNDI, not the XADataSource itself. It is crucial that you configure HA-JDBC to proxy the XADataSource, and NOT the application-facing DataSource directly. HA-JDBC must be able to detect the boundaries of a transaction, which, in the case of distributed transactions, are visible to the XAConnections created by the XADataSource, but not the Connections created by the application facing DataSource.

e.g.

The following is a sample HA-JDBC configuration that uses explicitly defines XADataSource facilities to obtain connections.

org.postgresql.xa.PGXADataSource host1  5432  mydatabase org.postgresql.xa.PGXADataSource host1  5432  mydatabase ]]>

The corresponding JBoss configuration might look like the following:

haDS net.sf.hajdbc.xa.XADataSource mycluster ]]>

Connections are made to the HA-JDBC cluster via the following code:

Unique identifier generation

As of version 2.0, HA-JDBC now supports database sequences and identity (i.e. auto-incrementing) columns.

It is important to note the performance implications when using sequences and/or identity columns in conjunction with HA-JDBC. Both algorithms introduce per statement regular expression matching and mutex costs in HA-JDBC, the latter being particularly costly for distributed environments. Because of their performance impact, support for both sequences and identity columns can be disabled via the detect-sequences and detect-identity-columns cluster attributes, respectively. Fortunately, the performance penalty for sequences can be mitigated via what Hibernate calls a Sequence-HiLo algorithm.

For best performance, HA-JDBC recommends using a table-based high-low or UUID algorithm so that statement parsing and locking costs can be avoided. Object-relation mapping (ORM) frameworks (e.g. Hibernate, OJB, Cayenne) typically include implementations of these mechanisms.

Failed Database Nodes

A database node may fail for any number of reasons:

  • Network outage
  • Hardware failure
  • Operating System crash
  • Database application crash
  • Out of disk space
  • No more free connections
  • etc.

Failed database nodes are detected after an SQLException is thrown when executing a given database operation. A database is determined to have failed if it fails to respond to a trivial query (e.g. SELECT 1). The query used to validate that a database is alive is defined by the configured dialect.

This query may be executed manually, via the isAlive(String) method on the management interface.

If HA-JDBC determines that a given database has failed:

  1. An ERROR message is logged.
  2. The database is removed from the internal registry of active databases. No more requests will be sent to this database.
  3. If the cluster was configured to be distributable, other servers are notified of the deactivation.

Databases can also be manually deactivated via the JMX management interface.

Optionally, you can configure HA-JDBC to proactively detect database failures via the failure-detect-schedule attribute. The value of this attribute defines a cron expression, which specifies the schedule a database cluster will detect failed databases and deactivate them.

e.g.

]]>
Database Cluster Administration

HA-JDBC database clusters are administered via one of two JMX interfaces:

Most of the management operations are defined the common super interface, net.sf.hajdbc.DatabaseClusterMBean.

A database cluster mbean is registered using the following object-name:

net.sf.ha-jdbc:cluster=database-cluster-id

JMX operations can be executed from the JConsole interface packaged with JDK 1.5+.

As an alternative to JConsole (namely, for Java 1.4 deployments), you can use any of several 3rd-party JMX clients:

HA-JDBC database clusters may also be administered programatically:

e.g.

Activating a Database

Database nodes are activated by executing one of the following methods on the database cluster mbean:

activate(String databaseId)
Synchronizes, using the default synchronization strategy, and activates the specified database.
activate(String databaseId, String strategyId)
Synchronizes, using the specified synchronization strategy, and activates the specified database.

In general, database synchronization is an intensive and intrusive task. To maintain database consistency, each database node in the cluster is read locked (i.e. writes are blocked) until synchronization completes. Since synchronization may take anywhere from seconds to hours (depending on the size of your database and synchronization strategy employed), if your database cluster is used in a high write volume environment, it is recommended that activation only be performed during off-peak hours.

As of version 1.1, HA-JDBC includes a useful database cluster option: "auto-activate-schedule". If specified, HA-JDBC will automatically attempt to activate database nodes that are inactive, but alive, according to the specified cron schedule.

e.g.

]]> In distributable mode, listening servers are automatically notified of any activated databases.
Deactivating a Database

There are a number of reasons why you might want to deactivate a database node manually - most commonly, to perform some maintenance on the database or the machine itself. Database nodes are deactivated by executing the following method on the database cluster mbean:

deactivate(String databaseId)
Deactivates the specified database.
In distributable mode, listening servers are automatically notified of any deactivated databases.
Adding a Database

In HA-JDBC 1.0, the database nodes in a cluster were static. They could not be altered while the application/server was running.

As of HA-JDBC 1.1, database nodes can be added, updated, or removed during runtime.

net.sf.hajdbc.sql.DriverDatabaseClusterMBean:

net.sf.hajdbc.sql.DataSourceDatabaseClusterMBean:

When a new database is added, it is initially inactive. Database nodes may also be removed from the cluster. A database node must first be inactive before it can be removed.

HA-JDBC 1.1 also adds mbean interfaces for individual database nodes:

Database mbeans are registered using the following object-name:

net.sf.ha-jdbc:cluster=cluster-id,database=database-id

While inactive, a database node's connection properties (e.g. user, password, etc.) may be modified. When active, a database node's connection properties are read-only.

When a database node is activated and it's configuration has changed, or when a database node is removed, the configuration is saved to it's original URL.

In distributable mode, listening servers are not notified of database node additions, updates, and removals. These cluster modifications must be made on each server.
Limitations
  • HA-JDBC does not safely support stored procedures that update sequences or insert rows containing identity columns.
Migrating from HA-JDBC 1.1
Environment
  • HA-JDBC is now compatible with JDBC 4.0 found in Java 1.6.
  • HA-JDBC now supports sequences and identity columns. Users should be aware of the performance implications of these mechanisms.
  • HA-JDBC now fully supports large objects implemented as SQL locators.
Configuration
  • Prior to version 2.0, the ha-jdbc.xml file could contain many ]]>s distinguished by an id attribute. As of version 2.0, each cluster is defined in its own XML file, named according to the pattern: ha-jdbc-{0}.xml.
  • The ]]> element no longer defines an id attribute.
  • The transaction-mode="parallel|serial" attribute replaces the transactions="local|xa" attribute of ]]>
  • New required meta-data-cache="none|lazy|eager" cluster attribute.
  • ]]> mode now uses JGroups channel multiplexing. The old protocol attribute is superceded by the new config and stack attributes.
  • dialect="default" is renamed dialect="standard".
  • Clusters of Firebird, Mckoi, or Ingres databases should use the respective dialects, instead of the standard dialect.
JMX
  • HA-JDBC no longer quotes identifiers when constructing the names for cluster and database mbeans.
ha-jdbc-2.0.16+rc1/doc/src/skinconf.xml0000644000175000017500000004460011151703035017321 0ustar moellermoeller true false true true true true false true .at. true HA-JDBC High-Availability JDBC http://ha-jdbc.sourceforge.net/ images/project.png SourceForge.net http://sourceforge.net http://sourceforge.net/sflogo.php?group_id=111957&type=5 http://sourceforge.net/images/favicon.ico false 2004 Paul Ferraro http://www.gnu.org/licenses/lgpl.txt Send feedback about the website to: p.quote { margin-left: 2em; padding: .5em; background-color: #f0f0f0; font-family: monospace; } #footer a { color: #0F3660; } #footer a:visited { color: #009999; } Page 1 1in 1in 1.25in 1in false false Support This Project http://sourceforge.net/donate/index.php?group_id=111957 http://images.sourceforge.net/images/project-support.jpg Open Source http://www.opensource.org/ http://opensource.org/trademarks/open_source_button.png java.net member http://www.java.net http://today.java.net/images/javanet_button_90.gif Built with Apache Forrest http://forrest.apache.org/ images/built-with-forrest-button.png 88 31 ha-jdbc-2.0.16+rc1/doc/src/status.xml0000644000175000017500000021610111217570147017040 0ustar moellermoeller Fixed NullPointerException in PreparedStatement.set/ResultSet.update stream/reader/blob/clob methods, if called with null value. Only consider hashed unique indexes when finding unique constraints. Ensure unique constraint columns are quoted, if necessary. Fix memory leak caused by batch method recording when using PreparedStatement pooling. Optimize recording of ResultSet navigation and update methods. Fix recording of CallableStatement.registerOutParameter(...) methods. Fix differential sync strategy breakage when a table contains only primary key columns. Determine column meta data from ResultSetMetaData instead of DatabaseMetaData.getColumns(...). This avoids the need for dialect specific IDENTITY column detection logic. Fixed StandardDialect.getIdentifierPattern(DatabaseMetaData) to require that identifiers begin with a letter. Upgraded JGroups to 2.6.10. Upgraded JiBX to 1.2.1. Upgraded Quartz to 1.6.5. Upgraded SLF4J to 1.5.7. Upgraded EasyMock to 2.5.1. Upgraded TestNG to 5.9. Fixes infinite loop regression in DistributableLockManager$DistributableLock.tryLock(long, TimeUnit) Fixes ExceptionInInitializerError regression when creating HA-JDBC connections in Java 1.4/1.5. Fixed parsing of local attribute of database, datasource, etc. Upgraded JiBX to 1.1.6a. Upgraded SLF4J to 1.5.6. Upgraded Retrotranslator to 1.2.8. Upgraded JGroups to 2.6.7. Upgraded Quartz to 1.6.4. Upgraded EasyMock to 2.4. Remove file list items during FileSupport.close() - rather than wait for finalization. FileSupport is no longer used for large object support and is now created/destroyed per statement, rather than per connection. This helps mitigate temp file build-up. Removed references to javax.sql.CommonDataSource - this broke binary compatibility with Java 1.4/1.5 for datasource configurations. Fixed java 1.4 binary incompatibility with Boolean (does not yet implement Comparable) not handled by Retrotranslator. Restore autoCommit mode to its original value at the end of synchronize(...) in each strategy. Fixed regression in lazy/none meta-data-cache that broke synchronization. Fixed misleading Spanish, French, Italian, and Portuguese translation of config-not-found message. Store child proxies using weak references to fix potential memory leak if proxy is not closed. Remote locks in DistributableLockManager now respect lock fairness. Startup will now also consult ha-jdbc.{0}.configuration system property when searching for configuration file. Add HA proxying of DatabaseMetaData interface. Added net.sf.hajdbc.util.servlet.DatabaseClusterShutdownContextListener to automatically shutdown a list of database clusters scoped to a servlet context. The clusters to shutdown are defined in a comma delimited init parameter: ha-jdbc.clusters Fixed SybaseDialect.getSimpleSQL() to query for GETDATE(). Added event handler support for activation, deactivation, and synchronization events. Clients can opt to be notified of such events by registering themselves as handlers using the appropriate methods on the database cluster mbean. Fixed close() methods of Connection, Statement, and ResultSet proxies to use driver (instead of database) write invocation strategy to prevent unnecessary creation of SQL objects (potentially triggering query execution) just to be closed. Fixed exception handling in FullSynchronizationStrategy. Exceptions wrapped as SQLException were not getting re-thrown. Fixed logic in DatabaseMetaDataSupport.quote(String) to properly deal with identifier case. Fixed synchronization to allow schemas with auto-generated constraint names (i.e. constraint names are not uniform in all databases) to function properly when meta-data-cache="none". Fixed bug where statements created from read-only connections were not getting properly load balanced. Added explicit, Referenceable DataSource, ConnectionPoolDataSource, and XADataSource proxy implementations. The ]]> element of a , , or ]]> configuration can define a data source implementation class name. If the ]]> element is a class name, then the subsequent ]]> elements will be interpreted as property values of the data source (e.g. serverName, portNumber, databaseName). Added missing definitions for ]]> and ]]> to DTD and XSD. Calls to PreparedStatement.addBatch() were not being recorded and, consequently, not getting replayed when a new database is activated. Fixed AcquireLockDecree to use write locks, instead of a read locks, so that database activation will block transactions on remote nodes. Upgraded TestNG to 2.8. Fixed case normalization in DatabaseMetaDataSupport.normalize(String, String). Fixed NullPointerException using CallableStatement stream methods. Optimized Balancer implementations using copy-on-write concurrent collections. Eliminated some unnecessary runtime reflection. Fixed potential deadlock when synchronization is triggered while there are open transactions. Refactored statement read locking to lock and unlock at transaction boundaries. Removed obsoleted table locking in synchronization strategies. Added ConnectionPoolDataSource and XADataSource proxies, the latter required to detect distributed transaction boundaries. Added necessary ]]> and ]]> configuration file elements. Renamed net.sf.hajdbc.sql.DataSource to net.sf.hajdbc.DataSourceFactory. This should hopefully eliminate some confusion about its usage, as it is a javax.naming.spi.ObjectFactory and not a java.sql.DataSource implementation. Fixed Spanish translation of log messages. Added linked source to javadoc. Upgraded Retrotranslator to 1.2.6. Upgraded JGroups to 2.6.2. Upgraded SLF4J to 1.5.0. Replaced accidental use of Method.getTypeParameters() with intended Method.getParameterTypes() in AbstractInvocationHandler. This fixes bug where state changing methods were not recorded properly and subsequently not replayed correctly on newly activated databases. Fixed CronThreadPoolExecutor to work around potential inaccuracies in java.util.Date that could cause a task to be scheduled multiple times in a single cron interval. Connection.setReadOnly() should use DatabaseWriteInvocationStrategy instead of DriverWriteInvocationStrategy. Refactored invoker recording to support any JDBC method regardless of InvocationStrategy implementation. Fixed replay of PreparedStatement and CallableStatement set*() methods for a newly activated database. Cleanup logic in DatabaseWriteInvocationStrategy by splitting into TransactionalDatabaseWriteInvocationStrategy and NonTransactionalDatabaseWriteInvocationStrategy. Rollback TestNG to 5.6. Version 5.7 mysteriously skipped test methods. CallableStatement does not need to parse out sequences nor identity columns, nor detect SELECT...FOR UPDATE in SQL. Fixed broken test cases. In DatabaseWriteInvocationStrategy, acquire read locks before Balancer.all() so that a newly activated database will not miss any pending write statements. Upgraded JGroups to 2.6.1. Fixed infinite loop in CronThreadPoolExecutor when scheduled task throws an ExecutionException. Upgraded JGroups to 2.6.0. Added local="true|false" attribute to database/datasource. Cluster panic detection now consults this flag instead of weight to determine whether a database is local or remote. LocalLockManager now uses a custom semaphore-based ReadWriteLock implementation instead of ReentrantReadWriteLock. Removed obsolete DistributableLockAdapter hack. Optimized DistributableLockManager using RpcDispatcher instead VotingAdapter. Fixed deadlocking in DistributableLockManager when simultaneous voting occurs for he same resource from different peers. Upgraded Retrotranslator to 1.2.3. Upgraded TestNG to 5.7. Fixed exception handling during startup to prevent subsequent javax.management.InstanceAlreadyExistsExceptions if database cluster fails to start. Fixed potential deadlocking sources and improved cpu friendliness of DistributableLockManger. Fixed bug in Dialect.getAlterSequenceSQL(...) and Dialect.getAlterIdentityColumnSQL(...) causing values > 999 to get formatted with grouping separators. Added "cluster panic" detection to prevent asymmetric database deactivation during a network fragmentation when in distributable mode where databases are colocated on peer nodes. If HA-JDBC detects a cluster panic, the cluster is stopped. Manual intervention is required to resolve any consequent synchronization problems and to start the cluster. Removed obsolete JBoss jmx-console FAQ entry. Added look-ahead and to Dialect.evaluateCurrentTime() regular expression so that it does not match CURRENT_TIMESTAMP functions. Fixed NullPointerException regression in DistributableLockManager preventing database activation in distributable mode. Use new official JDK 1.4 backport of JGroups instead of retrotranslating our own. Upgraded JGroups to 2.5.1. Fixed infinite loop in DistributableLockManager while acquiring a lock when only one peer node is present. Fixed missing membership listener registration in DistributableLockManager preventing proper lock cleanup. Defer creation of connection factories until needed since DataSource creation relies on JNDI environment properties that may not yet be established. Added Dialect.getIdentifierPattern(...) method to work around buggy DatabaseMetaData.getExtraNameCharacters() in PostgreSQL driver since version 8.1. Bug causes unexpected failures during identity column detection when schema or table name contains non-standard characters. Optimized StandardDialect.getDefaultSchemas() by replacing separate CURRENT_USER query with DatabaseMetaData.getUserName(). Fixed example Tomcat DataSource configuration. Fixed currentTimestampFunction() method of MaxDBDialect. Created separate OracleDialect, formerly an alias of MaxDBDialect. Created separate H2Dialect, formerly an alias of HSQLDBDialect. Added new dialect for Sybase. Added evaluateCurrentDate(String, java.sql.Date), evaluateCurrentTime(String, java.sql.Time), evaluateCurrentTimestamp(String, java.sql.Timestamp), and evaluateRandom(String) to Dialect interface to replace non-deterministic SQL functions (e.g. CURRENT_TIMESTAMP, RAND()) with deterministic static values. Added optional eval-current-date, eval-current-time, eval-current-timestamp, and eval-rand cluster attribute to enable these behaviors. Both sequence and identity column detection are no longer enabled by default. Removed supportsSequences() and supportsIdentityColumns() methods from Dialect interface. The corresponding parseSequence(String) and parseInsertTable(String) methods now return null for dialects that do not support these features. Fixed race condition in DistributableLockAdapter that may prevent a lock from being released. Upgraded SLF4J to 1.4.3. Added SynchronizationSupport.synchronizeIdentityColumns(...). Consequently, MySQL AUTO_INCREMENT columns are now fully supported. Added DatabaseProperties.getSequences() and TableProperties.getIdentityColumns() to meta data cache facility. LazyDatabaseMetaDataCache now caches DatabaseProperties using a SoftReference to prevent the cache from causing OutOfMemoryErrors. Refactored ThreadLocalDatabaseMetaDataCache to NullDatabaseMetaDataCache which no long stores its DatabaseProperties instance in a ThreadLocal since this can inadvertently act like a lazy cache if application threads are pooled. Replaced SynchronizationContext.getDatabaseMetaDataCache() with SynchronizationContext.getDatabaseProperties() so that meta data used during synchronization is still cached for the lifetime of the SynchronizationContext, regardless of cache implementation. Re-implemented BalancerFactory, DialectFactory, and DatabaseMetaDataCacheFactory using enums. In DatabaseMetaDataSupport.normalize(...), adjust case of table to match the way identifiers are stored in the database. In DatabaseMetaDataSupport.quote(...), normalize identifiers to lower case if database is case-insensitive, yet stores identifiers in mixed case. Fixed all benign compiler warnings reported by Eclipse. Migrated simple string constants to Strings. Optimized failure handling in DatabaseWriteInvocationStrategy. Optimized thread synchronization in DistributableLockAdapter. Upgraded EasyMock to 2.3. Upgraded SLF4J to 1.4.2. Upgraded JGroups to 2.5 GA. Revised documentation. In distributable mode, try to retrieve initial state from any remote node, not just "coordinator". Fixed deadlocking during activation/deactivation in distributable mode caused by redundant secondary notifications. In distributable mode, do not send activation notifications to other nodes during cluster startup. In distributable mode, do not respond to initial state queries until cluster startup is complete. Upgraded SLF4J to 1.4.1. FailureDetectionTask and SQLProxy.handleFailure() will not deactivate any databases if they all appear to be dead. Convert dynamic Class.cast() and Class.isInstance() to static cast and instanceof expressions wherever possible. Fixed bug during initialization where databases are added as dirty, triggering export of configuration file. When adding a database to the cluster, perform duplicate id check before registering database to avoid InstanceAlreadyExistsException. Fixed broken error message when attempting to remove a database that is still active. Added toString() to DatabaseClusterMBean interface so that log messages will display cluster id properly. Fixed IllegalAccessError in JiBX marshalling during configuration export.n Removed Retrotranslator plugin for java.lang.management.ManagementFactory. This is now natively supported by Retrotranslator. Upgraded Retrotranslator to 1.2.2. Fixed memory leak with CONCUR_READ_ONLY result sets when using ResultSet.getStatement().close(). Removed problematic singleton references to database clusters in DatabaseClusterFactory. Require separate XML config file per database cluster. Consolidated database-cluster and datasource cluster elements into single cluster element, as in 1.1. Removed id attribute from cluster element. Modified configuration locator logic to first check driver connection properties or datasource config property for resource URL. Default resource name is now ha-jdbc-{0}.xml, where {0} is the cluster id. Added test for UnsupportedOperationException thrown when Quartz cron expression uses both day-of-week and day-of-month values. If a group member leaves, any distributed locks it held must be freed. DistributableLockManager uses default vote response processor instead of its own implementation. Removed quoting of cluster ID and database ID in mbean ObjectName. JBoss users no longer need to patiently wait for this long standing jmx-console bug to be fixed. Fixed NoSuchElementException thrown during database activation when there are no active databases. Fixed IllegalMonitorStateExceptions in DistributableLockManager resulting from improper use of reentrant locks by multiple threads. Optimized DistributableLockManager using a single phase VotingAdapter. Re-implemented DistributableStateManager to use synchronous MessageDispatcher instead of asynchronous NotificationBus. This will ensure that all nodes are notified of database activation prior to unlocking database tables during synchronization. Changed default jgroups protocol stack to "udp-sync". Do not auto-deactivate the last database of a cluster. JGroups 2.5 uses Java 1.5 as a baseline, so retrotranslate this jar as part of 1.4 build. Modified build to produce 3 different binary distributions, for Java 1.4, 1.5, and 1.6. Upgraded SLF4J to 1.4.0. Upgraded JiBX to 1.1.5. Upgraded JGroups to 2.5.0-cr1. Upgraded TestNG to 5.6. Optimized PostgreSQLDialect.getLockTableSQL() by removing unnecessary select statement. Removed JVM shutdown hook since it may prevent proper shutdown of a server-managed connection pool. Fixed NullPointerException accessing meta data if database does not support schemas. Refactored Balancer.list() to return a set to better reflect balancer semantics. Refactored DatabaseClusterMBean interface into DriverDatabaseClusterMBean and DataSourceDatabaseClusterMBean. LocalDatabaseCluster refactored into generic AbstractDatabaseCluster. Replaced <cluster> element in DTD with <database-cluster> and <datasource-cluster>. Created StateManager to encapsulate management of database cluster state. Distributable functionality no longer added via inheritance, but through lock manager and state manager implementations. Created schema definition of HA-JDBC configuration as an alternative to DTD. Reimplemented core logic to use dynamic instead of explicit proxies, decoupling HA-JDBC from a specific version of the JDBC API. Resulting jar is approximately half the size as before. Refactored SynchronousExecutor implementation to extend AbstractExecutorService since the ExecutorService interface in Java 1.6 is not compatible with that of 1.5. Java 1.6 adds auto-increment column identification to DatabaseMetaData.getColumns(). Added isAutoIncrement() to ColumnProperties interface populated only if this information exists. This value is now be consulted prior to querying the dialect to identify identity columns. Fixed regular expressions in dialects to properly negotiate whitespace. Added support for JDBC 4.0 (i.e. Java 1.6). Added support for mutable LOBs. Added Java 1.6 service provider hook for HA-JDBC driver. Added max batch size property to differential synchronization strategy to help prevent out of memory errors when a table contains many changes. Use platform mbean server for cluster/database mbean registration. Provide retrotranslator plugin for java.lang.management.ManagementFactory that uses old logic to locate mbean server. Forced cleanup of open java.sql objects that were not accessed during an deactivate/reactivate cycle. Fixed german message transations. Upgraded JiBX to 1.1.3. Upgraded JGroups to 2.5.0-beta-2. concurrent-*.jar is now obsolete. Upgraded SLF4J to 1.3.1. Upgraded Retrotranslator to 1.2.1. Upgraded Woodstox to 3.2.1. Upgraded TestNG to 5.5. Added JDBC RowSet API to Java 1.4 runtime dependencies. Updated documentation to use Forrest 0.8. Fixed sequence synchronization logic to use next value instead of current value since it may be undefined. Refactored SynchronizationStrategy interface into distinct prepare (e.g. lock), synchronize, and cleanup (e.g. unlock) stages. Created SynchronizationContext to simplify SynchronizationStrategy interface methods. Refactored CronExecutorService to use CronExpression instead of CronTrigger. Changed default distributable stack to "udp". Disabled support for identity columns in MySQL dialect. MySQL's implementation has no mechanism to synchronize auto-increment counter. Upgraded JGroups to 2.4 GA (final). Upgraded Retrotranslator to 1.1.0. Upgraded Quartz to 1.6.0. Upgraded Woodstox to 3.1.0. Upgraded SLF4J to 1.1.0 RC1. Upgraded TestNG to 5.3. Added support for identity columns. Added new cluster attributes "detect-sequences" and "detect-identity-columns". Added dialect implementations for Ingres and Mckoi. Upgraded Woodstox to 3.0.2. Fixed PostgreSQL Blob/Clob handling in differential and full synchronization strategies when large objects require updating. Refactored DefaultDialect to StandardDialect and renamed dialect alias from "default" to "standard". Upgraded TestNG to 5.2. Fixed binding compilation error that only seemed to affect windows users. Fixed mbean registration race condition during startup in distributable mode. Upgraded JGroups to 2.4-cr-2. Upgraded Woodstox to 3.0.1. Upgraded TestNG to 5.1. Force cleanup of underlying connections, statements, and result sets when a database is deactivated. Log cause of DatabaseCluster.isAlive(Database) failures. Fixed bug in DatabaseMetaDataSupport.getForeignKeyConstraints() causing method to always return an empty collection. Fixed bug in PostgreSQLDialect.getSequences(...) causing method to fail to when database does not contain any sequences. Fixed bug in DifferentialSynchronizationStrategy where generated select statements had duplicated columns. Extracted interfaces from ColumnProperties, ForeignKeyConstraint, and UniqueConstraint. Implementations refactored into net.sf.hajdbc.cache package. Added long needed unit tests for each synchronization strategy. Upgraded JGroups to 2.4-cr-1. Upgraded Retrotranslator to 1.0.8. Fixed bugs in MySQLDialect related to generating SQL for creating and dropping foreign keys and unique constraints. Upgraded TestNG to 5.0.1. Upgraded Woodstox to 3.0.0. Fixed premature quoting of schema and tables in DatabaseMetaDataCacheSupport. Fixed NullPointerException in ThreadLocalDatabaseMetaDataCache. Fixed bug in SimpleBalancer where a database deactivation would trigger the deactivation of other databases of identical weight. Upgraded Retrotranslator to version 1.0.7. Upgraded JiBX to version 1.1. Replaced XMLPull runtime library with StAX API + Woodstox implementation. Upgraded JGroups to version 2.3-sp1. Upgraded SLF4J to version 1.0.2. Upgraded Quartz to version 1.5.2. Upgraded EasyMock to version 2.2. Upgraded TestNG to version 5.0. Fixed create/drop constraint methods of DefaultDialect to quote constraint names. Modified Dialect interface to leverage ForeignKeyConstraint and UniqueConstraint objects to encapsulate constraint details. Fixed DefaultDialect to correctly generate create foreign key statements for foreign keys containing multiple columns, ON DELETE/UPDATE actions, and deferrability. Created dialects for MySQL and Firebird. DerbyDialect, HSQLDBDialect, MaxDBDialect now override createForeignKeySQL(). Fixed synchronization of PostgreSQL tables containing Blob (oid) columns. Modified differential synchronization strategy to use UPDATE statements instead of using updatable ResultSet, due to poor driver support. e.g. ResultSet.updateBlob(...) is not implemented in PostgreSQL driver. Added DatabaseMetaData caching. New meta-data-cache attribute of cluster. Options are eager, lazy, or none. Modified Dialect and SynchronizationStrategy interfaces to use DatabaseMetaDataCache objects. Refactored Dialect interface with much simpler method signatures. Leverages JGroups 2.3 multiplexing so that notification bus and distributable lock manager share the same channel. No more "discarded message from different group..." warnings in logs! "protocol" attribute of "distributable" element in DTD is replaced by "config" and "stack" attributes. Default for "config" is "stacks.xml" from JGroups distribution. Default for "stack" is "fc-fast-minimalthreads". Moved mbean registration to DatabaseCluster.start() and added mbean unregistration to DatabaseCluster.stop(). HA-JDBC initialization failures will no longer leave stray registered mbeans. Replaced simple read-write locking with named read-write locking encapsulated by a LockManager. Added support for sequences. Refactored unit tests so that test classes implement subject interfaces. Fixed non-default charset handling of Clobs. Ensure that causes of initialization failures are logged. Fixed IllegalArgumentException during startup when using transactions="xa". Fixed NullPointerException during startup when database does not define a driver. Fixed CronExecutorService to use daemon threads so that it doesn't prevent the shutdown hook from firing. Upgraded Retrotranslator to version 1.0.3. Fixed Blob/Clob handling in PreparedStatement.setBlob(...)/setBlob(...) and ResultSet.updateBlob(...)/updateClob(...) methods. Fixed bug in DefaultDialect.qualifyTable(...) for databases that do not support schemas. Added new required transactions="local|xa" option to cluster. When in local mode, database writes are performed concurrently. When in xa mode, database writes are performed synchronously to ensure a predictable execution order and prevent deadlocks. Added fault tolerance measures to cluster thread pool under high load. If pool size reaches max-threads threshold, database writes will be executed in the caller thread using java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy. Upgraded TestNG to 4.7. Added auto-activate-period cluster option that will auto-activate failed database nodes at a configurable interval. New dependency on Quartz (http://opensymphony.com/quartz/). Created CronThreadPoolExecutor, a java.util.concurrent.ThreadPoolExecutor that leverages a Quartz CronTrigger to calculate future execution times of a scheduled task. Enhanced auto-activation and failure detection to use a cron schedule, instead of a simple fixed-delay period. Renamed failure-detect-period to failure-detect-schedule and auto-activate-period to auto-activate-schedule in DTD. Migrated repository to Subversion. Migrated test suite to TestNG. Migrated logging facade from commons-logging to SLF4J. New dependency on SLF4J (http://slf4j.org). Upgraded Retrotranslator to version 1.0.1. Replaced commons-logging-1.0.4.jar with jcl104-over-slf4j.jar from SLF4J distribution. Added management interface methods for adding and removing databases from a cluster. Separated DatabaseMBean interface into InactiveDatabaseMBean (read-write) and ActiveDatabaseMBean (read-only). Activating/Deactivating database reregisters the database using the appropriate active/inactive mbean interface. Added dirty flag logic for Database attributes. If a database is dirty when it is activated, then the HA-JDBC configuration is exported. Renamed "name" property of DataSource to "cluster", since "name" cannot be set by the BeanFactory from Tomcat's server.xml file. Revised main documentation. Added more FAQs. Added workaround for missing ReentrantReadWriteLock(boolean) constructor in backport-util-concurrent package. Added verify flag to retrotranslator compilation to catch future Java 1.4 compatibility issues. Rollback change to PostgreSQL dialect. Removed batching of lock table commands. Database activation uses Lock.lockInterruptibly() instead of Lock.tryLock() to prevent activation from failing due to concurrent writes. Fixed getLockTableSQL() from PostgreSQL dialect so that it can be executed within a batch. Upgraded Retrotranslator to version 0.9.8. Added optional failure-detect-period to configuration file. If defined, HA-JDBC will proactively detect database failures every specified number of seconds. Replace DatabaseCluster.init() with start() and stop() methods. Added JVM shutdown hook that calls stop() on each DatabaseCluster. Derby dialect overrides getLockTableSQL(). Refactored DistributableDatabaseCluster to extend LocalDatabaseCluster rather than contain/decorate it. Refactored JiBX configuration to support both input and output binding directions. Removed configuration related methods from SynchronizationStrategy interface removing the need for AbstractSynchronizationStrategy. Implemented distributable read-write locking so that database writes are locked during database activation. This eliminates the need to deactivate databases that were newly actived upon completion of a database write. Added mbean interfaces for Databases. Changed exceptions thrown by DatabaseClusterMBean methods to built-in Java exceptions so that they can be interpretted by a remote JMX client. Added distributable locking to prevent multiple simultaneous synchronizations on the same cluster. Added configurable timeout attribute to DTD for distributable operations. Moved SELECT ... FOR UPDATE pattern definition to dialect. Fixed IndexOutOfBoundsException during database activation when one or more databases in the cluster is not alive. Upgraded JiBX to version 1.0.1. Upgraded JGroups to version 2.2.9.1. Recorded Operations are stored in a Map keyed by class instead of a List to prevent unnecessary boundless growth. DifferentialSynchronizationStrategy generates bad DELETE statements when table has multiple primary keys. Fixes german error message translations. DatabaseClusterFactory.createDatabaseClusterFactory() throws RuntimeException instead of SQLException to prevent java.sql.DriverManager from masking root cause of HA-JDBC configuration failures. Fixes potential NullPointerException if database is deactivated as a result of a read operation. Migrated code base to Java 1.5. Retrotranslator (http://retrotranslator.sf.net) leveraged for JDK 1.4 compatibility. Build script generates separate 1.4 jar and includes additional dependencies. Replaced Balancer.toArray() : Database[] with Balancer.list() : List]]> Unit tests now use EasyMock 2.0. Added requiresTableLocking() method to SynchronizationStrategy interface. During database activation, table locking is only performed if required by synchronization strategy. All vendor specific customizations to HA-JDBC are now encompassed in the Dialect attribute of a cluster. This replaces the validate-sql attribute of a cluster; and the truncateTableSQL, createForeignKeySQL, dropForeignKeySQL, createUniqueKeySQL, and dropUniqueKeySQL properties of the diff and full synchronization strategies. Created dialects for PostgreSQL, MaxDB, Derby, HSQLDB, and a default dialect. Changed default table locking query used during synchronization to use an innocuous UPDATE statement. Added more explicit logging for exceptions thrown during HA-JDBC initialization that end up getting masked by JiBX. Added missing rollback to exception handling in diff and full synchronization strategies. In distributable mode, JGroups channel and protocols are registed with the mbean server. Removed obsolete net.sf.hajdbc.sql.pool.xa and net.sf.hajdbc.sql.pool packages. New dependency on JDK 1.4 backport of JDK 1.5 java.util.concurrent package. Uses configurable thread pooling for asynchronously executed write operations for improved efficiency and fault tolerance under high load. Uses default-minimalthreads.xml from JGroups distribution as default distributable protocol. Synchronization strategies now use schema qualified table names when appropriate. Upgraded JGroups to version 2.2.9. Fixed problematic co-dependency between DatabaseCluster and ConnectionFactory. Fixed JDK 1.4 source compatibility issues. Added explicit logging to expose root causes of exceptions that are hidden by JiBX. Added FAQ section for manually deleting local cluster state. Added FAQ section for distinguishing application database users vs. HA-JDBC database users. Upgraded EasyMock to version 1.2. During DatabaseClusterFactory initialization, if no mbean server can be found, an exception is thrown, rather than attempting to create a new one. Quote all identifiers used in synchronization to prevent SQL syntax errors in identifier is a reserved word. Correct error message when connection to config url fails. Avoid wrapping SQLException cause when a database operation fails. Added FAQ section for running HA-JDBC under Tomcat 5.0. Fixed readProperties() and writeProperties(...) methods of AbstractSynchronizationStrategy to ignore the property "class". Reintroduced PassiveSynchronizationStrategy. Added logic to LocalDatabaseCluster.loadState() to validate locally persisted cluster state. Fixed NullPointerException bug in LocalDatabaseCluster.loadState(). Distributable database activation commands should not reinvoke synchronization. SELECT...FOR UPDATE queries are now detected and distributed to each database cluster node. Corrected German translation of error messages. Fixed infinite loop in AbstractSynchronizationStrategy.getProperties(). Fixed bug in LocalDatabaseCluster.loadState() when cluster is empty. Refactored HA-JDBC initialization and DTD. Synchronization strategies are now shared across all clusters. Each cluster defines a default synchronization strategy. Added properties to cluster configuration to allow DataSources to define custom JNDI environment parameters and to allow Driver to define additional runtime parameters. Changed default JGroups protocol stack to use FD instead of FD_SOCK. activate(String) method in DatabaseClusterMBean interface will synchronize using the default synchronization strategy for the cluster. Removed getSynchronizationStrategies() from DatabaseClusterMBean interface. Fixed ClassCastException during XADataSource initialization. SQLException wrapper properly reports vendor-specific error code and SQL state. Updated DifferentialSynchronizationStrategy to use PreparedStatements for inserts and deletions instead of using problematic updatable result set methods. Fixed DifferentialSynchronizationStrategy to drop and re-create unique keys on each table to prevent possible unique constraint violations during sync. DifferentialSynchronizationStrategy now correctly compares byte[] columns. Migrated unit tests from TestNG to JUnit in order to utilize EasyMock. Added unit tests for net.sf.hajdbc.sql package. Upgraded Forrest documentation to version 0.7. Upgraded JGroups to version 2.2.8. Upgraded JiBX to version 1.0-rc-1. Cluster state is now persisted locally so that it can be restored between application restarts. Added customizable fetchSize property to each synchronization strategy to avoid out of memory errors when synchronizing large tables. Added TestNG unit tests for Driver, Connection, Statement, and each balancer implementation. Fixed issue with driver returning non-distributable connections when in distributable mode. Fixed issue in DifferentialSynchronizationStrategy with some updatable result set implementations where inserted rows were deleted again. Fixed ClassCastException in Connection.releaseSavepoint(Savepoint) and Connection.rollback(Savepoint) methods. Minor fixes to zero weight handling in random and load balancers. Corrected German translation of error messages. executeWriteToDatabase() will now throw SQLException for Statements and ResultSets if some valid databases fail while others succeed and auto-commit is off, giving the client the opportunity to rollback the current transaction. Connection.isReadOnly() was changed from executeReadFromDatabase() to executeReadFromDriver(). Refactored java.sql.* proxy classes. Upgraded JiBX to version 1.0-rc-0. Fixed buggy weighted round-robin algorithm. Round-robin balancer now handles databases with 0 weight properly. Database cluster now specifies 1 of 4 different strategies for balancing read requests: simple, random, round-robin, or load. A database can define a weight to affect how it is prioritized by the balancer. In distributed environment, a database cluster will get its initial state from the JGroups group coordinator. Fixed bug where auto (i.e. non-manual) database deactivation behaved locally even if environment is distributed. Fixed bug where synchronization strategies will fail if foreign key constraints have names that require quoting (e.g. $1, $2). Lots of refactored code. Most notably, the HA-JDBC driver has moved to net.sf.hajdbc.sql.Driver Protocol parameter is now optional for distributable clusters. Added error message translations for German, Spanish, French, Italian, and Portuguese. Added error message for tables without primary keys in DifferentialSynchronizationStrategy. Added better data type support for SynchronizationStrategy properties. Fixed Java 1.4 compatibility. getActiveDatabases() and getInactiveDatabases() no longer throw SQLException Configuration DTD updated: Synchronization strategies and properties are now explicitly defined per cluster. Added getSynchronizationStrategies() method to cluster management interface. Changed symantics of activate(...) methods on management interface: activate(String, String) uses synchronization strategy identifier instead of class name; activate(String) now activates a database without synchronizing. PassiveSynchronizationStrategy is obsolete. Use activate(String) instead. synchronize() method of SynchronizationStrategy interface no longer uses DatabaseClusterDescriptor. Fixed various bugs in documentation and javadoc. All log/exception messages are now localized. Driver is no longer required when defining a driver-based cluster since underlying driver already be registered via the jdbc.drivers system property. Fixed bug in SQLException when nested exception chain is already initialized. Added JMX interface to DatabaseCluster to allow administration of each cluster. Refactored cluster initialization and management. Distributable behavior implemented using command pattern. Restructured configuration DTD adding new synchronization-related cluster properties. Refactored distributable behavior to support activation. Added ability to activate a failed database. Created database synchronization strategies used during activation. Allow simple names for DriverManager-based database cluster. Enhanced large object support. Upgraded Forrest documentation to v0.6. Fixed bug in connection.rollback() Fixed logic in PreparedStatement/CallableStatement.setXXXStream() and ResultSet.updateXXXStream() methods Optimized asynchronous execution of write operations. Improved consistancy of cluster when autocommit is true. Upgraded JGroups to v2.2.7 Prevent multiple logging of database deactivation Configuration DTD is now PUBLIC Upgraded JGroups to v2.2.6 Fixed thread safety bug in SQLProxy.executeWrite() Changed license to LGPL, added license details to source code Removed obsolete RowSetProxy class, javax.sql.RowSet implementation are implicitly supported Refactored package names to reflect project name Replaced CHANGES.txt with this page Added ability specify location of configuration file using a system property Extended classpath search for configuration file to include system classpath Fixed DataSource proxy initialization DriverProxy now expects the cluster name to match the JDBC url Several refactorings affecting configuration dtd Fixed bug in clean target of ant build file Initial Release Add diff synchronization strategy alternative that leverages a last modified timestamp column. This will minimize data needed to be queried, as well as speed up row comparisons. Create a feasible synchronization strategy for large databases. I envision a buddy schema that intelligently records inserted/modified/deleted primary key values per table. Synchronization will only need to insert/update/delete the recorded rows. Add optional "protect-commit" mode that detects and recovers from partial commits incurred as a result of a node crash. Create distributable balancer implementation for round-robin and load. Allow distributable configurations to opt for local balancer implementations. Add more robust handling of jgroups partitions. Create integration test suite using H2 or some full-featured, highly standard compliant embedded database. Update performance graphs with results from latest version. Support for using HA-JDBC in conjunction with native database replication capabilities. HA-JDBC would add high-availability to cluster through multiple master support while hiding write-to-master/read-from-slave details from the application. Investigate the potential of SQLState codes as a replacement for secondary isAlive() queries when determining how to handle failures. Also consider using Connection.isValid(int) with Retrotranslator plugin implementation to support Java 1.4 + 1.5. ha-jdbc-2.0.16+rc1/doc/forrest.properties0000644000175000017500000000262311151703035017777 0ustar moellermoeller# # HA-JDBC: High-Availability JDBC # Copyright (c) 2004-2007 Paul Ferraro # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by the # Free Software Foundation; either version 2.1 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License # for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Contact: ferraro@users.sourceforge.net # project.content-dir=src project.status=${project.content-dir}/status.xml forrest.validate=false forrest.validate.xdocs=true forrest.validate.skinconf=true project.bugtracking-url=http://sourceforge.net/tracker/index.php?func=detail&group_id=111957&atid=660861&aid= project.required.plugins=org.apache.forrest.plugin.output.pdf,org.apache.forrest.plugin.input.projectInfo,org.apache.forrest.plugin.input.feeder projectInfo.changes.includeCommitterList=false projectInfo.changes.includeContributorList=true projectInfo.changes.sort=true projectInfo.url=http://ha-jdbc.sourceforge.netha-jdbc-2.0.16+rc1/lib-1.4/0000775000175000017500000000000011674455666014525 5ustar moellermoellerha-jdbc-2.0.16+rc1/lib-1.4/runtime/0000755000175000017500000000000011674455666016206 5ustar moellermoellerha-jdbc-2.0.16+rc1/lib-1.4/compile/0000755000175000017500000000000011674455666016153 5ustar moellermoeller