Refactor YAML profile to deal with "!" profiles
Drop `SpringProfileDocumentMatcher` and replace it with two new implementations that restrict when YAML documents are loaded. YAML sections are now restricted both on the specific profile that is being loaded, and the profiles that are currently accepted. The `PropertySourceLoader` interface has been refined to include a predicate that determines when a profile is accepted. The `ConfigFileApplicationListener` simply delegates the predicate logic to the `Environment`. Fixes gh-8011pull/12156/head
parent
b03fd99209
commit
4bde6b80ee
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.function.Predicate;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link SpringProfilesDocumentMatcher} that tests if a profile is accepted.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class AcceptsProfilesDocumentMatcher extends SpringProfilesDocumentMatcher {
|
||||
|
||||
private final Predicate<String[]> acceptsProfiles;
|
||||
|
||||
AcceptsProfilesDocumentMatcher(Predicate<String[]> acceptsProfiles) {
|
||||
this.acceptsProfiles = acceptsProfiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matches(String[] profiles) {
|
||||
return ObjectUtils.isEmpty(profiles) || this.acceptsProfiles.test(profiles);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.Arrays;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link SpringProfilesDocumentMatcher} that matches a specific profile to load.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ProfileToLoadDocumentMatcher extends SpringProfilesDocumentMatcher {
|
||||
|
||||
private final String profile;
|
||||
|
||||
ProfileToLoadDocumentMatcher(String profile) {
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matches(String[] profiles) {
|
||||
String[] positiveProfiles = (profiles == null ? null : Arrays.stream(profiles)
|
||||
.filter(this::isPositveProfile).toArray(String[]::new));
|
||||
if (this.profile == null) {
|
||||
return ObjectUtils.isEmpty(positiveProfiles);
|
||||
}
|
||||
return ObjectUtils.containsElement(positiveProfiles, this.profile);
|
||||
}
|
||||
|
||||
private boolean isPositveProfile(String profile) {
|
||||
return !profile.startsWith("!");
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlProcessor.DocumentMatcher;
|
||||
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationProperty;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
||||
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
|
||||
import org.springframework.boot.origin.OriginTrackedValue;
|
||||
|
||||
/**
|
||||
* Base class for {@link DocumentMatcher DocumentMatchers} that check the
|
||||
* {@code spring.profiles} property.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see OriginTrackedYamlLoader
|
||||
*/
|
||||
abstract class SpringProfilesDocumentMatcher implements DocumentMatcher {
|
||||
|
||||
@Override
|
||||
public final MatchStatus matches(Properties properties) {
|
||||
Binder binder = new Binder(
|
||||
new OriginTrackedValueConfigurationPropertySource(properties));
|
||||
String[] profiles = binder.bind("spring.profiles", Bindable.of(String[].class))
|
||||
.orElse(null);
|
||||
return (matches(profiles) ? MatchStatus.ABSTAIN : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
protected abstract boolean matches(String[] profiles);
|
||||
|
||||
/**
|
||||
* {@link MapConfigurationPropertySource} that deals with unwrapping
|
||||
* {@link OriginTrackedValue OriginTrackedValues} from the underlying map.
|
||||
*/
|
||||
static class OriginTrackedValueConfigurationPropertySource
|
||||
extends MapConfigurationPropertySource {
|
||||
|
||||
OriginTrackedValueConfigurationPropertySource(Map<?, ?> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationProperty getConfigurationProperty(
|
||||
ConfigurationPropertyName name) {
|
||||
ConfigurationProperty property = super.getConfigurationProperty(name);
|
||||
if (property != null && property.getValue() instanceof OriginTrackedValue) {
|
||||
OriginTrackedValue originTrackedValue = (OriginTrackedValue) property
|
||||
.getValue();
|
||||
property = new ConfigurationProperty(property.getName(),
|
||||
originTrackedValue.getValue(), originTrackedValue.getOrigin());
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.yaml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlProcessor.DocumentMatcher;
|
||||
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link DocumentMatcher} backed by {@link Environment#getActiveProfiles()}. A YAML
|
||||
* document may define a "spring.profiles" element as a comma-separated list of Spring
|
||||
* profile names, optionally negated using the {@code !} character. If both negated and
|
||||
* non-negated profiles are specified for a single document, at least one non-negated
|
||||
* profile must match and no negated profiles may match.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Matt Benson
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
public class SpringProfileDocumentMatcher implements DocumentMatcher {
|
||||
|
||||
private String[] activeProfiles = new String[0];
|
||||
|
||||
public SpringProfileDocumentMatcher(String... profiles) {
|
||||
addActiveProfiles(profiles);
|
||||
}
|
||||
|
||||
public void addActiveProfiles(String... profiles) {
|
||||
LinkedHashSet<String> set = new LinkedHashSet<>(
|
||||
Arrays.asList(this.activeProfiles));
|
||||
Collections.addAll(set, profiles);
|
||||
this.activeProfiles = set.toArray(new String[set.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
return matches(extractSpringProfiles(properties));
|
||||
}
|
||||
|
||||
protected List<String> extractSpringProfiles(Properties properties) {
|
||||
Binder binder = new Binder(new MapConfigurationPropertySource(properties));
|
||||
return binder.bind("spring.profiles", Bindable.of(String[].class))
|
||||
.map(Arrays::asList).orElse(Collections.emptyList());
|
||||
}
|
||||
|
||||
private MatchStatus matches(List<String> profiles) {
|
||||
ProfilesMatcher profilesMatcher = getProfilesMatcher();
|
||||
Set<String> negative = extractProfiles(profiles, ProfileType.NEGATIVE);
|
||||
Set<String> positive = extractProfiles(profiles, ProfileType.POSITIVE);
|
||||
if (!CollectionUtils.isEmpty(negative)) {
|
||||
if (profilesMatcher.matches(negative) == MatchStatus.FOUND) {
|
||||
return MatchStatus.NOT_FOUND;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(positive)) {
|
||||
return MatchStatus.FOUND;
|
||||
}
|
||||
}
|
||||
return profilesMatcher.matches(positive);
|
||||
}
|
||||
|
||||
private ProfilesMatcher getProfilesMatcher() {
|
||||
return this.activeProfiles.length == 0 ? new EmptyProfilesMatcher()
|
||||
: new ActiveProfilesMatcher(
|
||||
new HashSet<>(Arrays.asList(this.activeProfiles)));
|
||||
}
|
||||
|
||||
private Set<String> extractProfiles(List<String> profiles, ProfileType type) {
|
||||
if (CollectionUtils.isEmpty(profiles)) {
|
||||
return null;
|
||||
}
|
||||
Set<String> extractedProfiles = new HashSet<>();
|
||||
for (String candidate : profiles) {
|
||||
ProfileType candidateType = ProfileType.POSITIVE;
|
||||
if (candidate.startsWith("!")) {
|
||||
candidateType = ProfileType.NEGATIVE;
|
||||
}
|
||||
if (candidateType == type) {
|
||||
extractedProfiles.add(type == ProfileType.POSITIVE ? candidate
|
||||
: candidate.substring(1));
|
||||
}
|
||||
}
|
||||
return extractedProfiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile match types.
|
||||
*/
|
||||
enum ProfileType {
|
||||
|
||||
POSITIVE, NEGATIVE
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for profile matchers.
|
||||
*/
|
||||
private abstract static class ProfilesMatcher {
|
||||
|
||||
public final MatchStatus matches(Set<String> profiles) {
|
||||
if (CollectionUtils.isEmpty(profiles)) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return doMatches(profiles);
|
||||
}
|
||||
|
||||
protected abstract MatchStatus doMatches(Set<String> profiles);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ProfilesMatcher} that matches when a value in {@code spring.profiles} is
|
||||
* also in {@code spring.profiles.active}.
|
||||
*/
|
||||
private static class ActiveProfilesMatcher extends ProfilesMatcher {
|
||||
|
||||
private final Set<String> activeProfiles;
|
||||
|
||||
ActiveProfilesMatcher(Set<String> activeProfiles) {
|
||||
this.activeProfiles = activeProfiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MatchStatus doMatches(Set<String> profiles) {
|
||||
if (profiles.isEmpty()) {
|
||||
return MatchStatus.NOT_FOUND;
|
||||
}
|
||||
for (String activeProfile : this.activeProfiles) {
|
||||
if (profiles.contains(activeProfile)) {
|
||||
return MatchStatus.FOUND;
|
||||
}
|
||||
}
|
||||
return MatchStatus.NOT_FOUND;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ProfilesMatcher} that matches when {@code
|
||||
* spring.profiles} is empty or contains a value with no text.
|
||||
*
|
||||
* @see StringUtils#hasText(String)
|
||||
*/
|
||||
private static class EmptyProfilesMatcher extends ProfilesMatcher {
|
||||
|
||||
@Override
|
||||
public MatchStatus doMatches(Set<String> springProfiles) {
|
||||
if (springProfiles.isEmpty()) {
|
||||
return MatchStatus.FOUND;
|
||||
}
|
||||
for (String profile : springProfiles) {
|
||||
if (!StringUtils.hasText(profile)) {
|
||||
return MatchStatus.FOUND;
|
||||
}
|
||||
}
|
||||
return MatchStatus.NOT_FOUND;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for binding {@code spring.profiles} property.
|
||||
*/
|
||||
static class SpringProperties {
|
||||
|
||||
private List<String> profiles = new ArrayList<>();
|
||||
|
||||
public List<String> getProfiles() {
|
||||
return this.profiles;
|
||||
}
|
||||
|
||||
public void setProfiles(List<String> profiles) {
|
||||
this.profiles = profiles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Spring Boot extensions to Spring Framework's support for parsing YAML.
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.YamlPropertiesFactoryBean
|
||||
* @see org.springframework.beans.factory.config.YamlMapFactoryBean
|
||||
*/
|
||||
package org.springframework.boot.yaml;
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.Properties;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
|
||||
/**
|
||||
* Tests for {@link AcceptsProfilesDocumentMatcher}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class AcceptsProfilesDocumentMatcherTests {
|
||||
|
||||
@Mock
|
||||
private Predicate<String[]> acceptsProfiles;
|
||||
|
||||
private AcceptsProfilesDocumentMatcher matcher;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
this.matcher = new AcceptsProfilesDocumentMatcher(this.acceptsProfiles);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenHasNoProfilePropertyShouldReturnAbstain() {
|
||||
Properties properties = new Properties();
|
||||
assertThat(this.matcher.matches(properties)).isEqualTo(MatchStatus.ABSTAIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenAcceptsProfileShouldReturnAbstain() {
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles", "foo");
|
||||
given(this.acceptsProfiles.test(new String[] { "foo" })).willReturn(true);
|
||||
assertThat(this.matcher.matches(properties)).isEqualTo(MatchStatus.ABSTAIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenDoesNotAcceptProfileShouldReturnNotFound() {
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles", "foo");
|
||||
given(this.acceptsProfiles.test(new String[] { "foo" })).willReturn(false);
|
||||
assertThat(this.matcher.matches(properties)).isEqualTo(MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ProfileToLoadDocumentMatcher}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ProfileToLoadDocumentMatcherTests {
|
||||
|
||||
@Test
|
||||
public void matchesWhenProfilesIsNullAndHasNoProfilePropertiesShouldReturnAbstain() {
|
||||
ProfileToLoadDocumentMatcher matcher = new ProfileToLoadDocumentMatcher(null);
|
||||
Properties properties = new Properties();
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.ABSTAIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenProfileIsNullAndHasOnlyNegativeProfilePropertiesShouldReturnAbstain() {
|
||||
ProfileToLoadDocumentMatcher matcher = new ProfileToLoadDocumentMatcher(null);
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles", "!foo,!bar");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.ABSTAIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenProfileIsNullAndHasProfilePropertyShouldReturnNotFound() {
|
||||
ProfileToLoadDocumentMatcher matcher = new ProfileToLoadDocumentMatcher(null);
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles", "!foo,!bar,baz");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenProfilesIsSetAndHasNoProfilePropertiesShouldReturnNotFound() {
|
||||
ProfileToLoadDocumentMatcher matcher = new ProfileToLoadDocumentMatcher("bar");
|
||||
Properties properties = new Properties();
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenProfileIsSetAndHasOnlyNegativeProfilePropertiesShouldReturnNotFound() {
|
||||
ProfileToLoadDocumentMatcher matcher = new ProfileToLoadDocumentMatcher("bar");
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles", "!foo,!bar,baz");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenProfileIsSetAndHasProfilePropertyShouldReturnAbstain() {
|
||||
ProfileToLoadDocumentMatcher matcher = new ProfileToLoadDocumentMatcher("bar");
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles", "!foo,bar,baz");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.ABSTAIN);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2012-2018 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.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||
import org.springframework.boot.origin.OriginTrackedValue;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringProfilesDocumentMatcher}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class SpringProfilesDocumentMatcherTests {
|
||||
|
||||
private TestSpringProfilesDocumentMatcher matcher = new TestSpringProfilesDocumentMatcher();
|
||||
|
||||
@Test
|
||||
public void matchesShouldBindAgainstCommaList() {
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles", "foo,bar");
|
||||
this.matcher.matches(properties);
|
||||
assertThat(this.matcher.getProfiles()).containsExactly("foo", "bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesShouldBindAgainstYamlList() {
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles[0]", "foo");
|
||||
properties.put("spring.profiles[1]", "bar");
|
||||
this.matcher.matches(properties);
|
||||
assertThat(this.matcher.getProfiles()).containsExactly("foo", "bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesShouldBindAgainstOriginTrackedValue() {
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles", OriginTrackedValue.of("foo,bar"));
|
||||
this.matcher.matches(properties);
|
||||
assertThat(this.matcher.getProfiles()).containsExactly("foo", "bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenMatchShouldReturnAbstain() {
|
||||
Properties properties = new Properties();
|
||||
properties.put("spring.profiles", "foo,bar");
|
||||
assertThat(this.matcher.matches(properties)).isEqualTo(MatchStatus.ABSTAIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesWhenNoMatchShouldReturnNotFound() {
|
||||
Properties properties = new Properties();
|
||||
assertThat(this.matcher.matches(properties)).isEqualTo(MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
private static class TestSpringProfilesDocumentMatcher
|
||||
extends SpringProfilesDocumentMatcher {
|
||||
|
||||
private String[] profiles;
|
||||
|
||||
@Override
|
||||
protected boolean matches(String[] profiles) {
|
||||
this.profiles = profiles;
|
||||
return !ObjectUtils.isEmpty(profiles);
|
||||
}
|
||||
|
||||
public String[] getProfiles() {
|
||||
return this.profiles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,131 +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.yaml;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlProcessor.DocumentMatcher;
|
||||
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
|
||||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpringProfileDocumentMatcher}.
|
||||
*
|
||||
* @author Matt Benson
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class SpringProfileDocumentMatcherTests {
|
||||
|
||||
@Test
|
||||
public void matchesSingleProfile() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar");
|
||||
Properties properties = getProperties("spring.ProfILEs: foo");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void abstainNoConfiguredProfiles() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar");
|
||||
Properties properties = getProperties("some.property: spam");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.ABSTAIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noActiveProfiles() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher();
|
||||
Properties properties = getProperties("spring.profiles: bar,spam");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesCommaSeparatedString() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar");
|
||||
Properties properties = getProperties("spring.profiles: bar,spam");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesCommaSeparatedArray() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar");
|
||||
Properties properties = getProperties("spring.profiles: [bar, spam]");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void matchesList() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar");
|
||||
Properties properties = getProperties(
|
||||
String.format("spring.profiles:%n - bar%n - spam"));
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noMatchingProfiles() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar");
|
||||
Properties properties = getProperties("spring.profiles: baz,blah");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inverseMatchSingle() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar");
|
||||
Properties properties = getProperties("spring.profiles: '!baz'");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInverseMatchMulti() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar");
|
||||
Properties properties = getProperties("spring.profiles: '!baz,!blah'");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negatedWithMatch() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar", "blah");
|
||||
Properties properties = getProperties("spring.profiles: '!baz,blah'");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negatedWithNoMatch() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "bar", "blah");
|
||||
Properties properties = getProperties("spring.profiles: '!baz,another'");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negatedTrumpsMatching() {
|
||||
DocumentMatcher matcher = new SpringProfileDocumentMatcher("foo", "baz", "blah");
|
||||
Properties properties = getProperties("spring.profiles: '!baz,blah'");
|
||||
assertThat(matcher.matches(properties)).isEqualTo(MatchStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
private Properties getProperties(String values) {
|
||||
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
|
||||
ByteArrayResource resource = new ByteArrayResource(values.getBytes());
|
||||
yamlPropertiesFactoryBean.setResources(resource);
|
||||
yamlPropertiesFactoryBean.afterPropertiesSet();
|
||||
return yamlPropertiesFactoryBean.getObject();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
---
|
||||
my:
|
||||
property: fromyamlfile
|
||||
other: notempty
|
||||
---
|
||||
spring:
|
||||
profiles: dev
|
||||
my:
|
||||
property: fromdevprofile
|
||||
---
|
||||
spring:
|
||||
profiles: other
|
||||
my:
|
||||
property: fromotherprofile
|
||||
---
|
||||
spring:
|
||||
profiles: "!other"
|
||||
my:
|
||||
property: fromnototherprofile
|
||||
notother: foo
|
Loading…
Reference in New Issue