1
15
16 package software.amazon.awssdk.core.internal.http.loader;
17
18 import java.util.Iterator;
19 import java.util.Optional;
20 import java.util.ServiceLoader;
21 import software.amazon.awssdk.annotations.SdkInternalApi;
22 import software.amazon.awssdk.annotations.SdkTestInternalApi;
23 import software.amazon.awssdk.core.SdkSystemSetting;
24 import software.amazon.awssdk.core.exception.SdkClientException;
25 import software.amazon.awssdk.http.SdkHttpService;
26 import software.amazon.awssdk.http.async.SdkAsyncHttpService;
27 import software.amazon.awssdk.utils.SystemSetting;
28
29
33 @SdkInternalApi
34 final class ClasspathSdkHttpServiceProvider<T> implements SdkHttpServiceProvider<T> {
35
36 private final SdkServiceLoader serviceLoader;
37 private final SystemSetting implSystemProperty;
38 private final Class<T> serviceClass;
39
40 @SdkTestInternalApi
41 ClasspathSdkHttpServiceProvider(SdkServiceLoader serviceLoader, SystemSetting implSystemProperty, Class<T> serviceClass) {
42 this.serviceLoader = serviceLoader;
43 this.implSystemProperty = implSystemProperty;
44 this.serviceClass = serviceClass;
45 }
46
47 @Override
48 public Optional<T> loadService() {
49 Iterator<T> httpServices = serviceLoader.loadServices(serviceClass);
50 if (!httpServices.hasNext()) {
51 return Optional.empty();
52 }
53 T httpService = httpServices.next();
54
55 if (httpServices.hasNext()) {
56 throw SdkClientException.builder().message(
57 String.format(
58 "Multiple HTTP implementations were found on the classpath. To avoid non-deterministic loading " +
59 "implementations, please explicitly provide an HTTP client via the client builders, set the %s " +
60 "system property with the FQCN of the HTTP service to use as the default, or remove all but one " +
61 "HTTP implementation from the classpath", implSystemProperty.property()))
62 .build();
63 }
64 return Optional.of(httpService);
65 }
66
67
70 static SdkHttpServiceProvider<SdkHttpService> syncProvider() {
71 return new ClasspathSdkHttpServiceProvider<>(SdkServiceLoader.INSTANCE,
72 SdkSystemSetting.SYNC_HTTP_SERVICE_IMPL,
73 SdkHttpService.class);
74 }
75
76
79 static SdkHttpServiceProvider<SdkAsyncHttpService> asyncProvider() {
80 return new ClasspathSdkHttpServiceProvider<>(SdkServiceLoader.INSTANCE,
81 SdkSystemSetting.ASYNC_HTTP_SERVICE_IMPL,
82 SdkAsyncHttpService.class);
83 }
84
85 }
86