1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.common.util.property;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.Properties;
22
23 import org.apache.commons.lang3.StringUtils;
24 import org.jasypt.util.text.TextEncryptor;
25 import org.kuali.common.util.EncUtils;
26 import org.kuali.common.util.EncryptionMode;
27 import org.kuali.common.util.EncryptionStrength;
28 import org.kuali.common.util.LoggerUtils;
29 import org.kuali.common.util.PropertyUtils;
30 import org.kuali.common.util.Str;
31 import org.kuali.common.util.obscure.DefaultObscurer;
32 import org.kuali.common.util.obscure.Obscurer;
33 import org.kuali.common.util.property.processor.AddPrefixProcessor;
34 import org.kuali.common.util.property.processor.EndsWithDecryptProcessor;
35 import org.kuali.common.util.property.processor.EndsWithEncryptProcessor;
36 import org.kuali.common.util.property.processor.GlobalOverrideProcessor;
37 import org.kuali.common.util.property.processor.OverrideProcessor;
38 import org.kuali.common.util.property.processor.PropertyProcessor;
39 import org.kuali.common.util.property.processor.ReformatKeysAsEnvVarsProcessor;
40 import org.kuali.common.util.property.processor.ResolvePlaceholdersProcessor;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43 import org.springframework.util.Assert;
44 import org.springframework.util.PropertyPlaceholderHelper;
45
46 public class DefaultPropertyContext implements PropertyContext {
47
48 private static final Logger logger = LoggerFactory.getLogger(DefaultPropertyContext.class);
49 PropertyPlaceholderHelper helper = Constants.DEFAULT_PROPERTY_PLACEHOLDER_HELPER;
50 String globalPropertiesMode = Constants.DEFAULT_GLOBAL_PROPERTIES_MODE.name();
51 String resolvePlaceholders = Boolean.toString(Constants.DEFAULT_RESOLVE_PLACEHOLDERS);
52 Obscurer obscurer = new DefaultObscurer();
53 String style = PropertyStyle.NORMAL.name();
54 String encryptionMode = EncryptionMode.NONE.name();
55 String encryptionStrength = EncryptionStrength.BASIC.name();
56 String encryptionPassword;
57 String prefix;
58 List<PropertyProcessor> processors;
59 Properties properties;
60 Properties buildProperties;
61 List<String> buildPropertyIncludes;
62 List<String> buildPropertyExcludes;
63
64 protected List<PropertyProcessor> getDefaultProcessors() {
65 List<PropertyProcessor> processors = new ArrayList<PropertyProcessor>();
66
67
68 if (buildProperties != null) {
69 OverrideProcessor overrideProcessor = new OverrideProcessor(Constants.DEFAULT_PROPERTY_OVERWRITE_MODE, buildProperties);
70 if (buildPropertyIncludes != null) {
71 overrideProcessor.setIncludes(buildPropertyIncludes);
72 }
73 if (buildPropertyExcludes != null) {
74 overrideProcessor.setExcludes(buildPropertyExcludes);
75 }
76 processors.add(overrideProcessor);
77 }
78
79
80 if (encryptionMode != null) {
81 EncryptionMode mode = EncryptionMode.valueOf(encryptionMode);
82 EncryptionStrength strength = EncryptionStrength.valueOf(encryptionStrength);
83 processors.add(getEncProcessor(mode, strength, encryptionPassword));
84 }
85
86
87
88
89
90
91
92 this.encryptionPassword = null;
93
94 GlobalPropertiesMode gpm = GlobalPropertiesMode.valueOf(globalPropertiesMode);
95
96
97 processors.add(new GlobalOverrideProcessor(gpm));
98
99
100 if (Boolean.parseBoolean(resolvePlaceholders)) {
101 processors.add(new ResolvePlaceholdersProcessor(helper, gpm));
102 }
103
104
105 if (!StringUtils.isBlank(prefix)) {
106 processors.add(new AddPrefixProcessor(prefix));
107 }
108
109
110 if (style != null) {
111 processors.add(getStyleProcessor(style));
112 }
113
114
115 return processors;
116 }
117
118 protected PropertyProcessor getStyleProcessor(String style) {
119 switch (PropertyStyle.valueOf(style)) {
120 case NORMAL:
121 return Constants.NO_OP_PROCESSOR;
122 case ENVIRONMENT_VARIABLE:
123 return new ReformatKeysAsEnvVarsProcessor();
124 default:
125 throw new IllegalArgumentException("Property style " + style + " is unknown");
126 }
127 }
128
129 protected PropertyProcessor getEncProcessor(EncryptionMode mode, EncryptionStrength strength, String password) {
130 switch (mode) {
131 case NONE:
132 return Constants.NO_OP_PROCESSOR;
133 case ENCRYPT:
134 TextEncryptor encryptor = EncUtils.getTextEncryptor(strength, password);
135 return new EndsWithEncryptProcessor(encryptor);
136 case DECRYPT:
137 TextEncryptor decryptor = EncUtils.getTextEncryptor(strength, password);
138 return new EndsWithDecryptProcessor(decryptor);
139 default:
140 throw new IllegalArgumentException("Encryption mode '" + mode + "' is unknown");
141 }
142 }
143
144 protected void log() {
145 if (!StringUtils.equals(EncryptionMode.NONE.name(), encryptionMode)) {
146 logger.info("Encryption mode - " + StringUtils.trimToEmpty(encryptionMode));
147 logger.info("Encryption strength - " + StringUtils.trimToEmpty(encryptionStrength));
148 String displayPassword = LoggerUtils.getNullAsNone(encryptionPassword);
149 if (encryptionPassword != null) {
150 displayPassword = obscurer.obscure(encryptionPassword);
151 }
152 logger.info("Encryption password - " + displayPassword);
153 }
154 if (!StringUtils.equals(PropertyStyle.NORMAL.name(), style)) {
155 logger.info("Property style - " + StringUtils.trimToEmpty(style));
156 }
157 if (!StringUtils.isEmpty(prefix)) {
158 logger.info("Property prefix - " + StringUtils.trimToEmpty(prefix));
159 }
160 if (!StringUtils.equals(Boolean.toString(Constants.DEFAULT_RESOLVE_PLACEHOLDERS), resolvePlaceholders)) {
161 logger.info("Resolve placeholders - " + resolvePlaceholders);
162 }
163 }
164
165 @Override
166 public void initialize(Properties properties) {
167 GlobalPropertiesMode gpm = GlobalPropertiesMode.valueOf(globalPropertiesMode);
168 Properties global = PropertyUtils.getProperties(properties, gpm);
169 this.encryptionMode = resolve(encryptionMode, global);
170 this.encryptionPassword = resolveAndRemove(encryptionPassword, global, properties);
171 this.encryptionStrength = resolve(encryptionStrength, global);
172 this.style = resolve(style, global);
173 this.prefix = resolve(prefix, global);
174 this.resolvePlaceholders = resolve(resolvePlaceholders, global);
175 log();
176 validate();
177 addProcessors();
178 logger.info("Proceeding with " + processors.size() + " processors.");
179 }
180
181 protected void addProcessors() {
182 List<PropertyProcessor> defaultProcessors = getDefaultProcessors();
183 if (processors == null) {
184 processors = defaultProcessors;
185 } else {
186 processors.addAll(0, defaultProcessors);
187 }
188 }
189
190 protected void validate() {
191 EncryptionMode.valueOf(encryptionMode);
192 EncryptionStrength.valueOf(encryptionStrength);
193 PropertyStyle.valueOf(style);
194 Boolean.parseBoolean(resolvePlaceholders);
195 }
196
197 protected String getPlaceholderKey(String string) {
198 String prefix = Constants.DEFAULT_PLACEHOLDER_PREFIX;
199 String suffix = Constants.DEFAULT_PLACEHOLDER_SUFFIX;
200 String separator = Constants.DEFAULT_VALUE_SEPARATOR;
201 String key = StringUtils.substringBetween(string, prefix, separator);
202 if (key == null) {
203 return StringUtils.substringBetween(string, prefix, suffix);
204 } else {
205 return key;
206 }
207 }
208
209 protected void remove(String string, String resolvedString, Properties properties) {
210 boolean placeholder = PropertyUtils.isSingleUnresolvedPlaceholder(string);
211 boolean resolved = !StringUtils.equals(string, resolvedString);
212 boolean irrelevant = Str.contains(Arrays.asList(Constants.NONE, Constants.NULL), resolvedString, false);
213 boolean remove = placeholder && resolved && !irrelevant;
214 if (remove) {
215 String key = getPlaceholderKey(string);
216 Assert.notNull(key, "key is null");
217 if (properties.getProperty(key) != null) {
218 logger.info("Removing property '" + key + "'");
219 properties.remove(key);
220 }
221 }
222 }
223
224 protected String resolveAndRemove(String string, Properties global, Properties properties) {
225 String resolvedString = resolve(string, global);
226 remove(string, resolvedString, properties);
227 return resolvedString;
228 }
229
230 protected String resolve(String string, Properties properties) {
231 if (string == null) {
232 return null;
233 } else {
234 String resolvedValue = helper.replacePlaceholders(string, properties);
235 if (!StringUtils.equals(string, resolvedValue)) {
236 logger.debug("Resolved {} -> {}", string, resolvedValue);
237 }
238 return resolvedValue;
239 }
240 }
241
242 public String getPrefix() {
243 return prefix;
244 }
245
246 public void setPrefix(String prefix) {
247 this.prefix = prefix;
248 }
249
250 public String getStyle() {
251 return style;
252 }
253
254 public void setStyle(String style) {
255 this.style = style;
256 }
257
258 public PropertyPlaceholderHelper getHelper() {
259 return helper;
260 }
261
262 public void setHelper(PropertyPlaceholderHelper helper) {
263 this.helper = helper;
264 }
265
266 public String getEncryptionMode() {
267 return encryptionMode;
268 }
269
270 public void setEncryptionMode(String encryptionMode) {
271 this.encryptionMode = encryptionMode;
272 }
273
274 public String getEncryptionStrength() {
275 return encryptionStrength;
276 }
277
278 public void setEncryptionStrength(String encryptionStrength) {
279 this.encryptionStrength = encryptionStrength;
280 }
281
282 public String getEncryptionPassword() {
283 return encryptionPassword;
284 }
285
286 public void setEncryptionPassword(String encryptionPassword) {
287 this.encryptionPassword = encryptionPassword;
288 }
289
290 @Override
291 public List<PropertyProcessor> getProcessors() {
292 return processors;
293 }
294
295 public void setProcessors(List<PropertyProcessor> processors) {
296 this.processors = processors;
297 }
298
299 public Properties getProperties() {
300 return properties;
301 }
302
303 public void setProperties(Properties properties) {
304 this.properties = properties;
305 }
306
307 public String getGlobalPropertiesMode() {
308 return globalPropertiesMode;
309 }
310
311 public void setGlobalPropertiesMode(String globalPropertiesMode) {
312 this.globalPropertiesMode = globalPropertiesMode;
313 }
314
315 public String getResolvePlaceholders() {
316 return resolvePlaceholders;
317 }
318
319 public void setResolvePlaceholders(String resolvePlaceholders) {
320 this.resolvePlaceholders = resolvePlaceholders;
321 }
322
323 public Obscurer getObscurer() {
324 return obscurer;
325 }
326
327 public void setObscurer(Obscurer obscurer) {
328 this.obscurer = obscurer;
329 }
330
331 public Properties getBuildProperties() {
332 return buildProperties;
333 }
334
335 public void setBuildProperties(Properties buildProperties) {
336 this.buildProperties = buildProperties;
337 }
338
339 public List<String> getBuildPropertyIncludes() {
340 return buildPropertyIncludes;
341 }
342
343 public void setBuildPropertyIncludes(List<String> buildPropertyIncludes) {
344 this.buildPropertyIncludes = buildPropertyIncludes;
345 }
346
347 public List<String> getBuildPropertyExcludes() {
348 return buildPropertyExcludes;
349 }
350
351 public void setBuildPropertyExcludes(List<String> buildPropertyExcludes) {
352 this.buildPropertyExcludes = buildPropertyExcludes;
353 }
354 }