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.util.HashMap;
020: import java.util.HashSet;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Map;
024: import java.util.Set;
025:
026: import org.springframework.beans.MutablePropertyValues;
027: import org.springframework.beans.PropertyValue;
028: import org.springframework.util.Assert;
029: import org.springframework.util.ObjectUtils;
030: import org.springframework.util.StringValueResolver;
031:
032: /**
033: * Visitor class for traversing {@link BeanDefinition} objects, in particular
034: * the property values and constructor argument values contained in them,
035: * resolving bean metadata values.
036: *
037: * <p>Used by {@link PropertyPlaceholderConfigurer} to parse all String values
038: * contained in a BeanDefinition, resolving any placeholders found.
039: *
040: * @author Juergen Hoeller
041: * @since 1.2
042: * @see BeanDefinition
043: * @see BeanDefinition#getPropertyValues
044: * @see BeanDefinition#getConstructorArgumentValues
045: * @see PropertyPlaceholderConfigurer
046: */
047: public class BeanDefinitionVisitor {
048:
049: private StringValueResolver valueResolver;
050:
051: /**
052: * Create a new BeanDefinitionVisitor, applying the specified
053: * value resolver to all bean metadata values.
054: * @param valueResolver the StringValueResolver to apply
055: */
056: public BeanDefinitionVisitor(StringValueResolver valueResolver) {
057: Assert.notNull(valueResolver,
058: "StringValueResolver must not be null");
059: this .valueResolver = valueResolver;
060: }
061:
062: /**
063: * Create a new BeanDefinitionVisitor for subclassing.
064: * Subclasses need to override the {@link #resolveStringValue} method.
065: */
066: protected BeanDefinitionVisitor() {
067: }
068:
069: /**
070: * Traverse the given BeanDefinition object and the MutablePropertyValues
071: * and ConstructorArgumentValues contained in them.
072: * @param beanDefinition the BeanDefinition object to traverse
073: * @see #resolveStringValue(String)
074: */
075: public void visitBeanDefinition(BeanDefinition beanDefinition) {
076: visitParentName(beanDefinition);
077: visitBeanClassName(beanDefinition);
078: visitFactoryBeanName(beanDefinition);
079: visitFactoryMethodName(beanDefinition);
080: visitScope(beanDefinition);
081: visitPropertyValues(beanDefinition.getPropertyValues());
082: ConstructorArgumentValues cas = beanDefinition
083: .getConstructorArgumentValues();
084: visitIndexedArgumentValues(cas.getIndexedArgumentValues());
085: visitGenericArgumentValues(cas.getGenericArgumentValues());
086: }
087:
088: protected void visitParentName(BeanDefinition beanDefinition) {
089: String parentName = beanDefinition.getParentName();
090: if (parentName != null) {
091: String resolvedName = resolveStringValue(parentName);
092: if (!parentName.equals(resolvedName)) {
093: beanDefinition.setParentName(resolvedName);
094: }
095: }
096: }
097:
098: protected void visitBeanClassName(BeanDefinition beanDefinition) {
099: String beanClassName = beanDefinition.getBeanClassName();
100: if (beanClassName != null) {
101: String resolvedName = resolveStringValue(beanClassName);
102: if (!beanClassName.equals(resolvedName)) {
103: beanDefinition.setBeanClassName(resolvedName);
104: }
105: }
106: }
107:
108: protected void visitFactoryBeanName(BeanDefinition beanDefinition) {
109: String factoryBeanName = beanDefinition.getFactoryBeanName();
110: if (factoryBeanName != null) {
111: String resolvedName = resolveStringValue(factoryBeanName);
112: if (!factoryBeanName.equals(resolvedName)) {
113: beanDefinition.setFactoryBeanName(resolvedName);
114: }
115: }
116: }
117:
118: protected void visitFactoryMethodName(BeanDefinition beanDefinition) {
119: String factoryMethodName = beanDefinition.getFactoryBeanName();
120: if (factoryMethodName != null) {
121: String resolvedName = resolveStringValue(factoryMethodName);
122: if (!factoryMethodName.equals(resolvedName)) {
123: beanDefinition.setFactoryMethodName(resolvedName);
124: }
125: }
126: }
127:
128: protected void visitScope(BeanDefinition beanDefinition) {
129: String scope = beanDefinition.getScope();
130: if (scope != null) {
131: String resolvedScope = resolveStringValue(scope);
132: if (!scope.equals(resolvedScope)) {
133: beanDefinition.setScope(resolvedScope);
134: }
135: }
136: }
137:
138: protected void visitPropertyValues(MutablePropertyValues pvs) {
139: PropertyValue[] pvArray = pvs.getPropertyValues();
140: for (int i = 0; i < pvArray.length; i++) {
141: PropertyValue pv = pvArray[i];
142: Object newVal = resolveValue(pv.getValue());
143: if (!ObjectUtils.nullSafeEquals(newVal, pv.getValue())) {
144: pvs.addPropertyValue(pv.getName(), newVal);
145: }
146: }
147: }
148:
149: protected void visitIndexedArgumentValues(Map ias) {
150: for (Iterator it = ias.values().iterator(); it.hasNext();) {
151: ConstructorArgumentValues.ValueHolder valueHolder = (ConstructorArgumentValues.ValueHolder) it
152: .next();
153: Object newVal = resolveValue(valueHolder.getValue());
154: if (!ObjectUtils.nullSafeEquals(newVal, valueHolder
155: .getValue())) {
156: valueHolder.setValue(newVal);
157: }
158: }
159: }
160:
161: protected void visitGenericArgumentValues(List gas) {
162: for (Iterator it = gas.iterator(); it.hasNext();) {
163: ConstructorArgumentValues.ValueHolder valueHolder = (ConstructorArgumentValues.ValueHolder) it
164: .next();
165: Object newVal = resolveValue(valueHolder.getValue());
166: if (!ObjectUtils.nullSafeEquals(newVal, valueHolder
167: .getValue())) {
168: valueHolder.setValue(newVal);
169: }
170: }
171: }
172:
173: protected Object resolveValue(Object value) {
174: if (value instanceof BeanDefinition) {
175: visitBeanDefinition((BeanDefinition) value);
176: } else if (value instanceof BeanDefinitionHolder) {
177: visitBeanDefinition(((BeanDefinitionHolder) value)
178: .getBeanDefinition());
179: } else if (value instanceof RuntimeBeanReference) {
180: RuntimeBeanReference ref = (RuntimeBeanReference) value;
181: String newBeanName = resolveStringValue(ref.getBeanName());
182: if (!newBeanName.equals(ref.getBeanName())) {
183: return new RuntimeBeanReference(newBeanName);
184: }
185: } else if (value instanceof List) {
186: visitList((List) value);
187: } else if (value instanceof Set) {
188: visitSet((Set) value);
189: } else if (value instanceof Map) {
190: visitMap((Map) value);
191: } else if (value instanceof TypedStringValue) {
192: TypedStringValue typedStringValue = (TypedStringValue) value;
193: String stringValue = typedStringValue.getValue();
194: if (stringValue != null) {
195: String visitedString = resolveStringValue(stringValue);
196: typedStringValue.setValue(visitedString);
197: }
198: } else if (value instanceof String) {
199: return resolveStringValue((String) value);
200: }
201: return value;
202: }
203:
204: protected void visitList(List listVal) {
205: for (int i = 0; i < listVal.size(); i++) {
206: Object elem = listVal.get(i);
207: Object newVal = resolveValue(elem);
208: if (!ObjectUtils.nullSafeEquals(newVal, elem)) {
209: listVal.set(i, newVal);
210: }
211: }
212: }
213:
214: protected void visitSet(Set setVal) {
215: for (Iterator it = new HashSet(setVal).iterator(); it.hasNext();) {
216: Object elem = it.next();
217: Object newVal = resolveValue(elem);
218: if (!ObjectUtils.nullSafeEquals(newVal, elem)) {
219: setVal.remove(elem);
220: setVal.add(newVal);
221: }
222: }
223: }
224:
225: protected void visitMap(Map mapVal) {
226: for (Iterator it = new HashMap(mapVal).entrySet().iterator(); it
227: .hasNext();) {
228: Map.Entry entry = (Map.Entry) it.next();
229: Object key = entry.getKey();
230: Object newKey = resolveValue(key);
231: boolean isNewKey = !ObjectUtils.nullSafeEquals(key, newKey);
232: Object val = entry.getValue();
233: Object newVal = resolveValue(val);
234: if (isNewKey) {
235: mapVal.remove(key);
236: }
237: if (isNewKey || !ObjectUtils.nullSafeEquals(newVal, val)) {
238: mapVal.put(newKey, newVal);
239: }
240: }
241: }
242:
243: /**
244: * Resolve the given String value, for example parsing placeholders.
245: * @param strVal the original String value
246: * @return the resolved String value
247: */
248: protected String resolveStringValue(String strVal) {
249: if (this .valueResolver == null) {
250: throw new IllegalStateException(
251: "No StringValueResolver specified - pass a resolver "
252: + "object into the constructor or override the 'resolveStringValue' method");
253: }
254: return this.valueResolver.resolveStringValue(strVal);
255: }
256:
257: }
|