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

TAKETODAY / today-infrastructure / 15794111114

21 Jun 2025 08:54AM UTC coverage: 81.755% (+0.008%) from 81.747%
15794111114

Pull #286

github

web-flow
Merge e7915e795 into 8470e463d
Pull Request #286: 开发分支

59270 of 77451 branches covered (76.53%)

Branch coverage included in aggregate %.

140365 of 166736 relevant lines covered (84.18%)

3.6 hits per line

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

89.9
today-context/src/main/java/infra/context/properties/source/DefaultConfigurationPropertySource.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 java.util.Locale;
21
import java.util.Map;
22
import java.util.Random;
23

24
import infra.context.properties.source.ConfigurationPropertyName.Form;
25
import infra.core.env.EnumerablePropertySource;
26
import infra.core.env.PropertySource;
27
import infra.core.env.StandardEnvironment;
28
import infra.core.env.SystemEnvironmentPropertySource;
29
import infra.lang.Assert;
30
import infra.lang.Nullable;
31
import infra.origin.Origin;
32
import infra.origin.PropertySourceOrigin;
33

34
/**
35
 * {@link ConfigurationPropertySource} backed by a non-enumerable Framework
36
 * {@link PropertySource} or a restricted {@link EnumerablePropertySource} implementation
37
 * (such as a security restricted {@code systemEnvironment} source). A
38
 * {@link PropertySource} is adapted with the help of a {@link PropertyMapper} which
39
 * provides the mapping rules for individual properties.
40
 * <p>
41
 * Each {@link ConfigurationPropertySource#getConfigurationProperty
42
 * getConfigurationProperty} call attempts to
43
 * {@link PropertyMapper#map(ConfigurationPropertyName) map} the
44
 * {@link ConfigurationPropertyName} to one or more {@code String} based names. This
45
 * allows fast property resolution for well formed property sources.
46
 * <p>
47
 * When possible the {@link DefaultIterableConfigurationPropertySource} will be used in
48
 * preference to this implementation since it supports full "relaxed" style resolution.
49
 *
50
 * @author Phillip Webb
51
 * @author Madhura Bhave
52
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
53
 * @see #from(PropertySource)
54
 * @see PropertyMapper
55
 * @see DefaultIterableConfigurationPropertySource
56
 * @since 4.0
57
 */
58
class DefaultConfigurationPropertySource implements ConfigurationPropertySource {
59

60
  private static final PropertyMapper[] DEFAULT_MAPPERS = {
7✔
61
          DefaultPropertyMapper.INSTANCE
62
  };
63

64
  private static final PropertyMapper[] SYSTEM_ENVIRONMENT_MAPPERS = {
12✔
65
          SystemEnvironmentPropertyMapper.INSTANCE,
66
          DefaultPropertyMapper.INSTANCE
67
  };
68

69
  private final PropertySource<?> propertySource;
70

71
  private final boolean systemEnvironmentSource;
72

73
  private final PropertyMapper[] mappers;
74

75
  /**
76
   * Create a new {@link DefaultConfigurationPropertySource} implementation.
77
   *
78
   * @param propertySource the source property source
79
   * @param mappers the property mappers
80
   */
81
  DefaultConfigurationPropertySource(PropertySource<?> propertySource, boolean systemEnvironmentSource, PropertyMapper... mappers) {
2✔
82
    Assert.notNull(propertySource, "PropertySource is required");
3✔
83
    Assert.isTrue(mappers.length > 0, "Mappers must contain at least one item");
7!
84
    this.systemEnvironmentSource = systemEnvironmentSource;
3✔
85
    this.propertySource = propertySource;
3✔
86
    this.mappers = mappers;
3✔
87
  }
1✔
88

89
  @Nullable
90
  @Override
91
  public ConfigurationProperty getConfigurationProperty(@Nullable ConfigurationPropertyName name) {
92
    if (name == null) {
2!
93
      return null;
×
94
    }
95
    for (PropertyMapper mapper : this.mappers) {
17✔
96
      try {
97
        for (String candidate : mapper.map(name)) {
12✔
98
          Object value = getPropertySourceProperty(candidate);
4✔
99
          if (value != null) {
2✔
100
            Origin origin = PropertySourceOrigin.get(this.propertySource, candidate);
5✔
101
            return ConfigurationProperty.of(this, name, value, origin);
6✔
102
          }
103
        }
1✔
104
      }
105
      catch (Exception ignored) {
×
106
      }
1✔
107
    }
108
    return null;
2✔
109
  }
110

111
  @Nullable
112
  protected final Object getPropertySourceProperty(String name) {
113
    // Save calls to SystemEnvironmentPropertySource.resolvePropertyName(...)
114
    // since we've already done the mapping
115
    PropertySource<?> propertySource = getPropertySource();
3✔
116
    return (!this.systemEnvironmentSource) ? propertySource.getProperty(name)
8✔
117
            : getSystemEnvironmentProperty(((SystemEnvironmentPropertySource) propertySource).getSource(), name);
7✔
118
  }
119

120
  Object getSystemEnvironmentProperty(Map<String, Object> systemEnvironment, String name) {
121
    Object value = systemEnvironment.get(name);
×
122
    return value != null ? value : systemEnvironment.get(name.toLowerCase(Locale.ROOT));
×
123
  }
124

125
  @Override
126
  public ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name) {
127
    PropertySource<?> source = getPropertySource();
3✔
128
    if (source.getSource() instanceof Random) {
4✔
129
      return containsDescendantOfForRandom("random", name);
4✔
130
    }
131
    if (source.getSource() instanceof PropertySource<?>
5✔
132
            && ((PropertySource<?>) source.getSource()).getSource() instanceof Random) {
5!
133
      // Assume wrapped random sources use the source name as the prefix
134
      return containsDescendantOfForRandom(source.getName(), name);
5✔
135
    }
136
    return ConfigurationPropertyState.UNKNOWN;
2✔
137
  }
138

139
  private static ConfigurationPropertyState containsDescendantOfForRandom(
140
          String prefix, ConfigurationPropertyName name) {
141
    if (name.getNumberOfElements() > 1 && name.getElement(0, Form.DASHED).equals(prefix)) {
11✔
142
      return ConfigurationPropertyState.PRESENT;
2✔
143
    }
144
    return ConfigurationPropertyState.ABSENT;
2✔
145
  }
146

147
  @Override
148
  public Object getUnderlyingSource() {
149
    return this.propertySource;
3✔
150
  }
151

152
  protected PropertySource<?> getPropertySource() {
153
    return this.propertySource;
3✔
154
  }
155

156
  protected final boolean isSystemEnvironmentSource() {
157
    return this.systemEnvironmentSource;
3✔
158
  }
159

160
  protected final PropertyMapper[] getMappers() {
161
    return this.mappers;
3✔
162
  }
163

164
  @Override
165
  public String toString() {
166
    return this.propertySource.toString();
×
167
  }
168

169
  /**
170
   * Create a new {@link DefaultConfigurationPropertySource} for the specified
171
   * {@link PropertySource}.
172
   *
173
   * @param source the source Framework {@link PropertySource}
174
   * @return a {@link DefaultConfigurationPropertySource} or
175
   * {@link DefaultIterableConfigurationPropertySource} instance
176
   */
177
  static DefaultConfigurationPropertySource from(PropertySource<?> source) {
178
    Assert.notNull(source, "Source is required");
3✔
179
    boolean systemEnvironmentSource = isSystemEnvironmentPropertySource(source);
3✔
180
    PropertyMapper[] mappers = (!systemEnvironmentSource) ? DEFAULT_MAPPERS : SYSTEM_ENVIRONMENT_MAPPERS;
6✔
181
    return (!isFullEnumerable(source))
4✔
182
            ? new DefaultConfigurationPropertySource(source, systemEnvironmentSource, mappers)
7✔
183
            : new DefaultIterableConfigurationPropertySource((EnumerablePropertySource<?>) source,
7✔
184
                    systemEnvironmentSource, mappers);
185
  }
186

187
  private static boolean isSystemEnvironmentPropertySource(PropertySource<?> source) {
188
    String name = source.getName();
3✔
189
    return (source instanceof SystemEnvironmentPropertySource)
6✔
190
            && (StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME.equals(name)
4✔
191
            || name.endsWith("-" + StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME));
5✔
192
  }
193

194
  private static boolean isFullEnumerable(PropertySource<?> source) {
195
    PropertySource<?> rootSource = getRootSource(source);
3✔
196
    if (rootSource.getSource() instanceof Map map) {
9✔
197
      // Check we're not security restricted
198
      try {
199
        map.size();
3✔
200
      }
201
      catch (UnsupportedOperationException ex) {
1✔
202
        return false;
2✔
203
      }
1✔
204
    }
205
    return (source instanceof EnumerablePropertySource);
3✔
206
  }
207

208
  private static PropertySource<?> getRootSource(PropertySource<?> source) {
209
    while (source.getSource() instanceof PropertySource) {
4✔
210
      source = (PropertySource<?>) source.getSource();
5✔
211
    }
212
    return source;
2✔
213
  }
214

215
}
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