diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/internal/ServicesRegistryBootstrap.java b/hibernate-core/src/main/java/org/hibernate/cfg/internal/ServicesRegistryBootstrap.java new file mode 100644 index 0000000000..5c7b459b11 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/cfg/internal/ServicesRegistryBootstrap.java @@ -0,0 +1,68 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.cfg.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator; +import org.hibernate.service.classloading.internal.ClassLoaderServiceInitiator; +import org.hibernate.service.internal.ServicesRegistryImpl; +import org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator; +import org.hibernate.service.jdbc.dialect.internal.DialectFactoryInitiator; +import org.hibernate.service.jdbc.dialect.internal.DialectResolverInitiator; +import org.hibernate.service.jmx.internal.JmxServiceInitiator; +import org.hibernate.service.jndi.internal.JndiServiceInitiator; +import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator; +import org.hibernate.service.spi.ServiceInitiator; + +/** + * The standard bootstrap process for Hibernate services + * + * @author Steve Ebersole + */ +public class ServicesRegistryBootstrap { + private List serviceInitiators = new ArrayList(); + + public ServicesRegistryBootstrap() { + serviceInitiators.add( ClassLoaderServiceInitiator.INSTANCE ); + serviceInitiators.add( JndiServiceInitiator.INSTANCE ); + serviceInitiators.add( JmxServiceInitiator.INSTANCE ); + + serviceInitiators.add( ConnectionProviderInitiator.INSTANCE ); + serviceInitiators.add( DialectResolverInitiator.INSTANCE ); + serviceInitiators.add( DialectFactoryInitiator.INSTANCE ); + serviceInitiators.add( JdbcServicesInitiator.INSTANCE ); + + serviceInitiators.add( JtaPlatformInitiator.INSTANCE ); + //serviceInitiators.add( TransactionFactoryInitiator.INSTANCE ); + } + + public ServicesRegistryImpl initiateServicesRegistry(Map configurationValues) { + final ServicesRegistryImpl servicesRegistry = new ServicesRegistryImpl( serviceInitiators ); + servicesRegistry.initialize( configurationValues ); + return servicesRegistry; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/internal/ServiceBootstrappingTest.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/internal/ServiceBootstrappingTest.java new file mode 100644 index 0000000000..ada581417b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/cfg/internal/ServiceBootstrappingTest.java @@ -0,0 +1,95 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cfg.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import org.hibernate.testing.junit.UnitTestCase; + +import org.hibernate.cfg.Environment; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.service.classloading.internal.ClassLoaderServiceInitiator; +import org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator; +import org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl; +import org.hibernate.service.jdbc.dialect.internal.DialectFactoryInitiator; +import org.hibernate.service.jdbc.dialect.internal.DialectResolverInitiator; +import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.service.internal.ServicesRegistryImpl; +import org.hibernate.service.spi.ServiceInitiator; +import org.hibernate.test.common.ConnectionProviderBuilder; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class ServiceBootstrappingTest extends UnitTestCase { + private ServicesRegistryImpl servicesRegistry; + + public ServiceBootstrappingTest(String string) { + super( string ); + } + + protected void setUp() { + List serviceInitiators = new ArrayList(); + serviceInitiators.add( ClassLoaderServiceInitiator.INSTANCE ); + serviceInitiators.add( ConnectionProviderInitiator.INSTANCE ); + serviceInitiators.add( DialectResolverInitiator.INSTANCE ); + serviceInitiators.add( DialectFactoryInitiator.INSTANCE ); + serviceInitiators.add( JdbcServicesInitiator.INSTANCE ); + + servicesRegistry = new ServicesRegistryImpl( serviceInitiators ); + } + + protected void tearDown() { + servicesRegistry.destroy(); + } + + public void testBasicBuild() { + servicesRegistry.initialize( ConnectionProviderBuilder.getConnectionProviderProperties() ); + JdbcServices jdbcServices = servicesRegistry.getService( JdbcServices.class ); + + assertTrue( jdbcServices.getDialect() instanceof H2Dialect ); + assertTrue( jdbcServices.getConnectionProvider() instanceof DriverManagerConnectionProviderImpl ); + assertFalse( jdbcServices.getSqlStatementLogger().isLogToStdout() ); + } + + public void testBuildWithLogging() { + Properties props = ConnectionProviderBuilder.getConnectionProviderProperties(); + props.put( Environment.SHOW_SQL, "true" ); + + servicesRegistry.initialize( props ); + JdbcServices jdbcServices = servicesRegistry.getService( JdbcServices.class ); + + assertTrue( jdbcServices.getDialect() instanceof H2Dialect ); + assertTrue( jdbcServices.getConnectionProvider() instanceof DriverManagerConnectionProviderImpl ); + assertTrue( jdbcServices.getSqlStatementLogger().isLogToStdout() ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/cfg/internal/TestServicesRegistryBootstrapping.java b/hibernate-core/src/test/java/org/hibernate/test/cfg/internal/TestServicesRegistryBootstrapping.java new file mode 100644 index 0000000000..8aa830440d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/cfg/internal/TestServicesRegistryBootstrapping.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.cfg.internal; + +import org.hibernate.cfg.internal.ServicesRegistryBootstrap; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.service.internal.ServicesRegistryImpl; +import org.hibernate.test.common.ConnectionProviderBuilder; +import org.hibernate.testing.junit.UnitTestCase; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class TestServicesRegistryBootstrapping extends UnitTestCase { + + public TestServicesRegistryBootstrapping(String string) { + super( string ); + } + + public void testBasicBootstrapping() { + ServicesRegistryImpl servicesRegistry = new ServicesRegistryBootstrap().initiateServicesRegistry( + ConnectionProviderBuilder.getConnectionProviderProperties() + ); + + assertNotNull( servicesRegistry.getService( JdbcServices.class ) ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java b/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java new file mode 100644 index 0000000000..b4c21660f5 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/common/BasicTestingJdbcServiceImpl.java @@ -0,0 +1,145 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.common; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.JdbcSupport; +import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; +import org.hibernate.engine.jdbc.spi.SQLExceptionHelper; +import org.hibernate.engine.jdbc.spi.SQLStatementLogger; +import org.hibernate.engine.jdbc.spi.JdbcServices; +import org.hibernate.internal.util.jdbc.TypeInfo; +import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.service.spi.Stoppable; + + +/** + * Implementation of the {@link JdbcServices} contract for use by these + * tests. + * + * @author Steve Ebersole + */ +public class BasicTestingJdbcServiceImpl implements JdbcServices { + private ConnectionProvider connectionProvider; + private Dialect dialect; + private SQLStatementLogger sqlStatementLogger; + private SQLExceptionHelper exceptionHelper; + private final ExtractedDatabaseMetaData metaDataSupport = new MetaDataSupportImpl(); + + + public void start() { + } + + public void stop() { + release(); + } + + public void prepare(boolean allowAggressiveRelease) { + connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease ); + dialect = ConnectionProviderBuilder.getCorrespondingDialect(); + sqlStatementLogger = new SQLStatementLogger( true, false ); + exceptionHelper = new SQLExceptionHelper(); + + } + + public void release() { + if ( connectionProvider instanceof Stoppable ) { + ( (Stoppable) connectionProvider ).stop(); + } + } + + public ConnectionProvider getConnectionProvider() { + return connectionProvider; + } + + public Dialect getDialect() { + return dialect; + } + + public JdbcSupport getJdbcSupport() { + return null; + } + + public SQLStatementLogger getSqlStatementLogger() { + return sqlStatementLogger; + } + + public SQLExceptionHelper getSqlExceptionHelper() { + return exceptionHelper; + } + + public ExtractedDatabaseMetaData getExtractedMetaDataSupport() { + return metaDataSupport; + } + + private static class MetaDataSupportImpl implements ExtractedDatabaseMetaData { + public boolean supportsScrollableResults() { + return false; + } + + public boolean supportsGetGeneratedKeys() { + return false; + } + + public boolean supportsBatchUpdates() { + return false; + } + + public boolean supportsDataDefinitionInTransaction() { + return false; + } + + public boolean doesDataDefinitionCauseTransactionCommit() { + return false; + } + + public Set getExtraKeywords() { + return Collections.emptySet(); + } + + public SQLStateType getSqlStateType() { + return SQLStateType.UNKOWN; + } + + public boolean doesLobLocatorUpdateCopy() { + return false; + } + + public String getConnectionSchemaName() { + return null; + } + + public String getConnectionCatalogName() { + return null; + } + + public LinkedHashSet getTypeInfoSet() { + return null; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/ConnectionProviderBuilder.java b/hibernate-core/src/test/java/org/hibernate/test/common/ConnectionProviderBuilder.java new file mode 100644 index 0000000000..1a135a3b4b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/common/ConnectionProviderBuilder.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.common; + +import java.util.Properties; + +import org.hibernate.cfg.Environment; +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.H2Dialect; +import org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl; +import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class ConnectionProviderBuilder { + public static final String DRIVER = "org.h2.Driver"; + public static final String URL = "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE"; + public static final String USER = "sa"; + public static final String PASS = ""; + + public static Properties getConnectionProviderProperties() { + Properties props = new Properties( null ); + props.put( Environment.DRIVER, DRIVER ); + props.put( Environment.URL, URL ); + props.put( Environment.USER, USER ); + return props; + } + + public static ConnectionProvider buildConnectionProvider() { + return buildConnectionProvider( false ); + } + + public static ConnectionProvider buildConnectionProvider(final boolean allowAggressiveRelease) { + final Properties props = getConnectionProviderProperties(); + DriverManagerConnectionProviderImpl connectionProvider = new DriverManagerConnectionProviderImpl() { + public boolean supportsAggressiveRelease() { + return allowAggressiveRelease; + } + }; + connectionProvider.configure( props ); + return connectionProvider; + } + + public static Dialect getCorrespondingDialect() { + return new H2Dialect(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/jdbc/TypeInfoTest.java b/hibernate-core/src/test/java/org/hibernate/test/jdbc/TypeInfoTest.java new file mode 100644 index 0000000000..d93f53b602 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/jdbc/TypeInfoTest.java @@ -0,0 +1,70 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.jdbc; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.LinkedHashSet; + +import org.hibernate.internal.util.jdbc.TypeInfo; +import org.hibernate.internal.util.jdbc.TypeInfoExtracter; +import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; +import org.hibernate.test.common.ConnectionProviderBuilder; +import org.hibernate.testing.junit.UnitTestCase; +import org.hibernate.util.ArrayHelper; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class TypeInfoTest extends UnitTestCase { + + public TypeInfoTest(String string) { + super( string ); + } + + public void testExtractTypeInfo() throws SQLException { + ConnectionProvider connectionProvider = ConnectionProviderBuilder.buildConnectionProvider(); + Connection connection = connectionProvider.getConnection(); + LinkedHashSet typeInfoSet = TypeInfoExtracter.extractTypeInfo( connection.getMetaData() ); + for ( TypeInfo typeInfo : typeInfoSet ) { + System.out.println( "~~~~~~ TYPE ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); + System.out.println( " type name : " + typeInfo.getTypeName() ); + System.out.println( " data type : " + typeInfo.getJdbcTypeCode() ); + System.out.println( " create params : " + ArrayHelper.toString( typeInfo.getCreateParams() ) ); + System.out.println( " unsigned : " + typeInfo.isUnsigned() ); + System.out.println( " precision : " + typeInfo.getPrecision() ); + System.out.println( " minimum scale : " + typeInfo.getMinimumScale() ); + System.out.println( " maximum scale : " + typeInfo.getMaximumScale() ); + System.out.println( " fixed-precision scale : " + typeInfo.isFixedPrecisionScale() ); + System.out.println( " literal prefix : " + typeInfo.getLiteralPrefix() ); + System.out.println( " literal suffix : " + typeInfo.getLiteralSuffix() ); + System.out.println( " case sensitive : " + typeInfo.isCaseSensitive() ); + System.out.println( " searchable : " + typeInfo.getSearchability().toString() ); + System.out.println( " nulability : " + typeInfo.getNullability().toString() ); + System.out.println( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ); + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/AggressiveReleaseTest.java b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/AggressiveReleaseTest.java new file mode 100644 index 0000000000..19a06af735 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/AggressiveReleaseTest.java @@ -0,0 +1,262 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.jdbc.proxies; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.hibernate.ConnectionReleaseMode; +import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl; +import org.hibernate.engine.jdbc.spi.ConnectionObserver; +import org.hibernate.engine.jdbc.proxy.ProxyBuilder; +import org.hibernate.test.common.BasicTestingJdbcServiceImpl; +import org.hibernate.testing.junit.UnitTestCase; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class AggressiveReleaseTest extends UnitTestCase { + + private static final Logger log = LoggerFactory.getLogger( AggressiveReleaseTest.class ); + private BasicTestingJdbcServiceImpl services = new BasicTestingJdbcServiceImpl(); + + private static class ConnectionCounter implements ConnectionObserver { + public int obtainCount = 0; + public int releaseCount = 0; + + public void physicalConnectionObtained(Connection connection) { + obtainCount++; + } + + public void physicalConnectionReleased() { + releaseCount++; + } + + public void logicalConnectionClosed() { + } + } + + public AggressiveReleaseTest(String string) { + super( string ); + } + + public void setUp() throws SQLException { + services.prepare( true ); + + Connection connection = null; + Statement stmnt = null; + try { + connection = services.getConnectionProvider().getConnection(); + stmnt = connection.createStatement(); + stmnt.execute( "drop table SANDBOX_JDBC_TST if exists" ); + stmnt.execute( "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" ); + } + finally { + if ( stmnt != null ) { + try { + stmnt.close(); + } + catch ( SQLException ignore ) { + log.warn( "could not close statement used to set up schema", ignore ); + } + } + if ( connection != null ) { + try { + connection.close(); + } + catch ( SQLException ignore ) { + log.warn( "could not close connection used to set up schema", ignore ); + } + } + } + } + + public void tearDown() throws SQLException { + Connection connection = null; + Statement stmnt = null; + try { + connection = services.getConnectionProvider().getConnection(); + stmnt = connection.createStatement(); + stmnt.execute( "drop table SANDBOX_JDBC_TST if exists" ); + } + finally { + if ( stmnt != null ) { + try { + stmnt.close(); + } + catch ( SQLException ignore ) { + log.warn( "could not close statement used to set up schema", ignore ); + } + } + if ( connection != null ) { + try { + connection.close(); + } + catch ( SQLException ignore ) { + log.warn( "could not close connection used to set up schema", ignore ); + } + } + } + + services.release(); + } + + public void testBasicRelease() { + LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services ); + Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection ); + ConnectionCounter observer = new ConnectionCounter(); + logicalConnection.addObserver( observer ); + + try { + PreparedStatement ps = proxiedConnection.prepareStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" ); + ps.setLong( 1, 1 ); + ps.setString( 2, "name" ); + ps.execute(); + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 1, observer.obtainCount ); + assertEquals( 0, observer.releaseCount ); + ps.close(); + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 1, observer.obtainCount ); + assertEquals( 1, observer.releaseCount ); + } + catch ( SQLException sqle ) { + fail( "incorrect exception type : sqlexception" ); + } + finally { + logicalConnection.close(); + } + + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + } + + public void testReleaseCircumventedByHeldResources() { + LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services ); + Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection ); + ConnectionCounter observer = new ConnectionCounter(); + logicalConnection.addObserver( observer ); + + try { + PreparedStatement ps = proxiedConnection.prepareStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" ); + ps.setLong( 1, 1 ); + ps.setString( 2, "name" ); + ps.execute(); + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 1, observer.obtainCount ); + assertEquals( 0, observer.releaseCount ); + ps.close(); + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 1, observer.obtainCount ); + assertEquals( 1, observer.releaseCount ); + + // open a result set and hold it open... + ps = proxiedConnection.prepareStatement( "select * from SANDBOX_JDBC_TST" ); + ps.executeQuery(); + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 2, observer.obtainCount ); + assertEquals( 1, observer.releaseCount ); + + // open a second result set + PreparedStatement ps2 = proxiedConnection.prepareStatement( "select * from SANDBOX_JDBC_TST" ); + ps2.execute(); + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 2, observer.obtainCount ); + assertEquals( 1, observer.releaseCount ); + // and close it... + ps2.close(); + // the release should be circumvented... + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 2, observer.obtainCount ); + assertEquals( 1, observer.releaseCount ); + + // let the close of the logical connection below release all resources (hopefully)... + } + catch ( SQLException sqle ) { + fail( "incorrect exception type : sqlexception" ); + } + finally { + logicalConnection.close(); + } + + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 2, observer.obtainCount ); + assertEquals( 2, observer.releaseCount ); + } + + public void testReleaseCircumventedManually() { + LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_STATEMENT, services ); + Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection ); + ConnectionCounter observer = new ConnectionCounter(); + logicalConnection.addObserver( observer ); + + try { + PreparedStatement ps = proxiedConnection.prepareStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" ); + ps.setLong( 1, 1 ); + ps.setString( 2, "name" ); + ps.execute(); + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 1, observer.obtainCount ); + assertEquals( 0, observer.releaseCount ); + ps.close(); + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 1, observer.obtainCount ); + assertEquals( 1, observer.releaseCount ); + + // disable releases... + logicalConnection.disableReleases(); + + // open a result set... + ps = proxiedConnection.prepareStatement( "select * from SANDBOX_JDBC_TST" ); + ps.executeQuery(); + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 2, observer.obtainCount ); + assertEquals( 1, observer.releaseCount ); + // and close it... + ps.close(); + // the release should be circumvented... + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 2, observer.obtainCount ); + assertEquals( 1, observer.releaseCount ); + + // let the close of the logical connection below release all resources (hopefully)... + } + catch ( SQLException sqle ) { + fail( "incorrect exception type : sqlexception" ); + } + finally { + logicalConnection.close(); + } + + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertEquals( 2, observer.obtainCount ); + assertEquals( 2, observer.releaseCount ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BasicConnectionProxyTest.java b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BasicConnectionProxyTest.java new file mode 100644 index 0000000000..b9b504bf99 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/jdbc/proxies/BasicConnectionProxyTest.java @@ -0,0 +1,133 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.jdbc.proxies; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.hibernate.ConnectionReleaseMode; +import org.hibernate.JDBCException; +import org.hibernate.engine.jdbc.internal.LogicalConnectionImpl; +import org.hibernate.engine.jdbc.proxy.ProxyBuilder; +import org.hibernate.test.common.BasicTestingJdbcServiceImpl; +import org.hibernate.testing.junit.UnitTestCase; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class BasicConnectionProxyTest extends UnitTestCase { + private BasicTestingJdbcServiceImpl services = new BasicTestingJdbcServiceImpl(); + + public BasicConnectionProxyTest(String string) { + super( string ); + } + + public void setUp() { + services.prepare( false ); + } + + public void tearDown() { + services.release(); + } + + public void testDatabaseMetaDataHandling() throws Throwable { + LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services ); + Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection ); + try { + DatabaseMetaData metaData = proxiedConnection.getMetaData(); + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + ResultSet rs1 = metaData.getCatalogs(); + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + rs1.close(); + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + metaData.getCatalogs(); + metaData.getSchemas(); + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + } + catch ( SQLException sqle ) { + fail( "incorrect exception type : sqlexception" ); + } + finally { + logicalConnection.close(); + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + } + } + + public void testExceptionHandling() { + LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services ); + Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection ); + try { + proxiedConnection.prepareStatement( "select count(*) from NON_EXISTENT" ).executeQuery(); + } + catch ( SQLException sqle ) { + fail( "incorrect exception type : sqlexception" ); + } + catch ( JDBCException ok ) { + // expected outcome + } + finally { + logicalConnection.close(); + } + } + + public void testBasicJdbcUsage() throws JDBCException { + LogicalConnectionImpl logicalConnection = new LogicalConnectionImpl( null, ConnectionReleaseMode.AFTER_TRANSACTION, services ); + Connection proxiedConnection = ProxyBuilder.buildConnection( logicalConnection ); + + try { + Statement stmnt = proxiedConnection.createStatement(); + stmnt.execute( "drop table SANDBOX_JDBC_TST if exists" ); + stmnt.execute( "create table SANDBOX_JDBC_TST ( ID integer, NAME varchar(100) )" ); + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertTrue( logicalConnection.isPhysicallyConnected() ); + stmnt.close(); + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + assertTrue( logicalConnection.isPhysicallyConnected() ); // after_transaction specified + + PreparedStatement ps = proxiedConnection.prepareStatement( "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" ); + ps.setLong( 1, 1 ); + ps.setString( 2, "name" ); + ps.execute(); + + ps = proxiedConnection.prepareStatement( "select * from SANDBOX_JDBC_TST" ); + ps.executeQuery(); + + assertTrue( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + } + catch ( SQLException sqle ) { + fail( "incorrect exception type : sqlexception" ); + } + finally { + logicalConnection.close(); + } + + assertFalse( logicalConnection.getResourceRegistry().hasRegisteredResources() ); + } +}