11/*
2- * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
33 *
44 * This program and the accompanying materials are made available under the
55 * terms of the Eclipse Public License v. 2.0, which is available at
3131import java .util .Iterator ;
3232import java .util .List ;
3333import java .util .NoSuchElementException ;
34+ import java .util .ServiceLoader ;
3435import java .util .Set ;
3536import java .util .TreeSet ;
3637import java .util .logging .Level ;
3738import java .util .logging .Logger ;
39+ import java .util .stream .Collectors ;
3840
3941import org .glassfish .jersey .internal .util .ReflectionHelper ;
4042
@@ -229,7 +231,9 @@ public static <T> ServiceFinder<T> find(final Class<T> service, final ClassLoade
229231 * class loader (or, failing that the bootstrap class loader) is to
230232 * be used
231233 * @param ignoreOnClassNotFound If a provider cannot be loaded by the class loader
232- * then move on to the next available provider.
234+ * then move on to the next available provider. This value does
235+ * not apply when the {@link ServiceIteratorProvider} is set to
236+ * {@link ServiceLookupIteratorProvider}.
233237 * @throws ServiceConfigurationError If a provider-configuration file violates the specified format
234238 * or names a provider class that cannot be found and instantiated
235239 * @see #find(Class)
@@ -279,7 +283,10 @@ public static <T> ServiceFinder<T> find(final Class<T> service)
279283 * </pre>
280284 * @param service The service's abstract service class
281285 * @param ignoreOnClassNotFound If a provider cannot be loaded by the class loader
282- * then move on to the next available provider.
286+ * then move on to the next available provider. This value does
287+ * not apply when the {@link ServiceIteratorProvider} is set to
288+ * {@link ServiceLookupIteratorProvider}.
289+ *
283290 * @throws ServiceConfigurationError If a provider-configuration file violates the specified format
284291 * or names a provider class that cannot be found and instantiated
285292 * @see #find(Class, ClassLoader)
@@ -312,7 +319,7 @@ public static ServiceFinder<?> find(final String serviceName) throws ServiceConf
312319 * Register the service iterator provider to iterate on provider instances
313320 * or classes.
314321 * <p>
315- * The default implementation registered, {@link DefaultServiceIteratorProvider },
322+ * The default implementation registered, {@link ServiceLookupIteratorProvider },
316323 * looks up provider classes in META-INF/service files.
317324 * <p>
318325 * This method must be called prior to any attempts to obtain provider
@@ -790,7 +797,7 @@ private void handleClassNotFoundException() throws ServiceConfigurationError {
790797 * Supports iteration of provider instances or classes.
791798 * <p>
792799 * The default implementation looks up provider classes from META-INF/services
793- * files, see {@link DefaultServiceIteratorProvider }.
800+ * files, see {@link ServiceLookupIteratorProvider }.
794801 * This implementation may be overridden by invoking
795802 * {@link ServiceFinder#setIteratorProvider(org.glassfish.jersey.internal.ServiceFinder.ServiceIteratorProvider)}.
796803 */
@@ -806,7 +813,7 @@ private static ServiceIteratorProvider getInstance() {
806813 synchronized (sipLock ) {
807814 result = sip ;
808815 if (result == null ) { // Second check (with locking)
809- sip = result = new DefaultServiceIteratorProvider ();
816+ sip = result = new ServiceLookupIteratorProvider ();
810817 }
811818 }
812819 }
@@ -834,7 +841,9 @@ private static void setInstance(final ServiceIteratorProvider sip) throws Securi
834841 * classes.
835842 * @param ignoreOnClassNotFound if true ignore an instance if the
836843 * corresponding provider class if cannot be found,
837- * otherwise throw a {@link ClassNotFoundException}.
844+ * otherwise throw a {@link ClassNotFoundException}. This value does
845+ * not apply when the {@link ServiceIteratorProvider} is set to
846+ * {@link ServiceLookupIteratorProvider}.
838847 * @return the provider instance iterator.
839848 */
840849 public abstract <T > Iterator <T > createIterator (Class <T > service ,
@@ -851,6 +860,8 @@ public abstract <T> Iterator<T> createIterator(Class<T> service,
851860 * @param ignoreOnClassNotFound if true ignore the provider class if
852861 * cannot be found,
853862 * otherwise throw a {@link ClassNotFoundException}.
863+ * This value does not apply when the {@link ServiceIteratorProvider}
864+ * is set to {@link ServiceLookupIteratorProvider}.
854865 * @return the provider class iterator.
855866 */
856867 public abstract <T > Iterator <Class <T >> createClassIterator (Class <T > service ,
@@ -860,13 +871,10 @@ public abstract <T> Iterator<Class<T>> createClassIterator(Class<T> service,
860871 }
861872
862873 /**
863- * The default service iterator provider that looks up provider classes in
874+ * The service iterator provider that looks up provider classes in
864875 * META-INF/services files.
865- * <p>
866- * This class may utilized if a {@link ServiceIteratorProvider} needs to
867- * reuse the default implementation.
868876 */
869- public static final class DefaultServiceIteratorProvider extends ServiceIteratorProvider {
877+ public static final class ServiceReflectionIteratorProvider extends ServiceIteratorProvider {
870878
871879 @ Override
872880 public <T > Iterator <T > createIterator (final Class <T > service , final String serviceName ,
@@ -880,4 +888,41 @@ public <T> Iterator<Class<T>> createClassIterator(final Class<T> service, final
880888 return new LazyClassIterator <T >(service , serviceName , loader , ignoreOnClassNotFound );
881889 }
882890 }
891+
892+ /**
893+ * The service iterator provider that looks up provider classes in
894+ * META-INF/services files using {@link ServiceLoader}.
895+ */
896+ public static final class ServiceLookupIteratorProvider extends ServiceIteratorProvider {
897+
898+ @ Override
899+ public <T > Iterator <T > createIterator (final Class <T > service , final String serviceName ,
900+ final ClassLoader loader , final boolean ignoreOnClassNotFound ) {
901+ Class <T > clazz = fixGenericService (service , serviceName , loader , ignoreOnClassNotFound );
902+ return ServiceLoader .load (clazz , loader ).iterator ();
903+ }
904+
905+ @ Override
906+ public <T > Iterator <Class <T >> createClassIterator (final Class <T > service , final String serviceName ,
907+ final ClassLoader loader , final boolean ignoreOnClassNotFound ) {
908+ Class <T > clazz = fixGenericService (service , serviceName , loader , ignoreOnClassNotFound );
909+ List <Class <T >> classes = ServiceLoader .load (clazz , loader ).stream ()
910+ .map (provider -> (Class <T >) provider .type ())
911+ .collect (Collectors .toList ());
912+ return classes .iterator ();
913+ }
914+
915+ private <T > Class <T > fixGenericService (final Class <T > service , final String serviceName ,
916+ final ClassLoader loader , final boolean ignoreOnClassNotFound ) {
917+ Class <T > clazz = service ;
918+ if (Object .class == service ) {
919+ try {
920+ clazz = (Class <T >) ReflectionHelper .classForNameWithExceptionPEA (serviceName , loader ).run ();
921+ } catch (Exception e ) {
922+ // Ignore it. Later, the service implementation will not be loaded.
923+ }
924+ }
925+ return clazz ;
926+ }
927+ }
883928}
0 commit comments