From d52a20a6933bbcc344839c0b0c8cb91fd2eb491f Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 27 Aug 2012 15:18:21 -0500 Subject: [PATCH] HHH-7552 - New StrategySelectorService : initial work --- .../internal/TransactionFactoryInitiator.java | 86 +--------- .../BootstrapServiceRegistryBuilder.java | 28 ++- .../BootstrapServiceRegistryImpl.java | 43 ++++- .../internal/StrategySelectorBuilder.java | 105 ++++++++++++ .../internal/StrategySelectorImpl.java | 161 ++++++++++++++++++ .../service/selector/package-info.java | 1 + .../spi/StrategySelectionException.java | 39 +++++ .../selector/spi/StrategySelector.java | 98 +++++++++++ .../embeddables/EmbeddableIntegratorTest.java | 27 +-- 9 files changed, 481 insertions(+), 107 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/service/selector/internal/StrategySelectorBuilder.java create mode 100644 hibernate-core/src/main/java/org/hibernate/service/selector/internal/StrategySelectorImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/service/selector/package-info.java create mode 100644 hibernate-core/src/main/java/org/hibernate/service/selector/spi/StrategySelectionException.java create mode 100644 hibernate-core/src/main/java/org/hibernate/service/selector/spi/StrategySelector.java diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionFactoryInitiator.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionFactoryInitiator.java index b38fbf2564..2f153e75f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionFactoryInitiator.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionFactoryInitiator.java @@ -27,16 +27,12 @@ import java.util.Map; import org.jboss.logging.Logger; -import org.hibernate.HibernateException; -import org.hibernate.cfg.Environment; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory; -import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; -import org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory; import org.hibernate.engine.transaction.spi.TransactionFactory; import org.hibernate.engine.transaction.spi.TransactionImplementor; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.service.classloading.spi.ClassLoaderService; -import org.hibernate.service.classloading.spi.ClassLoadingException; +import org.hibernate.service.selector.spi.StrategySelector; import org.hibernate.service.spi.BasicServiceInitiator; import org.hibernate.service.spi.ServiceRegistryImplementor; @@ -64,86 +60,14 @@ public class TransactionFactoryInitiator @Override @SuppressWarnings( {"unchecked"}) public TransactionFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) { - final Object strategy = configurationValues.get( Environment.TRANSACTION_STRATEGY ); + final Object strategy = configurationValues.get( AvailableSettings.TRANSACTION_STRATEGY ); + if ( strategy == null ) { LOG.usingDefaultTransactionStrategy(); return new JdbcTransactionFactory(); } - if ( TransactionFactory.class.isInstance( strategy ) ) { - return (TransactionFactory) strategy; - } - - Class transactionFactoryClass; - if ( Class.class.isInstance( strategy ) ) { - final Class theClass = (Class) strategy; - LOG.transactionStrategy( theClass.getName() ); - try { - transactionFactoryClass = (Class) theClass; - } - catch (ClassCastException e) { - throw new ClassLoadingException( - String.format( - "TransactionFactory implementation class [%s] did not implement TransactionFactory interface", - theClass.getName() - ) - ); - } - } - else { - final String strategyClassName = mapName( strategy.toString() ); - LOG.transactionStrategy( strategyClassName ); - - try { - transactionFactoryClass = registry.getService( ClassLoaderService.class ).classForName( strategyClassName ); - } - catch (ClassCastException e) { - throw new ClassLoadingException( - String.format( - "TransactionFactory implementation class [%s] did not implement TransactionFactory interface", - strategyClassName - ) - ); - } - } - - try { - return transactionFactoryClass.newInstance(); - } - catch ( Exception e ) { - throw new HibernateException( "Unable to instantiate specified TransactionFactory class [" + transactionFactoryClass.getName() + "]", e ); - } - } - - private String mapName(String name) { - // check legacy names ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if ( "org.hibernate.transaction.JDBCTransactionFactory".equals( name ) ) { - return JdbcTransactionFactory.class.getName(); - } - - if ( "org.hibernate.transaction.JTATransactionFactory".equals( name ) ) { - return JtaTransactionFactory.class.getName(); - } - - if ( "org.hibernate.transaction.CMTTransactionFactory".equals( name ) ) { - return CMTTransactionFactory.class.getName(); - } - - // check short names ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if ( JdbcTransactionFactory.SHORT_NAME.endsWith( name ) ) { - return JdbcTransactionFactory.class.getName(); - } - - if ( JtaTransactionFactory.SHORT_NAME.equals( name ) ) { - return JtaTransactionFactory.class.getName(); - } - - if ( CMTTransactionFactory.SHORT_NAME.equals( name ) ) { - return CMTTransactionFactory.class.getName(); - } - - - return name; + return registry.getService( StrategySelector.class ).resolveStrategy( TransactionFactory.class, strategy ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/service/BootstrapServiceRegistryBuilder.java b/hibernate-core/src/main/java/org/hibernate/service/BootstrapServiceRegistryBuilder.java index 165c9b436a..6c1107bb6b 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/BootstrapServiceRegistryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/service/BootstrapServiceRegistryBuilder.java @@ -29,6 +29,8 @@ import org.hibernate.integrator.internal.IntegratorServiceImpl; import org.hibernate.integrator.spi.Integrator; import org.hibernate.service.classloading.internal.ClassLoaderServiceImpl; import org.hibernate.service.internal.BootstrapServiceRegistryImpl; +import org.hibernate.service.selector.internal.StrategySelectorBuilder; +import org.hibernate.service.selector.internal.StrategySelectorImpl; /** * Builder for bootstrap {@link ServiceRegistry} instances. @@ -45,6 +47,8 @@ public class BootstrapServiceRegistryBuilder { private ClassLoader hibernateClassLoader; private ClassLoader environmentClassLoader; + private StrategySelectorBuilder strategySelectorBuilder = new StrategySelectorBuilder(); + /** * Add an {@link Integrator} to be applied to the bootstrap registry. * @@ -104,6 +108,23 @@ public class BootstrapServiceRegistryBuilder { return this; } + /** + * Applies a named strategy implementation to the bootstrap registry + * + * @param strategy The strategy + * @param name The registered name + * @param implementation The strategy implementation Class + * + * @return {@code this}, for method chaining + * + * @see org.hibernate.service.selector.spi.StrategySelector#registerStrategyImplementor(Class, String, Class) + */ + @SuppressWarnings( {"UnusedDeclaration"}) + public BootstrapServiceRegistryBuilder withStrategySelector(Class strategy, String name, Class implementation) { + this.strategySelectorBuilder.addCustomRegistration( strategy, name, implementation ); + return this; + } + /** * Build the bootstrap registry. * @@ -122,6 +143,11 @@ public class BootstrapServiceRegistryBuilder { classLoaderService ); - return new BootstrapServiceRegistryImpl( classLoaderService, integratorService ); + + return new BootstrapServiceRegistryImpl( + classLoaderService, + strategySelectorBuilder.buildSelector( classLoaderService ), + integratorService + ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/BootstrapServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/BootstrapServiceRegistryImpl.java index 5a33aeb1c6..3659ce8b71 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/BootstrapServiceRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/BootstrapServiceRegistryImpl.java @@ -33,6 +33,8 @@ import org.hibernate.service.Service; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.classloading.internal.ClassLoaderServiceImpl; import org.hibernate.service.classloading.spi.ClassLoaderService; +import org.hibernate.service.selector.internal.StrategySelectorImpl; +import org.hibernate.service.selector.spi.StrategySelector; import org.hibernate.service.spi.ServiceBinding; import org.hibernate.service.spi.ServiceException; import org.hibernate.service.spi.ServiceInitiator; @@ -51,6 +53,7 @@ public class BootstrapServiceRegistryImpl private static final LinkedHashSet NO_INTEGRATORS = new LinkedHashSet(); private final ServiceBinding classLoaderServiceBinding; + private final ServiceBinding strategySelectorBinding; private final ServiceBinding integratorServiceBinding; public BootstrapServiceRegistryImpl() { @@ -59,6 +62,30 @@ public class BootstrapServiceRegistryImpl public BootstrapServiceRegistryImpl( ClassLoaderService classLoaderService, + LinkedHashSet providedIntegrators) { + this.classLoaderServiceBinding = new ServiceBinding( + this, + ClassLoaderService.class, + classLoaderService + ); + + final StrategySelectorImpl strategySelector = new StrategySelectorImpl( classLoaderService ); + this.strategySelectorBinding = new ServiceBinding( + this, + StrategySelector.class, + strategySelector + ); + + this.integratorServiceBinding = new ServiceBinding( + this, + IntegratorService.class, + new IntegratorServiceImpl( providedIntegrators, classLoaderService ) + ); + } + + public BootstrapServiceRegistryImpl( + ClassLoaderService classLoaderService, + StrategySelector strategySelector, IntegratorService integratorService) { this.classLoaderServiceBinding = new ServiceBinding( this, @@ -66,6 +93,12 @@ public class BootstrapServiceRegistryImpl classLoaderService ); + this.strategySelectorBinding = new ServiceBinding( + this, + StrategySelector.class, + strategySelector + ); + this.integratorServiceBinding = new ServiceBinding( this, IntegratorService.class, @@ -74,13 +107,6 @@ public class BootstrapServiceRegistryImpl } - public BootstrapServiceRegistryImpl( - ClassLoaderService classLoaderService, - LinkedHashSet providedIntegrators) { - this( classLoaderService, new IntegratorServiceImpl( providedIntegrators, classLoaderService ) ); - } - - @Override public R getService(Class serviceRole) { @@ -94,6 +120,9 @@ public class BootstrapServiceRegistryImpl if ( ClassLoaderService.class.equals( serviceRole ) ) { return (ServiceBinding) classLoaderServiceBinding; } + else if ( StrategySelector.class.equals( serviceRole) ) { + return (ServiceBinding) strategySelectorBinding; + } else if ( IntegratorService.class.equals( serviceRole ) ) { return (ServiceBinding) integratorServiceBinding; } diff --git a/hibernate-core/src/main/java/org/hibernate/service/selector/internal/StrategySelectorBuilder.java b/hibernate-core/src/main/java/org/hibernate/service/selector/internal/StrategySelectorBuilder.java new file mode 100644 index 0000000000..54002abb84 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/service/selector/internal/StrategySelectorBuilder.java @@ -0,0 +1,105 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.service.selector.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.jboss.logging.Logger; + +import org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory; +import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory; +import org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory; +import org.hibernate.engine.transaction.spi.TransactionFactory; +import org.hibernate.service.classloading.internal.ClassLoaderServiceImpl; +import org.hibernate.service.selector.spi.StrategySelectionException; +import org.hibernate.service.selector.spi.StrategySelector; + +/** + * @author Steve Ebersole + */ +public class StrategySelectorBuilder { + private static final Logger log = Logger.getLogger( StrategySelectorBuilder.class ); + + private static class CustomRegistration { + private final Class strategy; + private final String name; + private final Class implementation; + + private CustomRegistration(Class strategy, String name, Class implementation) { + this.strategy = strategy; + this.name = name; + this.implementation = implementation; + } + + public void registerWith(StrategySelectorImpl strategySelector) { + strategySelector.registerStrategyImplementor( strategy, name, implementation ); + } + } + + private final List customRegistrations = new ArrayList(); + + @SuppressWarnings("unchecked") + public void addCustomRegistration(Class strategy, String name, Class implementation) { + if ( !strategy.isInterface() ) { + // not good form... + log.debug( "Registering non-interface strategy implementation : " + strategy.getName() ); + } + + if ( ! strategy.isAssignableFrom( implementation ) ) { + throw new StrategySelectionException( + "Implementation class [" + implementation.getName() + "] does not implement strategy interface [" + + strategy.getName() + "]" + ); + } + customRegistrations.add( new CustomRegistration( strategy, name, implementation ) ); + } + + public StrategySelector buildSelector(ClassLoaderServiceImpl classLoaderService) { + StrategySelectorImpl strategySelector = new StrategySelectorImpl( classLoaderService ); + + // build the baseline... + addTransactionFactories( strategySelector ); + + // todo : apply auto-discovered registrations + + // apply customizations + for ( CustomRegistration customRegistration : customRegistrations ) { + customRegistration.registerWith( strategySelector ); + } + + return strategySelector; + } + + private void addTransactionFactories(StrategySelectorImpl strategySelector) { + strategySelector.registerStrategyImplementor( TransactionFactory.class, JdbcTransactionFactory.SHORT_NAME, JdbcTransactionFactory.class ); + strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JDBCTransactionFactory", JdbcTransactionFactory.class ); + + strategySelector.registerStrategyImplementor( TransactionFactory.class, JtaTransactionFactory.SHORT_NAME, JtaTransactionFactory.class ); + strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.JTATransactionFactory", JtaTransactionFactory.class ); + + strategySelector.registerStrategyImplementor( TransactionFactory.class, CMTTransactionFactory.SHORT_NAME, CMTTransactionFactory.class ); + strategySelector.registerStrategyImplementor( TransactionFactory.class, "org.hibernate.transaction.CMTTransactionFactory", CMTTransactionFactory.class ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/service/selector/internal/StrategySelectorImpl.java b/hibernate-core/src/main/java/org/hibernate/service/selector/internal/StrategySelectorImpl.java new file mode 100644 index 0000000000..42e2d45e01 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/service/selector/internal/StrategySelectorImpl.java @@ -0,0 +1,161 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.service.selector.internal; + +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.jboss.logging.Logger; + +import org.hibernate.service.classloading.spi.ClassLoaderService; +import org.hibernate.service.classloading.spi.ClassLoadingException; +import org.hibernate.service.selector.spi.StrategySelectionException; +import org.hibernate.service.selector.spi.StrategySelector; + +/** + * @author Steve Ebersole + */ +public class StrategySelectorImpl implements StrategySelector { + private static final Logger log = Logger.getLogger( StrategySelectorImpl.class ); + + private final Map> namedStrategyImplementorByStrategyMap + = new ConcurrentHashMap>(); + + private final ClassLoaderService classLoaderService; + + public StrategySelectorImpl(ClassLoaderService classLoaderService) { + this.classLoaderService = classLoaderService; + } + + @Override + public void registerStrategyImplementor(Class strategy, String name, Class implementation) { + Map namedStrategyImplementorMap = namedStrategyImplementorByStrategyMap.get( strategy ); + if ( namedStrategyImplementorMap == null ) { + namedStrategyImplementorMap = new ConcurrentHashMap(); + namedStrategyImplementorByStrategyMap.put( strategy, namedStrategyImplementorMap ); + } + + Class old = namedStrategyImplementorMap.put( name, implementation ); + if ( old == null ) { + log.trace( + String.format( + "Registering named strategy selector [%s] : [%s] -> [%s]", + strategy.getName(), + name, + implementation.getName() + ) + ); + } + else { + log.debug( + String.format( + "Registering named strategy selector [%s] : [%s] -> [%s] (replacing [%s])", + strategy.getName(), + name, + implementation.getName(), + old.getName() + ) + ); + } + } + + @Override + public void unRegisterStrategyImplementor(Class strategy, Class implementation) { + Map namedStrategyImplementorMap = namedStrategyImplementorByStrategyMap.get( strategy ); + if ( namedStrategyImplementorMap == null ) { + log.debug( "Named strategy map did not exist on call to un-register" ); + return; + } + + final Iterator itr = namedStrategyImplementorMap.values().iterator(); + while ( itr.hasNext() ) { + final Class registered = (Class) itr.next(); + if ( registered.equals( implementation ) ) { + itr.remove(); + } + } + + // try tp clean up after ourselves... + if ( namedStrategyImplementorMap.isEmpty() ) { + namedStrategyImplementorByStrategyMap.remove( strategy ); + } + } + + @Override + @SuppressWarnings("unchecked") + public Class selectStrategyImplementor(Class strategy, String name) { + Map namedStrategyImplementorMap = namedStrategyImplementorByStrategyMap.get( strategy ); + if ( namedStrategyImplementorMap != null ) { + final Class registered = namedStrategyImplementorMap.get( name ); + if ( registered != null ) { + return (Class) registered; + } + } + + try { + return classLoaderService.classForName( name ); + } + catch (ClassLoadingException e) { + throw new StrategySelectionException( + "Unable to resolve name [" + name + "] as strategy [" + strategy.getName() + "]" + ); + } + } + + @Override + public T resolveStrategy(Class strategy, Object strategyReference) { + return resolveDefaultableStrategy( strategy, strategyReference, null ); + } + + @Override + @SuppressWarnings("unchecked") + public T resolveDefaultableStrategy(Class strategy, Object strategyReference, T defaultValue) { + if ( strategyReference == null ) { + return defaultValue; + } + + if ( strategy.isInstance( strategyReference ) ) { + return strategy.cast( strategyReference ); + } + + final Class implementationClass; + if ( Class.class.isInstance( strategyReference ) ) { + implementationClass = (Class) strategyReference; + } + else { + implementationClass = selectStrategyImplementor( strategy, strategyReference.toString() ); + } + + try { + return implementationClass.newInstance(); + } + catch (Exception e) { + throw new StrategySelectionException( + String.format( "Could not instantiate named strategy class [%s]", implementationClass.getName() ), + e + ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/service/selector/package-info.java b/hibernate-core/src/main/java/org/hibernate/service/selector/package-info.java new file mode 100644 index 0000000000..885cc72a2e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/service/selector/package-info.java @@ -0,0 +1 @@ +package org.hibernate.service.selector; \ No newline at end of file diff --git a/hibernate-core/src/main/java/org/hibernate/service/selector/spi/StrategySelectionException.java b/hibernate-core/src/main/java/org/hibernate/service/selector/spi/StrategySelectionException.java new file mode 100644 index 0000000000..5caf1e2804 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/service/selector/spi/StrategySelectionException.java @@ -0,0 +1,39 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.service.selector.spi; + +import org.hibernate.HibernateException; + +/** + * @author Steve Ebersole + */ +public class StrategySelectionException extends HibernateException { + public StrategySelectionException(String message) { + super( message ); + } + + public StrategySelectionException(String message, Throwable root) { + super( message, root ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/service/selector/spi/StrategySelector.java b/hibernate-core/src/main/java/org/hibernate/service/selector/spi/StrategySelector.java new file mode 100644 index 0000000000..222c4dc047 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/service/selector/spi/StrategySelector.java @@ -0,0 +1,98 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, 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.service.selector.spi; + +import org.hibernate.service.Service; + +/** + * Service which acts as a registry for named strategy implementations. + * + * @author Steve Ebersole + */ +public interface StrategySelector extends Service { + /** + * Registers a named implementor of a particular strategy contract. + * + * @param strategy The strategy contract. + * @param name The registration name + * @param implementation The implementation Class + */ + public void registerStrategyImplementor(Class strategy, String name, Class implementation); + + /** + * Un-registers a named implementor of a particular strategy contract. Un-registers all named registrations + * for the given strategy contract naming the given class. + * + * @param strategy The strategy contract. + * @param implementation The implementation Class + */ + public void unRegisterStrategyImplementor(Class strategy, Class implementation); + + /** + * Locate the named strategy implementation. + * + * @param strategy The type of strategy to be resolved. + * @param name The name of the strategy to locate; might be either a registered name or the implementation FQN. + * + * @return The named strategy implementation class. + */ + public Class selectStrategyImplementor(Class strategy, String name); + + /** + * Resolve strategy instances. See discussion on {@link #resolveDefaultableStrategy}. + * Only difference is that here, the implied default value is {@code null}. + * + * @param strategy The type (interface) of the strategy to be resolved. + * @param strategyReference The reference to the strategy for which we need to resolve an instance. + * + * @return The strategy instance + */ + public T resolveStrategy(Class strategy, Object strategyReference); + + /** + * Resolve strategy instances. The incoming reference might be:
    + *
  • + * {@code null} - in which case defaultValue is returned. + *
  • + *
  • + * An actual instance of the strategy type - it is returned, as is + *
  • + *
  • + * A reference to the implementation {@link Class} - an instance is created by calling + * {@link Class#newInstance()} (aka, the class's no-arg ctor). + *
  • + *
  • + * The name of the implementation class - First the implementation's {@link Class} reference + * is resolved, and then an instance is created by calling {@link Class#newInstance()} + *
  • + *
+ * + * @param strategy The type (interface) of the strategy to be resolved. + * @param strategyReference The reference to the strategy for which we need to resolve an instance. + * @param defaultValue THe default value to use if strategyReference is null + * + * @return The strategy instance + */ + public T resolveDefaultableStrategy(Class strategy, Object strategyReference, T defaultValue); +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java index 8b71febc67..5a0688b67c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/embeddables/EmbeddableIntegratorTest.java @@ -23,29 +23,26 @@ */ package org.hibernate.test.annotations.embeddables; -import static org.junit.Assert.assertEquals; - import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; -import java.util.LinkedHashSet; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.exception.GenericJDBCException; -import org.hibernate.integrator.internal.IntegratorServiceImpl; -import org.hibernate.integrator.spi.Integrator; -import org.hibernate.integrator.spi.IntegratorService; +import org.hibernate.service.BootstrapServiceRegistryBuilder; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; -import org.hibernate.service.classloading.internal.ClassLoaderServiceImpl; -import org.hibernate.service.classloading.spi.ClassLoaderService; import org.hibernate.service.internal.BootstrapServiceRegistryImpl; -import org.hibernate.testing.junit4.BaseUnitTestCase; + import org.junit.Test; +import org.hibernate.testing.junit4.BaseUnitTestCase; + +import static org.junit.Assert.assertEquals; + /** * @author Chris Pheby */ @@ -81,15 +78,9 @@ public class EmbeddableIntegratorTest extends BaseUnitTestCase { @Test public void testWithIntegrator() { - - LinkedHashSet providedIntegrators = new LinkedHashSet(); - providedIntegrators.add(new InvestorIntegrator()); - ClassLoaderService classLoaderService = new ClassLoaderServiceImpl(); - IntegratorService integratorService = new IntegratorServiceImpl(providedIntegrators, classLoaderService); - - ServiceRegistry reg = new ServiceRegistryBuilder(new BootstrapServiceRegistryImpl( - classLoaderService, - integratorService)).buildServiceRegistry(); + ServiceRegistry reg = new ServiceRegistryBuilder( + new BootstrapServiceRegistryBuilder().with( new InvestorIntegrator() ).build() + ).buildServiceRegistry(); SessionFactory sf = new Configuration() .addAnnotatedClass( Investor.class )