diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java index ad98076bbf..8630194f16 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationIntegrator.java @@ -37,7 +37,7 @@ import org.hibernate.HibernateLogger; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.impl.Integrator; +import org.hibernate.spi.Integrator; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.classloading.spi.ClassLoaderService; import org.hibernate.service.event.spi.EventListenerRegistry; @@ -49,6 +49,8 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistry; public class BeanValidationIntegrator implements Integrator { private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, BeanValidationIntegrator.class.getName()); + public static final String APPLY_CONSTRAINTS = "hibernate.validator.apply_to_ddl"; + public static final String BV_CHECK_CLASS = "javax.validation.Validation"; public static final String MODE_PROPERTY = "javax.persistence.validation.mode"; @@ -149,7 +151,7 @@ public class BeanValidationIntegrator implements Integrator { boolean beanValidationAvailable, Class typeSafeActivatorClass, Configuration configuration) { - if ( ! ConfigurationHelper.getBoolean( LegacyHibernateValidationIntegrator.APPLY_CONSTRAINTS, configuration.getProperties(), true ) ){ + if ( ! ConfigurationHelper.getBoolean( APPLY_CONSTRAINTS, configuration.getProperties(), true ) ){ LOG.debug( "Skipping application of relational constraints from legacy Hibernate Validator" ); return; } @@ -287,4 +289,8 @@ public class BeanValidationIntegrator implements Integrator { } } + @Override + public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + // nothing to do here afaik + } } diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/LegacyHibernateValidationIntegrator.java b/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/LegacyHibernateValidationIntegrator.java deleted file mode 100644 index b1f1c12972..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/LegacyHibernateValidationIntegrator.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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.cfg.beanvalidation; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.util.Map; -import java.util.ResourceBundle; - -import org.jboss.logging.Logger; - -import org.hibernate.AnnotationException; -import org.hibernate.HibernateLogger; -import org.hibernate.annotations.common.reflection.ReflectionManager; -import org.hibernate.cfg.Configuration; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.event.EventType; -import org.hibernate.event.PreInsertEventListener; -import org.hibernate.event.PreUpdateEventListener; -import org.hibernate.impl.Integrator; -import org.hibernate.internal.util.ReflectHelper; -import org.hibernate.internal.util.StringHelper; -import org.hibernate.internal.util.config.ConfigurationHelper; -import org.hibernate.mapping.PersistentClass; -import org.hibernate.service.classloading.spi.ClassLoaderService; -import org.hibernate.service.event.spi.EventListenerRegistry; -import org.hibernate.service.spi.SessionFactoryServiceRegistry; - -/** - * @author Steve Ebersole - */ -public class LegacyHibernateValidationIntegrator implements Integrator { - private static final HibernateLogger LOG = Logger.getMessageLogger( HibernateLogger.class, LegacyHibernateValidationIntegrator.class.getName() ); - - public static final String APPLY_CONSTRAINTS = "hibernate.validator.apply_to_ddl"; - public static final String CLASS_VALIDATOR_CLASS = "org.hibernate.validator.ClassValidator"; - public static final String MSG_INTERPOLATOR_CLASS = "org.hibernate.validator.MessageInterpolator"; - - public static final String AUTO_REGISTER = "hibernate.validator.autoregister_listeners"; - public static final String LISTENER_CLASS_NAME = "org.hibernate.validator.event.ValidateEventListener"; - - // this code mostly all copied and pasted from various spots... - - @Override - public void integrate( - Configuration configuration, - SessionFactoryImplementor sessionFactory, - SessionFactoryServiceRegistry serviceRegistry) { - applyRelationalConstraints( configuration, serviceRegistry ); - applyListeners( configuration, serviceRegistry ); - } - - @SuppressWarnings( {"unchecked"}) - private void applyRelationalConstraints(Configuration configuration, SessionFactoryServiceRegistry serviceRegistry) { - if ( ! ConfigurationHelper.getBoolean( APPLY_CONSTRAINTS, configuration.getProperties(), true ) ){ - LOG.debug( "Skipping application of relational constraints from legacy Hibernate Validator" ); - return; - } - - Constructor validatorCtr = null; - Method applyMethod = null; - try { - final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); - final Class classValidator = classLoaderService.classForName( CLASS_VALIDATOR_CLASS ); - final Class messageInterpolator = classLoaderService.classForName( MSG_INTERPOLATOR_CLASS ); - validatorCtr = classValidator.getDeclaredConstructor( - Class.class, ResourceBundle.class, messageInterpolator, Map.class, ReflectionManager.class - ); - applyMethod = classValidator.getMethod( "apply", PersistentClass.class ); - } - catch ( NoSuchMethodException e ) { - throw new AnnotationException( e ); - } - catch ( Exception e ) { - LOG.debug( "Legacy Hibernate Validator classes not found, ignoring" ); - } - - if ( applyMethod != null ) { - Iterable persistentClasses = ( (Map) configuration.createMappings().getClasses() ).values(); - for ( PersistentClass persistentClass : persistentClasses ) { - // integrate the validate framework - String className = persistentClass.getClassName(); - if ( StringHelper.isNotEmpty( className ) ) { - try { - Object validator = validatorCtr.newInstance( - ReflectHelper.classForName( className ), null, null, null, configuration.getReflectionManager() - ); - applyMethod.invoke( validator, persistentClass ); - } - catch ( Exception e ) { - LOG.unableToApplyConstraints(className, e); - } - } - } - } - } - - private void applyListeners(Configuration configuration, SessionFactoryServiceRegistry serviceRegistry) { - final boolean registerListeners = ConfigurationHelper.getBoolean( AUTO_REGISTER, configuration.getProperties(), false ); - if ( !registerListeners ) { - LOG.debug( "Skipping legacy validator auto registration" ); - return; - } - - final Class listenerClass = loadListenerClass( serviceRegistry ); - if ( listenerClass == null ) { - LOG.debug( "Skipping legacy validator auto registration - could not locate listener" ); - return; - } - - final Object validateEventListener; - try { - validateEventListener = listenerClass.newInstance(); - } - catch ( Exception e ) { - throw new AnnotationException( "Unable to instantiate Validator event listener", e ); - } - - EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class ); - // todo : duplication strategy - - listenerRegistry.appendListeners( EventType.PRE_INSERT, (PreInsertEventListener) validateEventListener ); - listenerRegistry.appendListeners( EventType.PRE_UPDATE, (PreUpdateEventListener) validateEventListener ); - } - - private Class loadListenerClass(SessionFactoryServiceRegistry serviceRegistry) { - try { - return serviceRegistry.getService( ClassLoaderService.class ).classForName( LISTENER_CLASS_NAME ); - } - catch (Exception e) { - return null; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/search/HibernateSearchIntegrator.java b/hibernate-core/src/main/java/org/hibernate/cfg/search/HibernateSearchIntegrator.java index 766652e5cf..a3dabdc764 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/search/HibernateSearchIntegrator.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/search/HibernateSearchIntegrator.java @@ -36,7 +36,7 @@ import org.hibernate.event.PostCollectionUpdateEventListener; import org.hibernate.event.PostDeleteEventListener; import org.hibernate.event.PostInsertEventListener; import org.hibernate.event.PostUpdateEventListener; -import org.hibernate.impl.Integrator; +import org.hibernate.spi.Integrator; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.classloading.spi.ClassLoaderService; import org.hibernate.service.event.spi.DuplicationStrategy; @@ -126,4 +126,9 @@ public class HibernateSearchIntegrator implements Integrator { return Action.KEEP_ORIGINAL; } } + + @Override + public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + // nothing to do here afaik + } } diff --git a/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java index 6daaaf096a..acc9bf4d82 100644 --- a/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/impl/SessionFactoryImpl.java @@ -27,13 +27,11 @@ import javax.naming.NamingException; import javax.naming.Reference; import javax.naming.StringRefAddr; import java.io.IOException; -import java.io.InputStream; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; import java.io.Serializable; -import java.net.URL; import java.sql.Connection; import java.util.ArrayList; import java.util.Collections; @@ -44,6 +42,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -82,7 +81,6 @@ import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.cfg.Settings; import org.hibernate.cfg.beanvalidation.BeanValidationIntegrator; -import org.hibernate.cfg.beanvalidation.LegacyHibernateValidationIntegrator; import org.hibernate.cfg.search.HibernateSearchIntegrator; import org.hibernate.context.CurrentSessionContext; import org.hibernate.context.JTASessionContext; @@ -125,12 +123,12 @@ import org.hibernate.persister.spi.PersisterFactory; import org.hibernate.pretty.MessageHelper; import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.service.ServiceRegistry; -import org.hibernate.service.classloading.spi.ClassLoaderService; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jta.platform.spi.JtaPlatform; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.SessionFactoryServiceRegistry; import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory; +import org.hibernate.spi.Integrator; import org.hibernate.stat.Statistics; import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.tool.hbm2ddl.SchemaExport; @@ -245,8 +243,26 @@ public final class SessionFactoryImpl // todo : everything above here consider implementing as standard SF service. specifically: stats, caches, types, function-reg + class IntegratorObserver implements SessionFactoryObserver { + private ArrayList integrators = new ArrayList(); + + @Override + public void sessionFactoryCreated(SessionFactory factory) { + } + + @Override + public void sessionFactoryClosed(SessionFactory factory) { + for ( Integrator integrator : integrators ) { + integrator.disintegrate( SessionFactoryImpl.this, SessionFactoryImpl.this.serviceRegistry ); + } + } + } + + final IntegratorObserver integratorObserver = new IntegratorObserver(); + this.observer.addObserver( integratorObserver ); for ( Integrator integrator : locateIntegrators( this.serviceRegistry ) ) { - integrator.integrate( cfg, this, (SessionFactoryServiceRegistry) this.serviceRegistry ); + integrator.integrate( cfg, this, this.serviceRegistry ); + integratorObserver.integrators.add( integrator ); } //Generators: @@ -490,43 +506,14 @@ public final class SessionFactoryImpl private Iterable locateIntegrators(ServiceRegistryImplementor serviceRegistry) { List integrators = new ArrayList(); - // todo : Envers needs to bbe handled by discovery to be because it is in a separate project - integrators.add( new LegacyHibernateValidationIntegrator() ); + // todo : Envers needs to be handled by discovery to be because it is in a separate project integrators.add( new BeanValidationIntegrator() ); integrators.add( new HibernateSearchIntegrator() ); - final Properties properties = new Properties(); - - ClassLoaderService classLoader = serviceRegistry.getService( ClassLoaderService.class ); - List urls = classLoader.locateResources( "META-INF/hibernate/org.hibernate.impl.Integrator" ); - for ( URL url : urls ) { - try { - final InputStream propertyStream = url.openStream(); - try { - properties.clear(); - properties.load( propertyStream ); - // for now we only understand 'implClass' as key - final String implClass = properties.getProperty( "implClass" ); - Class integratorClass = classLoader.classForName( implClass ); - try { - integrators.add( (Integrator) integratorClass.newInstance() ); - } - catch (Exception e) { - throw new HibernateException( "Unable to instantiate specified Integrator class [" + implClass + "]", e ); - } - } - finally { - try { - propertyStream.close(); - } - catch (IOException ignore) { - } - } - } - catch ( IOException ioe ) { - LOG.debugf( ioe, "Unable to process Integrator service file [%s], skipping" , url.toExternalForm() ); - } + for ( Integrator integrator : ServiceLoader.load( Integrator.class ) ) { + integrators.add( integrator ); } + return integrators; } diff --git a/hibernate-core/src/main/java/org/hibernate/impl/Integrator.java b/hibernate-core/src/main/java/org/hibernate/spi/Integrator.java similarity index 84% rename from hibernate-core/src/main/java/org/hibernate/impl/Integrator.java rename to hibernate-core/src/main/java/org/hibernate/spi/Integrator.java index 8559dcc13d..b01d1dc513 100644 --- a/hibernate-core/src/main/java/org/hibernate/impl/Integrator.java +++ b/hibernate-core/src/main/java/org/hibernate/spi/Integrator.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.impl; +package org.hibernate.spi; import org.hibernate.cfg.Configuration; import org.hibernate.engine.SessionFactoryImplementor; @@ -40,6 +40,7 @@ import org.hibernate.service.spi.SessionFactoryServiceRegistry; * @author Steve Ebersole * @since 4.0 * @jira HHH-5562 + * @jira HHH-6081 */ public interface Integrator { /** @@ -53,4 +54,12 @@ public interface Integrator { Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry); + + /** + * Tongue-in-cheek name for a shutdown callback. + * + * @param sessionFactory The session factory being closed. + * @param serviceRegistry That session factory's service registry + */ + public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry); } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversIntegrator.java b/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversIntegrator.java index 48500c7d30..9c75de4019 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversIntegrator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/event/EnversIntegrator.java @@ -30,7 +30,7 @@ import org.hibernate.cfg.Configuration; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.envers.configuration.AuditConfiguration; import org.hibernate.event.EventType; -import org.hibernate.impl.Integrator; +import org.hibernate.spi.Integrator; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.event.spi.EventListenerRegistry; import org.hibernate.service.spi.SessionFactoryServiceRegistry; @@ -70,4 +70,9 @@ public class EnversIntegrator implements Integrator { listenerRegistry.appendListeners( EventType.PRE_COLLECTION_UPDATE, new EnversPreCollectionUpdateEventListenerImpl( enversConfiguration ) ); } } + + @Override + public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { + // nothing to do afaik + } }