From 859eaaa1c5056432696c7ebeff5e03adbcea8bec Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Thu, 17 Oct 2013 15:18:32 -0500 Subject: [PATCH] HHH-8619 - Account for "shadow" services as part of ServiceRegistry impls --- .../hibernate/internal/CoreMessageLogger.java | 8 +++ .../internal/AbstractServiceRegistryImpl.java | 70 +++++++++++++++---- .../src/test/resources/hibernate.properties | 3 +- .../src/test/resources/hibernate.properties | 1 + .../src/test/resources/hibernate.properties | 1 + .../src/test/resources/hibernate.properties | 1 + .../src/test/resources/hibernate.properties | 25 +------ 7 files changed, 73 insertions(+), 36 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java index 52d6f2eaa2..956fa3ec35 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java @@ -56,6 +56,7 @@ import org.hibernate.engine.loading.internal.EntityLoadContext; import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.id.IntegralDataTypeHolder; +import org.hibernate.service.Service; import org.hibernate.type.BasicType; import org.hibernate.type.SerializationException; import org.hibernate.type.Type; @@ -1629,4 +1630,11 @@ public interface CoreMessageLogger extends BasicLogger { "using 'key'/'value' as required by spec; attempting to DoTheRightThing" ) void nonCompliantMapConversion(String collectionRole); + + @LogMessage(level = WARN) + @Message( + id = 450, + value = "Encountered request for Service by non-primary service role [%s -> %s]; please update usage" + ) + void alternateServiceRole(String requestedRole, String targetRole); } diff --git a/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java b/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java index 767f38e246..e705955f23 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java @@ -28,11 +28,12 @@ import java.util.List; import java.util.ListIterator; import java.util.concurrent.ConcurrentHashMap; -import org.jboss.logging.Logger; - +import org.hibernate.cfg.Environment; +import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.boot.registry.BootstrapServiceRegistry; +import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.Service; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.UnknownServiceException; @@ -48,19 +49,22 @@ import org.hibernate.service.spi.Startable; import org.hibernate.service.spi.Stoppable; /** + * Basic implementation of the ServiceRegistry and ServiceRegistryImplementor contracts + * * @author Steve Ebersole */ public abstract class AbstractServiceRegistryImpl implements ServiceRegistryImplementor, ServiceBinding.ServiceLifecycleOwner { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( - CoreMessageLogger.class, - AbstractServiceRegistryImpl.class.getName() - ); + private static final CoreMessageLogger log = CoreLogging.messageLogger( AbstractServiceRegistryImpl.class ); + + public static final String ALLOW_CRAWLING = "hibernate.service.allow_crawling"; private final ServiceRegistryImplementor parent; + private final boolean allowCrawling; private final ConcurrentHashMap serviceBindingMap = CollectionHelper.concurrentMap( 20 ); + private ConcurrentHashMap roleXref; // IMPL NOTE : the list used for ordered destruction. Cannot used map above because we need to // iterate it in reverse order which is only available through ListIterator @@ -74,13 +78,15 @@ public abstract class AbstractServiceRegistryImpl protected AbstractServiceRegistryImpl(ServiceRegistryImplementor parent) { this.parent = parent; + this.allowCrawling = ConfigurationHelper.getBoolean( ALLOW_CRAWLING, Environment.getProperties(), true ); } public AbstractServiceRegistryImpl(BootstrapServiceRegistry bootstrapServiceRegistry) { if ( ! ServiceRegistryImplementor.class.isInstance( bootstrapServiceRegistry ) ) { - throw new IllegalArgumentException( "Boot-strap registry was not " ); + throw new IllegalArgumentException( "ServiceRegistry parent needs to implement ServiceRegistryImplementor" ); } this.parent = (ServiceRegistryImplementor) bootstrapServiceRegistry; + this.allowCrawling = ConfigurationHelper.getBoolean( ALLOW_CRAWLING, Environment.getProperties(), true ); } @SuppressWarnings({ "unchecked" }) @@ -117,7 +123,47 @@ public abstract class AbstractServiceRegistryImpl // look in parent serviceBinding = parent.locateServiceBinding( serviceRole ); } - return serviceBinding; + + if ( serviceBinding != null ) { + return serviceBinding; + } + + if ( !allowCrawling ) { + return null; + } + + // look for a previously resolved alternate registration + if ( roleXref != null ) { + if ( roleXref.containsKey( serviceRole ) ) { + return serviceBindingMap.get( roleXref.get( serviceRole ) ); + } + } + + // perform a crawl looking for an alternate registration + for ( ServiceBinding binding : serviceBindingMap.values() ) { + if ( serviceRole.isAssignableFrom( binding.getServiceRole() ) ) { + // we found an alternate... + log.alternateServiceRole( serviceRole.getName(), binding.getServiceRole().getName() ); + registerAlternate( serviceRole, binding.getServiceRole() ); + return binding; + } + + if ( binding.getService() != null && serviceRole.isInstance( binding.getService() ) ) { + // we found an alternate... + log.alternateServiceRole( serviceRole.getName(), binding.getServiceRole().getName() ); + registerAlternate( serviceRole, binding.getServiceRole() ); + return binding; + } + } + + return null; + } + + private void registerAlternate(Class alternate, Class target) { + if ( roleXref == null ) { + roleXref = CollectionHelper.concurrentMap( 20 ); + } + roleXref.put( alternate, target ); } @Override @@ -143,8 +189,8 @@ public abstract class AbstractServiceRegistryImpl } private R initializeService(ServiceBinding serviceBinding) { - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Initializing service [role={0}]", serviceBinding.getServiceRole().getName() ); + if ( log.isTraceEnabled() ) { + log.tracev( "Initializing service [role={0}]", serviceBinding.getServiceRole().getName() ); } // PHASE 1 : create service @@ -211,7 +257,7 @@ public abstract class AbstractServiceRegistryImpl } } catch (NullPointerException e) { - LOG.error("NPE injecting service deps : " + service.getClass().getName()); + log.error( "NPE injecting service deps : " + service.getClass().getName() ); } } @@ -285,7 +331,7 @@ public abstract class AbstractServiceRegistryImpl ( (Stoppable) service ).stop(); } catch ( Exception e ) { - LOG.unableToStopService( service.getClass(), e.toString() ); + log.unableToStopService( service.getClass(), e.toString() ); } } } diff --git a/hibernate-core/src/test/resources/hibernate.properties b/hibernate-core/src/test/resources/hibernate.properties index 7494e354a6..7275528c40 100644 --- a/hibernate-core/src/test/resources/hibernate.properties +++ b/hibernate-core/src/test/resources/hibernate.properties @@ -39,4 +39,5 @@ hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFa # NOTE: hibernate.jdbc.batch_versioned_data should be set to false when testing with Oracle hibernate.jdbc.batch_versioned_data true -javax.persistence.validation.mode=NONE \ No newline at end of file +javax.persistence.validation.mode=NONE +hibernate.service.allow_crawling=false \ No newline at end of file diff --git a/hibernate-ehcache/src/test/resources/hibernate.properties b/hibernate-ehcache/src/test/resources/hibernate.properties index d2704c8e24..32a99357cb 100644 --- a/hibernate-ehcache/src/test/resources/hibernate.properties +++ b/hibernate-ehcache/src/test/resources/hibernate.properties @@ -32,3 +32,4 @@ hibernate.cache.region_prefix hibernate.test # NOTE: hibernate.jdbc.batch_versioned_data should be set to false when testing with Oracle hibernate.jdbc.batch_versioned_data true +hibernate.service.allow_crawling=false \ No newline at end of file diff --git a/hibernate-entitymanager/src/test/resources/hibernate.properties b/hibernate-entitymanager/src/test/resources/hibernate.properties index ada04a6588..13cb1f594d 100644 --- a/hibernate-entitymanager/src/test/resources/hibernate.properties +++ b/hibernate-entitymanager/src/test/resources/hibernate.properties @@ -40,3 +40,4 @@ hibernate.jdbc.batch_size 0 # NOTE: hibernate.jdbc.batch_versioned_data should be set to false when testing with Oracle hibernate.jdbc.batch_versioned_data true +hibernate.service.allow_crawling=false diff --git a/hibernate-envers/src/test/resources/hibernate.properties b/hibernate-envers/src/test/resources/hibernate.properties index 2c4ccee114..f766f38d0d 100644 --- a/hibernate-envers/src/test/resources/hibernate.properties +++ b/hibernate-envers/src/test/resources/hibernate.properties @@ -37,3 +37,4 @@ hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFa # NOTE: hibernate.jdbc.batch_versioned_data should be set to false when testing with Oracle hibernate.jdbc.batch_versioned_data true +hibernate.service.allow_crawling=false diff --git a/hibernate-infinispan/src/test/resources/hibernate.properties b/hibernate-infinispan/src/test/resources/hibernate.properties index 44135a8ab5..d811558591 100755 --- a/hibernate-infinispan/src/test/resources/hibernate.properties +++ b/hibernate-infinispan/src/test/resources/hibernate.properties @@ -1,26 +1,4 @@ -################################################################################ -# Hibernate, Relational Persistence for Idiomatic Java # -# # -# Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates 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. and/or it's affiliates. # -# # -# 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 # -################################################################################ + hibernate.dialect org.hibernate.dialect.H2Dialect hibernate.connection.driver_class org.h2.Driver hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE @@ -37,3 +15,4 @@ hibernate.generate_statistics true # NOTE: hibernate.jdbc.batch_versioned_data should be set to false when testing with Oracle hibernate.jdbc.batch_versioned_data true +hibernate.service.allow_crawling=false