2525import java .util .regex .Pattern ;
2626import java .util .stream .Stream ;
2727
28+ import com .fasterxml .jackson .annotation .JsonInclude ;
29+
2830import org .springframework .boot .actuate .endpoint .Sanitizer ;
2931import org .springframework .boot .actuate .endpoint .annotation .Endpoint ;
3032import org .springframework .boot .actuate .endpoint .annotation .ReadOperation ;
3133import org .springframework .boot .actuate .endpoint .annotation .Selector ;
32- import org .springframework .boot .actuate .env .EnvironmentEndpoint .EnvironmentDescriptor .PropertySourceDescriptor ;
33- import org .springframework .boot .actuate .env .EnvironmentEndpoint .EnvironmentDescriptor .PropertySourceDescriptor .PropertyValueDescriptor ;
3434import org .springframework .boot .context .properties .bind .PlaceholdersResolver ;
3535import org .springframework .boot .context .properties .bind .PropertySourcesPlaceholdersResolver ;
36+ import org .springframework .boot .context .properties .source .ConfigurationPropertySources ;
3637import org .springframework .boot .origin .OriginLookup ;
3738import org .springframework .core .env .CompositePropertySource ;
3839import org .springframework .core .env .ConfigurableEnvironment ;
5455 * @author Phillip Webb
5556 * @author Christian Dupuis
5657 * @author Madhura Bhave
58+ * @author Stephane Nicoll
5759 * @since 2.0.0
5860 */
5961@ Endpoint (id = "env" )
@@ -80,8 +82,8 @@ public EnvironmentDescriptor environment(String pattern) {
8082 }
8183
8284 @ ReadOperation
83- public EnvironmentDescriptor environmentEntry (@ Selector String toMatch ) {
84- return getEnvironmentDescriptor (toMatch :: equals );
85+ public EnvironmentEntryDescriptor environmentEntry (@ Selector String toMatch ) {
86+ return getEnvironmentEntryDescriptor (toMatch );
8587 }
8688
8789 private EnvironmentDescriptor getEnvironmentDescriptor (
@@ -99,6 +101,46 @@ private EnvironmentDescriptor getEnvironmentDescriptor(
99101 Arrays .asList (this .environment .getActiveProfiles ()), propertySources );
100102 }
101103
104+ private EnvironmentEntryDescriptor getEnvironmentEntryDescriptor (
105+ String propertyName ) {
106+ Map <String , PropertyValueDescriptor > descriptors = getPropertySourceDescriptors (
107+ propertyName );
108+ PropertySummaryDescriptor summary = getPropertySummaryDescriptor (descriptors );
109+ return new EnvironmentEntryDescriptor (summary ,
110+ Arrays .asList (this .environment .getActiveProfiles ()),
111+ toPropertySourceDescriptors (descriptors ));
112+ }
113+
114+ private List <PropertySourceEntryDescriptor > toPropertySourceDescriptors (
115+ Map <String , PropertyValueDescriptor > descriptors ) {
116+ List <PropertySourceEntryDescriptor > result = new ArrayList <>();
117+ for (Map .Entry <String , PropertyValueDescriptor > entry : descriptors .entrySet ()) {
118+ result .add (new PropertySourceEntryDescriptor (entry .getKey (), entry .getValue ()));
119+ }
120+ return result ;
121+ }
122+
123+ private PropertySummaryDescriptor getPropertySummaryDescriptor (
124+ Map <String , PropertyValueDescriptor > descriptors ) {
125+ for (Map .Entry <String , PropertyValueDescriptor > entry : descriptors .entrySet ()) {
126+ if (entry .getValue () != null ) {
127+ return new PropertySummaryDescriptor (entry .getKey (),
128+ entry .getValue ().getValue ());
129+ }
130+ }
131+ return null ;
132+ }
133+
134+ private Map <String , PropertyValueDescriptor > getPropertySourceDescriptors (
135+ String propertyName ) {
136+ Map <String , PropertyValueDescriptor > propertySources = new LinkedHashMap <>();
137+ PlaceholdersResolver resolver = getResolver ();
138+ getPropertySourcesAsMap ().forEach ((sourceName , source ) ->
139+ propertySources .put (sourceName , source .containsProperty (propertyName ) ?
140+ describeValueOf (propertyName , source , resolver ) : null ));
141+ return propertySources ;
142+ }
143+
102144 private PropertySourceDescriptor describeSource (String sourceName ,
103145 EnumerablePropertySource <?> source , PlaceholdersResolver resolver ,
104146 Predicate <String > namePredicate ) {
@@ -109,7 +151,7 @@ private PropertySourceDescriptor describeSource(String sourceName,
109151 }
110152
111153 private PropertyValueDescriptor describeValueOf (String name ,
112- EnumerablePropertySource <?> source , PlaceholdersResolver resolver ) {
154+ PropertySource <?> source , PlaceholdersResolver resolver ) {
113155 Object resolved = resolver .resolvePlaceholders (source .getProperty (name ));
114156 @ SuppressWarnings ("unchecked" )
115157 String origin = (source instanceof OriginLookup )
@@ -125,7 +167,9 @@ private PlaceholdersResolver getResolver() {
125167 private Map <String , PropertySource <?>> getPropertySourcesAsMap () {
126168 Map <String , PropertySource <?>> map = new LinkedHashMap <>();
127169 for (PropertySource <?> source : getPropertySources ()) {
128- extract ("" , map , source );
170+ if (!ConfigurationPropertySources .isMainConfigurationPropertySource (source )) {
171+ extract ("" , map , source );
172+ }
129173 }
130174 return map ;
131175 }
@@ -208,54 +252,141 @@ public List<PropertySourceDescriptor> getPropertySources() {
208252 return this .propertySources ;
209253 }
210254
211- /**
212- * A description of a {@link PropertySource}.
213- */
214- public static final class PropertySourceDescriptor {
255+ }
215256
216- private final String name ;
257+ /**
258+ * A description of an entry of the {@link Environment}.
259+ */
260+ @ JsonInclude (JsonInclude .Include .NON_NULL )
261+ public static final class EnvironmentEntryDescriptor {
217262
218- private final Map < String , PropertyValueDescriptor > properties ;
263+ private final PropertySummaryDescriptor property ;
219264
220- private PropertySourceDescriptor (String name ,
221- Map <String , PropertyValueDescriptor > properties ) {
222- this .name = name ;
223- this .properties = properties ;
224- }
265+ private final List <String > activeProfiles ;
225266
226- public String getName () {
227- return this .name ;
228- }
267+ private final List <PropertySourceEntryDescriptor > propertySources ;
229268
230- public Map <String , PropertyValueDescriptor > getProperties () {
231- return this .properties ;
232- }
269+ private EnvironmentEntryDescriptor (PropertySummaryDescriptor property ,
270+ List <String > activeProfiles ,
271+ List <PropertySourceEntryDescriptor > propertySources ) {
272+ this .property = property ;
273+ this .activeProfiles = activeProfiles ;
274+ this .propertySources = propertySources ;
275+ }
233276
234- /**
235- * A description of a property's value, including its origin if available.
236- */
237- public static final class PropertyValueDescriptor {
277+ public PropertySummaryDescriptor getProperty () {
278+ return this .property ;
279+ }
238280
239- private final Object value ;
281+ public List <String > getActiveProfiles () {
282+ return this .activeProfiles ;
283+ }
240284
241- private final String origin ;
285+ public List <PropertySourceEntryDescriptor > getPropertySources () {
286+ return this .propertySources ;
287+ }
242288
243- private PropertyValueDescriptor (Object value , String origin ) {
244- this .value = value ;
245- this .origin = origin ;
246- }
289+ }
247290
248- public Object getValue () {
249- return this .value ;
250- }
291+ /**
292+ * A summary of a particular entry of the {@link Environment}.
293+ */
294+ @ JsonInclude (JsonInclude .Include .NON_NULL )
295+ public static final class PropertySummaryDescriptor {
251296
252- public String getOrigin () {
253- return this .origin ;
254- }
297+ private final String source ;
255298
256- }
299+ private final Object value ;
300+
301+ public PropertySummaryDescriptor (String source , Object value ) {
302+ this .source = source ;
303+ this .value = value ;
304+ }
305+
306+ public String getSource () {
307+ return this .source ;
308+ }
309+
310+ public Object getValue () {
311+ return this .value ;
312+ }
313+
314+ }
315+
316+ /**
317+ * A description of a particular entry of {@link PropertySource}.
318+ */
319+ @ JsonInclude (JsonInclude .Include .NON_NULL )
320+ public static final class PropertySourceEntryDescriptor {
321+
322+ private final String name ;
323+
324+ private final PropertyValueDescriptor property ;
325+
326+ private PropertySourceEntryDescriptor (String name ,
327+ PropertyValueDescriptor property ) {
328+ this .name = name ;
329+ this .property = property ;
330+ }
257331
332+ public String getName () {
333+ return this .name ;
258334 }
335+
336+ public PropertyValueDescriptor getProperty () {
337+ return this .property ;
338+ }
339+
340+ }
341+
342+ /**
343+ * A description of a {@link PropertySource}.
344+ */
345+ public static final class PropertySourceDescriptor {
346+
347+ private final String name ;
348+
349+ private final Map <String , PropertyValueDescriptor > properties ;
350+
351+ private PropertySourceDescriptor (String name ,
352+ Map <String , PropertyValueDescriptor > properties ) {
353+ this .name = name ;
354+ this .properties = properties ;
355+ }
356+
357+ public String getName () {
358+ return this .name ;
359+ }
360+
361+ public Map <String , PropertyValueDescriptor > getProperties () {
362+ return this .properties ;
363+ }
364+
365+ }
366+
367+ /**
368+ * A description of a property's value, including its origin if available.
369+ */
370+ @ JsonInclude (JsonInclude .Include .NON_NULL )
371+ public static final class PropertyValueDescriptor {
372+
373+ private final Object value ;
374+
375+ private final String origin ;
376+
377+ private PropertyValueDescriptor (Object value , String origin ) {
378+ this .value = value ;
379+ this .origin = origin ;
380+ }
381+
382+ public Object getValue () {
383+ return this .value ;
384+ }
385+
386+ public String getOrigin () {
387+ return this .origin ;
388+ }
389+
259390 }
260391
261392 /**
0 commit comments