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 }