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.utils.internal;
17 
18 import static software.amazon.awssdk.utils.OptionalUtils.firstPresent;
19 
20 import java.util.Optional;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23 import software.amazon.awssdk.annotations.SdkInternalApi;
24 import software.amazon.awssdk.utils.SystemSetting;
25 
26 /**
27  * A set of static utility methods for shared code in {@link SystemSetting}.
28  */
29 @SdkInternalApi
30 public final class SystemSettingUtils {
31     private static final Logger LOG = LoggerFactory.getLogger(SystemSettingUtils.class);
32 
SystemSettingUtils()33     private SystemSettingUtils() {
34     }
35 
36     /**
37      * Resolve the value of this system setting, loading it from the System by checking:
38      * <ol>
39      *     <li>The system properties.</li>
40      *     <li>The environment variables.</li>
41      *     <li>The default value.</li>
42      * </ol>
43      */
resolveSetting(SystemSetting setting)44     public static Optional<String> resolveSetting(SystemSetting setting) {
45         return firstPresent(resolveProperty(setting), () -> resolveEnvironmentVariable(setting), () -> resolveDefault(setting))
46                 .map(String::trim);
47     }
48 
49     /**
50      * Resolve the value of this system setting, loading it from the System by checking:
51      * <ol>
52      *     <li>The system properties.</li>
53      *     <li>The environment variables.</li>
54      * </ol>
55      * <p>
56      * This is similar to {@link #resolveSetting(SystemSetting)} but does not fall back to the default value if neither
57      * the environment variable or system property value are present.
58      */
resolveNonDefaultSetting(SystemSetting setting)59     public static Optional<String> resolveNonDefaultSetting(SystemSetting setting) {
60         return firstPresent(resolveProperty(setting), () -> resolveEnvironmentVariable(setting))
61                 .map(String::trim);
62     }
63 
64     /**
65      * Attempt to load this setting from the system properties.
66      */
resolveProperty(SystemSetting setting)67     private static Optional<String> resolveProperty(SystemSetting setting) {
68         // CHECKSTYLE:OFF - This is the only place we're allowed to use System.getProperty
69         return Optional.ofNullable(setting.property()).map(System::getProperty);
70         // CHECKSTYLE:ON
71     }
72 
73     /**
74      * Attempt to load this setting from the environment variables.
75      */
resolveEnvironmentVariable(SystemSetting setting)76     public static Optional<String> resolveEnvironmentVariable(SystemSetting setting) {
77         return resolveEnvironmentVariable(setting.environmentVariable());
78     }
79 
80     /**
81      * Attempt to load a key from the environment variables.
82      */
resolveEnvironmentVariable(String key)83     public static Optional<String> resolveEnvironmentVariable(String key) {
84         try {
85             return Optional.ofNullable(key).map(SystemSettingUtilsTestBackdoor::getEnvironmentVariable);
86         } catch (SecurityException e) {
87             LOG.debug("Unable to load the environment variable '{}' because the security manager did not allow the SDK" +
88                       " to read this system property. This setting will be assumed to be null", key, e);
89             return Optional.empty();
90         }
91     }
92 
93     /**
94      * Load the default value from the setting.
95      */
resolveDefault(SystemSetting setting)96     private static Optional<String> resolveDefault(SystemSetting setting) {
97         return Optional.ofNullable(setting.defaultValue());
98     }
99 
100     /**
101      * Convert a string to boolean safely (as opposed to the less strict {@link Boolean#parseBoolean(String)}). If a customer
102      * specifies a boolean value it should be "true" or "false" (case insensitive) or an exception will be thrown.
103      */
safeStringToBoolean(SystemSetting setting, String value)104     public static Boolean safeStringToBoolean(SystemSetting setting, String value) {
105         if (value.equalsIgnoreCase("true")) {
106             return true;
107         } else if (value.equalsIgnoreCase("false")) {
108             return false;
109         }
110 
111         throw new IllegalStateException("Environment variable '" + setting.environmentVariable() + "' or system property '" +
112                                         setting.property() + "' was defined as '" + value + "', but should be 'false' or 'true'");
113     }
114 
115 
116 }
117