1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */

15
16 package software.amazon.awssdk.core.internal.http.loader;
17
18 import java.util.Optional;
19 import software.amazon.awssdk.annotations.SdkInternalApi;
20 import software.amazon.awssdk.core.SdkSystemSetting;
21 import software.amazon.awssdk.core.exception.SdkClientException;
22 import software.amazon.awssdk.http.SdkHttpService;
23 import software.amazon.awssdk.http.async.SdkAsyncHttpService;
24 import software.amazon.awssdk.utils.SystemSetting;
25
26 /**
27  * Attempts to load the default implementation from the system property {@link SdkSystemSetting#SYNC_HTTP_SERVICE_IMPL}. The
28  * property value should be the fully qualified class name of the factory to use.
29  */

30 @SdkInternalApi
31 final class SystemPropertyHttpServiceProvider<T> implements SdkHttpServiceProvider<T> {
32
33     private final SystemSetting implSetting;
34     private final Class<T> serviceClass;
35
36     /**
37      * @param implSetting  {@link SystemSetting} to access the system property that has the implementation FQCN.
38      * @param serviceClass Service type being loaded.
39      */

40     private SystemPropertyHttpServiceProvider(SystemSetting implSetting, Class<T> serviceClass) {
41         this.implSetting = implSetting;
42         this.serviceClass = serviceClass;
43     }
44
45     @Override
46     public Optional<T> loadService() {
47         return implSetting
48                 .getStringValue()
49                 .map(this::createServiceFromProperty);
50     }
51
52     private T createServiceFromProperty(String httpImplFqcn) {
53         try {
54             return serviceClass.cast(Class.forName(httpImplFqcn).newInstance());
55         } catch (Exception e) {
56             throw SdkClientException.builder()
57                                     .message(String.format("Unable to load the HTTP factory implementation from the "
58                                              + "%s system property. Ensure the class '%s' is present on the classpath" +
59                                              "and has a no-arg constructor",
60                                              SdkSystemSetting.SYNC_HTTP_SERVICE_IMPL.property(), httpImplFqcn))
61                                     .cause(e)
62                                     .build();
63         }
64     }
65
66     /**
67      * @return SystemPropertyHttpServiceProvider instance using the sync HTTP system property.
68      */

69     static SystemPropertyHttpServiceProvider<SdkHttpService> syncProvider() {
70         return new SystemPropertyHttpServiceProvider<>(SdkSystemSetting.SYNC_HTTP_SERVICE_IMPL, SdkHttpService.class);
71     }
72
73     /**
74      * @return SystemPropertyHttpServiceProvider instance using the async HTTP system property.
75      */

76     static SystemPropertyHttpServiceProvider<SdkAsyncHttpService> asyncProvider() {
77         return new SystemPropertyHttpServiceProvider<>(SdkSystemSetting.ASYNC_HTTP_SERVICE_IMPL, SdkAsyncHttpService.class);
78     }
79 }
80