org.hibernate.event.spi.EventEngine Maven / Gradle / Ivy
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
package org.hibernate.event.spi;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
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.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.CallbackRegistryImplementor;
import org.hibernate.jpa.event.internal.CallbacksFactory;
import org.hibernate.jpa.event.spi.CallbackBuilder;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.service.spi.Stoppable;
/**
* Composite for the things related to Hibernate's event system.
*
* @author Steve Ebersole
*/
public class EventEngine {
@SuppressWarnings("rawtypes")
private final Map registeredEventTypes;
private final EventListenerRegistry listenerRegistry;
private final CallbackRegistryImplementor callbackRegistry;
private final CallbackBuilder callbackBuilder;
public EventEngine(
MetadataImplementor mappings,
SessionFactoryImplementor sessionFactory) {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// resolve (JPA) callback handlers
this.callbackRegistry = CallbacksFactory.buildCallbackRegistry( sessionFactory.getSessionFactoryOptions() );
this.callbackBuilder = CallbacksFactory.buildCallbackBuilder(
sessionFactory.getSessionFactoryOptions(),
sessionFactory.getServiceRegistry(),
mappings.getMetadataBuildingOptions().getReflectionManager()
);
for ( PersistentClass persistentClass : mappings.getEntityBindings() ) {
if ( persistentClass.getClassName() == null ) {
// we can have dynamic (non-java class) mapping
continue;
}
this.callbackBuilder.buildCallbacksForEntity( persistentClass.getMappedClass(), callbackRegistry );
for ( Iterator propertyIterator = persistentClass.getDeclaredPropertyIterator(); propertyIterator.hasNext(); ) {
final Property property = propertyIterator.next();
if ( property.isComposite() ) {
this.callbackBuilder.buildCallbacksForEmbeddable(
property,
persistentClass.getMappedClass(),
callbackRegistry
);
}
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// resolve event types and listeners
final EventListenerRegistryImpl.Builder listenerRegistryBuilder = new EventListenerRegistryImpl.Builder(
callbackRegistry,
sessionFactory.getSessionFactoryOptions().isJpaBootstrap()
);
final Map eventTypes = new HashMap<>();
EventType.registerStandardTypes( eventTypes );
final EventEngineContributions contributionManager = new EventEngineContributions() {
@Override
public EventType findEventType(String name) {
//noinspection unchecked
return eventTypes.get( name );
}
@Override
public EventType contributeEventType(String name, Class listenerRole) {
final EventType eventType = registerEventType( name, listenerRole );
listenerRegistryBuilder.prepareListeners( eventType );
return eventType;
}
private EventType registerEventType(String name, Class 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 eventType = EventType.create(
name,
listenerRole,
eventTypes.size()
);
eventTypes.put( name, eventType );
return eventType;
}
@Override
public EventType contributeEventType(String name, Class listenerRole, T... defaultListeners) {
final EventType eventType = contributeEventType( name, listenerRole );
if ( defaultListeners != null ) {
final EventListenerGroup listenerGroup = listenerRegistryBuilder.getListenerGroup( eventType );
listenerGroup.appendListeners( defaultListeners );
}
return eventType;
}
@Override
public void configureListeners(
EventType eventType,
Consumer> action) {
if ( ! eventTypes.containsValue( eventType ) ) {
throw new HibernateException( "EventType [" + eventType + "] not registered" );
}
action.accept( listenerRegistryBuilder.getListenerGroup( eventType ) );
}
};
final Collection discoveredContributors = sessionFactory.getServiceRegistry()
.getService( ClassLoaderService.class )
.loadJavaServices( EventEngineContributor.class );
if ( CollectionHelper.isNotEmpty( discoveredContributors ) ) {
for ( EventEngineContributor contributor : discoveredContributors ) {
contributor.contribute( contributionManager );
}
}
this.registeredEventTypes = Collections.unmodifiableMap( eventTypes );
this.listenerRegistry = listenerRegistryBuilder.buildRegistry( registeredEventTypes );
}
public Collection> getRegisteredEventTypes() {
//noinspection unchecked,rawtypes
return (Collection) registeredEventTypes.values();
}
public EventType findRegisteredEventType(String name) {
//noinspection unchecked
return registeredEventTypes.get( name );
}
public EventListenerRegistry getListenerRegistry() {
return listenerRegistry;
}
public CallbackRegistryImplementor getCallbackRegistry() {
return callbackRegistry;
}
public void stop() {
if ( listenerRegistry instanceof Stoppable ) {
( (Stoppable) listenerRegistry ).stop();
}
callbackRegistry.release();
callbackBuilder.release();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy