Skip to content

Commit eb1631f

Browse files
committed
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)
1 parent ff8e7a1 commit eb1631f

File tree

6 files changed

+91
-31
lines changed

6 files changed

+91
-31
lines changed

org.springframework.beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionVisitor.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -264,7 +264,9 @@ protected String resolveStringValue(String strVal) {
264264
throw new IllegalStateException("No StringValueResolver specified - pass a resolver " +
265265
"object into the constructor or override the 'resolveStringValue' method");
266266
}
267-
return this.valueResolver.resolveStringValue(strVal);
267+
String resolvedValue = this.valueResolver.resolveStringValue(strVal);
268+
// Return original String if not modified.
269+
return (strVal.equals(resolvedValue) ? strVal : resolvedValue);
268270
}
269271

270272
}

org.springframework.beans/src/test/java/org/springframework/beans/factory/config/PropertyResourceConfigurerTests.java

+50-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,23 +16,26 @@
1616

1717
package org.springframework.beans.factory.config;
1818

19-
import static org.junit.Assert.*;
20-
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;
21-
import static test.util.TestResourceUtils.qualifiedResource;
22-
19+
import java.util.Collections;
2320
import java.util.List;
2421
import java.util.Map;
2522
import java.util.Properties;
2623
import java.util.Set;
2724
import java.util.prefs.Preferences;
2825

26+
import static org.junit.Assert.*;
2927
import org.junit.Before;
3028
import org.junit.Ignore;
3129
import org.junit.Test;
30+
import test.beans.IndexedTestBean;
31+
import test.beans.TestBean;
32+
import static test.util.TestResourceUtils.*;
33+
3234
import org.springframework.beans.MutablePropertyValues;
3335
import org.springframework.beans.factory.BeanDefinitionStoreException;
3436
import org.springframework.beans.factory.BeanInitializationException;
3537
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
38+
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*;
3639
import org.springframework.beans.factory.support.ChildBeanDefinition;
3740
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
3841
import org.springframework.beans.factory.support.ManagedList;
@@ -41,9 +44,6 @@
4144
import org.springframework.beans.factory.support.RootBeanDefinition;
4245
import org.springframework.core.io.Resource;
4346

44-
import test.beans.IndexedTestBean;
45-
import test.beans.TestBean;
46-
4747
/**
4848
* Unit tests for various {@link PropertyResourceConfigurer} implementations including:
4949
* {@link PropertyPlaceholderConfigurer}, {@link PropertyOverrideConfigurer} and
@@ -296,7 +296,7 @@ public void testPropertyOverrideConfigurerWithInvalidKey() {
296296
poc.postProcessBeanFactory(factory);
297297
} catch (BeanInitializationException ex) {
298298
// prove that the processor chokes on the invalid key
299-
assertTrue(ex.getMessage().toLowerCase().indexOf("argh") != -1);
299+
assertTrue(ex.getMessage().toLowerCase().contains("argh"));
300300
}
301301
}
302302
}
@@ -345,13 +345,14 @@ public void testPropertyPlaceholderConfigurerWithParentChildSeparation() {
345345
}
346346

347347
private void doTestPropertyPlaceholderConfigurer(boolean parentChildSeparation) {
348+
Map singletonMap = Collections.singletonMap("myKey", "myValue");
348349
if (parentChildSeparation) {
349350
MutablePropertyValues pvs1 = new MutablePropertyValues();
350351
pvs1.addPropertyValue("age", "${age}");
351352
MutablePropertyValues pvs2 = new MutablePropertyValues();
352353
pvs2.addPropertyValue("name", "name${var}${var}${");
353354
pvs2.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
354-
355+
pvs2.addPropertyValue("someMap", singletonMap);
355356
RootBeanDefinition parent = new RootBeanDefinition(TestBean.class, pvs1);
356357
ChildBeanDefinition bd = new ChildBeanDefinition("${parent}", pvs2);
357358
factory.registerBeanDefinition("parent1", parent);
@@ -362,6 +363,7 @@ private void doTestPropertyPlaceholderConfigurer(boolean parentChildSeparation)
362363
pvs.addPropertyValue("age", "${age}");
363364
pvs.addPropertyValue("name", "name${var}${var}${");
364365
pvs.addPropertyValue("spouse", new RuntimeBeanReference("${ref}"));
366+
pvs.addPropertyValue("someMap", singletonMap);
365367
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class, pvs);
366368
factory.registerBeanDefinition("tb1", bd);
367369
}
@@ -415,6 +417,8 @@ private void doTestPropertyPlaceholderConfigurer(boolean parentChildSeparation)
415417
assertEquals("namemyvarmyvar${", tb1.getName());
416418
assertEquals("myvarname98", tb2.getName());
417419
assertEquals(tb2, tb1.getSpouse());
420+
assertEquals(1, tb1.getSomeMap().size());
421+
assertEquals("myValue", tb1.getSomeMap().get("myKey"));
418422
assertEquals(2, tb2.getFriends().size());
419423
assertEquals("na98me", tb2.getFriends().iterator().next());
420424
assertEquals(tb2, tb2.getFriends().toArray()[1]);
@@ -498,7 +502,7 @@ public void testPropertyPlaceholderConfigurerWithUnresolvableSystemProperty() {
498502
}
499503
catch (BeanDefinitionStoreException ex) {
500504
// expected
501-
assertTrue(ex.getMessage().indexOf("user.dir") != -1);
505+
assertTrue(ex.getMessage().contains("user.dir"));
502506
}
503507
}
504508

@@ -516,7 +520,7 @@ public void testPropertyPlaceholderConfigurerWithUnresolvablePlaceholder() {
516520
}
517521
catch (BeanDefinitionStoreException ex) {
518522
// expected
519-
assertTrue(ex.getMessage().indexOf("ref") != -1);
523+
assertTrue(ex.getMessage().contains("ref"));
520524
}
521525
}
522526

@@ -582,6 +586,39 @@ public void testPropertyPlaceholderConfigurerWithNestedPlaceholderInKey() {
582586
assertEquals("myname", tb.getName());
583587
}
584588

589+
@Test
590+
public void testPropertyPlaceholderConfigurerWithPlaceholderInAlias() {
591+
factory.registerBeanDefinition("tb",
592+
genericBeanDefinition(TestBean.class).getBeanDefinition());
593+
factory.registerAlias("tb", "${alias}");
594+
595+
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
596+
Properties props = new Properties();
597+
props.put("alias", "tb2");
598+
ppc.setProperties(props);
599+
ppc.postProcessBeanFactory(factory);
600+
601+
TestBean tb = (TestBean) factory.getBean("tb");
602+
TestBean tb2 = (TestBean) factory.getBean("tb2");
603+
assertSame(tb, tb2);
604+
}
605+
606+
@Test
607+
public void testPropertyPlaceholderConfigurerWithSelfReferencingPlaceholderInAlias() {
608+
factory.registerBeanDefinition("tb",
609+
genericBeanDefinition(TestBean.class).getBeanDefinition());
610+
factory.registerAlias("tb", "${alias}");
611+
612+
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
613+
Properties props = new Properties();
614+
props.put("alias", "tb");
615+
ppc.setProperties(props);
616+
ppc.postProcessBeanFactory(factory);
617+
618+
TestBean tb = (TestBean) factory.getBean("tb");
619+
assertEquals(0, factory.getAliases("tb").length);
620+
}
621+
585622
@Test
586623
public void testPropertyPlaceholderConfigurerWithCircularReference() {
587624
factory.registerBeanDefinition("tb",
@@ -760,6 +797,7 @@ public void testPreferencesPlaceholderConfigurerWithPathInPlaceholder() {
760797

761798

762799
private static class ConvertingOverrideConfigurer extends PropertyOverrideConfigurer {
800+
763801
protected String convertPropertyValue(String originalValue) {
764802
return "X" + originalValue;
765803
}

org.springframework.beans/src/test/java/org/springframework/beans/factory/xml/UtilNamespaceHandlerTests.java

+10-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2009 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,17 +24,16 @@
2424
import java.util.TreeMap;
2525

2626
import junit.framework.TestCase;
27+
import test.beans.CustomEnum;
28+
import test.beans.TestBean;
2729

30+
import org.springframework.beans.factory.config.FieldRetrievingFactoryBean;
31+
import org.springframework.beans.factory.config.PropertiesFactoryBean;
2832
import org.springframework.beans.factory.parsing.ComponentDefinition;
2933
import org.springframework.beans.factory.support.AbstractBeanDefinition;
3034
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
31-
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
32-
import org.springframework.beans.factory.config.PropertiesFactoryBean;
33-
import org.springframework.beans.factory.config.FieldRetrievingFactoryBean;
3435
import org.springframework.core.io.ClassPathResource;
3536

36-
import test.beans.TestBean;
37-
3837
/**
3938
* @author Rob Harrop
4039
* @author Juergen Hoeller
@@ -163,19 +162,19 @@ public void testNestedCollections() throws Exception {
163162

164163
public void testNestedInCollections() throws Exception {
165164
TestBean bean = (TestBean) this.beanFactory.getBean("nestedCustomTagBean");
166-
Integer min = new Integer(Integer.MIN_VALUE);
167165

168166
List list = bean.getSomeList();
169167
assertEquals(1, list.size());
170-
assertEquals(min, list.get(0));
168+
assertEquals(Integer.MIN_VALUE, list.get(0));
171169

172170
Set set = bean.getSomeSet();
173-
assertEquals(1, set.size());
174-
assertTrue(set.contains(min));
171+
assertEquals(2, set.size());
172+
assertTrue(set.contains(Thread.State.NEW));
173+
assertTrue(set.contains(Thread.State.RUNNABLE));
175174

176175
Map map = bean.getSomeMap();
177176
assertEquals(1, map.size());
178-
assertEquals(min, map.get("min"));
177+
assertEquals(CustomEnum.VALUE_1, map.get("min"));
179178
}
180179

181180
public void testCircularCollections() throws Exception {

org.springframework.beans/src/test/resources/org/springframework/beans/factory/xml/testUtilNamespace.xml

+3-2
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,15 @@
9797
</property>
9898
<property name="someSet">
9999
<set>
100-
<util:constant static-field="java.lang.Integer.MIN_VALUE"/>
100+
<util:constant static-field="java.lang.Thread$State.NEW"/>
101+
<util:constant static-field="java.lang.Thread.State.RUNNABLE"/>
101102
</set>
102103
</property>
103104
<property name="someMap">
104105
<map>
105106
<entry>
106107
<key><value>min</value></key>
107-
<util:constant static-field="java.lang.Integer.MIN_VALUE"/>
108+
<util:constant static-field="test.beans.CustomEnum.VALUE_1"/>
108109
</entry>
109110
</map>
110111
</property>

org.springframework.core/src/main/java/org/springframework/core/SimpleAliasRegistry.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,19 @@ public void resolveAliases(StringValueResolver valueResolver) {
117117
String registeredName = aliasCopy.get(alias);
118118
String resolvedAlias = valueResolver.resolveStringValue(alias);
119119
String resolvedName = valueResolver.resolveStringValue(registeredName);
120-
if (!resolvedAlias.equals(alias)) {
120+
if (resolvedAlias.equals(resolvedName)) {
121+
this.aliasMap.remove(alias);
122+
}
123+
else if (!resolvedAlias.equals(alias)) {
121124
String existingName = this.aliasMap.get(resolvedAlias);
122125
if (existingName != null && !existingName.equals(resolvedName)) {
123126
throw new IllegalStateException(
124127
"Cannot register resolved alias '" + resolvedAlias + "' (original: '" + alias +
125128
"') for name '" + resolvedName + "': It is already registered for name '" +
126129
registeredName + "'.");
127130
}
128-
this.aliasMap.put(resolvedAlias, resolvedName);
129131
this.aliasMap.remove(alias);
132+
this.aliasMap.put(resolvedAlias, resolvedName);
130133
}
131134
else if (!registeredName.equals(resolvedName)) {
132135
this.aliasMap.put(alias, resolvedName);

org.springframework.core/src/main/java/org/springframework/util/ClassUtils.java

+19-2
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,9 @@ public static Class forName(String name) throws ClassNotFoundException, LinkageE
201201

202202
/**
203203
* Replacement for <code>Class.forName()</code> that also returns Class instances
204-
* for primitives (like "int") and array class names (like "String[]").
204+
* for primitives (e.g."int") and array class names (e.g. "String[]").
205+
* Furthermore, it is also capable of resolving inner class names in Java source
206+
* style (e.g. "java.lang.Thread.State" instead of "java.lang.Thread$State").
205207
* @param name the name of the Class
206208
* @param classLoader the class loader to use
207209
* (may be <code>null</code>, which indicates the default class loader)
@@ -246,7 +248,22 @@ public static Class forName(String name, ClassLoader classLoader) throws ClassNo
246248
if (classLoaderToUse == null) {
247249
classLoaderToUse = getDefaultClassLoader();
248250
}
249-
return classLoaderToUse.loadClass(name);
251+
try {
252+
return classLoaderToUse.loadClass(name);
253+
}
254+
catch (ClassNotFoundException ex) {
255+
int lastDotIndex = name.lastIndexOf('.');
256+
if (lastDotIndex != -1) {
257+
String innerClassName = name.substring(0, lastDotIndex) + '$' + name.substring(lastDotIndex + 1);
258+
try {
259+
return classLoaderToUse.loadClass(innerClassName);
260+
}
261+
catch (ClassNotFoundException ex2) {
262+
// swallow - let original exception get through
263+
}
264+
}
265+
throw ex;
266+
}
250267
}
251268

252269
/**

0 commit comments

Comments
 (0)