Issue #4340 - ServiceLoader stream which doesn't break if hasNext throws
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
355d21317b
commit
edd671146d
|
@ -54,7 +54,7 @@ public class ALPNClientConnectionFactory extends NegotiatingClientConnectionFact
|
||||||
IllegalStateException failure = new IllegalStateException("No Client ALPNProcessors!");
|
IllegalStateException failure = new IllegalStateException("No Client ALPNProcessors!");
|
||||||
|
|
||||||
// Use a for loop on iterator so load exceptions can be caught and ignored
|
// Use a for loop on iterator so load exceptions can be caught and ignored
|
||||||
ServiceLoader.load(Client.class).stream().flatMap(TypeUtil::providerMap).forEach((processor) ->
|
TypeUtil.serviceLoaderStream(ServiceLoader.load(Client.class)).flatMap(TypeUtil::providerMap).forEach((processor) ->
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class ALPNServerConnectionFactory extends NegotiatingServerConnectionFact
|
||||||
|
|
||||||
IllegalStateException failure = new IllegalStateException("No Server ALPNProcessors!");
|
IllegalStateException failure = new IllegalStateException("No Server ALPNProcessors!");
|
||||||
// Use a for loop on iterator so load exceptions can be caught and ignored
|
// Use a for loop on iterator so load exceptions can be caught and ignored
|
||||||
ServiceLoader.load(Server.class).stream().flatMap(TypeUtil::providerMap).forEach((processor) ->
|
TypeUtil.serviceLoaderStream(ServiceLoader.load(Server.class)).flatMap(TypeUtil::providerMap).forEach((processor) ->
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -812,7 +812,7 @@ public class AnnotationConfiguration extends AbstractConfiguration
|
||||||
long start = 0;
|
long start = 0;
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
start = System.nanoTime();
|
start = System.nanoTime();
|
||||||
List<ServletContainerInitializer> scis = ServiceLoader.load(ServletContainerInitializer.class).stream()
|
List<ServletContainerInitializer> scis = TypeUtil.serviceLoaderStream(ServiceLoader.load(ServletContainerInitializer.class))
|
||||||
.flatMap(TypeUtil::providerMap)
|
.flatMap(TypeUtil::providerMap)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class PreEncodedHttpField extends HttpField
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
List<HttpFieldPreEncoder> encoders = ServiceLoader.load(HttpFieldPreEncoder.class).stream()
|
List<HttpFieldPreEncoder> encoders = TypeUtil.serviceLoaderStream(ServiceLoader.load(HttpFieldPreEncoder.class))
|
||||||
.flatMap(TypeUtil::providerMap)
|
.flatMap(TypeUtil::providerMap)
|
||||||
.filter(encoder -> index(encoder.getHttpVersion()) >= 0)
|
.filter(encoder -> index(encoder.getHttpVersion()) >= 0)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
|
@ -77,7 +77,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
ServiceLoader.load(Authenticator.Factory.class).stream()
|
TypeUtil.serviceLoaderStream(ServiceLoader.load(Authenticator.Factory.class))
|
||||||
.flatMap(TypeUtil::providerMap)
|
.flatMap(TypeUtil::providerMap)
|
||||||
.forEach(__knownAuthenticatorFactories::add);
|
.forEach(__knownAuthenticatorFactories::add);
|
||||||
__knownAuthenticatorFactories.add(new DefaultAuthenticatorFactory());
|
__knownAuthenticatorFactories.add(new DefaultAuthenticatorFactory());
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||||
|
//
|
||||||
|
// This program and the accompanying materials are made available under
|
||||||
|
// the terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
// https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// This Source Code may also be made available under the following
|
||||||
|
// Secondary Licenses when the conditions for such availability set
|
||||||
|
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||||
|
// the Apache License v2.0 which is available at
|
||||||
|
// https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.util;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.ServiceConfigurationError;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
import java.util.Spliterator;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
class ServiceLoaderSpliterator<T> implements Spliterator<ServiceLoader.Provider<T>>
|
||||||
|
{
|
||||||
|
private final Iterator<T> iterator;
|
||||||
|
|
||||||
|
public ServiceLoaderSpliterator(ServiceLoader<T> serviceLoader)
|
||||||
|
{
|
||||||
|
iterator = serviceLoader.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryAdvance(Consumer<? super ServiceLoader.Provider<T>> action)
|
||||||
|
{
|
||||||
|
Provider<T> next = new Provider<>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!iterator.hasNext())
|
||||||
|
return false;
|
||||||
|
next.setServiceProvider(iterator.next());
|
||||||
|
}
|
||||||
|
catch (Throwable t)
|
||||||
|
{
|
||||||
|
next.setError(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
action.accept(next);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Spliterator<ServiceLoader.Provider<T>> trySplit()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long estimateSize()
|
||||||
|
{
|
||||||
|
return Long.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int characteristics()
|
||||||
|
{
|
||||||
|
return Spliterator.ORDERED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Provider<T> implements ServiceLoader.Provider<T>
|
||||||
|
{
|
||||||
|
private T serviceProvider;
|
||||||
|
private Throwable error;
|
||||||
|
|
||||||
|
public void setServiceProvider(T serviceProvider)
|
||||||
|
{
|
||||||
|
this.serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setError(Throwable error)
|
||||||
|
{
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Class<? extends T> type()
|
||||||
|
{
|
||||||
|
return (Class<? extends T>)get().getClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get()
|
||||||
|
{
|
||||||
|
if (error != null)
|
||||||
|
throw new ServiceConfigurationError("", error);
|
||||||
|
return serviceProvider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,6 +46,7 @@ import java.util.ServiceConfigurationError;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
@ -778,4 +779,17 @@ public class TypeUtil
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility to create a stream which provides the same functionality as {@link ServiceLoader#stream()}.
|
||||||
|
* However this also guards the case in which {@link Iterator#hasNext()} throws. Any exceptions
|
||||||
|
* from the underlying iterator will be cached until the {@link ServiceLoader.Provider#get()} is called.
|
||||||
|
* @param serviceLoader the ServiceLoader instance to use.
|
||||||
|
* @param <T> the type of the service to load.
|
||||||
|
* @return A stream that lazily loads providers for this loader's service
|
||||||
|
*/
|
||||||
|
public static <T> Stream<ServiceLoader.Provider<T>> serviceLoaderStream(ServiceLoader<T> serviceLoader)
|
||||||
|
{
|
||||||
|
return StreamSupport.stream(new ServiceLoaderSpliterator<T>(serviceLoader), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ public abstract class Credential implements Serializable
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = -7760551052768181572L;
|
private static final long serialVersionUID = -7760551052768181572L;
|
||||||
private static final Logger LOG = Log.getLogger(Credential.class);
|
private static final Logger LOG = Log.getLogger(Credential.class);
|
||||||
private static final List<CredentialProvider> CREDENTIAL_PROVIDERS = ServiceLoader.load(CredentialProvider.class).stream().flatMap(TypeUtil::providerMap).collect(Collectors.toList());
|
private static final List<CredentialProvider> CREDENTIAL_PROVIDERS = TypeUtil.serviceLoaderStream(ServiceLoader.load(CredentialProvider.class)).flatMap(TypeUtil::providerMap).collect(Collectors.toList());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check a credential
|
* Check a credential
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class Configurations extends AbstractList<Configuration> implements Dumpa
|
||||||
{
|
{
|
||||||
if (__known.isEmpty())
|
if (__known.isEmpty())
|
||||||
{
|
{
|
||||||
ServiceLoader.load(Configuration.class).stream().flatMap(TypeUtil::providerMap).forEach(configuration ->
|
TypeUtil.serviceLoaderStream(ServiceLoader.load(Configuration.class)).flatMap(TypeUtil::providerMap).forEach(configuration ->
|
||||||
{
|
{
|
||||||
if (!configuration.isAvailable())
|
if (!configuration.isAvailable())
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,8 +96,8 @@ public class XmlConfiguration
|
||||||
{
|
{
|
||||||
ArrayList.class, HashSet.class, Queue.class, List.class, Set.class, Collection.class
|
ArrayList.class, HashSet.class, Queue.class, List.class, Set.class, Collection.class
|
||||||
};
|
};
|
||||||
private static final List<ConfigurationProcessorFactory> PROCESSOR_FACTORIES = ServiceLoader.load(ConfigurationProcessorFactory.class)
|
private static final List<ConfigurationProcessorFactory> PROCESSOR_FACTORIES = TypeUtil.serviceLoaderStream(ServiceLoader.load(ConfigurationProcessorFactory.class))
|
||||||
.stream().flatMap(TypeUtil::providerMap).collect(Collectors.toList());
|
.flatMap(TypeUtil::providerMap).collect(Collectors.toList());
|
||||||
private static final XmlParser PARSER = initParser();
|
private static final XmlParser PARSER = initParser();
|
||||||
private static final Comparator<Executable> EXECUTABLE_COMPARATOR = (o1, o2) ->
|
private static final Comparator<Executable> EXECUTABLE_COMPARATOR = (o1, o2) ->
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue