54
54
import org .springframework .boot .actuate .endpoint .Sanitizer ;
55
55
import org .springframework .boot .actuate .endpoint .annotation .Endpoint ;
56
56
import org .springframework .boot .actuate .endpoint .annotation .ReadOperation ;
57
+ import org .springframework .boot .context .properties .BoundConfigurationProperties ;
57
58
import org .springframework .boot .context .properties .ConfigurationProperties ;
58
59
import org .springframework .boot .context .properties .ConfigurationPropertiesBean ;
59
- import org .springframework .boot .context .properties .ConfigurationPropertiesBoundPropertiesHolder ;
60
60
import org .springframework .boot .context .properties .ConstructorBinding ;
61
61
import org .springframework .boot .context .properties .source .ConfigurationProperty ;
62
62
import org .springframework .boot .context .properties .source .ConfigurationPropertyName ;
@@ -111,46 +111,22 @@ public ApplicationConfigurationProperties configurationProperties() {
111
111
}
112
112
113
113
private ApplicationConfigurationProperties extract (ApplicationContext context ) {
114
- Map <String , ContextConfigurationProperties > contextProperties = new HashMap <>();
114
+ ObjectMapper mapper = getObjectMapper ();
115
+ Map <String , ContextConfigurationProperties > contexts = new HashMap <>();
115
116
ApplicationContext target = context ;
116
117
while (target != null ) {
117
- contextProperties .put (target .getId (), describeConfigurationProperties ( target , getObjectMapper () ));
118
+ contexts .put (target .getId (), describeBeans ( mapper , target ));
118
119
target = target .getParent ();
119
120
}
120
- return new ApplicationConfigurationProperties (contextProperties );
121
+ return new ApplicationConfigurationProperties (contexts );
121
122
}
122
123
123
- private ContextConfigurationProperties describeConfigurationProperties (ApplicationContext context ,
124
- ObjectMapper mapper ) {
125
- Map <String , ConfigurationPropertiesBean > beans = ConfigurationPropertiesBean .getAll (context );
126
- Map <String , ConfigurationPropertiesBeanDescriptor > descriptors = new HashMap <>();
127
- beans .forEach ((beanName , bean ) -> {
128
- String prefix = bean .getAnnotation ().prefix ();
129
- descriptors .put (beanName ,
130
- new ConfigurationPropertiesBeanDescriptor (prefix ,
131
- sanitize (prefix , safeSerialize (mapper , bean .getInstance (), prefix )),
132
- getInputs (prefix , safeSerialize (mapper , bean .getInstance (), prefix ))));
133
- });
134
- return new ContextConfigurationProperties (descriptors ,
135
- (context .getParent () != null ) ? context .getParent ().getId () : null );
136
- }
137
-
138
- /**
139
- * Cautiously serialize the bean to a map (returning a map with an error message
140
- * instead of throwing an exception if there is a problem).
141
- * @param mapper the object mapper
142
- * @param bean the source bean
143
- * @param prefix the prefix
144
- * @return the serialized instance
145
- */
146
- @ SuppressWarnings ("unchecked" )
147
- private Map <String , Object > safeSerialize (ObjectMapper mapper , Object bean , String prefix ) {
148
- try {
149
- return new HashMap <>(mapper .convertValue (bean , Map .class ));
150
- }
151
- catch (Exception ex ) {
152
- return new HashMap <>(Collections .singletonMap ("error" , "Cannot serialize '" + prefix + "'" ));
124
+ private ObjectMapper getObjectMapper () {
125
+ if (this .objectMapper == null ) {
126
+ this .objectMapper = new ObjectMapper ();
127
+ configureObjectMapper (this .objectMapper );
153
128
}
129
+ return this .objectMapper ;
154
130
}
155
131
156
132
/**
@@ -170,12 +146,10 @@ protected void configureObjectMapper(ObjectMapper mapper) {
170
146
mapper .registerModule (new JavaTimeModule ());
171
147
}
172
148
173
- private ObjectMapper getObjectMapper () {
174
- if (this .objectMapper == null ) {
175
- this .objectMapper = new ObjectMapper ();
176
- configureObjectMapper (this .objectMapper );
177
- }
178
- return this .objectMapper ;
149
+ private void applyConfigurationPropertiesFilter (ObjectMapper mapper ) {
150
+ mapper .setAnnotationIntrospector (new ConfigurationPropertiesAnnotationIntrospector ());
151
+ mapper .setFilterProvider (
152
+ new SimpleFilterProvider ().setDefaultFilter (new ConfigurationPropertiesPropertyFilter ()));
179
153
}
180
154
181
155
/**
@@ -188,10 +162,38 @@ private void applySerializationModifier(ObjectMapper mapper) {
188
162
mapper .setSerializerFactory (factory );
189
163
}
190
164
191
- private void applyConfigurationPropertiesFilter (ObjectMapper mapper ) {
192
- mapper .setAnnotationIntrospector (new ConfigurationPropertiesAnnotationIntrospector ());
193
- mapper .setFilterProvider (
194
- new SimpleFilterProvider ().setDefaultFilter (new ConfigurationPropertiesPropertyFilter ()));
165
+ private ContextConfigurationProperties describeBeans (ObjectMapper mapper , ApplicationContext context ) {
166
+ Map <String , ConfigurationPropertiesBean > beans = ConfigurationPropertiesBean .getAll (context );
167
+ Map <String , ConfigurationPropertiesBeanDescriptor > descriptors = new HashMap <>();
168
+ beans .forEach ((beanName , bean ) -> descriptors .put (beanName , describeBean (mapper , bean )));
169
+ return new ContextConfigurationProperties (descriptors ,
170
+ (context .getParent () != null ) ? context .getParent ().getId () : null );
171
+ }
172
+
173
+ private ConfigurationPropertiesBeanDescriptor describeBean (ObjectMapper mapper , ConfigurationPropertiesBean bean ) {
174
+ String prefix = bean .getAnnotation ().prefix ();
175
+ Map <String , Object > serialized = safeSerialize (mapper , bean .getInstance (), prefix );
176
+ Map <String , Object > properties = sanitize (prefix , serialized );
177
+ Map <String , Object > inputs = getInputs (prefix , serialized );
178
+ return new ConfigurationPropertiesBeanDescriptor (prefix , properties , inputs );
179
+ }
180
+
181
+ /**
182
+ * Cautiously serialize the bean to a map (returning a map with an error message
183
+ * instead of throwing an exception if there is a problem).
184
+ * @param mapper the object mapper
185
+ * @param bean the source bean
186
+ * @param prefix the prefix
187
+ * @return the serialized instance
188
+ */
189
+ @ SuppressWarnings ("unchecked" )
190
+ private Map <String , Object > safeSerialize (ObjectMapper mapper , Object bean , String prefix ) {
191
+ try {
192
+ return new HashMap <>(mapper .convertValue (bean , Map .class ));
193
+ }
194
+ catch (Exception ex ) {
195
+ return new HashMap <>(Collections .singletonMap ("error" , "Cannot serialize '" + prefix + "'" ));
196
+ }
195
197
}
196
198
197
199
/**
@@ -204,7 +206,7 @@ private void applyConfigurationPropertiesFilter(ObjectMapper mapper) {
204
206
@ SuppressWarnings ("unchecked" )
205
207
private Map <String , Object > sanitize (String prefix , Map <String , Object > map ) {
206
208
map .forEach ((key , value ) -> {
207
- String qualifiedKey = (prefix . isEmpty () ? prefix : prefix + "." ) + key ;
209
+ String qualifiedKey = getQualifiedKey (prefix , key ) ;
208
210
if (value instanceof Map ) {
209
211
map .put (key , sanitize (qualifiedKey , (Map <String , Object >) value ));
210
212
}
@@ -239,19 +241,20 @@ else if (item instanceof List) {
239
241
240
242
@ SuppressWarnings ("unchecked" )
241
243
private Map <String , Object > getInputs (String prefix , Map <String , Object > map ) {
244
+ Map <String , Object > augmented = new LinkedHashMap <>(map );
242
245
map .forEach ((key , value ) -> {
243
- String qualifiedKey = (prefix . isEmpty () ? prefix : prefix + "." ) + key ;
246
+ String qualifiedKey = getQualifiedKey (prefix , key ) ;
244
247
if (value instanceof Map ) {
245
- map .put (key , getInputs (qualifiedKey , (Map <String , Object >) value ));
248
+ augmented .put (key , getInputs (qualifiedKey , (Map <String , Object >) value ));
246
249
}
247
250
else if (value instanceof List ) {
248
- map .put (key , getInputs (qualifiedKey , (List <Object >) value ));
251
+ augmented .put (key , getInputs (qualifiedKey , (List <Object >) value ));
249
252
}
250
253
else {
251
- map .put (key , applyInput (qualifiedKey ));
254
+ augmented .put (key , applyInput (qualifiedKey ));
252
255
}
253
256
});
254
- return map ;
257
+ return augmented ;
255
258
}
256
259
257
260
@ SuppressWarnings ("unchecked" )
@@ -274,17 +277,14 @@ else if (item instanceof List) {
274
277
}
275
278
276
279
private Map <String , Object > applyInput (String qualifiedKey ) {
277
- if (!this .context .containsBean (ConfigurationPropertiesBoundPropertiesHolder .BEAN_NAME )) {
280
+ BoundConfigurationProperties bound = BoundConfigurationProperties .get (this .context );
281
+ if (bound == null ) {
278
282
return Collections .emptyMap ();
279
283
}
280
- ConfigurationPropertiesBoundPropertiesHolder bean = this .context .getBean (
281
- ConfigurationPropertiesBoundPropertiesHolder .BEAN_NAME ,
282
- ConfigurationPropertiesBoundPropertiesHolder .class );
283
- Map <ConfigurationPropertyName , ConfigurationProperty > boundProperties = bean .getProperties ();
284
284
ConfigurationPropertyName currentName = ConfigurationPropertyName .adapt (qualifiedKey , '.' );
285
- ConfigurationProperty candidate = boundProperties .get (currentName );
285
+ ConfigurationProperty candidate = bound .get (currentName );
286
286
if (candidate == null && currentName .isLastElementIndexed ()) {
287
- candidate = boundProperties .get (currentName .chop (currentName .getNumberOfElements () - 1 ));
287
+ candidate = bound .get (currentName .chop (currentName .getNumberOfElements () - 1 ));
288
288
}
289
289
return (candidate != null ) ? getInput (currentName .toString (), candidate ) : Collections .emptyMap ();
290
290
}
@@ -298,11 +298,14 @@ private Map<String, Object> getInput(String property, ConfigurationProperty cand
298
298
return input ;
299
299
}
300
300
301
+ private String getQualifiedKey (String prefix , String key ) {
302
+ return (prefix .isEmpty () ? prefix : prefix + "." ) + key ;
303
+ }
304
+
301
305
/**
302
306
* Extension to {@link JacksonAnnotationIntrospector} to suppress CGLIB generated bean
303
307
* properties.
304
308
*/
305
- @ SuppressWarnings ("serial" )
306
309
private static class ConfigurationPropertiesAnnotationIntrospector extends JacksonAnnotationIntrospector {
307
310
308
311
@ Override
0 commit comments