HHH-5943 - Make ServiceRegistry mutable

This commit is contained in:
Steve Ebersole 2011-02-21 17:31:40 -06:00 committed by JPAV
parent 02cf95da33
commit 11d32ba69c
25 changed files with 878 additions and 143 deletions

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.service.jdbc.connections.internal; package org.hibernate.service.jdbc.connections.internal;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Iterator; import java.util.Iterator;
@ -31,6 +32,7 @@ import org.hibernate.HibernateException;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.spi.UnknownUnwrapTypeException;
import org.hibernate.util.ReflectHelper; import org.hibernate.util.ReflectHelper;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import com.mchange.v2.c3p0.DataSources; import com.mchange.v2.c3p0.DataSources;
@ -87,10 +89,23 @@ public class C3P0ConnectionProvider implements ConnectionProvider {
conn.close(); conn.close();
} }
/** @Override
* @param props @SuppressWarnings( {"unchecked"})
* @throws HibernateException public <T> T unwrap(Class<T> unwrapType) {
*/ if ( ConnectionProvider.class.isAssignableFrom( unwrapType ) ) {
return (T) this;
}
else if ( DataSource.class.isAssignableFrom( unwrapType ) ) {
return (T) ds;
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}
/**
* {@inheritDoc}
*/
public void configure(Properties props) throws HibernateException { public void configure(Properties props) throws HibernateException {
String jdbcDriverClass = props.getProperty( Environment.DRIVER ); String jdbcDriverClass = props.getProperty( Environment.DRIVER );
String jdbcUrl = props.getProperty( Environment.URL ); String jdbcUrl = props.getProperty( Environment.URL );

View File

@ -22,19 +22,10 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.cfg.internal; package org.hibernate.cfg.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
import org.hibernate.service.classloading.internal.ClassLoaderServiceInitiator;
import org.hibernate.service.internal.ServiceRegistryImpl; import org.hibernate.service.internal.ServiceRegistryImpl;
import org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator; import org.hibernate.service.spi.StandardServiceInitiators;
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 * The standard bootstrap process for Hibernate services
@ -42,25 +33,7 @@ import org.hibernate.service.spi.ServiceInitiator;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ServicesRegistryBootstrap { public class ServicesRegistryBootstrap {
private List<ServiceInitiator> serviceInitiators = new ArrayList<ServiceInitiator>();
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 ServiceRegistryImpl initiateServicesRegistry(Map configurationValues) { public ServiceRegistryImpl initiateServicesRegistry(Map configurationValues) {
final ServiceRegistryImpl servicesRegistry = new ServiceRegistryImpl( serviceInitiators ); return new ServiceRegistryImpl( StandardServiceInitiators.LIST, configurationValues );
servicesRegistry.initialize( configurationValues );
return servicesRegistry;
} }
} }

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.service.internal; package org.hibernate.service.internal;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -44,15 +45,15 @@ import org.jboss.logging.Logger;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ServicesInitializer { public class ServiceInitializer {
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, ServicesInitializer.class.getName()); private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, ServiceInitializer.class.getName());
private final ServiceRegistryImpl servicesRegistry; private final ServiceRegistryImpl servicesRegistry;
private final Map<Class,ServiceInitiator> serviceInitiatorMap; private final Map<Class,ServiceInitiator> serviceInitiatorMap;
private final Map configurationValues; private final Map configurationValues;
public ServicesInitializer( public ServiceInitializer(
ServiceRegistryImpl servicesRegistry, ServiceRegistryImpl servicesRegistry,
List<ServiceInitiator> serviceInitiators, List<ServiceInitiator> serviceInitiators,
Map configurationValues) { Map configurationValues) {
@ -64,11 +65,12 @@ public class ServicesInitializer {
/** /**
* We convert the incoming list of initiators to a map for 2 reasons:<ul> * We convert the incoming list of initiators to a map for 2 reasons:<ul>
* <li>to make it easier to look up the initiator we need for a given service role</li> * <li>to make it easier to look up the initiator we need for a given service role</li>
* <li>to make sure there is only one initator for a given service role (last wins)</li> * <li>to make sure there is only one initiator for a given service role (last wins)</li>
* </ul> * </ul>
* *
* @param serviceInitiators * @param serviceInitiators The list of individual initiators
* @return *
* @return The map of initiators keyed by the service rle they initiate.
*/ */
private static Map<Class, ServiceInitiator> toMap(List<ServiceInitiator> serviceInitiators) { private static Map<Class, ServiceInitiator> toMap(List<ServiceInitiator> serviceInitiators) {
final Map<Class, ServiceInitiator> result = new HashMap<Class, ServiceInitiator>(); final Map<Class, ServiceInitiator> result = new HashMap<Class, ServiceInitiator>();
@ -78,6 +80,13 @@ public class ServicesInitializer {
return result; return result;
} }
void registerServiceInitiator(ServiceInitiator serviceInitiator) {
final Object previous = serviceInitiatorMap.put( serviceInitiator.getServiceInitiated(), serviceInitiator );
final boolean overwritten = previous != null;
if (overwritten) LOG.debugf("Over-wrote existing service initiator [role=%s]",
serviceInitiator.getServiceInitiated().getName());
}
/** /**
* The main function of this delegate. Used to initialize the service of a given role. * The main function of this delegate. Used to initialize the service of a given role.
* *
@ -158,7 +167,9 @@ public class ServicesInitializer {
dependentServiceRole = injectionMethod.getParameterTypes()[0]; dependentServiceRole = injectionMethod.getParameterTypes()[0];
} }
final Service dependantService = servicesRegistry.internalGetService( dependentServiceRole ); // todo : because of the use of proxies, this is no longer returning null here...
final Service dependantService = servicesRegistry.getService( dependentServiceRole );
if ( dependantService == null ) { if ( dependantService == null ) {
if ( injectService.required() ) { if ( injectService.required() ) {
throw new ServiceDependencyException( throw new ServiceDependencyException(

View File

@ -0,0 +1,41 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.internal;
import org.hibernate.service.spi.Service;
/**
* Marker interface for a service proxy which allows mixed-in ability to unproxy.
*
* @author Steve Ebersole
*/
public interface ServiceProxy extends Service {
/**
* Get the target service instance represented by this proxy.
*
* @param <T>
* @return
*/
public <T extends Service> T getTargetInstance();
}

View File

@ -0,0 +1,41 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.internal;
import org.hibernate.HibernateException;
/**
* Indicates a problem generating a service proxy
*
* @author Steve Ebersole
*/
public class ServiceProxyGenerationException extends HibernateException {
public ServiceProxyGenerationException(String string, Throwable root) {
super( string, root );
}
public ServiceProxyGenerationException(Throwable root) {
super( root );
}
}

View File

@ -22,44 +22,53 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.service.internal; package org.hibernate.service.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.HibernateException;
import org.hibernate.HibernateLogger; import org.hibernate.HibernateLogger;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.internal.proxy.javassist.ServiceProxyFactoryFactoryImpl;
import org.hibernate.service.spi.Service; import org.hibernate.service.spi.Service;
import org.hibernate.service.spi.ServiceInitiator; import org.hibernate.service.spi.ServiceInitiator;
import org.hibernate.service.spi.ServiceRegistry; import org.hibernate.service.spi.StandardServiceInitiators;
import org.hibernate.service.spi.Stoppable; import org.hibernate.service.spi.Stoppable;
import org.hibernate.service.spi.UnknownServiceException; import org.hibernate.service.spi.UnknownServiceException;
import org.hibernate.service.spi.proxy.ServiceProxyFactory;
import org.hibernate.service.spi.proxy.ServiceProxyTargetSource;
import org.hibernate.util.CollectionHelper;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
/** /**
* Basic Hibernate implementation of the service registry. * Standard Hibernate implementation of the service registry.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ServiceRegistryImpl implements ServiceRegistry { public class ServiceRegistryImpl implements ServiceProxyTargetSource {
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, ServiceRegistryImpl.class.getName()); private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, ServiceRegistryImpl.class.getName());
private final List<ServiceInitiator> serviceInitiators; private final ServiceInitializer initializer;
private ServicesInitializer initializer; // for now just hardcode the javassist factory
private ServiceProxyFactory serviceProxyFactory = new ServiceProxyFactoryFactoryImpl().makeServiceProxyFactory( this );
private HashMap<Class,Service> serviceMap = new HashMap<Class, Service>(); private ConcurrentHashMap<Class,ServiceBinding> serviceBindingMap;
// IMPL NOTE : the list used for ordered destruction. Cannot used ordered map above because we need to // IMPL NOTE : the list used for ordered destruction. Cannot used ordered map above because we need to
// iterate it in reverse order which is only available through ListIterator // iterate it in reverse order which is only available through ListIterator
private List<Service> serviceList = new ArrayList<Service>(); private List<Service> serviceList = new ArrayList<Service>();
public ServiceRegistryImpl(List<ServiceInitiator> serviceInitiators) { public ServiceRegistryImpl(Map configurationValues) {
this.serviceInitiators = Collections.unmodifiableList( serviceInitiators ); this( StandardServiceInitiators.LIST, configurationValues );
} }
public void initialize(Map configurationValues) { public ServiceRegistryImpl(List<ServiceInitiator> serviceInitiators, Map configurationValues) {
this.initializer = new ServicesInitializer( this, serviceInitiators, ConfigurationHelper.clone( configurationValues ) ); this.initializer = new ServiceInitializer( this, serviceInitiators, ConfigurationHelper.clone( configurationValues ) );
final int anticipatedSize = serviceInitiators.size() + 5; // allow some growth
serviceBindingMap = CollectionHelper.concurrentMap( anticipatedSize );
serviceList = CollectionHelper.arrayList( anticipatedSize );
} }
public void destroy() { public void destroy() {
@ -77,35 +86,84 @@ public class ServiceRegistryImpl implements ServiceRegistry {
} }
serviceList.clear(); serviceList.clear();
serviceList = null; serviceList = null;
serviceMap.clear(); serviceBindingMap.clear();
serviceMap = null; serviceBindingMap = null;
} }
@Override @Override
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public <T extends Service> T getService(Class<T> serviceRole) { public <T extends Service> T getService(Class<T> serviceRole) {
T service = internalGetService( serviceRole ); return locateOrCreateServiceBinding( serviceRole ).getProxy();
}
@SuppressWarnings({ "unchecked" })
private <T extends Service> ServiceBinding<T> locateOrCreateServiceBinding(Class<T> serviceRole) {
ServiceBinding<T> serviceBinding = serviceBindingMap.get( serviceRole );
if ( serviceBinding == null ) {
T proxy = serviceProxyFactory.makeProxy( serviceRole );
serviceBinding = new ServiceBinding<T>( proxy );
serviceBindingMap.put( serviceRole, serviceBinding );
}
return serviceBinding;
}
@Override
@SuppressWarnings( {"unchecked"})
public <T extends Service> T getServiceInternal(Class<T> serviceRole) {
ServiceBinding<T> serviceBinding = serviceBindingMap.get( serviceRole );
if ( serviceBinding == null ) {
throw new HibernateException( "Only proxies should invoke #getServiceInternal" );
}
T service = serviceBinding.getTarget();
if ( service == null ) {
service = initializer.initializeService( serviceRole );
serviceBinding.setTarget( service );
}
if ( service == null ) { if ( service == null ) {
throw new UnknownServiceException( serviceRole ); throw new UnknownServiceException( serviceRole );
} }
return service; return service;
} }
@SuppressWarnings({ "unchecked" }) @Override
private <T extends Service> T locateService(Class<T> serviceRole) { public <T extends Service> void registerService(Class<T> serviceRole, T service) {
return (T) serviceMap.get( serviceRole ); ServiceBinding<T> serviceBinding = locateOrCreateServiceBinding( serviceRole );
} T priorServiceInstance = serviceBinding.getTarget();
serviceBinding.setTarget( service );
<T extends Service> T internalGetService(Class<T> serviceRole) { if ( priorServiceInstance != null ) {
T service = locateService( serviceRole ); serviceList.remove( priorServiceInstance );
if ( service == null ) {
service = initializer.initializeService( serviceRole );
} }
return service; serviceList.add( service );
} }
<T extends Service> void registerService(Class<T> serviceRole, T service) { @Override
serviceList.add( service ); @SuppressWarnings( {"unchecked"})
serviceMap.put( serviceRole, service ); public void registerServiceInitiator(ServiceInitiator initiator) {
ServiceBinding serviceBinding = serviceBindingMap.get( initiator.getServiceInitiated() );
if ( serviceBinding != null ) {
serviceBinding.setTarget( null );
}
initializer.registerServiceInitiator( initiator );
}
private static final class ServiceBinding<T> {
private final T proxy;
private T target;
private ServiceBinding(T proxy) {
this.proxy = proxy;
}
public T getProxy() {
return proxy;
}
public T getTarget() {
return target;
}
public void setTarget(T target) {
this.target = target;
}
} }
} }

View File

@ -0,0 +1,38 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.internal.proxy.javassist;
import org.hibernate.service.spi.proxy.ServiceProxyFactory;
import org.hibernate.service.spi.proxy.ServiceProxyFactoryFactory;
import org.hibernate.service.spi.proxy.ServiceProxyTargetSource;
/**
* @author Steve Ebersole
*/
public class ServiceProxyFactoryFactoryImpl implements ServiceProxyFactoryFactory {
@Override
public ServiceProxyFactory makeServiceProxyFactory(ServiceProxyTargetSource registry) {
return new ServiceProxyFactoryImpl( registry );
}
}

View File

@ -0,0 +1,122 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.internal.proxy.javassist;
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;
import org.hibernate.service.internal.ServiceProxy;
import org.hibernate.service.internal.ServiceProxyGenerationException;
import org.hibernate.service.spi.Service;
import org.hibernate.service.spi.proxy.ServiceProxyFactory;
import org.hibernate.service.spi.proxy.ServiceProxyTargetSource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author Steve Ebersole
*/
public class ServiceProxyFactoryImpl implements ServiceProxyFactory {
private final ServiceProxyTargetSource serviceRegistry;
public ServiceProxyFactoryImpl(ServiceProxyTargetSource serviceRegistry) {
this.serviceRegistry = serviceRegistry;
}
private static final MethodFilter FINALIZE_FILTER = new MethodFilter() {
public boolean isHandled(Method m) {
// skip finalize methods
return !( m.getParameterTypes().length == 0 && m.getName().equals( "finalize" ) );
}
};
@Override
@SuppressWarnings( {"unchecked"})
public <T extends Service> T makeProxy(Class<T> serviceRole) {
try {
ProxyFactory factory = new ProxyFactory();
factory.setFilter( FINALIZE_FILTER );
Class[] interfaces = new Class[2];
interfaces[0] = serviceRole;
interfaces[1] = ServiceProxy.class;
factory.setInterfaces( interfaces );
Class proxyClass = factory.createClass();
ProxyObject proxyObject = (ProxyObject) proxyClass.newInstance();
proxyObject.setHandler( new ServiceProxyMethodInterceptor<T>( (T)proxyObject, serviceRole, serviceRegistry ) );
return (T) proxyObject;
}
catch (Exception e) {
throw new ServiceProxyGenerationException( "Unable to make service proxy", e );
}
}
private static class ServiceProxyMethodInterceptor<T extends Service> implements MethodHandler {
private final T proxy;
private final Class<T> serviceRole;
private final ServiceProxyTargetSource serviceRegistry;
private ServiceProxyMethodInterceptor(T proxy, Class<T> serviceRole, ServiceProxyTargetSource serviceRegistry) {
this.proxy = proxy;
this.serviceRole = serviceRole;
this.serviceRegistry = serviceRegistry;
}
@Override
@SuppressWarnings( {"UnnecessaryBoxing"} )
public Object invoke(
Object object,
Method method,
Method method1,
Object[] args) throws Exception {
String name = method.getName();
if ( "toString".equals( name ) ) {
return serviceRole.getName() + "_$$_Proxy@" + System.identityHashCode( object );
}
else if ( "equals".equals( name ) ) {
return proxy == object ? Boolean.TRUE : Boolean.FALSE;
}
else if ( "hashCode".equals( name ) ) {
return Integer.valueOf( System.identityHashCode( object ) );
}
else if ( "getTargetInstance".equals( name ) && ServiceProxy.class.equals( method.getDeclaringClass() ) ) {
return serviceRegistry.getServiceInternal( serviceRole );
}
else {
try {
T target = serviceRegistry.getServiceInternal( serviceRole );
return method.invoke( target, args );
}
catch (InvocationTargetException e) {
throw (Exception) e.getTargetException();
}
}
}
}
}

View File

@ -33,6 +33,7 @@ import org.hibernate.service.jndi.spi.JndiService;
import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.InjectService; import org.hibernate.service.spi.InjectService;
import org.hibernate.service.spi.Stoppable; import org.hibernate.service.spi.Stoppable;
import org.hibernate.service.spi.UnknownUnwrapTypeException;
/** /**
* A {@link ConnectionProvider} that manages connections from an underlying {@link DataSource}. * A {@link ConnectionProvider} that manages connections from an underlying {@link DataSource}.
@ -69,6 +70,28 @@ public class DatasourceConnectionProviderImpl implements ConnectionProvider, Con
this.jndiService = jndiService; this.jndiService = jndiService;
} }
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return ConnectionProvider.class.equals( unwrapType ) ||
DatasourceConnectionProviderImpl.class.isAssignableFrom( unwrapType ) ||
DataSource.class.isAssignableFrom( unwrapType );
}
@Override
@SuppressWarnings( {"unchecked"})
public <T> T unwrap(Class<T> unwrapType) {
if ( ConnectionProvider.class.equals( unwrapType ) ||
DatasourceConnectionProviderImpl.class.isAssignableFrom( unwrapType ) ) {
return (T) this;
}
else if ( DataSource.class.isAssignableFrom( unwrapType ) ) {
return (T) getDataSource();
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -35,6 +35,7 @@ import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Stoppable; import org.hibernate.service.spi.Stoppable;
import org.hibernate.service.spi.UnknownUnwrapTypeException;
import org.hibernate.util.ReflectHelper; import org.hibernate.util.ReflectHelper;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -61,6 +62,24 @@ public class DriverManagerConnectionProviderImpl implements ConnectionProvider,
private final ArrayList<Connection> pool = new ArrayList<Connection>(); private final ArrayList<Connection> pool = new ArrayList<Connection>();
private int checkedOut = 0; private int checkedOut = 0;
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return ConnectionProvider.class.equals( unwrapType ) ||
DriverManagerConnectionProviderImpl.class.isAssignableFrom( unwrapType );
}
@Override
@SuppressWarnings( {"unchecked"})
public <T> T unwrap(Class<T> unwrapType) {
if ( ConnectionProvider.class.equals( unwrapType ) ||
DriverManagerConnectionProviderImpl.class.isAssignableFrom( unwrapType ) ) {
return (T) this;
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}
public void configure(Map configurationValues) { public void configure(Map configurationValues) {
LOG.usingHibernateBuiltInConnectionPool(); LOG.usingHibernateBuiltInConnectionPool();

View File

@ -25,6 +25,7 @@ package org.hibernate.service.jdbc.connections.internal;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.spi.UnknownUnwrapTypeException;
/** /**
* An implementation of the {@link ConnectionProvider} interface that simply throws an exception when a connection * An implementation of the {@link ConnectionProvider} interface that simply throws an exception when a connection
@ -35,6 +36,24 @@ import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class UserSuppliedConnectionProviderImpl implements ConnectionProvider { public class UserSuppliedConnectionProviderImpl implements ConnectionProvider {
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return ConnectionProvider.class.equals( unwrapType ) ||
UserSuppliedConnectionProviderImpl.class.isAssignableFrom( unwrapType );
}
@Override
@SuppressWarnings( {"unchecked"})
public <T> T unwrap(Class<T> unwrapType) {
if ( ConnectionProvider.class.equals( unwrapType ) ||
UserSuppliedConnectionProviderImpl.class.isAssignableFrom( unwrapType ) ) {
return (T) this;
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -26,6 +26,7 @@ import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.service.spi.Service; import org.hibernate.service.spi.Service;
import org.hibernate.service.spi.Wrapped;
/** /**
* A contract for obtaining JDBC connections. * A contract for obtaining JDBC connections.
@ -37,7 +38,7 @@ import org.hibernate.service.spi.Service;
* @author Gavin King * @author Gavin King
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface ConnectionProvider extends Service { public interface ConnectionProvider extends Service, Wrapped {
/** /**
* Obtains a connection for Hibernate use according to the underlying strategy of this provider. * Obtains a connection for Hibernate use according to the underlying strategy of this provider.
* *
@ -62,7 +63,7 @@ public interface ConnectionProvider extends Service {
* Does this connection provider support aggressive release of JDBC * Does this connection provider support aggressive release of JDBC
* connections and re-acquistion of those connections (if need be) later? * connections and re-acquistion of those connections (if need be) later?
* <p/> * <p/>
* This is used in conjunction with {@link org.hibernate.cfg.Environment.RELEASE_CONNECTIONS} * This is used in conjunction with {@link org.hibernate.cfg.Environment#RELEASE_CONNECTIONS}
* to aggressively release JDBC connections. However, the configured ConnectionProvider * to aggressively release JDBC connections. However, the configured ConnectionProvider
* must support re-acquisition of the same underlying connection for that semantic to work. * must support re-acquisition of the same underlying connection for that semantic to work.
* <p/> * <p/>

View File

@ -31,14 +31,30 @@ package org.hibernate.service.spi;
*/ */
public interface ServiceRegistry { public interface ServiceRegistry {
/** /**
* Retrieve a service by role. * Retrieve a service by role. If service is not found, but a {@link ServiceInitiator} is registered for
* this service role, the service will be initialized and returned.
* *
* @param type The service role * @param serviceRole The service role
* @param <T> The type of the service * @param <T> The type of the service
* *
* @return The requested service. * @return The requested service.
* *
* @throws UnknownServiceException Indicates the service was not known. * @throws UnknownServiceException Indicates the service was not known.
*/ */
public <T extends Service> T getService(Class<T> type); public <T extends Service> T getService(Class<T> serviceRole);
/**
* Register a service into the registry.
*
* @param serviceRole The service role.
* @param service The service to register
*/
public <T extends Service> void registerService(Class<T> serviceRole, T service);
/**
* Register a service initiator.
*
* @param initiator The initiator of a service
*/
public void registerServiceInitiator(ServiceInitiator initiator);
} }

View File

@ -0,0 +1,61 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.spi;
import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
import org.hibernate.service.classloading.internal.ClassLoaderServiceInitiator;
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 java.util.ArrayList;
import java.util.List;
/**
* @author Steve Ebersole
*/
public class StandardServiceInitiators {
public static List<ServiceInitiator> LIST = buildStandardServiceInitiatorList();
private static List<ServiceInitiator> buildStandardServiceInitiatorList() {
final List<ServiceInitiator> serviceInitiators = new ArrayList<ServiceInitiator>();
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 );
return serviceInitiators;
}
}

View File

@ -0,0 +1,40 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.spi;
import org.hibernate.HibernateException;
/**
* @author Steve Ebersole
*/
public class UnknownUnwrapTypeException extends HibernateException {
public UnknownUnwrapTypeException(Class unwrapType) {
super( "Cannot unwrap to requested type [" + unwrapType.getName() + "]" );
}
public UnknownUnwrapTypeException(Class unwrapType, Throwable root) {
this( unwrapType );
super.initCause( root );
}
}

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.spi;
/**
* @author Steve Ebersole
*/
public interface Wrapped {
/**
* Can this wrapped service be unwrapped as the indicated type?
*
* @param unwrapType The type to check.
*
* @return True/false.
*/
public boolean isUnwrappableAs(Class unwrapType);
/**
* Unproxy the service proxy
*
* @param unwrapType The java type as which to unwrap this instance.
*
* @return The unwrapped reference
*/
public <T> T unwrap(Class<T> unwrapType);
}

View File

@ -0,0 +1,33 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.spi.proxy;
import org.hibernate.service.spi.Service;
/**
* @author Steve Ebersole
*/
public interface ServiceProxyFactory {
public <T extends Service> T makeProxy(Class<T> serviceRole);
}

View File

@ -0,0 +1,31 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.spi.proxy;
/**
* @author Steve Ebersole
*/
public interface ServiceProxyFactoryFactory {
public ServiceProxyFactory makeServiceProxyFactory(ServiceProxyTargetSource registry);
}

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2011, 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.service.spi.proxy;
import org.hibernate.service.spi.Service;
import org.hibernate.service.spi.ServiceRegistry;
/**
* Additional contract for service proxies. This allows the proxies access to their actual service instances.
*
* @author Steve Ebersole
*/
public interface ServiceProxyTargetSource extends ServiceRegistry {
/**
* Retrieve a service by role. Unlike {@link org.hibernate.service.spi.ServiceRegistry#getService}, this version
* will never return a proxy.
*
* @param serviceRole The service role
* @param <T> The type of the service
*
* @return The requested service.
*
* @throws org.hibernate.service.spi.UnknownServiceException Indicates the service was not known.
*/
public <T extends Service> T getServiceInternal(Class<T> serviceRole);
}

View File

@ -29,6 +29,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* Various help for handling collections. * Various help for handling collections.
@ -92,4 +93,37 @@ public final class CollectionHelper {
int actual = ( (int) (numberOfElements / LOAD_FACTOR) ) + 1; int actual = ( (int) (numberOfElements / LOAD_FACTOR) ) + 1;
return Math.max( actual, MINIMUM_INITIAL_CAPACITY ); return Math.max( actual, MINIMUM_INITIAL_CAPACITY );
} }
/**
* Create a properly sized {@link ConcurrentHashMap} based on the given expected number of elements.
*
* @param expectedNumberOfElements The expected number of elements for the created map
* @param <K> The map key type
* @param <V> The map value type
*
* @return The created map.
*/
public static <K,V> ConcurrentHashMap<K,V> concurrentMap(int expectedNumberOfElements) {
return concurrentMap( expectedNumberOfElements, LOAD_FACTOR );
}
/**
* Create a properly sized {@link ConcurrentHashMap} based on the given expected number of elements and an
* explicit load factor
*
* @param expectedNumberOfElements The expected number of elements for the created map
* @param loadFactor The collection load factor
* @param <K> The map key type
* @param <V> The map value type
*
* @return The created map.
*/
public static <K,V> ConcurrentHashMap<K,V> concurrentMap(int expectedNumberOfElements, float loadFactor) {
final int size = expectedNumberOfElements + 1 + (int) ( expectedNumberOfElements * loadFactor );
return new ConcurrentHashMap<K, V>( size, loadFactor );
}
public static <T> List<T> arrayList(int anticipatedSize) {
return new ArrayList<T>( anticipatedSize );
}
} }

View File

@ -22,20 +22,13 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.test.cfg.internal; package org.hibernate.test.cfg.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.H2Dialect;
import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.classloading.internal.ClassLoaderServiceInitiator;
import org.hibernate.service.internal.ServiceRegistryImpl; import org.hibernate.service.internal.ServiceRegistryImpl;
import org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator;
import org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl; 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.service.spi.ServiceInitiator;
import org.hibernate.test.common.ConnectionProviderBuilder; import org.hibernate.test.common.ConnectionProviderBuilder;
import org.hibernate.testing.junit.UnitTestCase; import org.hibernate.testing.junit.UnitTestCase;
@ -45,47 +38,32 @@ import org.hibernate.testing.junit.UnitTestCase;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ServiceBootstrappingTest extends UnitTestCase { public class ServiceBootstrappingTest extends UnitTestCase {
private ServiceRegistryImpl servicesRegistry;
public ServiceBootstrappingTest(String string) { public ServiceBootstrappingTest(String string) {
super( string ); super( string );
} }
@Override
protected void setUp() {
List<ServiceInitiator> serviceInitiators = new ArrayList<ServiceInitiator>();
serviceInitiators.add( ClassLoaderServiceInitiator.INSTANCE );
serviceInitiators.add( ConnectionProviderInitiator.INSTANCE );
serviceInitiators.add( DialectResolverInitiator.INSTANCE );
serviceInitiators.add( DialectFactoryInitiator.INSTANCE );
serviceInitiators.add( JdbcServicesInitiator.INSTANCE );
servicesRegistry = new ServiceRegistryImpl( serviceInitiators );
}
@Override
protected void tearDown() {
servicesRegistry.destroy();
}
public void testBasicBuild() { public void testBasicBuild() {
servicesRegistry.initialize( ConnectionProviderBuilder.getConnectionProviderProperties() ); ServiceRegistryImpl serviceRegistry = new ServiceRegistryImpl( ConnectionProviderBuilder.getConnectionProviderProperties() );
JdbcServices jdbcServices = servicesRegistry.getService( JdbcServices.class ); JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
assertTrue( jdbcServices.getDialect() instanceof H2Dialect ); assertTrue( jdbcServices.getDialect() instanceof H2Dialect );
assertTrue( jdbcServices.getConnectionProvider() instanceof DriverManagerConnectionProviderImpl ); assertTrue( jdbcServices.getConnectionProvider().isUnwrappableAs( DriverManagerConnectionProviderImpl.class ) );
assertFalse( jdbcServices.getSqlStatementLogger().isLogToStdout() ); assertFalse( jdbcServices.getSqlStatementLogger().isLogToStdout() );
serviceRegistry.destroy();
} }
public void testBuildWithLogging() { public void testBuildWithLogging() {
Properties props = ConnectionProviderBuilder.getConnectionProviderProperties(); Properties props = ConnectionProviderBuilder.getConnectionProviderProperties();
props.put( Environment.SHOW_SQL, "true" ); props.put( Environment.SHOW_SQL, "true" );
servicesRegistry.initialize( props ); ServiceRegistryImpl serviceRegistry = new ServiceRegistryImpl( props );
JdbcServices jdbcServices = servicesRegistry.getService( JdbcServices.class ); JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
assertTrue( jdbcServices.getDialect() instanceof H2Dialect ); assertTrue( jdbcServices.getDialect() instanceof H2Dialect );
assertTrue( jdbcServices.getConnectionProvider() instanceof DriverManagerConnectionProviderImpl ); assertTrue( jdbcServices.getConnectionProvider().isUnwrappableAs( DriverManagerConnectionProviderImpl.class ) );
assertTrue( jdbcServices.getSqlStatementLogger().isLogToStdout() ); assertTrue( jdbcServices.getSqlStatementLogger().isLogToStdout() );
serviceRegistry.destroy();
} }
} }

View File

@ -28,6 +28,7 @@ import java.util.Properties;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.spi.Stoppable; import org.hibernate.service.spi.Stoppable;
import org.hibernate.service.spi.UnknownUnwrapTypeException;
import org.hibernate.test.common.ConnectionProviderBuilder; import org.hibernate.test.common.ConnectionProviderBuilder;
/** /**
@ -49,6 +50,28 @@ public class ConnectionProviderImpl implements ConnectionProvider {
public void configure(Properties props) throws HibernateException { public void configure(Properties props) throws HibernateException {
} }
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return ConnectionProviderImpl.class.isAssignableFrom( unwrapType ) ||
ConnectionProvider.class.isAssignableFrom( unwrapType ) ||
getActualConnectionProvider().getClass().isAssignableFrom( unwrapType );
}
@Override
@SuppressWarnings( {"unchecked"})
public <T> T unwrap(Class<T> unwrapType) {
if ( ConnectionProviderImpl.class.isAssignableFrom( unwrapType ) ) {
return (T) this;
}
else if ( ConnectionProvider.class.isAssignableFrom( unwrapType ) ||
getActualConnectionProvider().getClass().isAssignableFrom( unwrapType ) ) {
return (T) getActualConnectionProvider();
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException {
SimpleJtaTransactionImpl currentTransaction = SimpleJtaTransactionManagerImpl.getInstance().getCurrentTransaction(); SimpleJtaTransactionImpl currentTransaction = SimpleJtaTransactionManagerImpl.getInstance().getCurrentTransaction();
if ( currentTransaction == null ) { if ( currentTransaction == null ) {

View File

@ -27,6 +27,7 @@ import java.sql.SQLException;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.spi.Stoppable; import org.hibernate.service.spi.Stoppable;
import org.hibernate.service.spi.UnknownUnwrapTypeException;
import org.hibernate.test.common.ConnectionProviderBuilder; import org.hibernate.test.common.ConnectionProviderBuilder;
/** /**
@ -40,6 +41,26 @@ public class DualNodeConnectionProviderImpl implements ConnectionProvider {
private String nodeId; private String nodeId;
private boolean isTransactional; private boolean isTransactional;
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return DualNodeConnectionProviderImpl.class.isAssignableFrom( unwrapType ) ||
ConnectionProvider.class.isAssignableFrom( unwrapType );
}
@Override
@SuppressWarnings( {"unchecked"})
public <T> T unwrap(Class<T> unwrapType) {
if ( DualNodeConnectionProviderImpl.class.isAssignableFrom( unwrapType ) ) {
return (T) this;
}
else if ( ConnectionProvider.class.isAssignableFrom( unwrapType ) ) {
return (T) actualConnectionProvider;
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}
public static ConnectionProvider getActualConnectionProvider() { public static ConnectionProvider getActualConnectionProvider() {
return actualConnectionProvider; return actualConnectionProvider;
} }

View File

@ -26,6 +26,7 @@ import java.util.Properties;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.spi.Stoppable; import org.hibernate.service.spi.Stoppable;
import org.hibernate.service.spi.UnknownUnwrapTypeException;
import org.hibernate.test.common.ConnectionProviderBuilder; import org.hibernate.test.common.ConnectionProviderBuilder;
/** /**
@ -35,45 +36,68 @@ import org.hibernate.test.common.ConnectionProviderBuilder;
* @since 3.5 * @since 3.5
*/ */
public class XaConnectionProvider implements ConnectionProvider { public class XaConnectionProvider implements ConnectionProvider {
private static ConnectionProvider actualConnectionProvider = ConnectionProviderBuilder.buildConnectionProvider(); private static ConnectionProvider actualConnectionProvider = ConnectionProviderBuilder.buildConnectionProvider();
private boolean isTransactional; private boolean isTransactional;
public static ConnectionProvider getActualConnectionProvider() { public static ConnectionProvider getActualConnectionProvider() {
return actualConnectionProvider; return actualConnectionProvider;
} }
public void configure(Properties props) throws HibernateException { @Override
} public boolean isUnwrappableAs(Class unwrapType) {
return XaConnectionProvider.class.isAssignableFrom( unwrapType ) ||
ConnectionProvider.class.equals( unwrapType ) ||
actualConnectionProvider.getClass().isAssignableFrom( unwrapType );
}
public Connection getConnection() throws SQLException { @Override
XaTransactionImpl currentTransaction = XaTransactionManagerImpl.getInstance().getCurrentTransaction(); @SuppressWarnings( {"unchecked"})
if (currentTransaction == null) { public <T> T unwrap(Class<T> unwrapType) {
isTransactional = false; if ( XaConnectionProvider.class.isAssignableFrom( unwrapType ) ) {
return actualConnectionProvider.getConnection(); return (T) this;
} else { }
isTransactional = true; else if ( ConnectionProvider.class.isAssignableFrom( unwrapType ) ||
Connection connection = currentTransaction.getEnlistedConnection(); actualConnectionProvider.getClass().isAssignableFrom( unwrapType ) ) {
if (connection == null) { return (T) getActualConnectionProvider();
connection = actualConnectionProvider.getConnection(); }
currentTransaction.enlistConnection(connection); else {
} throw new UnknownUnwrapTypeException( unwrapType );
return connection; }
} }
}
public void closeConnection(Connection conn) throws SQLException { public void configure(Properties props) throws HibernateException {
if (!isTransactional) { }
conn.close();
}
}
public void close() throws HibernateException { public Connection getConnection() throws SQLException {
if ( actualConnectionProvider instanceof Stoppable ) { XaTransactionImpl currentTransaction = XaTransactionManagerImpl.getInstance().getCurrentTransaction();
( ( Stoppable ) actualConnectionProvider ).stop(); if ( currentTransaction == null ) {
} isTransactional = false;
} return actualConnectionProvider.getConnection();
}
else {
isTransactional = true;
Connection connection = currentTransaction.getEnlistedConnection();
if ( connection == null ) {
connection = actualConnectionProvider.getConnection();
currentTransaction.enlistConnection( connection );
}
return connection;
}
}
public boolean supportsAggressiveRelease() { public void closeConnection(Connection conn) throws SQLException {
return true; if ( !isTransactional ) {
} conn.close();
}
}
public void close() throws HibernateException {
if ( actualConnectionProvider instanceof Stoppable ) {
((Stoppable) actualConnectionProvider).stop();
}
}
public boolean supportsAggressiveRelease() {
return true;
}
} }

View File

@ -30,6 +30,7 @@ import org.hibernate.HibernateException;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.spi.UnknownUnwrapTypeException;
import org.hibernate.util.ConfigHelper; import org.hibernate.util.ConfigHelper;
import org.hibernate.util.StringHelper; import org.hibernate.util.StringHelper;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -79,6 +80,24 @@ public class ProxoolConnectionProvider implements ConnectionProvider {
return c; return c;
} }
@Override
public boolean isUnwrappableAs(Class unwrapType) {
return ConnectionProvider.class.equals( unwrapType ) ||
ProxoolConnectionProvider.class.isAssignableFrom( unwrapType );
}
@Override
@SuppressWarnings( {"unchecked"})
public <T> T unwrap(Class<T> unwrapType) {
if ( ConnectionProvider.class.equals( unwrapType ) ||
ProxoolConnectionProvider.class.isAssignableFrom( unwrapType ) ) {
return (T) this;
}
else {
throw new UnknownUnwrapTypeException( unwrapType );
}
}
/** /**
* Dispose of a used connection. * Dispose of a used connection.
* @param conn a JDBC connection * @param conn a JDBC connection