View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.student.common.util;
17  
18  import java.util.HashSet;
19  import java.util.Properties;
20  
21  import org.springframework.beans.BeansException;
22  import org.springframework.beans.factory.BeanDefinitionStoreException;
23  import org.springframework.beans.factory.BeanFactory;
24  import org.springframework.beans.factory.InitializingBean;
25  import org.springframework.beans.factory.config.BeanDefinition;
26  import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
27  import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
28  import org.springframework.core.io.DefaultResourceLoader;
29  import org.springframework.core.io.Resource;
30  import org.springframework.util.StringValueResolver;
31  
32  public class ModPropertyPlaceholderConfigurer extends
33  		PropertyPlaceholderConfigurer implements InitializingBean  {
34  	
35  	private String customConfigSystemProperty;
36  	private String customConfigFileLocation;
37  	private Resource[] locations;	
38  	
39  	private String beanName;
40  	private BeanFactory beanFactory;
41  	private String nullValue;
42  	
43  	
44  	public String getCustomConfigSystemProperty() {
45  		return customConfigSystemProperty;
46  	}
47  
48  	public void setCustomConfigSystemProperty(String customConfigSystemProperty) {
49  		this.customConfigSystemProperty = customConfigSystemProperty;
50  	}
51  
52  	@Override
53  	public void setLocations(Resource[] locations) {
54          this.locations = new Resource[locations.length];
55          System.arraycopy(locations, 0, this.locations, 0, locations.length);
56  //        this.locations=locations;
57  		super.setLocations(locations);
58  		
59  	}
60  
61  	@Override
62  	public void afterPropertiesSet() throws Exception {
63  		if(customConfigSystemProperty!=null){
64  			String customConfigLocation = System.getProperty(customConfigSystemProperty);
65  			try{
66  				customConfigLocation = this.parseStringValue(customConfigLocation, System.getProperties(), new HashSet<String>());
67  
68  				Resource customConfigResource = new DefaultResourceLoader().getResource(customConfigLocation);
69  				if(customConfigResource.exists()){
70  					Resource[] finalLocations = new Resource[locations.length+1];
71  					int i=0;
72  					for(Resource resource:locations){
73  						finalLocations[i]=resource;
74  						i++;
75  					}
76  					finalLocations[i]=customConfigResource;
77  					
78  					super.setLocations(finalLocations);
79  				}else{
80  					logger.warn("File does not exist:"+customConfigLocation);
81  				}
82  			}catch(Exception e){
83  				logger.warn("Could not load custom properties from property:"+customConfigSystemProperty+" location:"+customConfigLocation);
84  			}
85  		}
86  		if(customConfigFileLocation!=null){
87  			String location = this.parseStringValue(customConfigFileLocation, System.getProperties(), new HashSet<String>());
88  			try{
89  				Resource customConfigResource = new DefaultResourceLoader().getResource(location);
90  		
91  				if(customConfigResource.exists()){
92  					Resource[] finalLocations = new Resource[locations.length+1];
93  					int i=0;
94  					for(Resource resource:locations){
95  						finalLocations[i] = resource;
96  						i++;
97  					}
98  					finalLocations[i] = customConfigResource;
99  					
100 					super.setLocations(finalLocations);
101 				}else{
102 					logger.warn("File does not exist:"+location);
103 				}
104 			}catch(Exception e){
105 				logger.warn("Could not load custom properties from file:"+location);
106 			}
107 		}
108 	}
109 
110 	@Override
111 	public void setBeanName(String beanName) {
112 		this.beanName = beanName;
113 		super.setBeanName(beanName);
114 	}
115 
116 	@Override
117 	public void setBeanFactory(BeanFactory beanFactory) {
118 		this.beanFactory = beanFactory;
119 		super.setBeanFactory(beanFactory);
120 	}
121 	
122 	@Override
123 	public void setNullValue(String nullValue) {
124 		this.nullValue = nullValue;
125 		super.setNullValue(nullValue);
126 	}
127 	
128 	@Override
129 	protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
130 			throws BeansException {
131 
132 		StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
133 		ModBeanDefinitionVisitor visitor = new ModBeanDefinitionVisitor(valueResolver);
134 		
135 		String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
136 		for (int i = 0; i < beanNames.length; i++) {
137 			// Check that we're not parsing our own bean definition,
138 			// to avoid failing on unresolvable placeholders in properties file locations.
139 			if (!(beanNames[i].equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
140 				BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(beanNames[i]);
141 				try {
142 					visitor.visitBeanDefinition(bd);
143 				}
144 				catch (BeanDefinitionStoreException ex) {
145 					throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanNames[i], ex.getMessage());
146 				}
147 			}
148 		}
149 		
150 		// New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
151 		beanFactoryToProcess.resolveAliases(valueResolver);
152 	}
153 	
154 	/**
155 	 * BeanDefinitionVisitor that resolves placeholders in String values,
156 	 * delegating to the <code>parseStringValue</code> method of the
157 	 * containing class.
158 	 */
159 	public class PlaceholderResolvingStringValueResolver implements StringValueResolver {
160 
161 		private final Properties props;
162 
163 		public PlaceholderResolvingStringValueResolver(Properties props) {
164 			this.props = props;
165 		}
166 
167 		public String resolveStringValue(String strVal) throws BeansException {
168 			String value = parseStringValue(strVal, this.props, new HashSet<String>());
169 			return (value.equals(nullValue) ? null : value);
170 		}
171 		
172 		public Properties resolvePropertyValue(String strVal){
173 			Properties prefixedProps = new Properties();
174 			
175 			for(Object key:props.keySet()){
176 				String keyStr = (String)key; 
177 				if(keyStr.startsWith(strVal)){
178 					String newKeyStr = keyStr.substring(strVal.length()+1);
179 					prefixedProps.put(newKeyStr, resolveStringValue((String)props.get(key)));
180 				}
181 			}
182 			
183 			return prefixedProps;
184 		}
185 		
186 	}
187 
188 	public String getCustomConfigFileLocation() {
189 		return customConfigFileLocation;
190 	}
191 
192 	public void setCustomConfigFileLocation(String customConfigFileLocation) {
193 		this.customConfigFileLocation = customConfigFileLocation;
194 	}
195 }