HHH-5562 - Improve how event listeners are handled and introduce a service pattern for integrators to leverage

This commit is contained in:
Steve Ebersole 2011-03-27 10:39:38 -05:00
parent 47abaf12fa
commit 7cba21dcd9
2 changed files with 100 additions and 4 deletions

View File

@ -0,0 +1,44 @@
/*
* 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.impl;
import org.hibernate.cfg.Configuration;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
/**
* Contract for stuff that integrates with Hibernate.
*
* @todo : obviously, come up with a better name :)
*
* @author Steve Ebersole
* @since 4.0
* @jira HHH-5562
*/
public interface Integrator {
public void integrate(
Configuration configuration,
SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry);
}

View File

@ -27,11 +27,13 @@ import javax.naming.NamingException;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidObjectException; import java.io.InvalidObjectException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
import java.io.Serializable; import java.io.Serializable;
import java.net.URL;
import java.sql.Connection; import java.sql.Connection;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -39,6 +41,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
@ -117,9 +120,11 @@ import org.hibernate.persister.spi.PersisterFactory;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.EntityNotFoundDelegate; import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.classloading.spi.ClassLoaderService;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.jta.platform.spi.JtaPlatform; import org.hibernate.service.jta.platform.spi.JtaPlatform;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory; import org.hibernate.service.spi.SessionFactoryServiceRegistryFactory;
import org.hibernate.stat.Statistics; import org.hibernate.stat.Statistics;
import org.hibernate.stat.internal.ConcurrentStatisticsImpl; import org.hibernate.stat.internal.ConcurrentStatisticsImpl;
@ -209,6 +214,7 @@ public final class SessionFactoryImpl
SessionFactoryObserver observer) throws HibernateException { SessionFactoryObserver observer) throws HibernateException {
LOG.buildingSessionFactory(); LOG.buildingSessionFactory();
// todo : move stats building to SF service reg building
this.statistics = buildStatistics( settings, serviceRegistry ); this.statistics = buildStatistics( settings, serviceRegistry );
this.properties = new Properties(); this.properties = new Properties();
@ -239,6 +245,12 @@ public final class SessionFactoryImpl
settings.getRegionFactory().start( settings, properties ); settings.getRegionFactory().start( settings, properties );
this.queryPlanCache = new QueryPlanCache( this ); this.queryPlanCache = new QueryPlanCache( this );
// todo : everything above here consider implementing as standard SF service. specifically: stats, caches, types, function-reg
for ( Integrator integrator : locateIntegrators( this.serviceRegistry ) ) {
integrator.integrate( cfg, this, (SessionFactoryServiceRegistry) this.serviceRegistry );
}
//Generators: //Generators:
identifierGenerators = new HashMap(); identifierGenerators = new HashMap();
@ -477,6 +489,46 @@ public final class SessionFactoryImpl
this.observer.sessionFactoryCreated( this ); this.observer.sessionFactoryCreated( this );
} }
private Iterable<Integrator> locateIntegrators(ServiceRegistryImplementor serviceRegistry) {
List<Integrator> integrators = new ArrayList<Integrator>();
// todo : add "known" integrators -> BV, hibernate validation, search, envers
final Properties properties = new Properties();
ClassLoaderService classLoader = serviceRegistry.getService( ClassLoaderService.class );
List<URL> urls = classLoader.locateResources( "META-INF/hibernate/org.hibernate.impl.Integrator" );
for ( URL url : urls ) {
try {
final InputStream propertyStream = url.openStream();
try {
properties.clear();
properties.load( propertyStream );
// for now we only understand 'implClass' as key
final String implClass = properties.getProperty( "implClass" );
Class integratorClass = classLoader.classForName( implClass );
try {
integrators.add( (Integrator) integratorClass.newInstance() );
}
catch (Exception e) {
throw new HibernateException( "Unable to instantiate specified Integrator class [" + implClass + "]", e );
}
}
finally {
try {
propertyStream.close();
}
catch (IOException ignore) {
}
}
}
catch ( IOException ioe ) {
LOG.debugf( ioe, "Unable to process Integrator service file [%s], skipping" , url.toExternalForm() );
}
}
return integrators;
}
@Override @Override
public void addObserver(SessionFactoryObserver observer) { public void addObserver(SessionFactoryObserver observer) {
this.observer.addObserver( observer ); this.observer.addObserver( observer );
@ -751,7 +803,7 @@ public final class SessionFactoryImpl
// from javax.naming.Referenceable // from javax.naming.Referenceable
public Reference getReference() throws NamingException { public Reference getReference() throws NamingException {
LOG.debugf("Returning a Reference to the SessionFactory"); LOG.debugf( "Returning a Reference to the SessionFactory" );
return new Reference( return new Reference(
SessionFactoryImpl.class.getName(), SessionFactoryImpl.class.getName(),
new StringRefAddr("uuid", uuid), new StringRefAddr("uuid", uuid),
@ -794,9 +846,9 @@ public final class SessionFactoryImpl
} }
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
LOG.trace("Deserializing"); LOG.trace( "Deserializing" );
in.defaultReadObject(); in.defaultReadObject();
LOG.debugf("Deserialized: %s", uuid); LOG.debugf( "Deserialized: %s", uuid );
} }
private void writeObject(ObjectOutputStream out) throws IOException { private void writeObject(ObjectOutputStream out) throws IOException {
@ -906,7 +958,7 @@ public final class SessionFactoryImpl
public Type getReferencedPropertyType(String className, String propertyName) public Type getReferencedPropertyType(String className, String propertyName)
throws MappingException { throws MappingException {
return getEntityPersister(className).getPropertyType(propertyName); return getEntityPersister( className ).getPropertyType( propertyName );
} }
public ConnectionProvider getConnectionProvider() { public ConnectionProvider getConnectionProvider() {