001/** 002 * Copyright 2010-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.common.util.property; 017 018import java.util.ArrayList; 019import java.util.Arrays; 020import java.util.List; 021import java.util.Properties; 022 023import org.apache.commons.lang3.StringUtils; 024import org.jasypt.util.text.TextEncryptor; 025import org.kuali.common.util.PropertyUtils; 026import org.kuali.common.util.Str; 027import org.kuali.common.util.obscure.DefaultObscurer; 028import org.kuali.common.util.obscure.Obscurer; 029import org.kuali.common.util.property.processor.AddPrefixProcessor; 030import org.kuali.common.util.property.processor.GlobalOverrideProcessor; 031import org.kuali.common.util.property.processor.OverrideProcessor; 032import org.kuali.common.util.property.processor.PropertyProcessor; 033import org.kuali.common.util.property.processor.ReformatKeysAsEnvVarsProcessor; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036import org.springframework.util.Assert; 037import org.springframework.util.PropertyPlaceholderHelper; 038 039/** 040 * @deprecated 041 */ 042@Deprecated 043public class DefaultPropertyContext implements PropertyContext { 044 045 private static final Logger logger = LoggerFactory.getLogger(DefaultPropertyContext.class); 046 PropertyPlaceholderHelper helper = Constants.DEFAULT_PROPERTY_PLACEHOLDER_HELPER; 047 String globalPropertiesMode = Constants.DEFAULT_GLOBAL_PROPERTIES_MODE.name(); 048 String resolvePlaceholders = Boolean.toString(Constants.DEFAULT_RESOLVE_PLACEHOLDERS); 049 Obscurer obscurer = new DefaultObscurer(); 050 String style = PropertyStyle.NORMAL.name(); 051 String encryptionMode = org.kuali.common.util.EncryptionMode.NONE.name(); 052 String encryptionStrength = org.kuali.common.util.EncryptionStrength.BASIC.name(); 053 String encryptionPassword; 054 String prefix; 055 List<PropertyProcessor> processors; 056 Properties properties; 057 Properties buildProperties; 058 List<String> buildPropertyIncludes; 059 List<String> buildPropertyExcludes; 060 061 protected List<PropertyProcessor> getDefaultProcessors() { 062 List<PropertyProcessor> processors = new ArrayList<PropertyProcessor>(); 063 064 // If this context is being loaded as part of a build process, build properties win over properties from .properties files 065 if (buildProperties != null) { 066 OverrideProcessor overrideProcessor = new OverrideProcessor(Constants.DEFAULT_PROPERTY_OVERWRITE_MODE, buildProperties); 067 if (buildPropertyIncludes != null) { 068 overrideProcessor.setIncludes(buildPropertyIncludes); 069 } 070 if (buildPropertyExcludes != null) { 071 overrideProcessor.setExcludes(buildPropertyExcludes); 072 } 073 processors.add(overrideProcessor); 074 } 075 076 // Decrypt/encrypt as appropriate 077 if (encryptionMode != null) { 078 org.kuali.common.util.EncryptionMode mode = org.kuali.common.util.EncryptionMode.valueOf(encryptionMode); 079 org.kuali.common.util.EncryptionStrength strength = org.kuali.common.util.EncryptionStrength.valueOf(encryptionStrength); 080 processors.add(getEncProcessor(mode, strength, encryptionPassword)); 081 } 082 083 /** 084 * Remove the local reference to the encryption password now that the TextEncryptor has been created.<br> 085 * Note that the encryption password is VERY likely to be hanging around in memory even after being set to null locally.<br> 086 * Setting it to null here just makes it slightly tougher for someone to obtain the password.<br> 087 * Having a reference to this bean no longer does them any good, they'll have to search around in memory to find it.<br> 088 */ 089 this.encryptionPassword = null; 090 091 GlobalPropertiesMode gpm = GlobalPropertiesMode.valueOf(globalPropertiesMode); 092 093 // By default, system/environment properties override loaded properties 094 processors.add(new GlobalOverrideProcessor(gpm)); 095 096 // By default, all placeholders in the properties are resolved 097 if (Boolean.parseBoolean(resolvePlaceholders)) { 098 processors.add(new org.kuali.common.util.property.processor.ResolvePlaceholdersProcessor(helper, gpm)); 099 } 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}