Merge branch '2.0.x'

This commit is contained in:
Madhura Bhave 2018-04-18 10:28:44 -07:00
commit a8707c520c
2 changed files with 47 additions and 88 deletions

View File

@ -26,7 +26,6 @@ import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
@ -302,7 +301,7 @@ public class ConfigFileApplicationListener
private final List<PropertySourceLoader> propertySourceLoaders;
private Queue<Profile> profiles;
private LinkedList<Profile> profiles;
private List<Profile> processedProfiles;
@ -321,7 +320,7 @@ public class ConfigFileApplicationListener
}
public void load() {
this.profiles = Collections.asLifoQueue(new LinkedList<Profile>());
this.profiles = new LinkedList<>();
this.processedProfiles = new LinkedList<>();
this.activatedProfiles = false;
this.loaded = new LinkedHashMap<>();
@ -343,62 +342,62 @@ public class ConfigFileApplicationListener
* properties that are already set.
*/
private void initializeProfiles() {
Set<Profile> initialActiveProfiles = initializeActiveProfiles();
this.profiles.addAll(getUnprocessedActiveProfiles(initialActiveProfiles));
if (this.profiles.isEmpty()) {
//The default profile for these purposes is represented as null. We add it
// first so that it is processed first and has lowest priority.
this.profiles.add(null);
Set<Profile> activatedViaProperty = getProfilesActivatedViaActiveProfileProperty();
processOtherActiveProfiles(activatedViaProperty);
// Any pre-existing active activeProfiles set via property sources (e.g. System
// properties) take precedence over those added in config files.
addActiveProfiles(activatedViaProperty);
if (this.profiles.size() == 1) { //only has null profile
for (String defaultProfileName : this.environment.getDefaultProfiles()) {
Profile defaultProfile = new Profile(defaultProfileName, true);
if (!this.profiles.contains(defaultProfile)) {
this.profiles.add(defaultProfile);
}
ConfigFileApplicationListener.Profile defaultProfile = new ConfigFileApplicationListener.Profile(
defaultProfileName, true);
this.profiles.add(defaultProfile);
}
}
// The default profile for these purposes is represented as null. We add it
// last so that it is first out of the queue (active profiles will then
// override any settings in the defaults when the list is reversed later).
this.profiles.add(null);
}
private Set<Profile> initializeActiveProfiles() {
private Set<Profile> getProfilesActivatedViaActiveProfileProperty() {
if (!this.environment.containsProperty(ACTIVE_PROFILES_PROPERTY)
&& !this.environment.containsProperty(INCLUDE_PROFILES_PROPERTY)) {
return Collections.emptySet();
}
// Any pre-existing active profiles set via property sources (e.g. System
// properties) take precedence over those added in config files.
Binder binder = Binder.get(this.environment);
Set<Profile> activeProfiles = new LinkedHashSet<>();
activeProfiles.addAll(getProfiles(binder, ACTIVE_PROFILES_PROPERTY));
activeProfiles.addAll(getProfiles(binder, INCLUDE_PROFILES_PROPERTY));
maybeActivateProfiles(activeProfiles);
return activeProfiles;
}
/**
* Return the active profiles that have not been processed yet. If a profile is
* enabled via both {@link #ACTIVE_PROFILES_PROPERTY} and
* {@link ConfigurableEnvironment#addActiveProfile(String)} it needs to be
* filtered so that the {@link #ACTIVE_PROFILES_PROPERTY} value takes precedence.
* <p>
* Concretely, if the "cloud" profile is enabled via the environment, it will take
* less precedence that any profile set via the {@link #ACTIVE_PROFILES_PROPERTY}.
* @param initialActiveProfiles the profiles that have been enabled via
* {@link #ACTIVE_PROFILES_PROPERTY}
* @return the unprocessed active profiles from the environment to enable
*/
private List<Profile> getUnprocessedActiveProfiles(
Set<Profile> initialActiveProfiles) {
List<Profile> unprocessedActiveProfiles = new ArrayList<>();
for (String profileName : this.environment.getActiveProfiles()) {
Profile profile = new Profile(profileName);
if (!initialActiveProfiles.contains(profile)) {
unprocessedActiveProfiles.add(profile);
}
private void processOtherActiveProfiles(Set<Profile> activatedViaProperty) {
List<Profile> otherActiveProfiles = Arrays.stream(this.environment.getActiveProfiles())
.map(Profile::new)
.filter(o -> !activatedViaProperty.contains(o)).collect(Collectors.toList());
this.profiles.addAll(otherActiveProfiles);
}
void addActiveProfiles(Set<Profile> profiles) {
if (this.activatedProfiles || profiles.isEmpty()) {
return;
}
// Reverse them so the order is the same as from getProfilesForValue()
// (last one wins when properties are eventually resolved)
Collections.reverse(unprocessedActiveProfiles);
return unprocessedActiveProfiles;
addProfiles(profiles);
this.logger.debug("Activated activeProfiles "
+ StringUtils.collectionToCommaDelimitedString(profiles));
this.activatedProfiles = true;
removeUnprocessedDefaultProfiles();
}
void addProfiles(Set<Profile> profiles) {
for (Profile profile : profiles) {
this.profiles.add(profile);
addProfileToEnvironment(profile.getName());
}
}
private void removeUnprocessedDefaultProfiles() {
this.profiles.removeIf(profile -> (profile != null && profile.isDefaultProfile()));
}
private DocumentFilter getPositiveProfileFilter(Profile profile) {
@ -520,7 +519,7 @@ public class ConfigFileApplicationListener
List<Document> loaded = new ArrayList<>();
for (Document document : documents) {
if (filter.match(document)) {
maybeActivateProfiles(document.getActiveProfiles());
addActiveProfiles(document.getActiveProfiles());
addProfiles(document.getIncludeProfiles());
loaded.add(document);
}
@ -587,58 +586,16 @@ public class ConfigFileApplicationListener
for (String profileName : profileNames) {
profiles.add(new Profile(profileName));
}
Collections.reverse(profiles);
return new LinkedHashSet<>(profiles);
}
private void maybeActivateProfiles(Set<Profile> profiles) {
if (profiles.isEmpty()) {
return;
}
if (this.activatedProfiles) {
this.logger.debug("Profiles already activated, '" + profiles
+ "' will not be applied");
return;
}
addProfiles(profiles);
this.logger.debug("Activated profiles "
+ StringUtils.collectionToCommaDelimitedString(profiles));
this.activatedProfiles = true;
removeUnprocessedDefaultProfiles();
}
private void removeUnprocessedDefaultProfiles() {
this.profiles.removeIf(Profile::isDefaultProfile);
}
private void addProfiles(Set<Profile> profiles) {
for (Profile profile : profiles) {
this.profiles.add(profile);
if (!environmentHasActiveProfile(profile.getName())) {
// If it's already accepted we assume the order was set
// intentionally
prependProfile(this.environment, profile);
}
}
}
private boolean environmentHasActiveProfile(String profile) {
private void addProfileToEnvironment(String profile) {
for (String activeProfile : this.environment.getActiveProfiles()) {
if (activeProfile.equals(profile)) {
return true;
return;
}
}
return false;
}
private void prependProfile(ConfigurableEnvironment environment,
Profile profile) {
Set<String> profiles = new LinkedHashSet<>();
environment.getActiveProfiles(); // ensure they are initialized
// But this one should go first (last wins in a property key clash)
profiles.add(profile.getName());
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
this.environment.addActiveProfile(profile);
}
private Set<String> getSearchLocations() {

View File

@ -758,6 +758,8 @@ public class ConfigFileApplicationListenerTests {
assertThat(environment).has(matchingProfile("morespecific"));
assertThat(environment).has(matchingProfile("yetmorespecific"));
assertThat(environment).doesNotHave(matchingProfile("missing"));
assertThat(this.out.toString())
.contains("The following profiles are active: includeprofile,specific,morespecific,yetmorespecific");
}
@Test