HHH-5913 - Implement set of event listeners as a service
This commit is contained in:
parent
42c609cfdd
commit
e3a0525fb1
|
@ -35,8 +35,6 @@ import java.io.InputStream;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringReader;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -50,7 +48,6 @@ import java.util.List;
|
|||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TreeMap;
|
||||
|
@ -83,7 +80,6 @@ import org.hibernate.annotations.common.reflection.ReflectionManager;
|
|||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
|
||||
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
|
||||
import org.hibernate.cfg.beanvalidation.BeanValidationActivator;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
|
@ -92,10 +88,6 @@ import org.hibernate.engine.Mapping;
|
|||
import org.hibernate.engine.NamedQueryDefinition;
|
||||
import org.hibernate.engine.NamedSQLQueryDefinition;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.event.EventListenerRegistration;
|
||||
import org.hibernate.event.EventType;
|
||||
import org.hibernate.event.PreInsertEventListener;
|
||||
import org.hibernate.event.PreUpdateEventListener;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
import org.hibernate.id.IdentifierGeneratorAggregator;
|
||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
|
@ -138,11 +130,7 @@ import org.hibernate.mapping.UniqueKey;
|
|||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||
import org.hibernate.secure.JACCConfiguration;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.service.StandardServiceInitiators;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.event.spi.EventListenerRegistry;
|
||||
import org.hibernate.service.internal.BasicServiceRegistryImpl;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
||||
import org.hibernate.tool.hbm2ddl.IndexMetadata;
|
||||
import org.hibernate.tool.hbm2ddl.TableMetadata;
|
||||
|
@ -1378,8 +1366,6 @@ public class Configuration implements Serializable {
|
|||
buildUniqueKeyFromColumnNames( table, keyName, holder.getColumns() );
|
||||
}
|
||||
}
|
||||
|
||||
applyConstraintsToDDL();
|
||||
}
|
||||
|
||||
private void processSecondPassesOfType(Class<? extends SecondPass> type) {
|
||||
|
@ -1577,68 +1563,6 @@ public class Configuration implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
private void applyConstraintsToDDL() {
|
||||
boolean applyOnDdl = getProperties().getProperty(
|
||||
"hibernate.validator.apply_to_ddl",
|
||||
"true"
|
||||
)
|
||||
.equalsIgnoreCase( "true" );
|
||||
|
||||
if ( !applyOnDdl ) {
|
||||
return; // nothing to do in this case
|
||||
}
|
||||
applyHibernateValidatorLegacyConstraintsOnDDL();
|
||||
applyBeanValidationConstraintsOnDDL();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private void applyHibernateValidatorLegacyConstraintsOnDDL() {
|
||||
//TODO search for the method only once and cache it?
|
||||
Constructor validatorCtr = null;
|
||||
Method applyMethod = null;
|
||||
try {
|
||||
Class classValidator = ReflectHelper.classForName(
|
||||
"org.hibernate.validator.ClassValidator", this.getClass()
|
||||
);
|
||||
Class messageInterpolator = ReflectHelper.classForName(
|
||||
"org.hibernate.validator.MessageInterpolator", this.getClass()
|
||||
);
|
||||
validatorCtr = classValidator.getDeclaredConstructor(
|
||||
Class.class, ResourceBundle.class, messageInterpolator, Map.class, ReflectionManager.class
|
||||
);
|
||||
applyMethod = classValidator.getMethod( "apply", PersistentClass.class );
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
if (!isValidatorNotPresentLogged) LOG.validatorNotFound();
|
||||
isValidatorNotPresentLogged = true;
|
||||
}
|
||||
catch ( NoSuchMethodException e ) {
|
||||
throw new AnnotationException( e );
|
||||
}
|
||||
if ( applyMethod != null ) {
|
||||
for ( PersistentClass persistentClazz : classes.values() ) {
|
||||
//integrate the validate framework
|
||||
String className = persistentClazz.getClassName();
|
||||
if ( StringHelper.isNotEmpty( className ) ) {
|
||||
try {
|
||||
Object validator = validatorCtr.newInstance(
|
||||
ReflectHelper.classForName( className ), null, null, null, reflectionManager
|
||||
);
|
||||
applyMethod.invoke( validator, persistentClazz );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.unableToApplyConstraints(className, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private void applyBeanValidationConstraintsOnDDL() {
|
||||
BeanValidationActivator.applyDDL( classes.values(), getProperties() );
|
||||
}
|
||||
|
||||
private void originalSecondPassCompile() throws MappingException {
|
||||
LOG.debugf("Processing extends queue");
|
||||
processExtendsQueue();
|
||||
|
@ -1789,12 +1713,8 @@ public class Configuration implements Serializable {
|
|||
secondPassCompile();
|
||||
if (!metadataSourceQueue.isEmpty()) LOG.incompleteMappingMetadataCacheProcessing();
|
||||
|
||||
// todo : processing listeners for validator and search (and envers) requires HHH-5562
|
||||
enableLegacyHibernateValidator( serviceRegistry );
|
||||
enableBeanValidation( serviceRegistry );
|
||||
// enableHibernateSearch();
|
||||
|
||||
validate();
|
||||
|
||||
Environment.verifyProperties( properties );
|
||||
Properties copy = new Properties();
|
||||
copy.putAll( properties );
|
||||
|
@ -1840,118 +1760,6 @@ public class Configuration implements Serializable {
|
|||
return buildSessionFactory( serviceRegistry );
|
||||
}
|
||||
|
||||
private static final String LEGACY_VALIDATOR_EVENT_LISTENER = "org.hibernate.validator.event.ValidateEventListener";
|
||||
|
||||
private void enableLegacyHibernateValidator(ServiceRegistry serviceRegistry) {
|
||||
serviceRegistry.getService( StandardServiceInitiators.EventListenerRegistrationService.class )
|
||||
.attachEventListenerRegistration( new LegacyHibernateValidatorEventListenerRegistration( properties ) );
|
||||
}
|
||||
|
||||
public static class LegacyHibernateValidatorEventListenerRegistration implements EventListenerRegistration {
|
||||
private final Properties configurationProperties;
|
||||
|
||||
public LegacyHibernateValidatorEventListenerRegistration(Properties configurationProperties) {
|
||||
this.configurationProperties = configurationProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(
|
||||
EventListenerRegistry eventListenerRegistry,
|
||||
Configuration configuration, Map<?, ?> configValues, ServiceRegistryImplementor serviceRegistry
|
||||
) {
|
||||
boolean loadLegacyValidator = ConfigurationHelper.getBoolean( "hibernate.validator.autoregister_listeners", configurationProperties, false );
|
||||
|
||||
Class validateEventListenerClass = null;
|
||||
try {
|
||||
validateEventListenerClass = serviceRegistry.getService( ClassLoaderService.class ).classForName( LEGACY_VALIDATOR_EVENT_LISTENER );
|
||||
}
|
||||
catch ( Exception ignored) {
|
||||
}
|
||||
|
||||
if ( ! loadLegacyValidator || validateEventListenerClass == null) {
|
||||
LOG.debugf( "Skipping legacy validator loading" );
|
||||
return;
|
||||
}
|
||||
|
||||
final Object validateEventListener;
|
||||
try {
|
||||
validateEventListener = validateEventListenerClass.newInstance();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new AnnotationException( "Unable to load 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 void enableBeanValidation(ServiceRegistry serviceRegistry) {
|
||||
serviceRegistry.getService( StandardServiceInitiators.EventListenerRegistrationService.class ).attachEventListenerRegistration(
|
||||
new EventListenerRegistration() {
|
||||
@Override
|
||||
public void apply(
|
||||
EventListenerRegistry eventListenerRegistry,
|
||||
Configuration configuration,
|
||||
Map<?, ?> configValues,
|
||||
ServiceRegistryImplementor serviceRegistry) {
|
||||
BeanValidationActivator.activateBeanValidation( eventListenerRegistry, getProperties() );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static final String SEARCH_EVENT_LISTENER_REGISTERER_CLASS = "org.hibernate.cfg.search.HibernateSearchEventListenerRegister";
|
||||
|
||||
/**
|
||||
* Tries to automatically register Hibernate Search event listeners by locating the
|
||||
* appropriate bootstrap class and calling the <code>enableHibernateSearch</code> method.
|
||||
*/
|
||||
// private void enableHibernateSearch() {
|
||||
// // load the bootstrap class
|
||||
// Class searchStartupClass;
|
||||
// try {
|
||||
// searchStartupClass = ReflectHelper.classForName( SEARCH_STARTUP_CLASS, getClass() );
|
||||
// }
|
||||
// catch ( ClassNotFoundException e ) {
|
||||
// // TODO remove this together with SearchConfiguration after 3.1.0 release of Search
|
||||
// // try loading deprecated HibernateSearchEventListenerRegister
|
||||
// try {
|
||||
// searchStartupClass = ReflectHelper.classForName( SEARCH_EVENT_LISTENER_REGISTERER_CLASS, getClass() );
|
||||
// }
|
||||
// catch ( ClassNotFoundException cnfe ) {
|
||||
// LOG.debugf("Search not present in classpath, ignoring event listener registration.");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // call the method for registering the listeners
|
||||
// try {
|
||||
// Object searchStartupInstance = searchStartupClass.newInstance();
|
||||
// Method enableSearchMethod = searchStartupClass.getDeclaredMethod(
|
||||
// SEARCH_STARTUP_METHOD,
|
||||
// EventListeners.class,
|
||||
// Properties.class
|
||||
// );
|
||||
// enableSearchMethod.invoke( searchStartupInstance, getEventListeners(), getProperties() );
|
||||
// }
|
||||
// catch ( InstantiationException e ) {
|
||||
// LOG.debugf("Unable to instantiate %s, ignoring event listener registration.", SEARCH_STARTUP_CLASS);
|
||||
// }
|
||||
// catch ( IllegalAccessException e ) {
|
||||
// LOG.debugf("Unable to instantiate %s, ignoring event listener registration.", SEARCH_STARTUP_CLASS);
|
||||
// }
|
||||
// catch ( NoSuchMethodException e ) {
|
||||
// LOG.debugf("Method %s() not found in %s", SEARCH_STARTUP_METHOD, SEARCH_STARTUP_CLASS);
|
||||
// }
|
||||
// catch ( InvocationTargetException e ) {
|
||||
// LOG.debugf("Unable to execute %s, ignoring event listener registration.", SEARCH_STARTUP_METHOD);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Rterieve the configured {@link Interceptor}.
|
||||
*
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg.beanvalidation;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.service.event.spi.EventListenerRegistry;
|
||||
|
||||
/**
|
||||
* This class has no hard dependency on Bean Validation APIs
|
||||
* It must use reflection every time BV is required.
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class BeanValidationActivator {
|
||||
private static final String BV_DISCOVERY_CLASS = "javax.validation.Validation";
|
||||
private static final String TYPE_SAFE_ACTIVATOR_CLASS = "org.hibernate.cfg.beanvalidation.TypeSafeActivator";
|
||||
private static final String TYPE_SAFE_DDL_METHOD = "applyDDL";
|
||||
private static final String TYPE_SAFE_ACTIVATOR_METHOD = "activateBeanValidation";
|
||||
private static final String MODE_PROPERTY = "javax.persistence.validation.mode";
|
||||
|
||||
public static void activateBeanValidation(EventListenerRegistry listenerRegistry, Properties properties) {
|
||||
Set<ValidationMode> modes = ValidationMode.getModes( properties.get( MODE_PROPERTY ) );
|
||||
|
||||
try {
|
||||
//load Validation
|
||||
ReflectHelper.classForName( BV_DISCOVERY_CLASS, BeanValidationActivator.class );
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
if ( modes.contains( ValidationMode.CALLBACK ) ) {
|
||||
throw new HibernateException( "Bean Validation not available in the class path but required in " + MODE_PROPERTY );
|
||||
}
|
||||
else if (modes.contains( ValidationMode.AUTO ) ) {
|
||||
//nothing to activate
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//de-activate not-null tracking at the core level when Bean Validation
|
||||
// is present unless the user really asks for it
|
||||
//Note that if BV is not present, the behavior is backward compatible
|
||||
if ( properties.getProperty( Environment.CHECK_NULLABILITY ) == null ) {
|
||||
properties.setProperty( Environment.CHECK_NULLABILITY, "false" );
|
||||
}
|
||||
|
||||
if ( ! ( modes.contains( ValidationMode.CALLBACK ) || modes.contains( ValidationMode.AUTO ) ) ) return;
|
||||
|
||||
try {
|
||||
Class<?> activator = ReflectHelper.classForName( TYPE_SAFE_ACTIVATOR_CLASS, BeanValidationActivator.class );
|
||||
Method activateBeanValidation =
|
||||
activator.getMethod( TYPE_SAFE_ACTIVATOR_METHOD, EventListenerRegistry.class, Properties.class );
|
||||
activateBeanValidation.invoke( null, listenerRegistry, properties );
|
||||
}
|
||||
catch ( NoSuchMethodException e ) {
|
||||
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||
}
|
||||
catch ( IllegalAccessException e ) {
|
||||
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||
}
|
||||
catch ( InvocationTargetException e ) {
|
||||
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void applyDDL(Collection<PersistentClass> persistentClasses, Properties properties) {
|
||||
Set<ValidationMode> modes = ValidationMode.getModes( properties.get( MODE_PROPERTY ) );
|
||||
if ( ! ( modes.contains( ValidationMode.DDL ) || modes.contains( ValidationMode.AUTO ) ) ) return;
|
||||
try {
|
||||
//load Validation
|
||||
ReflectHelper.classForName( BV_DISCOVERY_CLASS, BeanValidationActivator.class );
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
if ( modes.contains( ValidationMode.DDL ) ) {
|
||||
throw new HibernateException( "Bean Validation not available in the class path but required in " + MODE_PROPERTY );
|
||||
}
|
||||
else if (modes.contains( ValidationMode.AUTO ) ) {
|
||||
//nothing to activate
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Class<?> activator = ReflectHelper.classForName( TYPE_SAFE_ACTIVATOR_CLASS, BeanValidationActivator.class );
|
||||
Method applyDDL =
|
||||
activator.getMethod( TYPE_SAFE_DDL_METHOD, Collection.class, Properties.class );
|
||||
applyDDL.invoke( null, persistentClasses, properties );
|
||||
}
|
||||
catch ( NoSuchMethodException e ) {
|
||||
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||
}
|
||||
catch ( IllegalAccessException e ) {
|
||||
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||
}
|
||||
catch ( InvocationTargetException e ) {
|
||||
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
throw new HibernateException( "Unable to get the default Bean Validation factory", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static enum ValidationMode {
|
||||
AUTO,
|
||||
CALLBACK,
|
||||
NONE,
|
||||
DDL;
|
||||
|
||||
public static Set<ValidationMode> getModes(Object modeProperty) {
|
||||
Set<ValidationMode> modes = new HashSet<ValidationMode>(3);
|
||||
if (modeProperty == null) {
|
||||
modes.add(ValidationMode.AUTO);
|
||||
}
|
||||
else {
|
||||
final String[] modesInString = modeProperty.toString().split( "," );
|
||||
for ( String modeInString : modesInString ) {
|
||||
modes.add( getMode(modeInString) );
|
||||
}
|
||||
}
|
||||
if ( modes.size() > 1 && ( modes.contains( ValidationMode.AUTO ) || modes.contains( ValidationMode.NONE ) ) ) {
|
||||
StringBuilder message = new StringBuilder( "Incompatible validation modes mixed: " );
|
||||
for (ValidationMode mode : modes) {
|
||||
message.append( mode ).append( ", " );
|
||||
}
|
||||
throw new HibernateException( message.substring( 0, message.length() - 2 ) );
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
|
||||
private static ValidationMode getMode(String modeProperty) {
|
||||
if (modeProperty == null || modeProperty.length() == 0) {
|
||||
return AUTO;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return valueOf( modeProperty.trim().toUpperCase() );
|
||||
}
|
||||
catch ( IllegalArgumentException e ) {
|
||||
throw new HibernateException( "Unknown validation mode in " + MODE_PROPERTY + ": " + modeProperty.toString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* 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.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
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.internal.util.config.ConfigurationHelper;
|
||||
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 BeanValidationIntegrator implements Integrator {
|
||||
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, BeanValidationIntegrator.class.getName());
|
||||
|
||||
public static final String MODE_PROPERTY = "javax.persistence.validation.mode";
|
||||
|
||||
private static final String ACTIVATOR_CLASS = "org.hibernate.cfg.beanvalidation.TypeSafeActivator";
|
||||
private static final String DDL_METHOD = "applyDDL";
|
||||
private static final String ACTIVATE_METHOD = "activateBeanValidation";
|
||||
|
||||
@Override
|
||||
public void integrate(
|
||||
Configuration configuration,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
// determine requested validation modes.
|
||||
final Set<ValidationMode> modes = ValidationMode.getModes( configuration.getProperties().get( MODE_PROPERTY ) );
|
||||
|
||||
// locate the type safe activator class
|
||||
final Class typeSafeActivatorClass = loadTypeSafeActivatorClass( serviceRegistry );
|
||||
|
||||
// todo : if this works out, probably better to simply alter TypeSafeActivator into a single method...
|
||||
|
||||
applyRelationalConstraints(
|
||||
modes,
|
||||
typeSafeActivatorClass,
|
||||
configuration
|
||||
);
|
||||
applyHibernateListeners(
|
||||
modes,
|
||||
typeSafeActivatorClass,
|
||||
configuration,
|
||||
sessionFactory,
|
||||
serviceRegistry
|
||||
);
|
||||
}
|
||||
|
||||
private Class loadTypeSafeActivatorClass(SessionFactoryServiceRegistry serviceRegistry) {
|
||||
try {
|
||||
return serviceRegistry.getService( ClassLoaderService.class ).classForName( ACTIVATOR_CLASS );
|
||||
}
|
||||
catch (Exception e) {
|
||||
// might be ok for the class loading to fail depending on what validation modes were requested...
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void applyRelationalConstraints(
|
||||
Set<ValidationMode> modes,
|
||||
Class typeSafeActivatorClass,
|
||||
Configuration configuration) {
|
||||
if ( ! ConfigurationHelper.getBoolean( LegacyHibernateValidationIntegrator.APPLY_CONSTRAINTS, configuration.getProperties(), true ) ){
|
||||
LOG.debug( "Skipping application of relational constraints from legacy Hibernate Validator" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! ( modes.contains( ValidationMode.DDL ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
||||
return;
|
||||
}
|
||||
if ( typeSafeActivatorClass == null ) {
|
||||
if ( modes.contains( ValidationMode.DDL ) ) {
|
||||
throw new HibernateException( "Bean Validation not available in the class path but required in " + MODE_PROPERTY );
|
||||
}
|
||||
else if (modes.contains( ValidationMode.AUTO ) ) {
|
||||
//nothing to activate
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Method applyDDLMethod = typeSafeActivatorClass.getMethod( DDL_METHOD, Collection.class, Properties.class );
|
||||
try {
|
||||
applyDDLMethod.invoke(
|
||||
null,
|
||||
configuration.createMappings().getClasses().values(),
|
||||
configuration.getProperties()
|
||||
);
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Error applying BeanValidation relational constraints", e );
|
||||
}
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Unable to locate TypeSafeActivator#applyDDL method", e );
|
||||
}
|
||||
}
|
||||
|
||||
private void applyHibernateListeners(
|
||||
Set<ValidationMode> modes,
|
||||
Class typeSafeActivatorClass,
|
||||
Configuration configuration,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
// de-activate not-null tracking at the core level when Bean Validation is present unless the user explicitly
|
||||
// asks for it
|
||||
if ( configuration.getProperty( Environment.CHECK_NULLABILITY ) == null ) {
|
||||
sessionFactory.getSettings().setCheckNullability( false );
|
||||
}
|
||||
|
||||
if ( ! ( modes.contains( ValidationMode.CALLBACK ) || modes.contains( ValidationMode.AUTO ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( typeSafeActivatorClass == null ) {
|
||||
if ( modes.contains( ValidationMode.CALLBACK ) ) {
|
||||
throw new HibernateException( "Bean Validation not available in the class path but required in " + MODE_PROPERTY );
|
||||
}
|
||||
else if (modes.contains( ValidationMode.AUTO ) ) {
|
||||
//nothing to activate
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Method activateMethod = typeSafeActivatorClass.getMethod( ACTIVATE_METHOD, EventListenerRegistry.class, Properties.class );
|
||||
try {
|
||||
activateMethod.invoke(
|
||||
null,
|
||||
serviceRegistry.getService( EventListenerRegistry.class ),
|
||||
configuration.getProperties()
|
||||
);
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Error applying BeanValidation relational constraints", e );
|
||||
}
|
||||
}
|
||||
catch (HibernateException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Unable to locate TypeSafeActivator#applyDDL method", e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Because the javax validation classes might not be on the runtime classpath
|
||||
private static enum ValidationMode {
|
||||
AUTO,
|
||||
CALLBACK,
|
||||
NONE,
|
||||
DDL;
|
||||
|
||||
public static Set<ValidationMode> getModes(Object modeProperty) {
|
||||
Set<ValidationMode> modes = new HashSet<ValidationMode>(3);
|
||||
if (modeProperty == null) {
|
||||
modes.add(ValidationMode.AUTO);
|
||||
}
|
||||
else {
|
||||
final String[] modesInString = modeProperty.toString().split( "," );
|
||||
for ( String modeInString : modesInString ) {
|
||||
modes.add( getMode(modeInString) );
|
||||
}
|
||||
}
|
||||
if ( modes.size() > 1 && ( modes.contains( ValidationMode.AUTO ) || modes.contains( ValidationMode.NONE ) ) ) {
|
||||
StringBuilder message = new StringBuilder( "Incompatible validation modes mixed: " );
|
||||
for (ValidationMode mode : modes) {
|
||||
message.append( mode ).append( ", " );
|
||||
}
|
||||
throw new HibernateException( message.substring( 0, message.length() - 2 ) );
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
|
||||
private static ValidationMode getMode(String modeProperty) {
|
||||
if (modeProperty == null || modeProperty.length() == 0) {
|
||||
return AUTO;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return valueOf( modeProperty.trim().toUpperCase() );
|
||||
}
|
||||
catch ( IllegalArgumentException e ) {
|
||||
throw new HibernateException( "Unknown validation mode in " + MODE_PROPERTY + ": " + modeProperty );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg.search;
|
||||
|
||||
import java.util.Properties;
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.HibernateLogger;
|
||||
import org.hibernate.event.EventListeners;
|
||||
import org.hibernate.event.PostCollectionRecreateEventListener;
|
||||
import org.hibernate.event.PostCollectionRemoveEventListener;
|
||||
import org.hibernate.event.PostCollectionUpdateEventListener;
|
||||
import org.hibernate.event.PostDeleteEventListener;
|
||||
import org.hibernate.event.PostInsertEventListener;
|
||||
import org.hibernate.event.PostUpdateEventListener;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Helper methods initializing Hibernate Search event listeners.
|
||||
*
|
||||
* @deprecated as of release 3.4.0.CR2, replaced by Hibernate Search's {@link org.hibernate.search.cfg.EventListenerRegister}
|
||||
* @author Emmanuel Bernard
|
||||
* @author Hardy Ferentschik
|
||||
*/
|
||||
@Deprecated
|
||||
public class HibernateSearchEventListenerRegister {
|
||||
|
||||
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class,
|
||||
HibernateSearchEventListenerRegister.class.getName());
|
||||
|
||||
/**
|
||||
* Class name of the class needed to enable Search.
|
||||
*/
|
||||
private static final String FULL_TEXT_INDEX_EVENT_LISTENER_CLASS = "org.hibernate.search.event.FullTextIndexEventListener";
|
||||
|
||||
/**
|
||||
* @deprecated as of release 3.4.0.CR2, replaced by Hibernate Search's {@link org.hibernate.search.cfg.EventListenerRegister#enableHibernateSearch(EventListeners, Properties)}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Deprecated
|
||||
public static void enableHibernateSearch(EventListeners eventListeners, Properties properties) {
|
||||
// check whether search is explicitly enabled - if so there is nothing
|
||||
// to do
|
||||
String enableSearchListeners = properties.getProperty( "hibernate.search.autoregister_listeners" );
|
||||
if("false".equalsIgnoreCase(enableSearchListeners )) {
|
||||
LOG.willNotRegisterListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
// add search events if the jar is available and class can be loaded
|
||||
Class searchEventListenerClass = attemptToLoadSearchEventListener();
|
||||
if ( searchEventListenerClass == null ) {
|
||||
LOG.unableToFindListenerClass(FULL_TEXT_INDEX_EVENT_LISTENER_CLASS);
|
||||
return;
|
||||
}
|
||||
|
||||
Object searchEventListener = instantiateEventListener(searchEventListenerClass);
|
||||
|
||||
// TODO Generalize this. Pretty much the same code all the time. Reflection?
|
||||
{
|
||||
boolean present = false;
|
||||
PostInsertEventListener[] listeners = eventListeners
|
||||
.getPostInsertEventListeners();
|
||||
if (listeners != null) {
|
||||
for (Object eventListener : listeners) {
|
||||
// not isAssignableFrom since the user could subclass
|
||||
present = present
|
||||
|| searchEventListenerClass == eventListener
|
||||
.getClass();
|
||||
}
|
||||
if (!present) {
|
||||
int length = listeners.length + 1;
|
||||
PostInsertEventListener[] newListeners = new PostInsertEventListener[length];
|
||||
System.arraycopy(listeners, 0, newListeners, 0, length - 1);
|
||||
newListeners[length - 1] = (PostInsertEventListener) searchEventListener;
|
||||
eventListeners.setPostInsertEventListeners(newListeners);
|
||||
}
|
||||
} else {
|
||||
eventListeners
|
||||
.setPostInsertEventListeners(new PostInsertEventListener[] { (PostInsertEventListener) searchEventListener });
|
||||
}
|
||||
}
|
||||
{
|
||||
boolean present = false;
|
||||
PostUpdateEventListener[] listeners = eventListeners
|
||||
.getPostUpdateEventListeners();
|
||||
if (listeners != null) {
|
||||
for (Object eventListener : listeners) {
|
||||
// not isAssignableFrom since the user could subclass
|
||||
present = present
|
||||
|| searchEventListenerClass == eventListener
|
||||
.getClass();
|
||||
}
|
||||
if (!present) {
|
||||
int length = listeners.length + 1;
|
||||
PostUpdateEventListener[] newListeners = new PostUpdateEventListener[length];
|
||||
System.arraycopy(listeners, 0, newListeners, 0, length - 1);
|
||||
newListeners[length - 1] = (PostUpdateEventListener) searchEventListener;
|
||||
eventListeners.setPostUpdateEventListeners(newListeners);
|
||||
}
|
||||
} else {
|
||||
eventListeners
|
||||
.setPostUpdateEventListeners(new PostUpdateEventListener[] { (PostUpdateEventListener) searchEventListener });
|
||||
}
|
||||
}
|
||||
{
|
||||
boolean present = false;
|
||||
PostDeleteEventListener[] listeners = eventListeners
|
||||
.getPostDeleteEventListeners();
|
||||
if (listeners != null) {
|
||||
for (Object eventListener : listeners) {
|
||||
// not isAssignableFrom since the user could subclass
|
||||
present = present
|
||||
|| searchEventListenerClass == eventListener
|
||||
.getClass();
|
||||
}
|
||||
if (!present) {
|
||||
int length = listeners.length + 1;
|
||||
PostDeleteEventListener[] newListeners = new PostDeleteEventListener[length];
|
||||
System.arraycopy(listeners, 0, newListeners, 0, length - 1);
|
||||
newListeners[length - 1] = (PostDeleteEventListener) searchEventListener;
|
||||
eventListeners.setPostDeleteEventListeners(newListeners);
|
||||
}
|
||||
} else {
|
||||
eventListeners
|
||||
.setPostDeleteEventListeners(new PostDeleteEventListener[] { (PostDeleteEventListener) searchEventListener });
|
||||
}
|
||||
}
|
||||
{
|
||||
boolean present = false;
|
||||
PostCollectionRecreateEventListener[] listeners = eventListeners.getPostCollectionRecreateEventListeners();
|
||||
if ( listeners != null ) {
|
||||
for (Object eventListener : listeners) {
|
||||
//not isAssignableFrom since the user could subclass
|
||||
present = present || searchEventListenerClass == eventListener.getClass();
|
||||
}
|
||||
if ( !present ) {
|
||||
int length = listeners.length + 1;
|
||||
PostCollectionRecreateEventListener[] newListeners = new PostCollectionRecreateEventListener[length];
|
||||
System.arraycopy( listeners, 0, newListeners, 0, length - 1 );
|
||||
newListeners[length - 1] = (PostCollectionRecreateEventListener) searchEventListener;
|
||||
eventListeners.setPostCollectionRecreateEventListeners( newListeners );
|
||||
}
|
||||
}
|
||||
else {
|
||||
eventListeners.setPostCollectionRecreateEventListeners(
|
||||
new PostCollectionRecreateEventListener[] { (PostCollectionRecreateEventListener) searchEventListener }
|
||||
);
|
||||
}
|
||||
}
|
||||
{
|
||||
boolean present = false;
|
||||
PostCollectionRemoveEventListener[] listeners = eventListeners.getPostCollectionRemoveEventListeners();
|
||||
if ( listeners != null ) {
|
||||
for (Object eventListener : listeners) {
|
||||
//not isAssignableFrom since the user could subclass
|
||||
present = present || searchEventListenerClass == eventListener.getClass();
|
||||
}
|
||||
if ( !present ) {
|
||||
int length = listeners.length + 1;
|
||||
PostCollectionRemoveEventListener[] newListeners = new PostCollectionRemoveEventListener[length];
|
||||
System.arraycopy( listeners, 0, newListeners, 0, length - 1 );
|
||||
newListeners[length - 1] = (PostCollectionRemoveEventListener) searchEventListener;
|
||||
eventListeners.setPostCollectionRemoveEventListeners( newListeners );
|
||||
}
|
||||
}
|
||||
else {
|
||||
eventListeners.setPostCollectionRemoveEventListeners(
|
||||
new PostCollectionRemoveEventListener[] { (PostCollectionRemoveEventListener) searchEventListener }
|
||||
);
|
||||
}
|
||||
}
|
||||
{
|
||||
boolean present = false;
|
||||
PostCollectionUpdateEventListener[] listeners = eventListeners.getPostCollectionUpdateEventListeners();
|
||||
if ( listeners != null ) {
|
||||
for (Object eventListener : listeners) {
|
||||
//not isAssignableFrom since the user could subclass
|
||||
present = present || searchEventListenerClass == eventListener.getClass();
|
||||
}
|
||||
if ( !present ) {
|
||||
int length = listeners.length + 1;
|
||||
PostCollectionUpdateEventListener[] newListeners = new PostCollectionUpdateEventListener[length];
|
||||
System.arraycopy( listeners, 0, newListeners, 0, length - 1 );
|
||||
newListeners[length - 1] = (PostCollectionUpdateEventListener) searchEventListener;
|
||||
eventListeners.setPostCollectionUpdateEventListeners( newListeners );
|
||||
}
|
||||
}
|
||||
else {
|
||||
eventListeners.setPostCollectionUpdateEventListeners(
|
||||
new PostCollectionUpdateEventListener[] { (PostCollectionUpdateEventListener) searchEventListener }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to load Hibernate Search event listener.
|
||||
*
|
||||
* @return An event listener instance in case the jar was available.
|
||||
*/
|
||||
private static Class<?> attemptToLoadSearchEventListener() {
|
||||
Class searchEventListenerClass = null;
|
||||
try {
|
||||
searchEventListenerClass = ReflectHelper.classForName(
|
||||
FULL_TEXT_INDEX_EVENT_LISTENER_CLASS,
|
||||
HibernateSearchEventListenerRegister.class);
|
||||
} catch (ClassNotFoundException e) {
|
||||
LOG.debugf("Search not present in classpath, ignoring event listener registration.");
|
||||
}
|
||||
return searchEventListenerClass;
|
||||
}
|
||||
|
||||
private static Object instantiateEventListener(Class<?> clazz) {
|
||||
Object searchEventListener;
|
||||
try {
|
||||
searchEventListener = clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new AnnotationException(
|
||||
"Unable to load Search event listener", e);
|
||||
}
|
||||
return searchEventListener;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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.search;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.AnnotationException;
|
||||
import org.hibernate.HibernateLogger;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.SessionFactoryImplementor;
|
||||
import org.hibernate.event.EventType;
|
||||
import org.hibernate.event.PostCollectionRecreateEventListener;
|
||||
import org.hibernate.event.PostCollectionRemoveEventListener;
|
||||
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.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.event.spi.DuplicationStrategy;
|
||||
import org.hibernate.service.event.spi.EventListenerRegistry;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
|
||||
/**
|
||||
* Integrates Hibernate Search into Hibernate Core by registering its needed listeners
|
||||
* <p/>
|
||||
* The note on the original (now removed) org.hibernate.cfg.search.HibernateSearchEventListenerRegister class indicated
|
||||
* that Search now uses a new means for this. However that signature is relying on removed classes...
|
||||
*
|
||||
* @author Emmanuel Bernard
|
||||
* @author Hardy Ferentschik
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class HibernateSearchIntegrator implements Integrator {
|
||||
private static final HibernateLogger LOG = Logger.getMessageLogger(HibernateLogger.class, HibernateSearchIntegrator.class.getName() );
|
||||
|
||||
public static final String AUTO_REGISTER = "hibernate.search.autoregister_listeners";
|
||||
public static final String LISTENER_CLASS = "org.hibernate.search.event.FullTextIndexEventListener";
|
||||
|
||||
@Override
|
||||
public void integrate(
|
||||
Configuration configuration,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
SessionFactoryServiceRegistry serviceRegistry) {
|
||||
final boolean registerListeners = ConfigurationHelper.getBoolean( AUTO_REGISTER, configuration.getProperties(), false );
|
||||
if ( !registerListeners ) {
|
||||
LOG.debug( "Skipping search event listener auto registration" );
|
||||
return;
|
||||
}
|
||||
|
||||
final Class listenerClass = loadSearchEventListener( serviceRegistry );
|
||||
if ( listenerClass == null ) {
|
||||
LOG.debug( "Skipping search event listener auto registration - could not fid listener class" );
|
||||
return;
|
||||
}
|
||||
|
||||
final Object listener = instantiateListener( listenerClass );
|
||||
|
||||
EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
|
||||
|
||||
listenerRegistry.addDuplicationStrategy( new DuplicationStrategyImpl( listenerClass ) );
|
||||
|
||||
listenerRegistry.getEventListenerGroup( EventType.POST_INSERT ).appendListener( (PostInsertEventListener) listener );
|
||||
listenerRegistry.getEventListenerGroup( EventType.POST_UPDATE ).appendListener( (PostUpdateEventListener) listener );
|
||||
listenerRegistry.getEventListenerGroup( EventType.POST_DELETE ).appendListener( (PostDeleteEventListener) listener );
|
||||
listenerRegistry.getEventListenerGroup( EventType.POST_COLLECTION_RECREATE ).appendListener( (PostCollectionRecreateEventListener) listener );
|
||||
listenerRegistry.getEventListenerGroup( EventType.POST_COLLECTION_REMOVE ).appendListener( (PostCollectionRemoveEventListener) listener );
|
||||
listenerRegistry.getEventListenerGroup( EventType.POST_COLLECTION_UPDATE ).appendListener( (PostCollectionUpdateEventListener) listener );
|
||||
}
|
||||
|
||||
private Class loadSearchEventListener(SessionFactoryServiceRegistry serviceRegistry) {
|
||||
try {
|
||||
return serviceRegistry.getService( ClassLoaderService.class ).classForName( LISTENER_CLASS );
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Object instantiateListener(Class listenerClass) {
|
||||
try {
|
||||
return listenerClass.newInstance();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new AnnotationException( "Unable to instantiate Search event listener", e );
|
||||
}
|
||||
}
|
||||
|
||||
public static class DuplicationStrategyImpl implements DuplicationStrategy {
|
||||
private final Class checkClass;
|
||||
|
||||
public DuplicationStrategyImpl(Class checkClass) {
|
||||
this.checkClass = checkClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areMatch(Object listener, Object original) {
|
||||
// not isAssignableFrom since the user could subclass
|
||||
return checkClass == original.getClass() && checkClass == listener.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action getAction() {
|
||||
return Action.KEEP_ORIGINAL;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -79,6 +79,9 @@ import org.hibernate.cache.impl.CacheDataDescriptionImpl;
|
|||
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;
|
||||
import org.hibernate.context.ManagedSessionContext;
|
||||
|
@ -488,7 +491,10 @@ public final class SessionFactoryImpl
|
|||
private Iterable<Integrator> locateIntegrators(ServiceRegistryImplementor serviceRegistry) {
|
||||
List<Integrator> integrators = new ArrayList<Integrator>();
|
||||
|
||||
// todo : add "known" integrators -> BV, hibernate validation, search, envers
|
||||
// todo : Envers needs to bbe handled by discovery to be because it is in a separate project
|
||||
integrators.add( new LegacyHibernateValidationIntegrator() );
|
||||
integrators.add( new BeanValidationIntegrator() );
|
||||
integrators.add( new HibernateSearchIntegrator() );
|
||||
|
||||
final Properties properties = new Properties();
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.service.classloading.internal;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
@ -29,6 +30,7 @@ import java.util.Enumeration;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.classloading.spi.ClassLoadingException;
|
||||
|
||||
|
@ -50,7 +52,7 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
|
|||
this( determineClassLoaders( configVales ) );
|
||||
}
|
||||
|
||||
private ClassLoaderServiceImpl(ClassLoader[] classLoaders) {
|
||||
private ClassLoaderServiceImpl(ClassLoader... classLoaders) {
|
||||
this( classLoaders[0], classLoaders[1], classLoaders[2], classLoaders[3] );
|
||||
}
|
||||
|
||||
|
@ -128,7 +130,7 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
|
|||
try {
|
||||
return classLoader.loadClass( className );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
catch ( Exception ignore) {
|
||||
}
|
||||
}
|
||||
throw new ClassLoadingException( "Unable to load class [" + className + "]" );
|
||||
|
@ -140,13 +142,13 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
|
|||
try {
|
||||
return new URL( name );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
|
||||
try {
|
||||
return resourcesClassLoader.getResource( name );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -158,13 +160,13 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
|
|||
try {
|
||||
return new URL( name ).openStream();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
|
||||
try {
|
||||
return resourcesClassLoader.getResourceAsStream( name );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -172,20 +174,19 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
|
|||
|
||||
@Override
|
||||
public List<URL> locateResources(String name) {
|
||||
ArrayList<URL> urls = new ArrayList<URL>();
|
||||
try {
|
||||
Enumeration<URL> urlEnumeration = resourcesClassLoader.getResources( name );
|
||||
if ( urlEnumeration != null && urlEnumeration.hasMoreElements() ) {
|
||||
ArrayList<URL> urls = new ArrayList<URL>();
|
||||
while ( urlEnumeration.hasMoreElements() ) {
|
||||
urls.add( urlEnumeration.nextElement() );
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
catch ( Exception ignore ) {
|
||||
}
|
||||
|
||||
return null;
|
||||
return urls;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -74,9 +74,9 @@ public class CallbackTest extends BaseCoreFunctionalTestCase {
|
|||
public void apply(
|
||||
EventListenerRegistry eventListenerRegistry,
|
||||
Configuration configuration,
|
||||
Map<?, ?> configValues, ServiceRegistryImplementor serviceRegistry
|
||||
) {
|
||||
serviceRegistry.getService( EventListenerRegistry.class ).setListeners( EventType.DELETE, listener );
|
||||
Map<?, ?> configValues,
|
||||
ServiceRegistryImplementor serviceRegistry) {
|
||||
eventListenerRegistry.setListeners( EventType.DELETE, listener );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue