View Javadoc

1   /**
2    * Copyright 2010-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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.PropertyUtils;
26  import org.kuali.common.util.Str;
27  import org.kuali.common.util.obscure.DefaultObscurer;
28  import org.kuali.common.util.obscure.Obscurer;
29  import org.kuali.common.util.property.processor.AddPrefixProcessor;
30  import org.kuali.common.util.property.processor.GlobalOverrideProcessor;
31  import org.kuali.common.util.property.processor.OverrideProcessor;
32  import org.kuali.common.util.property.processor.PropertyProcessor;
33  import org.kuali.common.util.property.processor.ReformatKeysAsEnvVarsProcessor;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  import org.springframework.util.Assert;
37  import org.springframework.util.PropertyPlaceholderHelper;
38  
39  /**
40   * @deprecated
41   */
42  @Deprecated
43  public class DefaultPropertyContext implements PropertyContext {
44  
45  	private static final Logger logger = LoggerFactory.getLogger(DefaultPropertyContext.class);
46  	PropertyPlaceholderHelper helper = Constants.DEFAULT_PROPERTY_PLACEHOLDER_HELPER;
47  	String globalPropertiesMode = Constants.DEFAULT_GLOBAL_PROPERTIES_MODE.name();
48  	String resolvePlaceholders = Boolean.toString(Constants.DEFAULT_RESOLVE_PLACEHOLDERS);
49  	Obscurer obscurer = new DefaultObscurer();
50  	String style = PropertyStyle.NORMAL.name();
51  	String encryptionMode = org.kuali.common.util.EncryptionMode.NONE.name();
52  	String encryptionStrength = org.kuali.common.util.EncryptionStrength.BASIC.name();
53  	String encryptionPassword;
54  	String prefix;
55  	List<PropertyProcessor> processors;
56  	Properties properties;
57  	Properties buildProperties;
58  	List<String> buildPropertyIncludes;
59  	List<String> buildPropertyExcludes;
60  
61  	protected List<PropertyProcessor> getDefaultProcessors() {
62  		List<PropertyProcessor> processors = new ArrayList<PropertyProcessor>();
63  
64  		// If this context is being loaded as part of a build process, build properties win over properties from .properties files
65  		if (buildProperties != null) {
66  			OverrideProcessor overrideProcessor = new OverrideProcessor(Constants.DEFAULT_PROPERTY_OVERWRITE_MODE, buildProperties);
67  			if (buildPropertyIncludes != null) {
68  				overrideProcessor.setIncludes(buildPropertyIncludes);
69  			}
70  			if (buildPropertyExcludes != null) {
71  				overrideProcessor.setExcludes(buildPropertyExcludes);
72  			}
73  			processors.add(overrideProcessor);
74  		}
75  
76  		// Decrypt/encrypt as appropriate
77  		if (encryptionMode != null) {
78  			org.kuali.common.util.EncryptionMode mode = org.kuali.common.util.EncryptionMode.valueOf(encryptionMode);
79  			org.kuali.common.util.EncryptionStrength strength = org.kuali.common.util.EncryptionStrength.valueOf(encryptionStrength);
80  			processors.add(getEncProcessor(mode, strength, encryptionPassword));
81  		}
82  
83  		/**
84  		 * Remove the local reference to the encryption password now that the TextEncryptor has been created.<br>
85  		 * Note that the encryption password is VERY likely to be hanging around in memory even after being set to null locally.<br>
86  		 * Setting it to null here just makes it slightly tougher for someone to obtain the password.<br>
87  		 * Having a reference to this bean no longer does them any good, they'll have to search around in memory to find it.<br>
88  		 */
89  		this.encryptionPassword = null;
90  
91  		GlobalPropertiesMode gpm = GlobalPropertiesMode.valueOf(globalPropertiesMode);
92  
93  		// By default, system/environment properties override loaded properties
94  		processors.add(new GlobalOverrideProcessor(gpm));
95  
96  		// By default, all placeholders in the properties are resolved
97  		if (Boolean.parseBoolean(resolvePlaceholders)) {
98  			processors.add(new org.kuali.common.util.property.processor.ResolvePlaceholdersProcessor(helper, gpm));
99  		}
100 
101 		// Add a prefix to the property keys if appropriate
102 		if (!StringUtils.isBlank(prefix)) {
103 			processors.add(new AddPrefixProcessor(prefix));
104 		}
105 
106 		// Reformat the keys in environment variable format if appropriate
107 		if (style != null) {
108 			processors.add(getStyleProcessor(style));
109 		}
110 
111 		// Return the list of processors
112 		return processors;
113 	}
114 
115 	protected PropertyProcessor getStyleProcessor(String style) {
116 		switch (PropertyStyle.valueOf(style)) {
117 		case NORMAL:
118 			return Constants.NO_OP_PROCESSOR;
119 		case ENVIRONMENT_VARIABLE:
120 			return new ReformatKeysAsEnvVarsProcessor();
121 		default:
122 			throw new IllegalArgumentException("Property style " + style + " is unknown");
123 		}
124 	}
125 
126 	protected PropertyProcessor getEncProcessor(org.kuali.common.util.EncryptionMode mode, org.kuali.common.util.EncryptionStrength strength, String password) {
127 		switch (mode) {
128 		case NONE:
129 			return Constants.NO_OP_PROCESSOR;
130 		case ENCRYPT:
131 			TextEncryptor encryptor = org.kuali.common.util.EncUtils.getTextEncryptor(strength, password);
132 			return new org.kuali.common.util.property.processor.EndsWithEncryptProcessor(encryptor);
133 		case DECRYPT:
134 			TextEncryptor decryptor = org.kuali.common.util.EncUtils.getTextEncryptor(strength, password);
135 			return new org.kuali.common.util.property.processor.EndsWithDecryptProcessor(decryptor);
136 		default:
137 			throw new IllegalArgumentException("Encryption mode '" + mode + "' is unknown");
138 		}
139 	}
140 
141 	protected void log() {
142 		if (!StringUtils.equals(org.kuali.common.util.EncryptionMode.NONE.name(), encryptionMode)) {
143 			logger.info("Encryption mode - " + StringUtils.trimToEmpty(encryptionMode));
144 			logger.info("Encryption strength - " + StringUtils.trimToEmpty(encryptionStrength));
145 			String displayPassword = org.kuali.common.util.LoggerUtils.getNullAsNone(encryptionPassword);
146 			if (encryptionPassword != null) {
147 				displayPassword = obscurer.obscure(encryptionPassword);
148 			}
149 			logger.info("Encryption password - " + displayPassword);
150 		}
151 		if (!StringUtils.equals(PropertyStyle.NORMAL.name(), style)) {
152 			logger.info("Property style - " + StringUtils.trimToEmpty(style));
153 		}
154 		if (!StringUtils.isEmpty(prefix)) {
155 			logger.info("Property prefix - " + StringUtils.trimToEmpty(prefix));
156 		}
157 		if (!StringUtils.equals(Boolean.toString(Constants.DEFAULT_RESOLVE_PLACEHOLDERS), resolvePlaceholders)) {
158 			logger.info("Resolve placeholders - " + resolvePlaceholders);
159 		}
160 	}
161 
162 	@Override
163 	public void initialize(Properties properties) {
164 		GlobalPropertiesMode gpm = GlobalPropertiesMode.valueOf(globalPropertiesMode);
165 		Properties global = PropertyUtils.getProperties(properties, gpm);
166 		this.encryptionMode = resolve(encryptionMode, global);
167 		this.encryptionPassword = resolveAndRemove(encryptionPassword, global, properties);
168 		this.encryptionStrength = resolve(encryptionStrength, global);
169 		this.style = resolve(style, global);
170 		this.prefix = resolve(prefix, global);
171 		this.resolvePlaceholders = resolve(resolvePlaceholders, global);
172 		log();
173 		validate();
174 		addProcessors();
175 		logger.info("Proceeding with " + processors.size() + " processors.");
176 	}
177 
178 	protected void addProcessors() {
179 		List<PropertyProcessor> defaultProcessors = getDefaultProcessors();
180 		if (processors == null) {
181 			processors = defaultProcessors;
182 		} else {
183 			processors.addAll(0, defaultProcessors);
184 		}
185 	}
186 
187 	protected void validate() {
188 		org.kuali.common.util.EncryptionMode.valueOf(encryptionMode);
189 		org.kuali.common.util.EncryptionStrength.valueOf(encryptionStrength);
190 		PropertyStyle.valueOf(style);
191 		Boolean.parseBoolean(resolvePlaceholders);
192 	}
193 
194 	protected String getPlaceholderKey(String string) {
195 		String prefix = Constants.DEFAULT_PLACEHOLDER_PREFIX;
196 		String suffix = Constants.DEFAULT_PLACEHOLDER_SUFFIX;
197 		String separator = Constants.DEFAULT_VALUE_SEPARATOR;
198 		String key = StringUtils.substringBetween(string, prefix, separator);
199 		if (key == null) {
200 			return StringUtils.substringBetween(string, prefix, suffix);
201 		} else {
202 			return key;
203 		}
204 	}
205 
206 	protected void remove(String string, String resolvedString, Properties properties) {
207 		boolean placeholder = PropertyUtils.isSingleUnresolvedPlaceholder(string);
208 		boolean resolved = !StringUtils.equals(string, resolvedString);
209 		boolean irrelevant = Str.contains(Arrays.asList(Constants.NONE, Constants.NULL), resolvedString, false);
210 		boolean remove = placeholder && resolved && !irrelevant;
211 		if (remove) {
212 			String key = getPlaceholderKey(string);
213 			Assert.notNull(key, "key is null");
214 			if (properties.getProperty(key) != null) {
215 				logger.info("Removing property '" + key + "'");
216 				properties.remove(key);
217 			}
218 		}
219 	}
220 
221 	protected String resolveAndRemove(String string, Properties global, Properties properties) {
222 		String resolvedString = resolve(string, global);
223 		remove(string, resolvedString, properties);
224 		return resolvedString;
225 	}
226 
227 	protected String resolve(String string, Properties properties) {
228 		if (string == null) {
229 			return null;
230 		} else {
231 			String resolvedValue = helper.replacePlaceholders(string, properties);
232 			if (!StringUtils.equals(string, resolvedValue)) {
233 				logger.debug("Resolved {} -> {}", string, resolvedValue);
234 			}
235 			return resolvedValue;
236 		}
237 	}
238 
239 	public String getPrefix() {
240 		return prefix;
241 	}
242 
243 	public void setPrefix(String prefix) {
244 		this.prefix = prefix;
245 	}
246 
247 	public String getStyle() {
248 		return style;
249 	}
250 
251 	public void setStyle(String style) {
252 		this.style = style;
253 	}
254 
255 	public PropertyPlaceholderHelper getHelper() {
256 		return helper;
257 	}
258 
259 	public void setHelper(PropertyPlaceholderHelper helper) {
260 		this.helper = helper;
261 	}
262 
263 	public String getEncryptionMode() {
264 		return encryptionMode;
265 	}
266 
267 	public void setEncryptionMode(String encryptionMode) {
268 		this.encryptionMode = encryptionMode;
269 	}
270 
271 	public String getEncryptionStrength() {
272 		return encryptionStrength;
273 	}
274 
275 	public void setEncryptionStrength(String encryptionStrength) {
276 		this.encryptionStrength = encryptionStrength;
277 	}
278 
279 	public String getEncryptionPassword() {
280 		return encryptionPassword;
281 	}
282 
283 	public void setEncryptionPassword(String encryptionPassword) {
284 		this.encryptionPassword = encryptionPassword;
285 	}
286 
287 	@Override
288 	public List<PropertyProcessor> getProcessors() {
289 		return processors;
290 	}
291 
292 	public void setProcessors(List<PropertyProcessor> processors) {
293 		this.processors = processors;
294 	}
295 
296 	public Properties getProperties() {
297 		return properties;
298 	}
299 
300 	public void setProperties(Properties properties) {
301 		this.properties = properties;
302 	}
303 
304 	public String getGlobalPropertiesMode() {
305 		return globalPropertiesMode;
306 	}
307 
308 	public void setGlobalPropertiesMode(String globalPropertiesMode) {
309 		this.globalPropertiesMode = globalPropertiesMode;
310 	}
311 
312 	public String getResolvePlaceholders() {
313 		return resolvePlaceholders;
314 	}
315 
316 	public void setResolvePlaceholders(String resolvePlaceholders) {
317 		this.resolvePlaceholders = resolvePlaceholders;
318 	}
319 
320 	public Obscurer getObscurer() {
321 		return obscurer;
322 	}
323 
324 	public void setObscurer(Obscurer obscurer) {
325 		this.obscurer = obscurer;
326 	}
327 
328 	public Properties getBuildProperties() {
329 		return buildProperties;
330 	}
331 
332 	public void setBuildProperties(Properties buildProperties) {
333 		this.buildProperties = buildProperties;
334 	}
335 
336 	public List<String> getBuildPropertyIncludes() {
337 		return buildPropertyIncludes;
338 	}
339 
340 	public void setBuildPropertyIncludes(List<String> buildPropertyIncludes) {
341 		this.buildPropertyIncludes = buildPropertyIncludes;
342 	}
343 
344 	public List<String> getBuildPropertyExcludes() {
345 		return buildPropertyExcludes;
346 	}
347 
348 	public void setBuildPropertyExcludes(List<String> buildPropertyExcludes) {
349 		this.buildPropertyExcludes = buildPropertyExcludes;
350 	}
351 }