View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2008 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  package ch.elca.el4j.env.beans;
18  
19  import java.io.IOException;
20  import java.util.Properties;
21  
22  import org.slf4j.Logger;
23  import org.slf4j.LoggerFactory;
24  import org.springframework.beans.BeansException;
25  import org.springframework.beans.factory.BeanDefinitionStoreException;
26  import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
27  import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
28  import org.springframework.context.ApplicationContext;
29  import org.springframework.context.ApplicationContextAware;
30  import org.springframework.core.io.Resource;
31  
32  import ch.elca.el4j.core.context.ModuleApplicationContext;
33  import ch.elca.el4j.core.exceptions.MisconfigurationRTException;
34  import ch.elca.el4j.env.xml.EnvXml;
35  import ch.elca.el4j.services.monitoring.notification.CoreNotificationHelper;
36  import ch.elca.el4j.util.encryption.AbstractPropertyEncryptor;
37  import ch.elca.el4j.util.encryption.EncryptionException;
38  import ch.elca.el4j.util.encryption.PasswordSource;
39  import ch.elca.el4j.util.env.PropertyEncryptionUtil;
40  
41  /**
42   * Specific property placeholder configurer for the EL4J environment.
43   *
44   * @svnLink $Revision: 3874 $;$Date: 2009-08-04 14:25:40 +0200 (Di, 04. Aug 2009) $;$Author: swismer $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/env/src/main/java/ch/elca/el4j/env/beans/EnvPropertyPlaceholderConfigurer.java $
45   *
46   * @author Martin Zeltner (MZE)
47   * @author Stefan Wismer (SWI)
48   */
49  public class EnvPropertyPlaceholderConfigurer
50  	extends PropertyPlaceholderConfigurer implements ApplicationContextAware {
51  	
52  	/**
53  	 * The correct env location.
54  	 */
55  	public static final String ENV_PLACEHOLDER_PROPERTIES_LOCATION
56  		= "classpath:env-placeholder.properties";
57  	
58  	/**
59  	 * The deprecated env location.
60  	 */
61  	public static final String OLD_ENV_PROPERTIES_LOCATION
62  		= "classpath:env/env.properties";
63  
64  	/**
65  	 * This logger is used to print out some global debugging info.
66  	 * Consult it for info what is going on.
67  	 */
68  	protected static final Logger s_logger
69  		= LoggerFactory.getLogger(ModuleApplicationContext.EL4J_DEBUGGING_LOGGER);
70  	
71  	/**
72  	 * Is the used application context.
73  	 */
74  	protected ApplicationContext m_applicationContext;
75  	
76  	/**
77  	 * This handles encryption.
78  	 */
79  	protected PropertyEncryptionUtil m_util = new PropertyEncryptionUtil();
80  	
81  	/** The cryptor is available in internal and handles resource decryption.
82  	 *  It is initialized by util.
83  	 */
84  	private AbstractPropertyEncryptor m_cryptor;
85  
86  	/**
87  	 * Custom location and name for the cryptor.properties file.
88  	 */
89  	private String m_cryptorFile = null;
90  	
91  	/**
92  	 * Sets the location of the env placeholder properties file. A fallback to
93  	 * the old env location is possible.
94  	 *
95  	 * {@inheritDoc}
96  	 */
97  	@Override
98  	public void postProcessBeanFactory(
99  			ConfigurableListableBeanFactory beanFactory) throws BeansException {
100 		
101 		// very old env location is not supported anymore
102 		Resource oldEnvLocation = m_applicationContext.getResource(OLD_ENV_PROPERTIES_LOCATION);
103 		if (oldEnvLocation.exists()) {
104 			throw new MisconfigurationRTException(
105 				"DEPRECATED: The used env placeholder properties file '"
106 					+ oldEnvLocation.toString()
107 					+ "' is deprecated. Please use the new loaction '"
108 					+ ENV_PLACEHOLDER_PROPERTIES_LOCATION + "'.");
109 		}
110 		
111 		// new inheritable env support
112 		boolean envXmlFound = false;
113 		EnvXml envXmlConfigLoader;
114 		if (m_applicationContext instanceof ModuleApplicationContext) {
115 			ModuleApplicationContext mac = (ModuleApplicationContext) m_applicationContext;
116 			envXmlConfigLoader = new EnvXml(m_applicationContext, mac.isMostSpecificResourceLast());
117 		} else {
118 			envXmlConfigLoader = new EnvXml();
119 		}
120 		if (envXmlConfigLoader.hasValidConfigurations()) {
121 			super.setProperties((Properties) envXmlConfigLoader.getGroupConfiguration(EnvXml.ENV_GROUP_PLACEHOLDERS));
122 			super.setLocalOverride(true);
123 			envXmlFound = true;
124 		}
125 		
126 		// old only-one-env-on-classpath strategy
127 		Resource envLocation = m_applicationContext.getResource(ENV_PLACEHOLDER_PROPERTIES_LOCATION);
128 		String envLocationUrl = "no url";
129 		if (envLocation.exists()) {
130 			try {
131 				envLocationUrl = envLocation.getURL().toString();
132 			} catch (IOException e) {
133 				envLocationUrl = "unknown url";
134 			}
135 		}
136 		
137 		if (!envXmlFound) {
138 			if (envLocation.exists()) {
139 				s_logger.debug("The used env placeholder properties file is '"
140 					+ envLocationUrl + "'.");
141 				super.setLocation(envLocation);
142 			} else {
143 				s_logger.warn(
144 					"No env placeholder properties file could be found. The "
145 						+ "correct location for this file is '"
146 						+ EnvXml.ENV_XML_LOCATION + "'.");
147 			}
148 		}
149 		
150 		super.postProcessBeanFactory(beanFactory);
151 	}
152 	
153 	/**
154 	 * NOT ALLOWED TO USE!
155 	 *
156 	 * {@inheritDoc}
157 	 */
158 	@Override
159 	public void setLocation(Resource location) {
160 		CoreNotificationHelper.notifyMisconfiguration(
161 			"It is not allowed to set the location manually!");
162 	}
163 	
164 	/**
165 	 * NOT ALLOWED TO USE!
166 	 *
167 	 * {@inheritDoc}
168 	 */
169 	@Override
170 	public void setLocations(Resource[] locations) {
171 		CoreNotificationHelper.notifyMisconfiguration(
172 			"It is not allowed to set the locations manually!");
173 	}
174 
175 	/**
176 	 * {@inheritDoc}
177 	 */
178 	public void setApplicationContext(ApplicationContext applicationContext)
179 		throws BeansException {
180 		m_applicationContext = applicationContext;
181 	}
182 	
183 	/**
184 	 * This is meant to be used as a bean property to turn off encryption
185 	 * in an internal setting.
186 	 */
187 	public void setNoEncryption() {
188 		m_util.deactivate();
189 	}
190 	
191 	/**
192 	 * Set a true custom password.
193 	 * @param source A PasswordSource (interface).
194 	 */
195 	public void setPasswordSource(PasswordSource source) {
196 		m_util.setSource(source);
197 	}
198 	
199 	/**
200 	 * @param file The file containing the cryptor settings.
201 	 */
202 	public void setCryptorFile(String file) {
203 		m_cryptorFile = file;
204 	}
205 	
206 	/**
207 	 * Decrypts values read from the env-*.properties files.
208 	 * 
209 	 * @param originalValue  The value read from env-*.properties
210 	 * @return The value with all encrypted values decrypted.
211 	 */
212 	protected String convertPropertyValue(String originalValue) {
213 		String value = originalValue;
214 		
215 		if (!m_util.isInited()) {
216 			if (m_cryptorFile != null) {
217 				m_util.init(m_applicationContext, m_cryptorFile);
218 			} else {
219 				m_util.init(m_applicationContext);
220 			}
221 			if (m_util.isActive()) {
222 				m_cryptor = m_util.getCryptor();
223 			}
224 		}
225 		if (m_util.isActive()) {
226 			try {
227 				value = m_cryptor.processString(originalValue);
228 			} catch (EncryptionException e) {
229 				throw new BeanDefinitionStoreException(
230 					"Error during decryption.");
231 			}
232 		}
233 		
234 		return super.convertPropertyValue(value);
235 	}
236 }