001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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: */
016:
017: package org.springframework.beans.factory.config;
018:
019: import java.io.IOException;
020: import java.util.Enumeration;
021: import java.util.Properties;
022:
023: import org.springframework.beans.BeansException;
024: import org.springframework.beans.factory.BeanInitializationException;
025: import org.springframework.core.Ordered;
026: import org.springframework.core.io.support.PropertiesLoaderSupport;
027: import org.springframework.util.ObjectUtils;
028:
029: /**
030: * Allows for configuration of individual bean property values from a property resource,
031: * i.e. a properties file. Useful for custom config files targetted at system
032: * administrators that override bean properties configured in the application context.
033: *
034: * <p>2 concrete implementations are provided in the distribution:
035: * <ul>
036: * <li>PropertyOverrideConfigurer for "beanName.property=value" style overriding
037: * (<i>pushing</i> values from a properties file into bean definitions)
038: * <li>PropertyPlaceholderConfigurer for replacing "${...}" placeholders
039: * (<i>pulling</i> values from a properties file into bean definitions)
040: * </ul>
041: *
042: * <p>Property values can be converted after reading them in, through overriding
043: * the <code>convertPropertyValue</code> method. For example, encrypted values
044: * can be detected and decrypted accordingly before processing them.
045: *
046: * @author Juergen Hoeller
047: * @since 02.10.2003
048: * @see PropertyOverrideConfigurer
049: * @see PropertyPlaceholderConfigurer
050: * @see #convertPropertyValue
051: */
052: public abstract class PropertyResourceConfigurer extends
053: PropertiesLoaderSupport implements BeanFactoryPostProcessor,
054: Ordered {
055:
056: private int order = Ordered.LOWEST_PRECEDENCE; // default: same as non-Ordered
057:
058: public void setOrder(int order) {
059: this .order = order;
060: }
061:
062: public int getOrder() {
063: return order;
064: }
065:
066: public void postProcessBeanFactory(
067: ConfigurableListableBeanFactory beanFactory)
068: throws BeansException {
069: try {
070: Properties mergedProps = mergeProperties();
071:
072: // Convert the merged properties, if necessary.
073: convertProperties(mergedProps);
074:
075: // Let the subclass process the properties.
076: processProperties(beanFactory, mergedProps);
077: } catch (IOException ex) {
078: throw new BeanInitializationException(
079: "Could not load properties", ex);
080: }
081: }
082:
083: /**
084: * Convert the given merged properties, converting property values
085: * if necessary. The result will then be processed.
086: * <p>Default implementation will invoke <code>convertPropertyValue</code>
087: * for each property value, replacing the original with the converted value.
088: * @see #convertPropertyValue
089: * @see #processProperties
090: */
091: protected void convertProperties(Properties props) {
092: Enumeration propertyNames = props.propertyNames();
093: while (propertyNames.hasMoreElements()) {
094: String propertyName = (String) propertyNames.nextElement();
095: String propertyValue = props.getProperty(propertyName);
096: String convertedValue = convertPropertyValue(propertyValue);
097: if (!ObjectUtils.nullSafeEquals(propertyValue,
098: convertedValue)) {
099: props.setProperty(propertyName, convertedValue);
100: }
101: }
102: }
103:
104: /**
105: * Convert the given property value from the properties source
106: * to the value that should be applied.
107: * <p>Default implementation simply returns the original value.
108: * Can be overridden in subclasses, for example to detect
109: * encrypted values and decrypt them accordingly.
110: * @param originalValue the original value from the properties source
111: * (properties file or local "properties")
112: * @return the converted value, to be used for processing
113: * @see #setProperties
114: * @see #setLocations
115: * @see #setLocation
116: */
117: protected String convertPropertyValue(String originalValue) {
118: return originalValue;
119: }
120:
121: /**
122: * Apply the given Properties to the bean factory.
123: * @param beanFactory the bean factory used by the application context
124: * @param props the Properties to apply
125: * @throws org.springframework.beans.BeansException in case of errors
126: */
127: protected abstract void processProperties(
128: ConfigurableListableBeanFactory beanFactory,
129: Properties props) throws BeansException;
130:
131: }
|