light refactoring of EventEngine and CallbacksFactory
This commit is contained in:
parent
9442f4da19
commit
ddeaffc917
|
@ -5,7 +5,6 @@
|
||||||
package org.hibernate.event.spi;
|
package org.hibernate.event.spi;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -13,15 +12,19 @@ import java.util.function.Consumer;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
import org.hibernate.boot.spi.MetadataImplementor;
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.event.service.internal.EventListenerRegistryImpl;
|
import org.hibernate.event.service.internal.EventListenerRegistryImpl;
|
||||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
|
||||||
import org.hibernate.jpa.event.internal.CallbacksFactory;
|
|
||||||
import org.hibernate.jpa.event.spi.CallbackRegistry;
|
import org.hibernate.jpa.event.spi.CallbackRegistry;
|
||||||
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
import org.hibernate.service.spi.Stoppable;
|
import org.hibernate.service.spi.Stoppable;
|
||||||
|
|
||||||
|
import static java.util.Collections.unmodifiableMap;
|
||||||
|
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
|
||||||
|
import static org.hibernate.jpa.event.internal.CallbacksFactory.buildCallbackRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Composite for the things related to Hibernate's event system.
|
* Composite for the things related to Hibernate's event system.
|
||||||
*
|
*
|
||||||
|
@ -36,102 +39,39 @@ public class EventEngine {
|
||||||
|
|
||||||
public EventEngine(MetadataImplementor mappings, SessionFactoryImplementor sessionFactory) {
|
public EventEngine(MetadataImplementor mappings, SessionFactoryImplementor sessionFactory) {
|
||||||
|
|
||||||
|
final SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions();
|
||||||
|
final ServiceRegistryImplementor serviceRegistry = sessionFactory.getServiceRegistry();
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// resolve (JPA) callback handlers
|
// resolve (JPA) callback handlers
|
||||||
|
|
||||||
callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions(),
|
callbackRegistry = buildCallbackRegistry( sessionFactoryOptions, serviceRegistry, mappings.getEntityBindings() );
|
||||||
sessionFactory.getServiceRegistry(), mappings.getEntityBindings() );
|
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// resolve event types and listeners
|
// resolve event types and listeners
|
||||||
|
|
||||||
final EventListenerRegistryImpl.Builder listenerRegistryBuilder = new EventListenerRegistryImpl.Builder(
|
final EventListenerRegistryImpl.Builder listenerRegistryBuilder =
|
||||||
callbackRegistry,
|
new EventListenerRegistryImpl.Builder( callbackRegistry, sessionFactoryOptions.isJpaBootstrap() );
|
||||||
sessionFactory.getSessionFactoryOptions().isJpaBootstrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
final Map<String,EventType<?>> eventTypes = new HashMap<>();
|
final Map<String,EventType<?>> eventTypes = new HashMap<>();
|
||||||
EventType.registerStandardTypes( eventTypes );
|
EventType.registerStandardTypes( eventTypes );
|
||||||
|
|
||||||
final EventEngineContributions contributionManager = new EventEngineContributions() {
|
callContributors( serviceRegistry, new ContributionManager( eventTypes, listenerRegistryBuilder ) );
|
||||||
@Override
|
|
||||||
public <T> EventType<T> findEventType(String name) {
|
registeredEventTypes = unmodifiableMap( eventTypes );
|
||||||
//noinspection unchecked
|
listenerRegistry = listenerRegistryBuilder.buildRegistry( registeredEventTypes );
|
||||||
return (EventType<T>) eventTypes.get( name );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private static void callContributors(
|
||||||
public <T> EventType<T> contributeEventType(String name, Class<T> listenerRole) {
|
ServiceRegistryImplementor serviceRegistry, EventEngineContributions contributionManager) {
|
||||||
final EventType<T> eventType = registerEventType( name, listenerRole );
|
|
||||||
|
|
||||||
listenerRegistryBuilder.prepareListeners( eventType );
|
|
||||||
|
|
||||||
return eventType;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> EventType<T> registerEventType(String name, Class<T> listenerRole) {
|
|
||||||
if ( name == null ) {
|
|
||||||
throw new HibernateException( "Custom event-type name must be non-null." );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( listenerRole == null ) {
|
|
||||||
throw new HibernateException( "Custom event-type listener role must be non-null." );
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure it does not match an existing name...
|
|
||||||
if ( eventTypes.containsKey( name ) ) {
|
|
||||||
final EventType<?> existing = eventTypes.get( name );
|
|
||||||
throw new HibernateException(
|
|
||||||
"Custom event-type already registered: " + name + " => " + existing
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final EventType<T> eventType = EventType.create(
|
|
||||||
name,
|
|
||||||
listenerRole,
|
|
||||||
eventTypes.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
eventTypes.put( name, eventType );
|
|
||||||
return eventType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override @SafeVarargs
|
|
||||||
public final <T> EventType<T> contributeEventType(String name, Class<T> listenerRole, T... defaultListeners) {
|
|
||||||
final EventType<T> eventType = contributeEventType( name, listenerRole );
|
|
||||||
|
|
||||||
if ( defaultListeners != null ) {
|
|
||||||
listenerRegistryBuilder.getListenerGroup( eventType ).appendListeners( defaultListeners );
|
|
||||||
}
|
|
||||||
|
|
||||||
return eventType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> void configureListeners(
|
|
||||||
EventType<T> eventType,
|
|
||||||
Consumer<EventListenerGroup<T>> action) {
|
|
||||||
if ( ! eventTypes.containsValue( eventType ) ) {
|
|
||||||
throw new HibernateException( "EventType [" + eventType + "] not registered" );
|
|
||||||
}
|
|
||||||
|
|
||||||
action.accept( listenerRegistryBuilder.getListenerGroup( eventType ) );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
final Collection<EventEngineContributor> discoveredContributors =
|
final Collection<EventEngineContributor> discoveredContributors =
|
||||||
sessionFactory.getServiceRegistry()
|
serviceRegistry.requireService( ClassLoaderService.class )
|
||||||
.requireService( ClassLoaderService.class )
|
|
||||||
.loadJavaServices( EventEngineContributor.class );
|
.loadJavaServices( EventEngineContributor.class );
|
||||||
if ( CollectionHelper.isNotEmpty( discoveredContributors ) ) {
|
if ( isNotEmpty( discoveredContributors ) ) {
|
||||||
for ( EventEngineContributor contributor : discoveredContributors ) {
|
for ( EventEngineContributor contributor : discoveredContributors ) {
|
||||||
contributor.contribute( contributionManager );
|
contributor.contribute( contributionManager );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.registeredEventTypes = Collections.unmodifiableMap( eventTypes );
|
|
||||||
this.listenerRegistry = listenerRegistryBuilder.buildRegistry( registeredEventTypes );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<EventType<?>> getRegisteredEventTypes() {
|
public Collection<EventType<?>> getRegisteredEventTypes() {
|
||||||
|
@ -152,10 +92,73 @@ public class EventEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if ( listenerRegistry instanceof Stoppable ) {
|
if ( listenerRegistry instanceof Stoppable stoppable ) {
|
||||||
( (Stoppable) listenerRegistry ).stop();
|
stoppable.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
callbackRegistry.release();
|
callbackRegistry.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ContributionManager implements EventEngineContributions {
|
||||||
|
private final Map<String, EventType<?>> eventTypes;
|
||||||
|
private final EventListenerRegistryImpl.Builder listenerRegistryBuilder;
|
||||||
|
|
||||||
|
public ContributionManager(
|
||||||
|
Map<String, EventType<?>> eventTypes,
|
||||||
|
EventListenerRegistryImpl.Builder listenerRegistryBuilder) {
|
||||||
|
this.eventTypes = eventTypes;
|
||||||
|
this.listenerRegistryBuilder = listenerRegistryBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> EventType<T> findEventType(String name) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (EventType<T>) eventTypes.get( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> EventType<T> contributeEventType(String name, Class<T> listenerRole) {
|
||||||
|
final EventType<T> eventType = registerEventType( name, listenerRole );
|
||||||
|
listenerRegistryBuilder.prepareListeners( eventType );
|
||||||
|
return eventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> EventType<T> registerEventType(String name, Class<T> listenerRole) {
|
||||||
|
if ( name == null ) {
|
||||||
|
throw new HibernateException( "Custom event-type name must be non-null." );
|
||||||
|
}
|
||||||
|
else if ( listenerRole == null ) {
|
||||||
|
throw new HibernateException( "Custom event-type listener role must be non-null." );
|
||||||
|
}
|
||||||
|
// make sure it does not match an existing name...
|
||||||
|
else if ( eventTypes.containsKey( name ) ) {
|
||||||
|
final EventType<?> existing = eventTypes.get( name );
|
||||||
|
throw new HibernateException(
|
||||||
|
"Custom event-type already registered: " + name + " => " + existing
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final EventType<T> eventType = EventType.create( name, listenerRole, eventTypes.size() );
|
||||||
|
eventTypes.put( name, eventType );
|
||||||
|
return eventType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SafeVarargs
|
||||||
|
public final <T> EventType<T> contributeEventType(String name, Class<T> listenerRole, T... defaultListeners) {
|
||||||
|
final EventType<T> eventType = contributeEventType( name, listenerRole );
|
||||||
|
if ( defaultListeners != null ) {
|
||||||
|
listenerRegistryBuilder.getListenerGroup( eventType ).appendListeners( defaultListeners );
|
||||||
|
}
|
||||||
|
return eventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void configureListeners(EventType<T> eventType, Consumer<EventListenerGroup<T>> action) {
|
||||||
|
if ( !eventTypes.containsValue( eventType ) ) {
|
||||||
|
throw new HibernateException( "EventType [" + eventType + "] not registered" );
|
||||||
|
}
|
||||||
|
action.accept( listenerRegistryBuilder.getListenerGroup( eventType ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,25 +29,21 @@ import org.jboss.logging.Logger;
|
||||||
public final class CallbacksFactory {
|
public final class CallbacksFactory {
|
||||||
private static final Logger log = Logger.getLogger( CallbacksFactory.class );
|
private static final Logger log = Logger.getLogger( CallbacksFactory.class );
|
||||||
|
|
||||||
public static CallbackRegistry buildCallbackRegistry(SessionFactoryOptions options, ServiceRegistry serviceRegistry, Collection<PersistentClass> entityBindings) {
|
public static CallbackRegistry buildCallbackRegistry(
|
||||||
if ( !jpaCallBacksEnabled( options ) ) {
|
SessionFactoryOptions options, ServiceRegistry serviceRegistry, Collection<PersistentClass> entityBindings) {
|
||||||
|
if ( !options.areJPACallbacksEnabled() ) {
|
||||||
return new EmptyCallbackRegistryImpl();
|
return new EmptyCallbackRegistryImpl();
|
||||||
}
|
}
|
||||||
ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
|
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
|
||||||
CallbackRegistryImpl.Builder registryBuilder = new CallbackRegistryImpl.Builder();
|
final CallbackRegistryImpl.Builder registryBuilder = new CallbackRegistryImpl.Builder();
|
||||||
Set<Class<?>> entityClasses = new HashSet<>();
|
final Set<Class<?>> entityClasses = new HashSet<>();
|
||||||
|
|
||||||
for ( PersistentClass persistentClass : entityBindings ) {
|
for ( PersistentClass persistentClass : entityBindings ) {
|
||||||
if ( persistentClass.getClassName() == null ) {
|
if ( persistentClass.getClassName() != null ) {
|
||||||
// we can have dynamic (non-java class) mapping
|
final Class<?> entityClass = persistentClass.getMappedClass();
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<?> entityClass = persistentClass.getMappedClass();
|
|
||||||
|
|
||||||
if ( !entityClasses.add( entityClass ) ) {
|
if ( !entityClasses.add( entityClass ) ) {
|
||||||
// this most likely means we have a class mapped multiple times using the hbm.xml
|
// this most likely means we have a class mapped multiple
|
||||||
// "entity name" feature
|
// times using the hbm.xml "entity name" feature
|
||||||
if ( log.isDebugEnabled() ) {
|
if ( log.isDebugEnabled() ) {
|
||||||
log.debugf(
|
log.debugf(
|
||||||
"Class [%s] already has callbacks registered; " +
|
"Class [%s] already has callbacks registered; " +
|
||||||
|
@ -57,35 +53,43 @@ public final class CallbacksFactory {
|
||||||
entityClass.getName()
|
entityClass.getName()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
registryBuilder.registerCallbacks( persistentClass.getMappedClass(),
|
registerAllCallbacks( persistentClass, registryBuilder, entityClass, beanRegistry );
|
||||||
buildCallbacks( persistentClass.getCallbackDefinitions(), beanRegistry ) );
|
|
||||||
|
|
||||||
for ( Property property : persistentClass.getDeclaredProperties() ) {
|
|
||||||
registryBuilder.registerCallbacks( persistentClass.getMappedClass(),
|
|
||||||
buildCallbacks( property.getCallbackDefinitions(), beanRegistry ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// else we can have dynamic (non-java class) mapping
|
||||||
|
}
|
||||||
|
|
||||||
return registryBuilder.build();
|
return registryBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void registerAllCallbacks(
|
||||||
|
PersistentClass persistentClass,
|
||||||
|
CallbackRegistryImpl.Builder registryBuilder,
|
||||||
|
Class<?> entityClass,
|
||||||
|
ManagedBeanRegistry beanRegistry) {
|
||||||
|
registryBuilder.registerCallbacks( entityClass,
|
||||||
|
buildCallbacks( persistentClass.getCallbackDefinitions(), beanRegistry ) );
|
||||||
|
|
||||||
|
for ( Property property : persistentClass.getDeclaredProperties() ) {
|
||||||
|
registryBuilder.registerCallbacks( entityClass,
|
||||||
|
buildCallbacks( property.getCallbackDefinitions(), beanRegistry ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Callback[] buildCallbacks(List<CallbackDefinition> callbackDefinitions,
|
private static Callback[] buildCallbacks(List<CallbackDefinition> callbackDefinitions,
|
||||||
ManagedBeanRegistry beanRegistry) {
|
ManagedBeanRegistry beanRegistry) {
|
||||||
if ( callbackDefinitions == null || callbackDefinitions.isEmpty() ) {
|
if ( callbackDefinitions == null || callbackDefinitions.isEmpty() ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
List<Callback> callbacks = new ArrayList<>();
|
else {
|
||||||
|
final List<Callback> callbacks = new ArrayList<>();
|
||||||
for ( CallbackDefinition definition : callbackDefinitions ) {
|
for ( CallbackDefinition definition : callbackDefinitions ) {
|
||||||
callbacks.add( definition.createCallback( beanRegistry ) );
|
callbacks.add( definition.createCallback( beanRegistry ) );
|
||||||
}
|
}
|
||||||
return callbacks.toArray( new Callback[0] );
|
return callbacks.toArray( new Callback[0] );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean jpaCallBacksEnabled(SessionFactoryOptions options) {
|
|
||||||
return options.areJPACallbacksEnabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue