light refactoring of EventEngine and CallbacksFactory
This commit is contained in:
parent
9442f4da19
commit
ddeaffc917
|
@ -5,7 +5,6 @@
|
|||
package org.hibernate.event.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -13,15 +12,19 @@ import java.util.function.Consumer;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.event.service.internal.EventListenerRegistryImpl;
|
||||
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||
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.service.spi.ServiceRegistryImplementor;
|
||||
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.
|
||||
*
|
||||
|
@ -36,102 +39,39 @@ public class EventEngine {
|
|||
|
||||
public EventEngine(MetadataImplementor mappings, SessionFactoryImplementor sessionFactory) {
|
||||
|
||||
final SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions();
|
||||
final ServiceRegistryImplementor serviceRegistry = sessionFactory.getServiceRegistry();
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// resolve (JPA) callback handlers
|
||||
|
||||
callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions(),
|
||||
sessionFactory.getServiceRegistry(), mappings.getEntityBindings() );
|
||||
|
||||
callbackRegistry = buildCallbackRegistry( sessionFactoryOptions, serviceRegistry, mappings.getEntityBindings() );
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// resolve event types and listeners
|
||||
|
||||
final EventListenerRegistryImpl.Builder listenerRegistryBuilder = new EventListenerRegistryImpl.Builder(
|
||||
callbackRegistry,
|
||||
sessionFactory.getSessionFactoryOptions().isJpaBootstrap()
|
||||
);
|
||||
final EventListenerRegistryImpl.Builder listenerRegistryBuilder =
|
||||
new EventListenerRegistryImpl.Builder( callbackRegistry, sessionFactoryOptions.isJpaBootstrap() );
|
||||
|
||||
final Map<String,EventType<?>> eventTypes = new HashMap<>();
|
||||
EventType.registerStandardTypes( eventTypes );
|
||||
|
||||
final EventEngineContributions contributionManager = new EventEngineContributions() {
|
||||
@Override
|
||||
public <T> EventType<T> findEventType(String name) {
|
||||
//noinspection unchecked
|
||||
return (EventType<T>) eventTypes.get( name );
|
||||
}
|
||||
callContributors( serviceRegistry, new ContributionManager( eventTypes, listenerRegistryBuilder ) );
|
||||
|
||||
@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." );
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
};
|
||||
registeredEventTypes = unmodifiableMap( eventTypes );
|
||||
listenerRegistry = listenerRegistryBuilder.buildRegistry( registeredEventTypes );
|
||||
}
|
||||
|
||||
private static void callContributors(
|
||||
ServiceRegistryImplementor serviceRegistry, EventEngineContributions contributionManager) {
|
||||
final Collection<EventEngineContributor> discoveredContributors =
|
||||
sessionFactory.getServiceRegistry()
|
||||
.requireService( ClassLoaderService.class )
|
||||
serviceRegistry.requireService( ClassLoaderService.class )
|
||||
.loadJavaServices( EventEngineContributor.class );
|
||||
if ( CollectionHelper.isNotEmpty( discoveredContributors ) ) {
|
||||
if ( isNotEmpty( discoveredContributors ) ) {
|
||||
for ( EventEngineContributor contributor : discoveredContributors ) {
|
||||
contributor.contribute( contributionManager );
|
||||
}
|
||||
}
|
||||
|
||||
this.registeredEventTypes = Collections.unmodifiableMap( eventTypes );
|
||||
this.listenerRegistry = listenerRegistryBuilder.buildRegistry( registeredEventTypes );
|
||||
}
|
||||
|
||||
public Collection<EventType<?>> getRegisteredEventTypes() {
|
||||
|
@ -152,10 +92,73 @@ public class EventEngine {
|
|||
}
|
||||
|
||||
public void stop() {
|
||||
if ( listenerRegistry instanceof Stoppable ) {
|
||||
( (Stoppable) listenerRegistry ).stop();
|
||||
if ( listenerRegistry instanceof Stoppable stoppable ) {
|
||||
stoppable.stop();
|
||||
}
|
||||
|
||||
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,63 +29,67 @@ import org.jboss.logging.Logger;
|
|||
public final class CallbacksFactory {
|
||||
private static final Logger log = Logger.getLogger( CallbacksFactory.class );
|
||||
|
||||
public static CallbackRegistry buildCallbackRegistry(SessionFactoryOptions options, ServiceRegistry serviceRegistry, Collection<PersistentClass> entityBindings) {
|
||||
if ( !jpaCallBacksEnabled( options ) ) {
|
||||
public static CallbackRegistry buildCallbackRegistry(
|
||||
SessionFactoryOptions options, ServiceRegistry serviceRegistry, Collection<PersistentClass> entityBindings) {
|
||||
if ( !options.areJPACallbacksEnabled() ) {
|
||||
return new EmptyCallbackRegistryImpl();
|
||||
}
|
||||
ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
|
||||
CallbackRegistryImpl.Builder registryBuilder = new CallbackRegistryImpl.Builder();
|
||||
Set<Class<?>> entityClasses = new HashSet<>();
|
||||
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
|
||||
final CallbackRegistryImpl.Builder registryBuilder = new CallbackRegistryImpl.Builder();
|
||||
final Set<Class<?>> entityClasses = new HashSet<>();
|
||||
|
||||
for ( PersistentClass persistentClass : entityBindings ) {
|
||||
if ( persistentClass.getClassName() == null ) {
|
||||
// we can have dynamic (non-java class) mapping
|
||||
continue;
|
||||
}
|
||||
|
||||
Class<?> entityClass = persistentClass.getMappedClass();
|
||||
|
||||
if ( !entityClasses.add( entityClass ) ) {
|
||||
// this most likely means we have a class mapped multiple times using the hbm.xml
|
||||
// "entity name" feature
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debugf(
|
||||
"Class [%s] already has callbacks registered; " +
|
||||
"assuming this means the class was mapped twice " +
|
||||
"(using hbm.xml entity-name support) - skipping subsequent registrations" +
|
||||
"to avoid duplicates",
|
||||
entityClass.getName()
|
||||
);
|
||||
if ( persistentClass.getClassName() != null ) {
|
||||
final Class<?> entityClass = persistentClass.getMappedClass();
|
||||
if ( !entityClasses.add( entityClass ) ) {
|
||||
// this most likely means we have a class mapped multiple
|
||||
// times using the hbm.xml "entity name" feature
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debugf(
|
||||
"Class [%s] already has callbacks registered; " +
|
||||
"assuming this means the class was mapped twice " +
|
||||
"(using hbm.xml entity-name support) - skipping subsequent registrations" +
|
||||
"to avoid duplicates",
|
||||
entityClass.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
registerAllCallbacks( persistentClass, registryBuilder, entityClass, beanRegistry );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
registryBuilder.registerCallbacks( persistentClass.getMappedClass(),
|
||||
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();
|
||||
}
|
||||
|
||||
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,
|
||||
ManagedBeanRegistry beanRegistry) {
|
||||
if ( callbackDefinitions == null || callbackDefinitions.isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
List<Callback> callbacks = new ArrayList<>();
|
||||
for ( CallbackDefinition definition : callbackDefinitions ) {
|
||||
callbacks.add( definition.createCallback( beanRegistry ) );
|
||||
else {
|
||||
final List<Callback> callbacks = new ArrayList<>();
|
||||
for ( CallbackDefinition definition : callbackDefinitions ) {
|
||||
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