001 /** 002 * Copyright 2010 The Kuali Foundation Licensed under the 003 * Educational Community License, Version 2.0 (the "License"); you may 004 * not use this file except in compliance with the License. You may 005 * obtain a copy of the License at 006 * 007 * http://www.osedu.org/licenses/ECL-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, 010 * software distributed under the License is distributed on an "AS IS" 011 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 012 * or implied. See the License for the specific language governing 013 * permissions and limitations under the License. 014 */ 015 016 package org.kuali.student.common.util; 017 018 import java.util.HashSet; 019 import java.util.Properties; 020 021 import org.springframework.beans.BeansException; 022 import org.springframework.beans.factory.BeanDefinitionStoreException; 023 import org.springframework.beans.factory.BeanFactory; 024 import org.springframework.beans.factory.InitializingBean; 025 import org.springframework.beans.factory.config.BeanDefinition; 026 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 027 import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; 028 import org.springframework.core.io.DefaultResourceLoader; 029 import org.springframework.core.io.Resource; 030 import org.springframework.util.StringValueResolver; 031 032 public class ModPropertyPlaceholderConfigurer extends 033 PropertyPlaceholderConfigurer implements InitializingBean { 034 035 private String customConfigSystemProperty; 036 private String customConfigFileLocation; 037 private Resource[] locations; 038 039 private String beanName; 040 private BeanFactory beanFactory; 041 private String nullValue; 042 043 044 public String getCustomConfigSystemProperty() { 045 return customConfigSystemProperty; 046 } 047 048 public void setCustomConfigSystemProperty(String customConfigSystemProperty) { 049 this.customConfigSystemProperty = customConfigSystemProperty; 050 } 051 052 @Override 053 public void setLocations(Resource[] locations) { 054 this.locations=locations; 055 super.setLocations(locations); 056 057 } 058 059 @Override 060 public void afterPropertiesSet() throws Exception { 061 if(customConfigSystemProperty!=null){ 062 String customConfigLocation = System.getProperty(customConfigSystemProperty); 063 try{ 064 customConfigLocation = this.parseStringValue(customConfigLocation, System.getProperties(), new HashSet<String>()); 065 066 Resource customConfigResource = new DefaultResourceLoader().getResource(customConfigLocation); 067 if(customConfigResource.exists()){ 068 Resource[] finalLocations = new Resource[locations.length+1]; 069 int i=0; 070 for(Resource resource:locations){ 071 finalLocations[i]=resource; 072 i++; 073 } 074 finalLocations[i]=customConfigResource; 075 076 super.setLocations(finalLocations); 077 }else{ 078 logger.warn("File does not exist:"+customConfigLocation); 079 } 080 }catch(Exception e){ 081 logger.warn("Could not load custom properties from property:"+customConfigSystemProperty+" location:"+customConfigLocation); 082 } 083 } 084 if(customConfigFileLocation!=null){ 085 String location = this.parseStringValue(customConfigFileLocation, System.getProperties(), new HashSet<String>()); 086 try{ 087 Resource customConfigResource = new DefaultResourceLoader().getResource(location); 088 089 if(customConfigResource.exists()){ 090 Resource[] finalLocations = new Resource[locations.length+1]; 091 int i=0; 092 for(Resource resource:locations){ 093 finalLocations[i] = resource; 094 i++; 095 } 096 finalLocations[i] = customConfigResource; 097 098 super.setLocations(finalLocations); 099 }else{ 100 logger.warn("File does not exist:"+location); 101 } 102 }catch(Exception e){ 103 logger.warn("Could not load custom properties from file:"+location); 104 } 105 } 106 } 107 108 @Override 109 public void setBeanName(String beanName) { 110 this.beanName = beanName; 111 super.setBeanName(beanName); 112 } 113 114 @Override 115 public void setBeanFactory(BeanFactory beanFactory) { 116 this.beanFactory = beanFactory; 117 super.setBeanFactory(beanFactory); 118 } 119 120 @Override 121 public void setNullValue(String nullValue) { 122 this.nullValue = nullValue; 123 super.setNullValue(nullValue); 124 } 125 126 @Override 127 protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) 128 throws BeansException { 129 130 StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props); 131 ModBeanDefinitionVisitor visitor = new ModBeanDefinitionVisitor(valueResolver); 132 133 String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames(); 134 for (int i = 0; i < beanNames.length; i++) { 135 // Check that we're not parsing our own bean definition, 136 // to avoid failing on unresolvable placeholders in properties file locations. 137 if (!(beanNames[i].equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) { 138 BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(beanNames[i]); 139 try { 140 visitor.visitBeanDefinition(bd); 141 } 142 catch (BeanDefinitionStoreException ex) { 143 throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanNames[i], ex.getMessage()); 144 } 145 } 146 } 147 148 // New in Spring 2.5: resolve placeholders in alias target names and aliases as well. 149 beanFactoryToProcess.resolveAliases(valueResolver); 150 } 151 152 /** 153 * BeanDefinitionVisitor that resolves placeholders in String values, 154 * delegating to the <code>parseStringValue</code> method of the 155 * containing class. 156 */ 157 public class PlaceholderResolvingStringValueResolver implements StringValueResolver { 158 159 private final Properties props; 160 161 public PlaceholderResolvingStringValueResolver(Properties props) { 162 this.props = props; 163 } 164 165 public String resolveStringValue(String strVal) throws BeansException { 166 String value = parseStringValue(strVal, this.props, new HashSet<String>()); 167 return (value.equals(nullValue) ? null : value); 168 } 169 170 public Properties resolvePropertyValue(String strVal){ 171 Properties prefixedProps = new Properties(); 172 173 for(Object key:props.keySet()){ 174 String keyStr = (String)key; 175 if(keyStr.startsWith(strVal)){ 176 String newKeyStr = keyStr.substring(strVal.length()+1); 177 prefixedProps.put(newKeyStr, resolveStringValue((String)props.get(key))); 178 } 179 } 180 181 return prefixedProps; 182 } 183 184 } 185 186 public String getCustomConfigFileLocation() { 187 return customConfigFileLocation; 188 } 189 190 public void setCustomConfigFileLocation(String customConfigFileLocation) { 191 this.customConfigFileLocation = customConfigFileLocation; 192 } 193 }