SimpleAliasRegistry detects resolved aliases that loop back to the original name (SPR-5419); PropertyPlaceholderConfigurer does not modify Map in case of equal String keys (SPR-5318); inner class names in Java source style ("java.lang.Thread.State") supported as well (SPR-5210)
This commit is contained in:
parent
ff8e7a1289
commit
eb1631f458
|
@ -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.
|
||||
|
@ -264,7 +264,9 @@ public class BeanDefinitionVisitor {
|
|||
throw new IllegalStateException("No StringValueResolver specified - pass a resolver " +
|
||||
"object into the constructor or override the 'resolveStringValue' method");
|
||||
}
|
||||
return this.valueResolver.resolveStringValue(strVal);
|
||||
String resolvedValue = this.valueResolver.resolveStringValue(strVal);
|
||||
// Return original String if not modified.
|
||||
return (strVal.equals(resolvedValue) ? strVal : resolvedValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,23 +16,26 @@
|
|||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
|
||||
import static test.util.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import test.beans.IndexedTestBean;
|
||||
import test.beans.TestBean;
|
||||
import static test.util.TestResourceUtils.*;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
|
||||
import org.springframework.beans.factory.support.ChildBeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
|
@ -41,9 +44,6 @@ import org.springframework.beans.factory.support.ManagedSet;
|
|||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import test.beans.IndexedTestBean;
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* Unit tests for various {@link PropertyResourceConfigurer} implementations including:
|
||||
* {@link PropertyPlaceholderConfigurer}, {@link PropertyOverrideConfigurer} and
|
||||
|
@ -296,7 +296,7 @@ public final class PropertyResourceConfigurerTests {
|
|||
poc.postProcessBeanFactory(factory);
|
||||
} catch (BeanInitializationException ex) {
|
||||
// prove that the processor chokes on the invalid key
|
||||
assertTrue(ex.getMessage().toLowerCase().indexOf("argh") != -1);
|
||||
assertTrue(ex.getMessage().toLowerCase().contains("argh"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -345,13 +345,14 @@ public final class PropertyResourceConfigurerTests {
|
|||
}
|
||||
|
||||
private void doTestPropertyPlaceholderConfigurer(boolean parentChildSeparation) {
|
||||
Map singletonMap = Collections.singletonMap("myKey", "myValue");
|
||||
if (parentChildSeparation) {
|
||||
MutablePropertyValues pvs1 = new MutablePropertyValues();
|
||||
pvs1.addPropertyValue("age", "${age}");
|
||||
MutablePropertyValues pvs2 = new MutablePropertyValues();
|
||||
pvs2.addPropertyValue("name", "name${var}${var}${");
|
||||
pvs2.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
|
||||
|
||||
pvs2.addPropertyValue("someMap", singletonMap);
|
||||
RootBeanDefinition parent = new RootBeanDefinition(TestBean.class, pvs1);
|
||||
ChildBeanDefinition bd = new ChildBeanDefinition("${parent}", pvs2);
|
||||
factory.registerBeanDefinition("parent1", parent);
|
||||
|
@ -362,6 +363,7 @@ public final class PropertyResourceConfigurerTests {
|
|||
pvs.addPropertyValue("age", "${age}");
|
||||
pvs.addPropertyValue("name", "name${var}${var}${");
|
||||
pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
|
||||
pvs.addPropertyValue("someMap", singletonMap);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, pvs);
|
||||
factory.registerBeanDefinition("tb1", bd);
|
||||
}
|
||||
|
@ -415,6 +417,8 @@ public final class PropertyResourceConfigurerTests {
|
|||
assertEquals("namemyvarmyvar${", tb1.getName());
|
||||
assertEquals("myvarname98", tb2.getName());
|
||||
assertEquals(tb2, tb1.getSpouse());
|
||||
assertEquals(1, tb1.getSomeMap().size());
|
||||
assertEquals("myValue", tb1.getSomeMap().get("myKey"));
|
||||
assertEquals(2, tb2.getFriends().size());
|
||||
assertEquals("na98me", tb2.getFriends().iterator().next());
|
||||
assertEquals(tb2, tb2.getFriends().toArray()[1]);
|
||||
|
@ -498,7 +502,7 @@ public final class PropertyResourceConfigurerTests {
|
|||
}
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("user.dir") != -1);
|
||||
assertTrue(ex.getMessage().contains("user.dir"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -516,7 +520,7 @@ public final class PropertyResourceConfigurerTests {
|
|||
}
|
||||
catch (BeanDefinitionStoreException ex) {
|
||||
// expected
|
||||
assertTrue(ex.getMessage().indexOf("ref") != -1);
|
||||
assertTrue(ex.getMessage().contains("ref"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -582,6 +586,39 @@ public final class PropertyResourceConfigurerTests {
|
|||
assertEquals("myname", tb.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithPlaceholderInAlias() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerAlias("tb", "${alias}");
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
props.put("alias", "tb2");
|
||||
ppc.setProperties(props);
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("tb");
|
||||
TestBean tb2 = (TestBean) factory.getBean("tb2");
|
||||
assertSame(tb, tb2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithSelfReferencingPlaceholderInAlias() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
genericBeanDefinition(TestBean.class).getBeanDefinition());
|
||||
factory.registerAlias("tb", "${alias}");
|
||||
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
props.put("alias", "tb");
|
||||
ppc.setProperties(props);
|
||||
ppc.postProcessBeanFactory(factory);
|
||||
|
||||
TestBean tb = (TestBean) factory.getBean("tb");
|
||||
assertEquals(0, factory.getAliases("tb").length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertyPlaceholderConfigurerWithCircularReference() {
|
||||
factory.registerBeanDefinition("tb",
|
||||
|
@ -760,6 +797,7 @@ public final class PropertyResourceConfigurerTests {
|
|||
|
||||
|
||||
private static class ConvertingOverrideConfigurer extends PropertyOverrideConfigurer {
|
||||
|
||||
protected String convertPropertyValue(String originalValue) {
|
||||
return "X" + originalValue;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -24,17 +24,16 @@ import java.util.Set;
|
|||
import java.util.TreeMap;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import test.beans.CustomEnum;
|
||||
import test.beans.TestBean;
|
||||
|
||||
import org.springframework.beans.factory.config.FieldRetrievingFactoryBean;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.beans.factory.parsing.ComponentDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.beans.factory.config.PropertiesFactoryBean;
|
||||
import org.springframework.beans.factory.config.FieldRetrievingFactoryBean;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import test.beans.TestBean;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
|
@ -163,19 +162,19 @@ public class UtilNamespaceHandlerTests extends TestCase {
|
|||
|
||||
public void testNestedInCollections() throws Exception {
|
||||
TestBean bean = (TestBean) this.beanFactory.getBean("nestedCustomTagBean");
|
||||
Integer min = new Integer(Integer.MIN_VALUE);
|
||||
|
||||
List list = bean.getSomeList();
|
||||
assertEquals(1, list.size());
|
||||
assertEquals(min, list.get(0));
|
||||
assertEquals(Integer.MIN_VALUE, list.get(0));
|
||||
|
||||
Set set = bean.getSomeSet();
|
||||
assertEquals(1, set.size());
|
||||
assertTrue(set.contains(min));
|
||||
assertEquals(2, set.size());
|
||||
assertTrue(set.contains(Thread.State.NEW));
|
||||
assertTrue(set.contains(Thread.State.RUNNABLE));
|
||||
|
||||
Map map = bean.getSomeMap();
|
||||
assertEquals(1, map.size());
|
||||
assertEquals(min, map.get("min"));
|
||||
assertEquals(CustomEnum.VALUE_1, map.get("min"));
|
||||
}
|
||||
|
||||
public void testCircularCollections() throws Exception {
|
||||
|
|
|
@ -97,14 +97,15 @@
|
|||
</property>
|
||||
<property name="someSet">
|
||||
<set>
|
||||
<util:constant static-field="java.lang.Integer.MIN_VALUE"/>
|
||||
<util:constant static-field="java.lang.Thread$State.NEW"/>
|
||||
<util:constant static-field="java.lang.Thread.State.RUNNABLE"/>
|
||||
</set>
|
||||
</property>
|
||||
<property name="someMap">
|
||||
<map>
|
||||
<entry>
|
||||
<key><value>min</value></key>
|
||||
<util:constant static-field="java.lang.Integer.MIN_VALUE"/>
|
||||
<util:constant static-field="test.beans.CustomEnum.VALUE_1"/>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
|
|
|
@ -117,7 +117,10 @@ public class SimpleAliasRegistry implements AliasRegistry {
|
|||
String registeredName = aliasCopy.get(alias);
|
||||
String resolvedAlias = valueResolver.resolveStringValue(alias);
|
||||
String resolvedName = valueResolver.resolveStringValue(registeredName);
|
||||
if (!resolvedAlias.equals(alias)) {
|
||||
if (resolvedAlias.equals(resolvedName)) {
|
||||
this.aliasMap.remove(alias);
|
||||
}
|
||||
else if (!resolvedAlias.equals(alias)) {
|
||||
String existingName = this.aliasMap.get(resolvedAlias);
|
||||
if (existingName != null && !existingName.equals(resolvedName)) {
|
||||
throw new IllegalStateException(
|
||||
|
@ -125,8 +128,8 @@ public class SimpleAliasRegistry implements AliasRegistry {
|
|||
"') for name '" + resolvedName + "': It is already registered for name '" +
|
||||
registeredName + "'.");
|
||||
}
|
||||
this.aliasMap.put(resolvedAlias, resolvedName);
|
||||
this.aliasMap.remove(alias);
|
||||
this.aliasMap.put(resolvedAlias, resolvedName);
|
||||
}
|
||||
else if (!registeredName.equals(resolvedName)) {
|
||||
this.aliasMap.put(alias, resolvedName);
|
||||
|
|
|
@ -201,7 +201,9 @@ public abstract class ClassUtils {
|
|||
|
||||
/**
|
||||
* Replacement for <code>Class.forName()</code> that also returns Class instances
|
||||
* for primitives (like "int") and array class names (like "String[]").
|
||||
* for primitives (e.g."int") and array class names (e.g. "String[]").
|
||||
* Furthermore, it is also capable of resolving inner class names in Java source
|
||||
* style (e.g. "java.lang.Thread.State" instead of "java.lang.Thread$State").
|
||||
* @param name the name of the Class
|
||||
* @param classLoader the class loader to use
|
||||
* (may be <code>null</code>, which indicates the default class loader)
|
||||
|
@ -246,7 +248,22 @@ public abstract class ClassUtils {
|
|||
if (classLoaderToUse == null) {
|
||||
classLoaderToUse = getDefaultClassLoader();
|
||||
}
|
||||
return classLoaderToUse.loadClass(name);
|
||||
try {
|
||||
return classLoaderToUse.loadClass(name);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
int lastDotIndex = name.lastIndexOf('.');
|
||||
if (lastDotIndex != -1) {
|
||||
String innerClassName = name.substring(0, lastDotIndex) + '$' + name.substring(lastDotIndex + 1);
|
||||
try {
|
||||
return classLoaderToUse.loadClass(innerClassName);
|
||||
}
|
||||
catch (ClassNotFoundException ex2) {
|
||||
// swallow - let original exception get through
|
||||
}
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue