diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/AggregatedServiceLoader.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/AggregatedServiceLoader.java index 59c195782d..376c9a9f60 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/AggregatedServiceLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/AggregatedServiceLoader.java @@ -6,8 +6,6 @@ */ package org.hibernate.boot.registry.classloading.internal; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -18,10 +16,8 @@ import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Stream; -import org.hibernate.AssertionFailure; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; @@ -33,46 +29,9 @@ abstract class AggregatedServiceLoader { private static final CoreMessageLogger log = CoreLogging.messageLogger( AggregatedServiceLoader.class ); - private static final Method SERVICE_LOADER_STREAM_METHOD; - private static final Method PROVIDER_TYPE_METHOD; - - static { - Class serviceLoaderClass = ServiceLoader.class; - Method serviceLoaderStreamMethod = null; - Method providerTypeMethod = null; - try { - /* - * JDK 9 introduced the stream() method on ServiceLoader, - * which we need in order to avoid duplicate service instantiation. - * See ClassPathAndModulePathAggregatedServiceLoader. - */ - serviceLoaderStreamMethod = serviceLoaderClass.getMethod( "stream" ); - Class providerClass = Class.forName( serviceLoaderClass.getName() + "$Provider" ); - providerTypeMethod = providerClass.getMethod( "type" ); - } - catch (NoSuchMethodException | ClassNotFoundException e) { - /* - * Probably Java 8. - * Leave the method constants null, - * we will automatically use a service loader implementation that doesn't rely on them. - * See create(...). - */ - } - - SERVICE_LOADER_STREAM_METHOD = serviceLoaderStreamMethod; - PROVIDER_TYPE_METHOD = providerTypeMethod; - } - static AggregatedServiceLoader create(AggregatedClassLoader aggregatedClassLoader, Class serviceContract) { - if ( SERVICE_LOADER_STREAM_METHOD != null ) { - // Java 9+ return new ClassPathAndModulePathAggregatedServiceLoader<>( aggregatedClassLoader, serviceContract ); - } - else { - // Java 8 - return new ClassPathOnlyAggregatedServiceLoader<>( aggregatedClassLoader, serviceContract ); - } } /** @@ -85,44 +44,10 @@ static AggregatedServiceLoader create(AggregatedClassLoader aggregatedCla */ public abstract void close(); - /** - * An {@link AggregatedServiceLoader} that will only detect services defined in the class path, - * not in the module path, - * because it passes the aggregated classloader directly to the service loader. - *

- * This implementation is best when running Hibernate ORM on Java 8. - * On Java 9 and above, {@link ClassPathAndModulePathAggregatedServiceLoader} should be used. - * - * @param The type of loaded services. - */ - private static class ClassPathOnlyAggregatedServiceLoader extends AggregatedServiceLoader { - private final ServiceLoader delegate; - - private ClassPathOnlyAggregatedServiceLoader(AggregatedClassLoader aggregatedClassLoader, Class serviceContract) { - this.delegate = ServiceLoader.load( serviceContract, aggregatedClassLoader ); - } - - @Override - public Collection getAll() { - final Set services = new LinkedHashSet<>(); - for ( S service : delegate ) { - services.add( service ); - } - return services; - } - - @Override - public void close() { - // Clear service providers - delegate.reload(); - } - } - /** * An {@link AggregatedServiceLoader} that will detect services defined in the class path or in the module path. *

* This implementation only works when running Hibernate ORM on Java 9 and above. - * On Java 8, {@link ClassPathOnlyAggregatedServiceLoader} must be used. *

* When retrieving services from providers in the module path, * the service loader internally uses a map from classloader to service catalog. @@ -182,7 +107,7 @@ public Collection getAll() { * as well as the close() method, * and also the service loader map in ClassLoaderServiceImpl, * and we can simply call .reload() on the service loader after we load services - * in ClassPathOnlyAggregatedServiceLoader.getAll(). + * in ClassPathAndModulePathAggregatedServiceLoader.getAll(). */ cache = Collections.unmodifiableCollection( loadAll() ); } @@ -194,9 +119,9 @@ private Collection loadAll() { Set result = new LinkedHashSet<>(); // Always try the aggregated class loader first - Iterator> providerIterator = providerStream( aggregatedClassLoaderServiceLoader ).iterator(); + Iterator> providerIterator = aggregatedClassLoaderServiceLoader.stream().iterator(); while ( providerIterator.hasNext() ) { - Supplier provider = providerIterator.next(); + ServiceLoader.Provider provider = providerIterator.next(); collectServiceIfNotDuplicate( result, alreadyEncountered, provider ); } @@ -205,7 +130,7 @@ private Collection loadAll() { * because only them can instantiate services provided by jars in the module path. */ for ( ServiceLoader delegate : delegates ) { - providerIterator = providerStream( delegate ).iterator(); + providerIterator = delegate.stream().iterator(); /* * Note that advancing the stream itself can lead to (arguably) "legitimate" errors, * where we fail to load the service, @@ -216,7 +141,7 @@ private Collection loadAll() { * See https://hibernate.atlassian.net/browse/HHH-13551. */ while ( hasNextIgnoringServiceConfigurationError( providerIterator ) ) { - Supplier provider = providerIterator.next(); + ServiceLoader.Provider provider = providerIterator.next(); collectServiceIfNotDuplicate( result, alreadyEncountered, provider ); } } @@ -224,16 +149,6 @@ private Collection loadAll() { return result; } - @SuppressWarnings("unchecked") - private Stream> providerStream(ServiceLoader serviceLoader) { - try { - return ( (Stream>) SERVICE_LOADER_STREAM_METHOD.invoke( serviceLoader ) ); - } - catch (RuntimeException | IllegalAccessException | InvocationTargetException e) { - throw new AssertionFailure( "Error calling ServiceLoader.stream()", e ); - } - } - private boolean hasNextIgnoringServiceConfigurationError(Iterator iterator) { while ( true ) { try { @@ -262,14 +177,8 @@ private boolean hasNextIgnoringServiceConfigurationError(Iterator iterator) { * and one provider may return different types of services * depending on conditions known only to itself. */ - private void collectServiceIfNotDuplicate(Set result, Set alreadyEncountered, Supplier provider) { - Class type; - try { - type = (Class) PROVIDER_TYPE_METHOD.invoke( provider ); - } - catch (RuntimeException | IllegalAccessException | InvocationTargetException e) { - throw new AssertionFailure( "Error calling ServiceLoader.Provider.type()", e ); - } + private void collectServiceIfNotDuplicate(Set result, Set alreadyEncountered, ServiceLoader.Provider provider) { + final Class type = provider.type(); String typeName = type.getName(); if ( alreadyEncountered.add( typeName ) ) { result.add( provider.get() );