001package org.kuali.common.util.spring.env;
002
003import java.io.File;
004import java.util.Properties;
005
006import org.kuali.common.util.Assert;
007import org.kuali.common.util.ModeUtils;
008import org.kuali.common.util.spring.env.model.EnvironmentServiceContext;
009
010/**
011 * <p>
012 * By default, an exception is thrown if a value cannot be located (unless a default value has been supplied).
013 * </p>
014 * 
015 * <p>
016 * By default, an exception is thrown if any placeholders cannot be resolved in any string values.
017 * </p>
018 * 
019 * <p>
020 * By default, string values are resolved before being returned
021 * </p>
022 * 
023 * <p>
024 * By default, environment variables are automatically checked if a normal property value cannot be found.
025 * 
026 * For example, given the key <code>db.vendor</code> the service will also automatically check <code>env.DB_VENDOR</code>
027 * </p>
028 */
029public final class BasicEnvironmentService implements EnvironmentService {
030
031        private final EnvironmentServiceContext context;
032
033        /**
034         * Uses system properties / environment variables to resolve values
035         */
036        public BasicEnvironmentService() {
037                this(new EnvironmentServiceContext.Builder().build());
038        }
039
040        /**
041         * Uses <code>properties</code> to resolve values
042         */
043        public BasicEnvironmentService(Properties properties) {
044                this(new EnvironmentServiceContext.Builder().env(properties).build());
045        }
046
047        /**
048         * Uses <code>context</code> to resolve values
049         */
050        public BasicEnvironmentService(EnvironmentServiceContext context) {
051                Assert.noNulls(context);
052                this.context = context;
053        }
054
055        @Override
056        public boolean containsProperty(String key) {
057                Assert.noBlanks(key);
058                return context.getEnv().containsProperty(key);
059        }
060
061        @Override
062        public <T> T getProperty(EnvContext<T> context) {
063
064                // If context is null, we have issues
065                Assert.noNulls(context);
066
067                // Extract a value from Spring's Environment abstraction
068                T springValue = getSpringValue(context.getKey(), context.getType());
069
070                // If that value is null, use whatever default value they gave us (this might also be null)
071                T returnValue = (springValue == null) ? context.getDefaultValue() : springValue;
072
073                // If we could not locate a value, we may need to error out
074                if (returnValue == null) {
075                        ModeUtils.validate(this.context.getMissingPropertyMode(), getMissingPropertyMessage(context.getKey()));
076                }
077
078                // Return the value we've located
079                return returnValue;
080        }
081
082        @Override
083        public <T> T getProperty(String key, Class<T> type, T provided) {
084                return getProperty(EnvContext.newCtx(key, type, provided));
085        }
086
087        @Override
088        public <T> T getProperty(String key, Class<T> type) {
089                return getProperty(EnvContext.newCtx(key, type, null));
090        }
091
092        protected String getMissingPropertyMessage(String key) {
093                if (context.isCheckEnvironmentVariables()) {
094                        String envKey = EnvUtils.getEnvironmentVariableKey(key);
095                        return "No value for [" + key + "] or [" + envKey + "]";
096                } else {
097                        return "No value for [" + key + "]";
098                }
099        }
100
101        protected <T> T getSpringValue(String key, Class<T> type) {
102                T value = context.getEnv().getProperty(key, type);
103                if (value == null && context.isCheckEnvironmentVariables()) {
104                        String envKey = EnvUtils.getEnvironmentVariableKey(key);
105                        return context.getEnv().getProperty(envKey, type);
106                } else {
107                        return value;
108                }
109        }
110
111        protected <T> Class<T> getSpringValueAsClass(String key, Class<T> type) {
112                Class<T> value = context.getEnv().getPropertyAsClass(key, type);
113                if (value == null && context.isCheckEnvironmentVariables()) {
114                        String envKey = EnvUtils.getEnvironmentVariableKey(key);
115                        return context.getEnv().getPropertyAsClass(envKey, type);
116                } else {
117                        return value;
118                }
119        }
120
121        @Override
122        public <T> Class<T> getClass(String key, Class<T> type) {
123                return getClass(key, type, null);
124        }
125
126        @Override
127        public <T> Class<T> getClass(String key, Class<T> type, Class<T> defaultValue) {
128                Class<T> springValue = getSpringValueAsClass(key, type);
129                Class<T> returnValue = (springValue == null) ? defaultValue : springValue;
130
131                // If we could not locate a value, we may need to error out
132                if (returnValue == null) {
133                        ModeUtils.validate(context.getMissingPropertyMode(), getMissingPropertyMessage(key));
134                }
135
136                // Return what we've got
137                return returnValue;
138        }
139
140        @Override
141        public String getString(String key) {
142                return getString(key, null);
143        }
144
145        @Override
146        public String getString(String key, String defaultValue) {
147                String string = getProperty(EnvContext.newString(key, defaultValue));
148                if (context.isResolveStrings()) {
149                        return context.getEnv().resolveRequiredPlaceholders(string);
150                } else {
151                        return string;
152                }
153        }
154
155        @Override
156        public Boolean getBoolean(String key) {
157                return getBoolean(key, null);
158        }
159
160        @Override
161        public Boolean getBoolean(String key, Boolean defaultValue) {
162                return getProperty(EnvContext.newBoolean(key, defaultValue));
163        }
164
165        @Override
166        public File getFile(String key) {
167                return getFile(key, null);
168        }
169
170        @Override
171        public File getFile(String key, File defaultValue) {
172                return getProperty(EnvContext.newFile(key, defaultValue));
173        }
174
175        @Override
176        public Integer getInteger(String key, Integer defaultValue) {
177                return getProperty(EnvContext.newInteger(key, defaultValue));
178        }
179
180        @Override
181        public Integer getInteger(String key) {
182                return getInteger(key, null);
183        }
184
185        public EnvironmentServiceContext getContext() {
186                return context;
187        }
188
189}