001: /*
002: * Copyright 2002-2007 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.PriorityOrdered;
027: import org.springframework.core.io.support.PropertiesLoaderSupport;
028: import org.springframework.util.ObjectUtils;
029:
030: /**
031: * Allows for configuration of individual bean property values from a property resource,
032: * i.e. a properties file. Useful for custom config files targetted at system
033: * administrators that override bean properties configured in the application context.
034: *
035: * <p>Two concrete implementations are provided in the distribution:
036: * <ul>
037: * <li>{@link PropertyOverrideConfigurer} for "beanName.property=value" style overriding
038: * (<i>pushing</i> values from a properties file into bean definitions)
039: * <li>{@link PropertyPlaceholderConfigurer} for replacing "${...}" placeholders
040: * (<i>pulling</i> values from a properties file into bean definitions)
041: * </ul>
042: *
043: * <p>Property values can be converted after reading them in, through overriding
044: * the {@link #convertPropertyValue} method. For example, encrypted values
045: * can be detected and decrypted accordingly before processing them.
046: *
047: * @author Juergen Hoeller
048: * @since 02.10.2003
049: * @see PropertyOverrideConfigurer
050: * @see PropertyPlaceholderConfigurer
051: */
052: public abstract class PropertyResourceConfigurer extends
053: PropertiesLoaderSupport implements BeanFactoryPostProcessor,
054: PriorityOrdered {
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 this .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>The default implementation will invoke {@link #convertPropertyValue}
087: * for each property value, replacing the original with the converted value.
088: * @param props the Properties to convert
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>The 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 given BeanFactory.
123: * @param beanFactory the BeanFactory 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: }
|