HHH-6081 - Finish up Integrator

This commit is contained in:
Steve Ebersole 2011-04-05 16:10:41 -05:00
parent bd5c483b67
commit aad256c634
6 changed files with 55 additions and 198 deletions

View File

@ -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
}
}

View File

@ -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<PersistentClass> persistentClasses = ( (Map<String,PersistentClass>) 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;
}
}
}

View File

@ -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
}
}

View File

@ -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<Integrator> integrators = new ArrayList<Integrator>();
@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<Integrator> locateIntegrators(ServiceRegistryImplementor serviceRegistry) {
List<Integrator> integrators = new ArrayList<Integrator>();
// 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();
for ( Integrator integrator : ServiceLoader.load( Integrator.class ) ) {
integrators.add( integrator );
}
ClassLoaderService classLoader = serviceRegistry.getService( ClassLoaderService.class );
List<URL> 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() );
}
}
return integrators;
}

View File

@ -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);
}

View File

@ -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
}
}