|
16 | 16 |
|
17 | 17 | package org.springframework.boot.bind;
|
18 | 18 |
|
| 19 | +import java.lang.reflect.Field; |
19 | 20 | import java.util.Arrays;
|
20 | 21 | import java.util.Collection;
|
21 | 22 | import java.util.Map;
|
|
24 | 25 | import org.springframework.beans.MutablePropertyValues;
|
25 | 26 | import org.springframework.beans.PropertyValue;
|
26 | 27 | import org.springframework.beans.PropertyValues;
|
| 28 | +import org.springframework.core.env.CompositePropertySource; |
27 | 29 | import org.springframework.core.env.EnumerablePropertySource;
|
28 | 30 | import org.springframework.core.env.PropertySource;
|
29 | 31 | import org.springframework.core.env.PropertySources;
|
30 | 32 | import org.springframework.core.env.PropertySourcesPropertyResolver;
|
31 | 33 | import org.springframework.core.env.StandardEnvironment;
|
32 | 34 | import org.springframework.util.PatternMatchUtils;
|
| 35 | +import org.springframework.util.ReflectionUtils; |
33 | 36 | import org.springframework.validation.DataBinder;
|
34 | 37 |
|
35 | 38 | /**
|
@@ -73,48 +76,75 @@ public PropertySourcesPropertyValues(PropertySources propertySources,
|
73 | 76 | .toArray(new String[0]);
|
74 | 77 | String[] exacts = names == null ? new String[0] : names.toArray(new String[0]);
|
75 | 78 | for (PropertySource<?> source : propertySources) {
|
76 |
| - if (source instanceof EnumerablePropertySource) { |
77 |
| - EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source; |
78 |
| - if (enumerable.getPropertyNames().length > 0) { |
79 |
| - for (String propertyName : enumerable.getPropertyNames()) { |
80 |
| - if (this.NON_ENUMERABLE_ENUMERABLES.contains(source.getName()) |
81 |
| - && !PatternMatchUtils.simpleMatch(includes, propertyName)) { |
82 |
| - continue; |
83 |
| - } |
84 |
| - Object value = source.getProperty(propertyName); |
85 |
| - try { |
86 |
| - value = resolver.getProperty(propertyName); |
87 |
| - } |
88 |
| - catch (RuntimeException ex) { |
89 |
| - // Probably could not resolve placeholders, ignore it here |
90 |
| - } |
91 |
| - if (!this.propertyValues.containsKey(propertyName)) { |
92 |
| - this.propertyValues.put(propertyName, new PropertyValue( |
93 |
| - propertyName, value)); |
94 |
| - } |
95 |
| - } |
96 |
| - } |
97 |
| - } |
98 |
| - else { |
99 |
| - // We can only do exact matches for non-enumerable property names, but |
100 |
| - // that's better than nothing... |
101 |
| - for (String propertyName : exacts) { |
102 |
| - Object value; |
103 |
| - value = resolver.getProperty(propertyName); |
104 |
| - if (value != null && !this.propertyValues.containsKey(propertyName)) { |
105 |
| - this.propertyValues.put(propertyName, new PropertyValue( |
106 |
| - propertyName, value)); |
| 79 | + processPropertSource(source, resolver, includes, exacts); |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + private void processPropertSource(PropertySource<?> source, |
| 84 | + PropertySourcesPropertyResolver resolver, String[] includes, String[] exacts) { |
| 85 | + if (source instanceof EnumerablePropertySource) { |
| 86 | + EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source; |
| 87 | + if (enumerable.getPropertyNames().length > 0) { |
| 88 | + for (String propertyName : enumerable.getPropertyNames()) { |
| 89 | + if (this.NON_ENUMERABLE_ENUMERABLES.contains(source.getName()) |
| 90 | + && !PatternMatchUtils.simpleMatch(includes, propertyName)) { |
107 | 91 | continue;
|
108 | 92 | }
|
109 |
| - value = source.getProperty(propertyName.toUpperCase()); |
110 |
| - if (value != null && !this.propertyValues.containsKey(propertyName)) { |
| 93 | + Object value = source.getProperty(propertyName); |
| 94 | + try { |
| 95 | + value = resolver.getProperty(propertyName); |
| 96 | + } |
| 97 | + catch (RuntimeException ex) { |
| 98 | + // Probably could not resolve placeholders, ignore it here |
| 99 | + } |
| 100 | + if (!this.propertyValues.containsKey(propertyName)) { |
111 | 101 | this.propertyValues.put(propertyName, new PropertyValue(
|
112 | 102 | propertyName, value));
|
113 |
| - continue; |
114 | 103 | }
|
115 | 104 | }
|
116 | 105 | }
|
117 | 106 | }
|
| 107 | + else if (source instanceof CompositePropertySource) { |
| 108 | + CompositePropertySource composite = (CompositePropertySource) source; |
| 109 | + for (PropertySource<?> nested : extractSources(composite)) { |
| 110 | + processPropertSource(nested, resolver, includes, exacts); |
| 111 | + } |
| 112 | + } |
| 113 | + else { |
| 114 | + // We can only do exact matches for non-enumerable property names, but |
| 115 | + // that's better than nothing... |
| 116 | + for (String propertyName : exacts) { |
| 117 | + Object value; |
| 118 | + value = resolver.getProperty(propertyName); |
| 119 | + if (value != null && !this.propertyValues.containsKey(propertyName)) { |
| 120 | + this.propertyValues.put(propertyName, new PropertyValue(propertyName, |
| 121 | + value)); |
| 122 | + continue; |
| 123 | + } |
| 124 | + value = source.getProperty(propertyName.toUpperCase()); |
| 125 | + if (value != null && !this.propertyValues.containsKey(propertyName)) { |
| 126 | + this.propertyValues.put(propertyName, new PropertyValue(propertyName, |
| 127 | + value)); |
| 128 | + continue; |
| 129 | + } |
| 130 | + } |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + private Collection<PropertySource<?>> extractSources(CompositePropertySource composite) { |
| 135 | + Field field = ReflectionUtils.findField(CompositePropertySource.class, |
| 136 | + "propertySources"); |
| 137 | + field.setAccessible(true); |
| 138 | + try { |
| 139 | + @SuppressWarnings("unchecked") |
| 140 | + Collection<PropertySource<?>> collection = (Collection<PropertySource<?>>) field |
| 141 | + .get(composite); |
| 142 | + return collection; |
| 143 | + } |
| 144 | + catch (Exception e) { |
| 145 | + throw new IllegalStateException( |
| 146 | + "Cannot extract property sources from composite", e); |
| 147 | + } |
118 | 148 | }
|
119 | 149 |
|
120 | 150 | @Override
|
|
0 commit comments