Browse Source
Refactor `ConfigFileApplicationListener` to use a `MultiValueMap` when loading sources. The helps to simplify the code and removes the need for the inner `LoadedPropertySources` class. We're also able to delete the now unused `EnumerableCompositePropertySource` and `PropertySourcesLoader` classes. Fixes gh-9144pull/9145/head
5 changed files with 160 additions and 566 deletions
@ -1,78 +0,0 @@
@@ -1,78 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.env; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.List; |
||||
|
||||
import org.springframework.core.env.EnumerablePropertySource; |
||||
import org.springframework.core.env.PropertySource; |
||||
|
||||
/** |
||||
* An mutable, enumerable, composite property source. New sources are added last (and |
||||
* hence resolved with lowest priority). |
||||
* |
||||
* @author Dave Syer |
||||
* @see PropertySource |
||||
* @see EnumerablePropertySource |
||||
*/ |
||||
public class EnumerableCompositePropertySource |
||||
extends EnumerablePropertySource<Collection<PropertySource<?>>> { |
||||
|
||||
private volatile String[] names; |
||||
|
||||
public EnumerableCompositePropertySource(String sourceName) { |
||||
super(sourceName, new LinkedHashSet<PropertySource<?>>()); |
||||
} |
||||
|
||||
@Override |
||||
public Object getProperty(String name) { |
||||
for (PropertySource<?> propertySource : getSource()) { |
||||
Object value = propertySource.getProperty(name); |
||||
if (value != null) { |
||||
return value; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public String[] getPropertyNames() { |
||||
String[] result = this.names; |
||||
if (result == null) { |
||||
List<String> names = new ArrayList<>(); |
||||
for (PropertySource<?> source : new ArrayList<>(getSource())) { |
||||
if (source instanceof EnumerablePropertySource) { |
||||
names.addAll(Arrays.asList( |
||||
((EnumerablePropertySource<?>) source).getPropertyNames())); |
||||
} |
||||
} |
||||
this.names = names.toArray(new String[0]); |
||||
result = this.names; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public void add(PropertySource<?> source) { |
||||
getSource().add(source); |
||||
this.names = null; |
||||
} |
||||
|
||||
} |
||||
@ -1,210 +0,0 @@
@@ -1,210 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.env; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.Arrays; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import org.springframework.core.env.MutablePropertySources; |
||||
import org.springframework.core.env.PropertySource; |
||||
import org.springframework.core.io.Resource; |
||||
import org.springframework.core.io.support.SpringFactoriesLoader; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* Utility that can be used to update {@link MutablePropertySources} using |
||||
* {@link PropertySourceLoader PropertySourceLoaders}. |
||||
* |
||||
* @author Phillip Webb |
||||
*/ |
||||
public class PropertySourcesLoader { |
||||
|
||||
private static final Log logger = LogFactory.getLog(PropertySourcesLoader.class); |
||||
|
||||
private final MutablePropertySources propertySources; |
||||
|
||||
private final List<PropertySourceLoader> loaders; |
||||
|
||||
/** |
||||
* Create a new {@link PropertySourceLoader} instance backed by a new |
||||
* {@link MutablePropertySources}. |
||||
*/ |
||||
public PropertySourcesLoader() { |
||||
this(new MutablePropertySources()); |
||||
} |
||||
|
||||
/** |
||||
* Create a new {@link PropertySourceLoader} instance backed by the specified |
||||
* {@link MutablePropertySources}. |
||||
* @param propertySources the destination property sources |
||||
*/ |
||||
public PropertySourcesLoader(MutablePropertySources propertySources) { |
||||
Assert.notNull(propertySources, "PropertySources must not be null"); |
||||
this.propertySources = propertySources; |
||||
this.loaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, |
||||
getClass().getClassLoader()); |
||||
} |
||||
|
||||
/** |
||||
* Load the specified resource (if possible) and add it as the first source. |
||||
* @param resource the source resource (may be {@code null}). |
||||
* @return the loaded property source or {@code null} |
||||
* @throws IOException if the source cannot be loaded |
||||
*/ |
||||
public PropertySource<?> load(Resource resource) throws IOException { |
||||
return load(resource, null); |
||||
} |
||||
|
||||
/** |
||||
* Load the profile-specific properties from the specified resource (if any) and add |
||||
* it as the first source. |
||||
* @param resource the source resource (may be {@code null}). |
||||
* @param profile a specific profile to load or {@code null} to load the default. |
||||
* @return the loaded property source or {@code null} |
||||
* @throws IOException if the source cannot be loaded |
||||
*/ |
||||
public PropertySource<?> load(Resource resource, String profile) throws IOException { |
||||
return load(resource, resource.getDescription(), profile); |
||||
} |
||||
|
||||
/** |
||||
* Load the profile-specific properties from the specified resource (if any), give the |
||||
* name provided and add it as the first source. |
||||
* @param resource the source resource (may be {@code null}). |
||||
* @param name the root property name (may be {@code null}). |
||||
* @param profile a specific profile to load or {@code null} to load the default. |
||||
* @return the loaded property source or {@code null} |
||||
* @throws IOException if the source cannot be loaded |
||||
*/ |
||||
public PropertySource<?> load(Resource resource, String name, String profile) |
||||
throws IOException { |
||||
return load(resource, null, name, profile); |
||||
} |
||||
|
||||
/** |
||||
* Load the profile-specific properties from the specified resource (if any), give the |
||||
* name provided and add it to a group of property sources identified by the group |
||||
* name. Property sources are added to the end of a group, but new groups are added as |
||||
* the first in the chain being assembled. This means the normal sequence of calls is |
||||
* to first create the group for the default (null) profile, and then add specific |
||||
* groups afterwards (with the highest priority last). Property resolution from the |
||||
* resulting sources will consider all keys for a given group first and then move to |
||||
* the next group. |
||||
* @param resource the source resource (may be {@code null}). |
||||
* @param group an identifier for the group that this source belongs to |
||||
* @param name the root property name (may be {@code null}). |
||||
* @param profile a specific profile to load or {@code null} to load the default. |
||||
* @return the loaded property source or {@code null} |
||||
* @throws IOException if the source cannot be loaded |
||||
*/ |
||||
public PropertySource<?> load(Resource resource, String group, String name, |
||||
String profile) throws IOException { |
||||
if (isFile(resource)) { |
||||
String sourceName = generatePropertySourceName(name, profile); |
||||
for (PropertySourceLoader loader : this.loaders) { |
||||
if (canLoadFileExtension(loader, resource)) { |
||||
PropertySource<?> specific = loader.load(sourceName, resource, |
||||
profile); |
||||
addPropertySource(group, specific, profile); |
||||
return specific; |
||||
} |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private boolean isFile(Resource resource) { |
||||
return resource != null && resource.exists() && StringUtils |
||||
.hasText(StringUtils.getFilenameExtension(resource.getFilename())); |
||||
} |
||||
|
||||
private String generatePropertySourceName(String name, String profile) { |
||||
return (profile == null ? name : name + "#" + profile); |
||||
} |
||||
|
||||
private boolean canLoadFileExtension(PropertySourceLoader loader, Resource resource) { |
||||
String filename = resource.getFilename().toLowerCase(); |
||||
for (String extension : loader.getFileExtensions()) { |
||||
if (filename.endsWith("." + extension.toLowerCase())) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private void addPropertySource(String basename, PropertySource<?> source, |
||||
String profile) { |
||||
|
||||
if (source == null) { |
||||
return; |
||||
} |
||||
|
||||
if (basename == null) { |
||||
this.propertySources.addLast(source); |
||||
return; |
||||
} |
||||
|
||||
EnumerableCompositePropertySource group = getGeneric(basename); |
||||
group.add(source); |
||||
logger.trace("Adding PropertySource: " + source + " in group: " + basename); |
||||
if (this.propertySources.contains(group.getName())) { |
||||
this.propertySources.replace(group.getName(), group); |
||||
} |
||||
else { |
||||
this.propertySources.addFirst(group); |
||||
} |
||||
|
||||
} |
||||
|
||||
private EnumerableCompositePropertySource getGeneric(String name) { |
||||
PropertySource<?> source = this.propertySources.get(name); |
||||
if (source instanceof EnumerableCompositePropertySource) { |
||||
return (EnumerableCompositePropertySource) source; |
||||
} |
||||
EnumerableCompositePropertySource composite = new EnumerableCompositePropertySource( |
||||
name); |
||||
return composite; |
||||
} |
||||
|
||||
/** |
||||
* Return the {@link MutablePropertySources} being loaded. |
||||
* @return the property sources |
||||
*/ |
||||
public MutablePropertySources getPropertySources() { |
||||
return this.propertySources; |
||||
} |
||||
|
||||
/** |
||||
* Returns all file extensions that could be loaded. |
||||
* @return the file extensions |
||||
*/ |
||||
public Set<String> getAllFileExtensions() { |
||||
Set<String> fileExtensions = new LinkedHashSet<>(); |
||||
for (PropertySourceLoader loader : this.loaders) { |
||||
fileExtensions.addAll(Arrays.asList(loader.getFileExtensions())); |
||||
} |
||||
return fileExtensions; |
||||
} |
||||
|
||||
} |
||||
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
/* |
||||
* Copyright 2012-2016 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.env; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link PropertySourcesLoader}. |
||||
* |
||||
* @author Dave Syer |
||||
*/ |
||||
public class PropertySourcesLoaderTests { |
||||
|
||||
private PropertySourcesLoader loader = new PropertySourcesLoader(); |
||||
|
||||
@Test |
||||
public void fileExtensions() { |
||||
assertThat(this.loader.getAllFileExtensions()).containsOnly("yml", "yaml", |
||||
"properties", "xml"); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue