• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TAKETODAY / today-infrastructure / 18154768944

01 Oct 2025 07:26AM UTC coverage: 81.882% (-0.005%) from 81.887%
18154768944

push

github

web-flow
Merge pull request #290 from TAKETODAY/dev/jspecify

jspecify

59788 of 78013 branches covered (76.64%)

Branch coverage included in aggregate %.

141239 of 167496 relevant lines covered (84.32%)

3.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.18
today-context/src/main/java/infra/context/properties/source/ConfigurationPropertySources.java
1
/*
2
 * Copyright 2017 - 2025 the original author or authors.
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see [https://www.gnu.org/licenses/]
16
 */
17

18
package infra.context.properties.source;
19

20
import org.jspecify.annotations.Nullable;
21

22
import java.util.Collections;
23
import java.util.stream.Stream;
24

25
import infra.core.env.ConfigurableEnvironment;
26
import infra.core.env.ConfigurablePropertyResolver;
27
import infra.core.env.Environment;
28
import infra.core.env.PropertyResolver;
29
import infra.core.env.PropertySource;
30
import infra.core.env.PropertySource.StubPropertySource;
31
import infra.core.env.PropertySources;
32
import infra.core.env.PropertySourcesPropertyResolver;
33

34
/**
35
 * Provides access to {@link ConfigurationPropertySource ConfigurationPropertySources}.
36
 *
37
 * @author Phillip Webb
38
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
39
 * @since 4.0
40
 */
41
public final class ConfigurationPropertySources {
42

43
  /**
44
   * The name of the {@link PropertySource} {@link #attach(ConfigurableEnvironment) adapter}.
45
   */
46
  private static final String ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties";
47

48
  private ConfigurationPropertySources() { }
49

50
  /**
51
   * Create a new {@link PropertyResolver} that resolves property values against an
52
   * underlying set of {@link PropertySources}. Provides an
53
   * {@link ConfigurationPropertySource} aware and optimized alternative to
54
   * {@link PropertySourcesPropertyResolver}.
55
   *
56
   * @param propertySources the set of {@link PropertySource} objects to use
57
   * @return a {@link ConfigurablePropertyResolver} implementation
58
   */
59
  public static ConfigurablePropertyResolver createPropertyResolver(PropertySources propertySources) {
60
    return new ConfigurationPropertySourcesPropertyResolver(propertySources);
5✔
61
  }
62

63
  /**
64
   * Determines if the specific {@link PropertySource} is the
65
   * {@link ConfigurationPropertySource} that was {@link #attach(ConfigurableEnvironment) attached}
66
   * to the {@link Environment}.
67
   *
68
   * @param propertySource the property source to test
69
   * @return {@code true} if this is the attached {@link ConfigurationPropertySource}
70
   */
71
  public static boolean isAttachedConfigurationPropertySource(PropertySource<?> propertySource) {
72
    return ATTACHED_PROPERTY_SOURCE_NAME.equals(propertySource.getName());
5✔
73
  }
74

75
  /**
76
   * Attach a {@link ConfigurationPropertySource} support to the specified
77
   * {@link Environment}. Adapts each {@link PropertySource} managed by the environment
78
   * to a {@link ConfigurationPropertySource} and allows classic
79
   * {@link PropertySourcesPropertyResolver} calls to resolve using
80
   * {@link ConfigurationPropertyName configuration property names}.
81
   * <p>
82
   * The attached resolver will dynamically track any additions or removals from the
83
   * underlying {@link Environment} property sources.
84
   *
85
   * @param environment the source environment (must be an instance of
86
   * {@link ConfigurableEnvironment})
87
   * @see #get(ConfigurableEnvironment)
88
   */
89
  public static void attach(ConfigurableEnvironment environment) {
90
    PropertySources sources = environment.getPropertySources();
3✔
91
    PropertySource<?> attached = getAttached(sources);
3✔
92
    if (attached == null || !isUsingSources(attached, sources)) {
6✔
93
      attached = new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
9✔
94
              new DefaultConfigurationPropertySources(sources));
95
    }
96
    sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
4✔
97
    sources.addFirst(attached);
3✔
98
  }
1✔
99

100
  private static boolean isUsingSources(PropertySource<?> attached, PropertySources sources) {
101
    return attached instanceof ConfigurationPropertySourcesPropertySource
5!
102
            && ((DefaultConfigurationPropertySources) attached.getSource()).isUsingSources(sources);
8✔
103
  }
104

105
  @Nullable
106
  static PropertySource<?> getAttached(@Nullable PropertySources sources) {
107
    return sources != null ? sources.get(ATTACHED_PROPERTY_SOURCE_NAME) : null;
7!
108
  }
109

110
  /**
111
   * Return a set of {@link ConfigurationPropertySource} instances that have previously
112
   * been {@link #attach(ConfigurableEnvironment) attached} to the {@link Environment}.
113
   *
114
   * @param environment the source environment (must be an instance of
115
   * {@link ConfigurableEnvironment})
116
   * @return an iterable set of configuration property sources
117
   * @throws IllegalStateException if not configuration property sources have been
118
   * attached
119
   */
120
  public static Iterable<ConfigurationPropertySource> get(ConfigurableEnvironment environment) {
121
    PropertySources sources = environment.getPropertySources();
3✔
122
    ConfigurationPropertySourcesPropertySource attached =
2✔
123
            (ConfigurationPropertySourcesPropertySource) sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
3✔
124
    if (attached == null) {
2✔
125
      return from(sources);
3✔
126
    }
127
    return attached.getSource();
4✔
128
  }
129

130
  /**
131
   * Return {@link Iterable} containing a single new {@link ConfigurationPropertySource}
132
   * adapted from the given Framework {@link PropertySource}.
133
   *
134
   * @param source the Framework property source to adapt
135
   * @return an {@link Iterable} containing a single newly adapted
136
   * {@link DefaultConfigurationPropertySource}
137
   */
138
  public static Iterable<ConfigurationPropertySource> from(PropertySource<?> source) {
139
    return Collections.singleton(ConfigurationPropertySource.from(source));
4✔
140
  }
141

142
  /**
143
   * Return {@link Iterable} containing new {@link ConfigurationPropertySource}
144
   * instances adapted from the given Framework {@link PropertySource PropertySources}.
145
   * <p>
146
   * This method will flatten any nested property sources and will filter all
147
   * {@link StubPropertySource stub property sources}. Updates to the underlying source,
148
   * identified by changes in the sources returned by its iterator, will be
149
   * automatically tracked. The underlying source should be thread safe, for example a
150
   * {@link PropertySources}
151
   *
152
   * @param sources the Framework property sources to adapt
153
   * @return an {@link Iterable} containing newly adapted
154
   * {@link DefaultConfigurationPropertySource} instances
155
   */
156
  public static Iterable<ConfigurationPropertySource> from(Iterable<PropertySource<?>> sources) {
157
    return new DefaultConfigurationPropertySources(sources);
5✔
158
  }
159

160
  private static Stream<PropertySource<?>> streamPropertySources(PropertySources sources) {
161
    return sources.stream().flatMap(ConfigurationPropertySources::flatten)
×
162
            .filter(ConfigurationPropertySources::isIncluded);
×
163
  }
164

165
  private static Stream<PropertySource<?>> flatten(PropertySource<?> source) {
166
    if (source.getSource() instanceof ConfigurableEnvironment) {
×
167
      return streamPropertySources(((ConfigurableEnvironment) source.getSource()).getPropertySources());
×
168
    }
169
    return Stream.of(source);
×
170
  }
171

172
  private static boolean isIncluded(PropertySource<?> source) {
173
    return !(source instanceof StubPropertySource)
×
174
            && !(source instanceof ConfigurationPropertySourcesPropertySource);
175
  }
176

177
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc