storing type information as specified (SPR-5556, SPR-5562); explicit XML array element in spring-beans-3.0.xsd (SPR-5543)

This commit is contained in:
Juergen Hoeller
2009-04-15 22:27:32 +00:00
parent 5a561bcd07
commit 1b5812da20
17 changed files with 1568 additions and 202 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,8 @@ public class TypedStringValue implements BeanMetadataElement {
private Object source;
private String specifiedTypeName;
/**
* Create a new {@link TypedStringValue} for the given String value.
@@ -169,6 +171,20 @@ public class TypedStringValue implements BeanMetadataElement {
return this.source;
}
/**
* Set the type name as actually specified for this particular value, if any.
*/
public void setSpecifiedTypeName(String specifiedTypeName) {
this.specifiedTypeName = specifiedTypeName;
}
/**
* Return the type name as actually specified for this particular value, if any.
*/
public String getSpecifiedTypeName() {
return this.specifiedTypeName;
}
@Override
public boolean equals(Object other) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package org.springframework.beans.factory.support;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -36,6 +37,8 @@ import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanNameReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Helper class for use in bean factory implementations,
@@ -121,6 +124,30 @@ class BeanDefinitionValueResolver {
BeanDefinition bd = (BeanDefinition) value;
return resolveInnerBean(argName, "(inner bean)", bd);
}
else if (value instanceof ManagedArray) {
// May need to resolve contained runtime references.
ManagedArray array = (ManagedArray) value;
Class elementType = array.resolvedElementType;
if (elementType == null) {
String elementTypeName = array.getElementTypeName();
if (StringUtils.hasText(elementTypeName)) {
try {
elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
array.resolvedElementType = elementType;
}
catch (Throwable ex) {
// Improve the message by showing the context.
throw new BeanCreationException(
this.beanDefinition.getResourceDescription(), this.beanName,
"Error resolving array type for " + argName, ex);
}
}
else {
elementType = Object.class;
}
}
return resolveManagedArray(argName, (List<?>) value, elementType);
}
else if (value instanceof ManagedList) {
// May need to resolve contained runtime references.
return resolveManagedList(argName, (List<?>) value);
@@ -292,7 +319,21 @@ class BeanDefinitionValueResolver {
}
/**
* For each element in the ManagedList, resolve reference if necessary.
* For each element in the managed array, resolve reference if necessary.
*/
private Object resolveManagedArray(Object argName, List<?> ml, Class elementType) {
Object resolved = Array.newInstance(elementType, ml.size());
for (int i = 0; i < ml.size(); i++) {
Array.set(resolved, i,
resolveValueIfNecessary(
argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + i + BeanWrapper.PROPERTY_KEY_SUFFIX,
ml.get(i)));
}
return resolved;
}
/**
* For each element in the managed list, resolve reference if necessary.
*/
private List resolveManagedList(Object argName, List<?> ml) {
List<Object> resolved = new ArrayList<Object>(ml.size());
@@ -306,7 +347,7 @@ class BeanDefinitionValueResolver {
}
/**
* For each element in the ManagedList, resolve reference if necessary.
* For each element in the managed set, resolve reference if necessary.
*/
private Set resolveManagedSet(Object argName, Set<?> ms) {
Set<Object> resolved = new LinkedHashSet<Object>(ms.size());
@@ -320,7 +361,7 @@ class BeanDefinitionValueResolver {
}
/**
* For each element in the ManagedMap, resolve reference if necessary.
* For each element in the managed map, resolve reference if necessary.
*/
private Map resolveManagedMap(Object argName, Map<?, ?> mm) {
Map<Object, Object> resolved = new LinkedHashMap<Object, Object>(mm.size());

View File

@@ -744,7 +744,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
* Determine the primary autowire candidate in the given set of beans.
* @param candidateBeans a Map of candidate names and candidate instances
* that match the required type, as returned by {@link #findAutowireCandidates}
* @param type the required type
* @param descriptor the target dependency to match against
* @return the name of the primary candidate, or <code>null</code> if none found
*/
protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) {

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.support;
import org.springframework.util.Assert;
/**
* Tag collection class used to hold managed array elements, which may
* include runtime bean references (to be resolved into bean objects).
*
* @author Juergen Hoeller
* @since 3.0
*/
public class ManagedArray extends ManagedList<Object> {
/** Resolved element type for runtime creation of the target array */
volatile Class resolvedElementType;
/**
* Create a new managed array placeholder.
* @param elementTypeName the target element type as a class name
* @param size the size of the array
*/
public ManagedArray(String elementTypeName, int size) {
super(size);
Assert.notNull(elementTypeName, "elementTypeName must not be null");
setElementTypeName(elementTypeName);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,8 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad
private Object source;
private String elementTypeName;
private boolean mergeEnabled;
@@ -58,6 +60,20 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad
return this.source;
}
/**
* Set the default element type name (class name) to be used for this list.
*/
public void setElementTypeName(String elementTypeName) {
this.elementTypeName = elementTypeName;
}
/**
* Return the default element type name (class name) to be used for this list.
*/
public String getElementTypeName() {
return this.elementTypeName;
}
/**
* Set whether merging should be enabled for this collection,
* in case of a 'parent' collection value being present.
@@ -70,7 +86,8 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad
return this.mergeEnabled;
}
public Object merge(Object parent) {
@SuppressWarnings("unchecked")
public List<E> merge(Object parent) {
if (!this.mergeEnabled) {
throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'");
}
@@ -80,7 +97,7 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad
if (!(parent instanceof List)) {
throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]");
}
List merged = new ManagedList();
List<E> merged = new ManagedList<E>();
merged.addAll((List) parent);
merged.addAll(this);
return merged;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,10 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable,
private Object source;
private String keyTypeName;
private String valueTypeName;
private boolean mergeEnabled;
@@ -57,6 +61,34 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable,
return this.source;
}
/**
* Set the default key type name (class name) to be used for this map.
*/
public void setKeyTypeName(String keyTypeName) {
this.keyTypeName = keyTypeName;
}
/**
* Return the default key type name (class name) to be used for this map.
*/
public String getKeyTypeName() {
return this.keyTypeName;
}
/**
* Set the default value type name (class name) to be used for this map.
*/
public void setValueTypeName(String valueTypeName) {
this.valueTypeName = valueTypeName;
}
/**
* Return the default value type name (class name) to be used for this map.
*/
public String getValueTypeName() {
return this.valueTypeName;
}
/**
* Set whether merging should be enabled for this collection,
* in case of a 'parent' collection value being present.
@@ -69,6 +101,7 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable,
return this.mergeEnabled;
}
@SuppressWarnings("unchecked")
public Object merge(Object parent) {
if (!this.mergeEnabled) {
throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'");
@@ -79,7 +112,7 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable,
if (!(parent instanceof Map)) {
throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]");
}
Map merged = new ManagedMap();
Map<K, V> merged = new ManagedMap<K, V>();
merged.putAll((Map) parent);
merged.putAll(this);
return merged;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,8 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe
private Object source;
private String elementTypeName;
private boolean mergeEnabled;
@@ -57,6 +59,20 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe
return this.source;
}
/**
* Set the default element type name (class name) to be used for this set.
*/
public void setElementTypeName(String elementTypeName) {
this.elementTypeName = elementTypeName;
}
/**
* Return the default element type name (class name) to be used for this set.
*/
public String getElementTypeName() {
return this.elementTypeName;
}
/**
* Set whether merging should be enabled for this collection,
* in case of a 'parent' collection value being present.
@@ -69,7 +85,8 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe
return this.mergeEnabled;
}
public Object merge(Object parent) {
@SuppressWarnings("unchecked")
public Set<E> merge(Object parent) {
if (!this.mergeEnabled) {
throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'");
}
@@ -79,7 +96,7 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe
if (!(parent instanceof Set)) {
throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]");
}
Set merged = new ManagedSet();
Set<E> merged = new ManagedSet<E>();
merged.addAll((Set) parent);
merged.addAll(this);
return merged;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.springframework.beans.factory.xml;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -26,6 +27,11 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.springframework.beans.BeanMetadataAttribute;
import org.springframework.beans.BeanMetadataAttributeAccessor;
import org.springframework.beans.PropertyValue;
@@ -45,6 +51,7 @@ import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.BeanDefinitionDefaults;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.LookupOverride;
import org.springframework.beans.factory.support.ManagedArray;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.ManagedProperties;
@@ -58,10 +65,6 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Stateful delegate class used to parse XML bean definitions.
@@ -185,6 +188,8 @@ public class BeanDefinitionParserDelegate {
public static final String NULL_ELEMENT = "null";
public static final String ARRAY_ELEMENT = "array";
public static final String LIST_ELEMENT = "list";
public static final String SET_ELEMENT = "set";
@@ -424,7 +429,7 @@ public class BeanDefinitionParserDelegate {
/**
* Validate that the specified bean name and aliases have not been used already.
*/
protected void checkNameUniqueness(String beanName, List aliases, Element beanElement) {
protected void checkNameUniqueness(String beanName, List<String> aliases, Element beanElement) {
String foundName = null;
if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) {
@@ -651,18 +656,18 @@ public class BeanDefinitionParserDelegate {
if (DEFAULT_VALUE.equals(att)) {
att = this.defaults.getDependencyCheck();
}
int dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE;
if (DEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE.equals(att)) {
dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_ALL;
}
else if (DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE.equals(att)) {
dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE;
return AbstractBeanDefinition.DEPENDENCY_CHECK_ALL;
}
else if (DEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE.equals(att)) {
dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS;
return AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS;
}
else if (DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE.equals(att)) {
return AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE;
}
else {
return AbstractBeanDefinition.DEPENDENCY_CHECK_NONE;
}
// Else leave default value.
return dependencyCheckCode;
}
/**
@@ -928,10 +933,10 @@ public class BeanDefinitionParserDelegate {
* Parse a value, ref or collection sub-element of a property or
* constructor-arg element.
* @param ele subelement of property element; we don't know which yet
* @param defaultTypeClassName the default type (class name) for any
* @param defaultValueType the default type (class name) for any
* <code>&lt;value&gt;</code> tag that might be created
*/
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultTypeClassName) {
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
if (!isDefaultNamespace(ele.getNamespaceURI())) {
return parseNestedCustomElement(ele, bd);
}
@@ -971,7 +976,7 @@ public class BeanDefinitionParserDelegate {
return parseIdRefElement(ele);
}
else if (DomUtils.nodeNameEquals(ele, VALUE_ELEMENT)) {
return parseValueElement(ele, defaultTypeClassName);
return parseValueElement(ele, defaultValueType);
}
else if (DomUtils.nodeNameEquals(ele, NULL_ELEMENT)) {
// It's a distinguished null value. Let's wrap it in a TypedStringValue
@@ -980,6 +985,9 @@ public class BeanDefinitionParserDelegate {
nullHolder.setSource(extractSource(ele));
return nullHolder;
}
else if (DomUtils.nodeNameEquals(ele, ARRAY_ELEMENT)) {
return parseArrayElement(ele, bd);
}
else if (DomUtils.nodeNameEquals(ele, LIST_ELEMENT)) {
return parseListElement(ele, bd);
}
@@ -1024,18 +1032,22 @@ public class BeanDefinitionParserDelegate {
/**
* Return a typed String value Object for the given value element.
*/
public Object parseValueElement(Element ele, String defaultTypeClassName) {
public Object parseValueElement(Element ele, String defaultTypeName) {
// It's a literal value.
String value = DomUtils.getTextValue(ele);
String typeClassName = ele.getAttribute(TYPE_ATTRIBUTE);
if (!StringUtils.hasText(typeClassName)) {
typeClassName = defaultTypeClassName;
String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);
String typeName = specifiedTypeName;
if (!StringUtils.hasText(typeName)) {
typeName = defaultTypeName;
}
try {
return buildTypedStringValue(value, typeClassName, ele);
TypedStringValue typedValue = buildTypedStringValue(value, typeName);
typedValue.setSource(extractSource(ele));
typedValue.setSpecifiedTypeName(specifiedTypeName);
return typedValue;
}
catch (ClassNotFoundException ex) {
error("Type class [" + typeClassName + "] not found for <value> element", ele, ex);
error("Type class [" + typeName + "] not found for <value> element", ele, ex);
return value;
}
}
@@ -1044,11 +1056,11 @@ public class BeanDefinitionParserDelegate {
* Build a typed String value Object for the given raw value.
* @see org.springframework.beans.factory.config.TypedStringValue
*/
protected Object buildTypedStringValue(String value, String targetTypeName, Element ele)
protected TypedStringValue buildTypedStringValue(String value, String targetTypeName)
throws ClassNotFoundException {
ClassLoader classLoader = this.readerContext.getBeanClassLoader();
TypedStringValue typedValue = null;
TypedStringValue typedValue;
if (!StringUtils.hasText(targetTypeName)) {
typedValue = new TypedStringValue(value);
}
@@ -1059,57 +1071,75 @@ public class BeanDefinitionParserDelegate {
else {
typedValue = new TypedStringValue(value, targetTypeName);
}
typedValue.setSource(extractSource(ele));
return typedValue;
}
/**
* Parse an array element.
*/
public Object parseArrayElement(Element arrayEle, BeanDefinition bd) {
String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
NodeList nl = arrayEle.getChildNodes();
ManagedArray target = new ManagedArray(elementType, nl.getLength());
target.setSource(extractSource(arrayEle));
target.setElementTypeName(elementType);
target.setMergeEnabled(parseMergeAttribute(arrayEle));
parseCollectionElements(nl, target, bd, elementType);
return target;
}
/**
* Parse a list element.
*/
public List<?> parseListElement(Element collectionEle, BeanDefinition bd) {
String defaultTypeClassName = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
public List parseListElement(Element collectionEle, BeanDefinition bd) {
String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
NodeList nl = collectionEle.getChildNodes();
ManagedList list = new ManagedList(nl.getLength());
list.setSource(extractSource(collectionEle));
list.setMergeEnabled(parseMergeAttribute(collectionEle));
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element && !DomUtils.nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
list.add(parsePropertySubElement((Element) node, bd, defaultTypeClassName));
}
}
return list;
ManagedList<Object> target = new ManagedList<Object>(nl.getLength());
target.setSource(extractSource(collectionEle));
target.setElementTypeName(defaultElementType);
target.setMergeEnabled(parseMergeAttribute(collectionEle));
parseCollectionElements(nl, target, bd, defaultElementType);
return target;
}
/**
* Parse a set element.
*/
public Set parseSetElement(Element collectionEle, BeanDefinition bd) {
String defaultTypeClassName = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
NodeList nl = collectionEle.getChildNodes();
ManagedSet set = new ManagedSet(nl.getLength());
set.setSource(extractSource(collectionEle));
set.setMergeEnabled(parseMergeAttribute(collectionEle));
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
ManagedSet<Object> target = new ManagedSet<Object>(nl.getLength());
target.setSource(extractSource(collectionEle));
target.setElementTypeName(defaultElementType);
target.setMergeEnabled(parseMergeAttribute(collectionEle));
parseCollectionElements(nl, target, bd, defaultElementType);
return target;
}
protected void parseCollectionElements(
NodeList elementNodes, Collection<Object> target, BeanDefinition bd, String defaultElementType) {
for (int i = 0; i < elementNodes.getLength(); i++) {
Node node = elementNodes.item(i);
if (node instanceof Element && !DomUtils.nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
set.add(parsePropertySubElement((Element) node, bd, defaultTypeClassName));
target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
}
}
return set;
}
/**
* Parse a map element.
*/
public Map parseMapElement(Element mapEle, BeanDefinition bd) {
String defaultKeyTypeClassName = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE);
String defaultValueTypeClassName = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE);
String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT);
ManagedMap map = new ManagedMap(entryEles.size());
map.setMergeEnabled(parseMergeAttribute(mapEle));
ManagedMap<Object, Object> map = new ManagedMap<Object, Object>(entryEles.size());
map.setSource(extractSource(mapEle));
map.setKeyTypeName(defaultKeyType);
map.setValueTypeName(defaultValueType);
map.setMergeEnabled(parseMergeAttribute(mapEle));
for (Element entryEle : entryEles) {
// Should only have one value child element: ref, value, list, etc.
@@ -1151,8 +1181,7 @@ public class BeanDefinitionParserDelegate {
"a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element", entryEle);
}
if (hasKeyAttribute) {
key = buildTypedStringValueForMap(
entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyTypeClassName, entryEle);
key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle);
}
else if (hasKeyRefAttribute) {
String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE);
@@ -1164,7 +1193,7 @@ public class BeanDefinitionParserDelegate {
key = ref;
}
else if (keyEle != null) {
key = parseKeyElement(keyEle, bd, defaultKeyTypeClassName);
key = parseKeyElement(keyEle, bd, defaultKeyType);
}
else {
error("<entry> element must specify a key", entryEle);
@@ -1180,8 +1209,7 @@ public class BeanDefinitionParserDelegate {
"'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle);
}
if (hasValueAttribute) {
value = buildTypedStringValueForMap(
entryEle.getAttribute(VALUE_ATTRIBUTE), defaultValueTypeClassName, entryEle);
value = buildTypedStringValueForMap(entryEle.getAttribute(VALUE_ATTRIBUTE), defaultValueType, entryEle);
}
else if (hasValueRefAttribute) {
String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE);
@@ -1193,7 +1221,7 @@ public class BeanDefinitionParserDelegate {
value = ref;
}
else if (valueEle != null) {
value = parsePropertySubElement(valueEle, bd, defaultValueTypeClassName);
value = parsePropertySubElement(valueEle, bd, defaultValueType);
}
else {
error("<entry> element must specify a value", entryEle);
@@ -1210,12 +1238,14 @@ public class BeanDefinitionParserDelegate {
* Build a typed String value Object for the given raw value.
* @see org.springframework.beans.factory.config.TypedStringValue
*/
protected final Object buildTypedStringValueForMap(String value, String defaultTypeClassName, Element entryEle) {
protected final Object buildTypedStringValueForMap(String value, String defaultTypeName, Element entryEle) {
try {
return buildTypedStringValue(value, defaultTypeClassName, entryEle);
TypedStringValue typedValue = buildTypedStringValue(value, defaultTypeName);
typedValue.setSource(extractSource(entryEle));
return typedValue;
}
catch (ClassNotFoundException ex) {
error("Type class [" + defaultTypeClassName + "] not found for Map key/value type", entryEle, ex);
error("Type class [" + defaultTypeName + "] not found for Map key/value type", entryEle, ex);
return value;
}
}
@@ -1223,7 +1253,7 @@ public class BeanDefinitionParserDelegate {
/**
* Parse a key sub-element of a map element.
*/
public Object parseKeyElement(Element keyEle, BeanDefinition bd, String defaultKeyTypeClassName) {
protected Object parseKeyElement(Element keyEle, BeanDefinition bd, String defaultKeyTypeName) {
NodeList nl = keyEle.getChildNodes();
Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) {
@@ -1238,7 +1268,7 @@ public class BeanDefinitionParserDelegate {
}
}
}
return parsePropertySubElement(subElement, bd, defaultKeyTypeClassName);
return parsePropertySubElement(subElement, bd, defaultKeyTypeName);
}
/**