diff --git a/documentation/src/main/asciidoc/topical/bootstrap/NativeBootstrapping.adoc b/documentation/src/main/asciidoc/topical/bootstrap/NativeBootstrapping.adoc index 1d20620c61..48cc9904f4 100644 --- a/documentation/src/main/asciidoc/topical/bootstrap/NativeBootstrapping.adoc +++ b/documentation/src/main/asciidoc/topical/bootstrap/NativeBootstrapping.adoc @@ -233,6 +233,7 @@ over the `SessionFactory` building process. === ServiceContributor === TypeContributor === MetadataSourcesContributor -=== MetadataBuilderContributor -=== SessionFactoryBuilderContributor (todo) +=== MetadataBuilderInitializer +=== SessionFactoryBuilderFactory +=== SessionFactoryBuilderInitializer (todo) === SessionFactoryObserver \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java index ae442cabc6..965dbb67a8 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java @@ -28,10 +28,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import org.hibernate.HibernateException; import org.hibernate.MappingException; import org.hibernate.SessionFactory; import org.hibernate.boot.SessionFactoryBuilder; @@ -39,8 +41,10 @@ import org.hibernate.boot.model.IdentifierGeneratorDefinition; import org.hibernate.boot.model.TypeDefinition; import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Schema; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.spi.MetadataBuildingOptions; import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.boot.spi.SessionFactoryBuilderFactory; import org.hibernate.cfg.annotations.NamedEntityGraphDefinition; import org.hibernate.cfg.annotations.NamedProcedureCallDefinition; import org.hibernate.dialect.function.SQLFunction; @@ -52,6 +56,7 @@ import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory; import org.hibernate.internal.NamedQueryRepository; import org.hibernate.internal.SessionFactoryImpl; +import org.hibernate.internal.util.StringHelper; import org.hibernate.mapping.Collection; import org.hibernate.mapping.FetchProfile; import org.hibernate.mapping.MappedSuperclass; @@ -144,6 +149,34 @@ public class MetadataImpl implements MetadataImplementor, Serializable { @Override public SessionFactoryBuilder getSessionFactoryBuilder() { + final ClassLoaderService cls = metadataBuildingOptions.getServiceRegistry().getService( ClassLoaderService.class ); + final java.util.Collection discoveredBuilderFactories = cls.loadJavaServices( SessionFactoryBuilderFactory.class ); + + SessionFactoryBuilder builder = null; + List activeFactoryNames = null; + + for ( SessionFactoryBuilderFactory discoveredBuilderFactory : discoveredBuilderFactories ) { + final SessionFactoryBuilder returnedBuilder = discoveredBuilderFactory.getSessionFactoryBuilder( this ); + if ( returnedBuilder != null ) { + if ( activeFactoryNames == null ) { + activeFactoryNames = new ArrayList(); + } + activeFactoryNames.add( discoveredBuilderFactory.getClass().getName() ); + builder = returnedBuilder; + } + } + + if ( activeFactoryNames != null && activeFactoryNames.size() > 1 ) { + throw new HibernateException( + "Multiple active SessionFactoryBuilderFactory definitions were discovered : " + + StringHelper.join( ", ", activeFactoryNames ) + ); + } + + if ( builder != null ) { + return builder; + } + return new SessionFactoryBuilderImpl( this ); } diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryBuilderFactory.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryBuilderFactory.java new file mode 100644 index 0000000000..5d1e300f99 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryBuilderFactory.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2015, 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.boot.spi; + +import org.hibernate.boot.SessionFactoryBuilder; + +/** + * An extension point for integrators that wish to hook into the process of how a SessionFactory + * is built. Intended as a "discoverable service" ({@link java.util.ServiceLoader}). There can + * be at most one implementation discovered that returns a non-null SessionFactoryBuilder. + * + * @author Steve Ebersole + */ +public interface SessionFactoryBuilderFactory { + /** + * The contract method. Return the SessionFactoryBuilder. May return {@code null} + * + * @param metadata The metadata from which we will be building a SessionFactory. + * + * @return The SessionFactoryBuilder, or {@code null} + */ + public SessionFactoryBuilder getSessionFactoryBuilder(MetadataImplementor metadata); +}