16
16
17
17
package org .springframework .boot .context .properties .migrator ;
18
18
19
+ import java .util .ArrayList ;
19
20
import java .util .Collections ;
20
21
import java .util .HashSet ;
21
22
import java .util .LinkedHashMap ;
22
23
import java .util .List ;
23
24
import java .util .Map ;
25
+ import java .util .Objects ;
24
26
import java .util .Set ;
25
27
import java .util .function .Predicate ;
26
28
33
35
import org .springframework .boot .context .properties .source .IterableConfigurationPropertySource ;
34
36
import org .springframework .boot .env .OriginTrackedMapPropertySource ;
35
37
import org .springframework .boot .origin .OriginTrackedValue ;
38
+ import org .springframework .boot .origin .PropertySourceOrigin ;
36
39
import org .springframework .core .env .ConfigurableEnvironment ;
37
40
import org .springframework .core .env .PropertySource ;
38
41
import org .springframework .util .LinkedMultiValueMap ;
@@ -64,7 +67,7 @@ class PropertiesMigrationReporter {
64
67
*/
65
68
PropertiesMigrationReport getReport () {
66
69
PropertiesMigrationReport report = new PropertiesMigrationReport ();
67
- Map <String , List <PropertyMigration >> properties = getMatchingProperties (
70
+ Map <String , List <PropertyMigration >> properties = getPropertySourceMigrations (
68
71
ConfigurationMetadataProperty ::isDeprecated );
69
72
if (properties .isEmpty ()) {
70
73
return report ;
@@ -78,66 +81,72 @@ PropertiesMigrationReport getReport() {
78
81
return report ;
79
82
}
80
83
81
- private PropertySource <?> mapPropertiesWithReplacement (PropertiesMigrationReport report , String name ,
82
- List <PropertyMigration > properties ) {
83
- report .add (name , properties );
84
- List <PropertyMigration > renamed = properties .stream ().filter (PropertyMigration ::isCompatibleType ).toList ();
85
- if (renamed .isEmpty ()) {
86
- return null ;
87
- }
88
- NameTrackingPropertySource nameTrackingPropertySource = new NameTrackingPropertySource ();
89
- this .environment .getPropertySources ().addFirst (nameTrackingPropertySource );
90
- try {
91
- String target = "migrate-" + name ;
92
- Map <String , OriginTrackedValue > content = new LinkedHashMap <>();
93
- for (PropertyMigration candidate : renamed ) {
94
- String newPropertyName = candidate .getNewPropertyName ();
95
- Object value = candidate .getProperty ().getValue ();
96
- if (nameTrackingPropertySource .isPlaceholderThatAccessesName (value , newPropertyName )) {
97
- continue ;
98
- }
99
- OriginTrackedValue originTrackedValue = OriginTrackedValue .of (value ,
100
- candidate .getProperty ().getOrigin ());
101
- content .put (newPropertyName , originTrackedValue );
84
+ private Map <String , List <PropertyMigration >> getPropertySourceMigrations (
85
+ Predicate <ConfigurationMetadataProperty > filter ) {
86
+ return getPropertySourceMigrations (this .allProperties .values ().stream ().filter (filter ).toList ());
87
+ }
88
+
89
+ private Map <String , List <PropertyMigration >> getPropertySourceMigrations (
90
+ List <ConfigurationMetadataProperty > metadataProperties ) {
91
+ MultiValueMap <String , PropertyMigration > result = new LinkedMultiValueMap <>();
92
+ getPropertySourcesAsMap ().forEach ((propertySourceName , propertySource ) -> {
93
+ for (ConfigurationMetadataProperty metadataProperty : metadataProperties ) {
94
+ result .addAll (propertySourceName , getMigrations (propertySource , metadataProperty ));
102
95
}
103
- return new OriginTrackedMapPropertySource (target , content );
96
+ });
97
+ return result ;
98
+ }
99
+
100
+ private Map <String , ConfigurationPropertySource > getPropertySourcesAsMap () {
101
+ Map <String , ConfigurationPropertySource > map = new LinkedHashMap <>();
102
+ for (ConfigurationPropertySource source : ConfigurationPropertySources .get (this .environment )) {
103
+ map .put (determinePropertySourceName (source ), source );
104
104
}
105
- finally {
106
- this .environment .getPropertySources ().remove (nameTrackingPropertySource .getName ());
105
+ return map ;
106
+ }
107
+
108
+ private String determinePropertySourceName (ConfigurationPropertySource source ) {
109
+ if (source .getUnderlyingSource () instanceof PropertySource <?> underlyingSource ) {
110
+ return underlyingSource .getName ();
107
111
}
112
+ return source .getUnderlyingSource ().toString ();
108
113
}
109
114
110
- private boolean isMapType (ConfigurationMetadataProperty property ) {
111
- String type = property .getType ();
112
- return type != null && type .startsWith (Map .class .getName ());
115
+ private List <PropertyMigration > getMigrations (ConfigurationPropertySource propertySource ,
116
+ ConfigurationMetadataProperty metadataProperty ) {
117
+ ConfigurationPropertyName propertyName = asConfigurationPropertyName (metadataProperty );
118
+ List <PropertyMigration > migrations = new ArrayList <>();
119
+ addMigration (propertySource , metadataProperty , propertyName , false , migrations );
120
+ if (isMapType (metadataProperty ) && propertySource instanceof IterableConfigurationPropertySource iterable ) {
121
+ iterable .stream ()
122
+ .filter (propertyName ::isAncestorOf )
123
+ .forEach ((ancestorPropertyName ) -> addMigration (propertySource , metadataProperty , ancestorPropertyName ,
124
+ true , migrations ));
125
+ }
126
+ return migrations ;
113
127
}
114
128
115
- private Map <String , List <PropertyMigration >> getMatchingProperties (
116
- Predicate <ConfigurationMetadataProperty > filter ) {
117
- MultiValueMap <String , PropertyMigration > result = new LinkedMultiValueMap <>();
118
- List <ConfigurationMetadataProperty > candidates = this .allProperties .values ().stream ().filter (filter ).toList ();
119
- getPropertySourcesAsMap ().forEach ((propertySourceName , propertySource ) -> candidates .forEach ((metadata ) -> {
120
- ConfigurationPropertyName metadataName = ConfigurationPropertyName .isValid (metadata .getId ())
121
- ? ConfigurationPropertyName .of (metadata .getId ())
122
- : ConfigurationPropertyName .adapt (metadata .getId (), '.' );
123
- // Direct match
124
- ConfigurationProperty match = propertySource .getConfigurationProperty (metadataName );
125
- if (match != null ) {
126
- result .add (propertySourceName ,
127
- new PropertyMigration (match , metadata , determineReplacementMetadata (metadata ), false ));
128
- }
129
- // Prefix match for maps
130
- if (isMapType (metadata ) && propertySource instanceof IterableConfigurationPropertySource iterableSource ) {
131
- iterableSource .stream ()
132
- .filter (metadataName ::isAncestorOf )
133
- .map (propertySource ::getConfigurationProperty )
134
- .forEach ((property ) -> {
135
- ConfigurationMetadataProperty replacement = determineReplacementMetadata (metadata );
136
- result .add (propertySourceName , new PropertyMigration (property , metadata , replacement , true ));
137
- });
129
+ private ConfigurationPropertyName asConfigurationPropertyName (ConfigurationMetadataProperty metadataProperty ) {
130
+ return ConfigurationPropertyName .isValid (metadataProperty .getId ())
131
+ ? ConfigurationPropertyName .of (metadataProperty .getId ())
132
+ : ConfigurationPropertyName .adapt (metadataProperty .getId (), '.' );
133
+ }
134
+
135
+ private void addMigration (ConfigurationPropertySource propertySource ,
136
+ ConfigurationMetadataProperty metadataProperty , ConfigurationPropertyName propertyName ,
137
+ boolean mapMigration , List <PropertyMigration > migrations ) {
138
+ ConfigurationProperty property = propertySource .getConfigurationProperty (propertyName );
139
+ if (property != null ) {
140
+ ConfigurationMetadataProperty replacement = determineReplacementMetadata (metadataProperty );
141
+ if (replacement == null || !hasSameName (property , replacement )) {
142
+ migrations .add (new PropertyMigration (property , metadataProperty , replacement , mapMigration ));
138
143
}
139
- }));
140
- return result ;
144
+ }
145
+ }
146
+
147
+ private boolean hasSameName (ConfigurationProperty property , ConfigurationMetadataProperty replacement ) {
148
+ return (property .getOrigin () instanceof PropertySourceOrigin propertySourceOrigin )
149
+ && Objects .equals (propertySourceOrigin .getPropertyName (), replacement .getName ());
141
150
}
142
151
143
152
private ConfigurationMetadataProperty determineReplacementMetadata (ConfigurationMetadataProperty metadata ) {
@@ -164,19 +173,38 @@ private ConfigurationMetadataProperty detectMapValueReplacement(String fullId) {
164
173
return null ;
165
174
}
166
175
167
- private Map <String , ConfigurationPropertySource > getPropertySourcesAsMap () {
168
- Map <String , ConfigurationPropertySource > map = new LinkedHashMap <>();
169
- for (ConfigurationPropertySource source : ConfigurationPropertySources .get (this .environment )) {
170
- map .put (determinePropertySourceName (source ), source );
171
- }
172
- return map ;
176
+ private boolean isMapType (ConfigurationMetadataProperty property ) {
177
+ String type = property .getType ();
178
+ return type != null && type .startsWith (Map .class .getName ());
173
179
}
174
180
175
- private String determinePropertySourceName (ConfigurationPropertySource source ) {
176
- if (source .getUnderlyingSource () instanceof PropertySource ) {
177
- return ((PropertySource <?>) source .getUnderlyingSource ()).getName ();
181
+ private PropertySource <?> mapPropertiesWithReplacement (PropertiesMigrationReport report , String name ,
182
+ List <PropertyMigration > properties ) {
183
+ report .add (name , properties );
184
+ List <PropertyMigration > renamed = properties .stream ().filter (PropertyMigration ::isCompatibleType ).toList ();
185
+ if (renamed .isEmpty ()) {
186
+ return null ;
187
+ }
188
+ NameTrackingPropertySource nameTrackingPropertySource = new NameTrackingPropertySource ();
189
+ this .environment .getPropertySources ().addFirst (nameTrackingPropertySource );
190
+ try {
191
+ String target = "migrate-" + name ;
192
+ Map <String , OriginTrackedValue > content = new LinkedHashMap <>();
193
+ for (PropertyMigration candidate : renamed ) {
194
+ String newPropertyName = candidate .getNewPropertyName ();
195
+ Object value = candidate .getProperty ().getValue ();
196
+ if (nameTrackingPropertySource .isPlaceholderThatAccessesName (value , newPropertyName )) {
197
+ continue ;
198
+ }
199
+ OriginTrackedValue originTrackedValue = OriginTrackedValue .of (value ,
200
+ candidate .getProperty ().getOrigin ());
201
+ content .put (newPropertyName , originTrackedValue );
202
+ }
203
+ return new OriginTrackedMapPropertySource (target , content );
204
+ }
205
+ finally {
206
+ this .environment .getPropertySources ().remove (nameTrackingPropertySource .getName ());
178
207
}
179
- return source .getUnderlyingSource ().toString ();
180
208
}
181
209
182
210
/**
0 commit comments