diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/JdbcProxyException.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/JdbcProxyException.java new file mode 100644 index 0000000000..86767ed6d9 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/JdbcProxyException.java @@ -0,0 +1,41 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.engine.jdbc.internal.proxy; + +import org.hibernate.HibernateException; + +/** + * Indicates a problem defining or instantiating a JDBC proxy class. + * + * @author Steve Ebersole + */ +public class JdbcProxyException extends HibernateException { + public JdbcProxyException(String message, Throwable root) { + super( message, root ); + } + + public JdbcProxyException(String message) { + super( message ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/ProxyBuilder.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/ProxyBuilder.java index 6f3613ce17..4db834e0d0 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/ProxyBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/proxy/ProxyBuilder.java @@ -22,6 +22,9 @@ * Boston, MA 02110-1301 USA */ package org.hibernate.engine.jdbc.internal.proxy; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.sql.CallableStatement; import java.sql.Connection; @@ -33,6 +36,7 @@ import java.sql.Statement; import org.hibernate.engine.jdbc.spi.InvalidatableWrapper; import org.hibernate.engine.jdbc.spi.JdbcWrapper; import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor; +import org.hibernate.internal.util.Value; /** * Centralized builder for proxy instances @@ -48,13 +52,36 @@ public class ProxyBuilder { JdbcWrapper.class }; + private static final Value> connectionProxyConstructorValue = new Value>( + new Value.DeferredInitializer>() { + @Override + public Constructor initialize() { + try { + return locateConnectionProxyClass().getConstructor( InvocationHandler.class ); + } + catch (NoSuchMethodException e) { + throw new JdbcProxyException( "Could not find proxy constructor in JDK generated Connection proxy class", e ); + } + } + + @SuppressWarnings("unchecked") + private Class locateConnectionProxyClass() { + return (Class) Proxy.getProxyClass( + JdbcWrapper.class.getClassLoader(), + CONNECTION_PROXY_INTERFACES + ); + } + } + ); + public static Connection buildConnection(LogicalConnectionImplementor logicalConnection) { - ConnectionProxyHandler proxyHandler = new ConnectionProxyHandler( logicalConnection ); - return ( Connection ) Proxy.newProxyInstance( - JdbcWrapper.class.getClassLoader(), - CONNECTION_PROXY_INTERFACES, - proxyHandler - ); + final ConnectionProxyHandler proxyHandler = new ConnectionProxyHandler( logicalConnection ); + try { + return connectionProxyConstructorValue.getValue().newInstance( proxyHandler ); + } + catch (Exception e) { + throw new JdbcProxyException( "Could not instantiate JDBC Connection proxy", e ); + } } @@ -66,20 +93,43 @@ public class ProxyBuilder { InvalidatableWrapper.class }; + private static final Value> statementProxyConstructorValue = new Value>( + new Value.DeferredInitializer>() { + @Override + public Constructor initialize() { + try { + return locateStatementProxyClass().getConstructor( InvocationHandler.class ); + } + catch (NoSuchMethodException e) { + throw new JdbcProxyException( "Could not find proxy constructor in JDK generated Statement proxy class", e ); + } + } + + @SuppressWarnings("unchecked") + private Class locateStatementProxyClass() { + return (Class) Proxy.getProxyClass( + JdbcWrapper.class.getClassLoader(), + STMNT_PROXY_INTERFACES + ); + } + } + ); + public static Statement buildStatement( Statement statement, ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy) { - BasicStatementProxyHandler proxyHandler = new BasicStatementProxyHandler( + final BasicStatementProxyHandler proxyHandler = new BasicStatementProxyHandler( statement, connectionProxyHandler, connectionProxy ); - return ( Statement ) Proxy.newProxyInstance( - JdbcWrapper.class.getClassLoader(), - STMNT_PROXY_INTERFACES, - proxyHandler - ); + try { + return statementProxyConstructorValue.getValue().newInstance( proxyHandler ); + } + catch (Exception e) { + throw new JdbcProxyException( "Could not instantiate JDBC Statement proxy", e ); + } } public static Statement buildImplicitStatement( @@ -89,12 +139,13 @@ public class ProxyBuilder { if ( statement == null ) { return null; } - ImplicitStatementProxyHandler handler = new ImplicitStatementProxyHandler( statement, connectionProxyHandler, connectionProxy ); - return ( Statement ) Proxy.newProxyInstance( - JdbcWrapper.class.getClassLoader(), - STMNT_PROXY_INTERFACES, - handler - ); + final ImplicitStatementProxyHandler proxyHandler = new ImplicitStatementProxyHandler( statement, connectionProxyHandler, connectionProxy ); + try { + return statementProxyConstructorValue.getValue().newInstance( proxyHandler ); + } + catch (Exception e) { + throw new JdbcProxyException( "Could not instantiate JDBC Statement proxy", e ); + } } @@ -106,22 +157,45 @@ public class ProxyBuilder { InvalidatableWrapper.class }; + private static final Value> preparedStatementProxyConstructorValue = new Value>( + new Value.DeferredInitializer>() { + @Override + public Constructor initialize() { + try { + return locatePreparedStatementProxyClass().getConstructor( InvocationHandler.class ); + } + catch (NoSuchMethodException e) { + throw new JdbcProxyException( "Could not find proxy constructor in JDK generated Statement proxy class", e ); + } + } + + @SuppressWarnings("unchecked") + private Class locatePreparedStatementProxyClass() { + return (Class) Proxy.getProxyClass( + JdbcWrapper.class.getClassLoader(), + PREPARED_STMNT_PROXY_INTERFACES + ); + } + } + ); + public static PreparedStatement buildPreparedStatement( String sql, Statement statement, ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy) { - PreparedStatementProxyHandler proxyHandler = new PreparedStatementProxyHandler( + final PreparedStatementProxyHandler proxyHandler = new PreparedStatementProxyHandler( sql, statement, connectionProxyHandler, connectionProxy ); - return ( PreparedStatement ) Proxy.newProxyInstance( - JdbcWrapper.class.getClassLoader(), - PREPARED_STMNT_PROXY_INTERFACES, - proxyHandler - ); + try { + return preparedStatementProxyConstructorValue.getValue().newInstance( proxyHandler ); + } + catch (Exception e) { + throw new JdbcProxyException( "Could not instantiate JDBC PreparedStatement proxy", e ); + } } @@ -133,22 +207,45 @@ public class ProxyBuilder { InvalidatableWrapper.class }; + private static final Value> callableStatementProxyConstructorValue = new Value>( + new Value.DeferredInitializer>() { + @Override + public Constructor initialize() { + try { + return locateCallableStatementProxyClass().getConstructor( InvocationHandler.class ); + } + catch (NoSuchMethodException e) { + throw new JdbcProxyException( "Could not find proxy constructor in JDK generated Statement proxy class", e ); + } + } + + @SuppressWarnings("unchecked") + private Class locateCallableStatementProxyClass() { + return (Class) Proxy.getProxyClass( + JdbcWrapper.class.getClassLoader(), + CALLABLE_STMNT_PROXY_INTERFACES + ); + } + } + ); + public static CallableStatement buildCallableStatement( String sql, CallableStatement statement, ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy) { - CallableStatementProxyHandler proxyHandler = new CallableStatementProxyHandler( + final CallableStatementProxyHandler proxyHandler = new CallableStatementProxyHandler( sql, statement, connectionProxyHandler, connectionProxy ); - return ( CallableStatement ) Proxy.newProxyInstance( - JdbcWrapper.class.getClassLoader(), - CALLABLE_STMNT_PROXY_INTERFACES, - proxyHandler - ); + try { + return callableStatementProxyConstructorValue.getValue().newInstance( proxyHandler ); + } + catch (Exception e) { + throw new JdbcProxyException( "Could not instantiate JDBC CallableStatement proxy", e ); + } } @@ -160,29 +257,56 @@ public class ProxyBuilder { InvalidatableWrapper.class }; + private static final Value> resultSetProxyConstructorValue = new Value>( + new Value.DeferredInitializer>() { + @Override + public Constructor initialize() { + try { + return locateCallableStatementProxyClass().getConstructor( InvocationHandler.class ); + } + catch (NoSuchMethodException e) { + throw new JdbcProxyException( "Could not find proxy constructor in JDK generated ResultSet proxy class", e ); + } + } + + @SuppressWarnings("unchecked") + private Class locateCallableStatementProxyClass() { + return (Class) Proxy.getProxyClass( + JdbcWrapper.class.getClassLoader(), + RESULTSET_PROXY_INTERFACES + ); + } + } + ); public static ResultSet buildResultSet( ResultSet resultSet, AbstractStatementProxyHandler statementProxyHandler, Statement statementProxy) { - ResultSetProxyHandler proxyHandler = new ResultSetProxyHandler( resultSet, statementProxyHandler, statementProxy ); - return ( ResultSet ) Proxy.newProxyInstance( - JdbcWrapper.class.getClassLoader(), - RESULTSET_PROXY_INTERFACES, - proxyHandler - ); + final ResultSetProxyHandler proxyHandler = new ResultSetProxyHandler( resultSet, statementProxyHandler, statementProxy ); + try { + return resultSetProxyConstructorValue.getValue().newInstance( proxyHandler ); + } + catch (Exception e) { + throw new JdbcProxyException( "Could not instantiate JDBC ResultSet proxy", e ); + } } public static ResultSet buildImplicitResultSet( ResultSet resultSet, ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy) { - ImplicitResultSetProxyHandler proxyHandler = new ImplicitResultSetProxyHandler( resultSet, connectionProxyHandler, connectionProxy ); - return ( ResultSet ) Proxy.newProxyInstance( - JdbcWrapper.class.getClassLoader(), - RESULTSET_PROXY_INTERFACES, - proxyHandler + final ImplicitResultSetProxyHandler proxyHandler = new ImplicitResultSetProxyHandler( + resultSet, + connectionProxyHandler, + connectionProxy ); + try { + return resultSetProxyConstructorValue.getValue().newInstance( proxyHandler ); + } + catch (Exception e) { + throw new JdbcProxyException( "Could not instantiate JDBC ResultSet proxy", e ); + } } public static ResultSet buildImplicitResultSet( @@ -190,12 +314,18 @@ public class ProxyBuilder { ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy, Statement sourceStatement) { - ImplicitResultSetProxyHandler proxyHandler = new ImplicitResultSetProxyHandler( resultSet, connectionProxyHandler, connectionProxy, sourceStatement ); - return ( ResultSet ) Proxy.newProxyInstance( - JdbcWrapper.class.getClassLoader(), - RESULTSET_PROXY_INTERFACES, - proxyHandler + final ImplicitResultSetProxyHandler proxyHandler = new ImplicitResultSetProxyHandler( + resultSet, + connectionProxyHandler, + connectionProxy, + sourceStatement ); + try { + return resultSetProxyConstructorValue.getValue().newInstance( proxyHandler ); + } + catch (Exception e) { + throw new JdbcProxyException( "Could not instantiate JDBC ResultSet proxy", e ); + } } @@ -206,15 +336,42 @@ public class ProxyBuilder { JdbcWrapper.class }; + private static final Value> metadataProxyConstructorValue = new Value>( + new Value.DeferredInitializer>() { + @Override + public Constructor initialize() { + try { + return locateDatabaseMetaDataProxyClass().getConstructor( InvocationHandler.class ); + } + catch (NoSuchMethodException e) { + throw new JdbcProxyException( "Could not find proxy constructor in JDK generated DatabaseMetaData proxy class", e ); + } + } + + @SuppressWarnings("unchecked") + private Class locateDatabaseMetaDataProxyClass() { + return (Class) Proxy.getProxyClass( + JdbcWrapper.class.getClassLoader(), + METADATA_PROXY_INTERFACES + ); + } + } + ); + public static DatabaseMetaData buildDatabaseMetaData( DatabaseMetaData metaData, ConnectionProxyHandler connectionProxyHandler, Connection connectionProxy) { - DatabaseMetaDataProxyHandler handler = new DatabaseMetaDataProxyHandler( metaData, connectionProxyHandler, connectionProxy ); - return ( DatabaseMetaData ) Proxy.newProxyInstance( - JdbcWrapper.class.getClassLoader(), - METADATA_PROXY_INTERFACES, - handler + final DatabaseMetaDataProxyHandler proxyHandler = new DatabaseMetaDataProxyHandler( + metaData, + connectionProxyHandler, + connectionProxy ); + try { + return metadataProxyConstructorValue.getValue().newInstance( proxyHandler ); + } + catch (Exception e) { + throw new JdbcProxyException( "Could not instantiate JDBC DatabaseMetaData proxy", e ); + } } }