Commit 4bde6b80 authored by Phillip Webb's avatar Phillip Webb

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-8011
parent b03fd992
...@@ -22,6 +22,7 @@ import org.springframework.boot.SpringApplication; ...@@ -22,6 +22,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
...@@ -40,16 +41,17 @@ public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor ...@@ -40,16 +41,17 @@ public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor
public void postProcessEnvironment(ConfigurableEnvironment environment, public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) { SpringApplication application) {
Resource path = new ClassPathResource("com/example/myapp/config.yml"); Resource path = new ClassPathResource("com/example/myapp/config.yml");
PropertySource<?> propertySource = loadYaml(path); PropertySource<?> propertySource = loadYaml(path, environment);
environment.getPropertySources().addLast(propertySource); environment.getPropertySources().addLast(propertySource);
} }
private PropertySource<?> loadYaml(Resource path) { private PropertySource<?> loadYaml(Resource path, Environment environment) {
if (!path.exists()) { if (!path.exists()) {
throw new IllegalArgumentException("Resource " + path + " does not exist"); throw new IllegalArgumentException("Resource " + path + " does not exist");
} }
try { try {
return this.loader.load("custom-resource", path, null); return this.loader.load("custom-resource", path, null,
environment::acceptsProfiles);
} }
catch (IOException ex) { catch (IOException ex) {
throw new IllegalStateException( throw new IllegalStateException(
......
...@@ -181,7 +181,7 @@ public class PropertiesMigrationReporterTests { ...@@ -181,7 +181,7 @@ public class PropertiesMigrationReporterTests {
throws IOException { throws IOException {
ClassPathResource resource = new ClassPathResource(path); ClassPathResource resource = new ClassPathResource(path);
PropertySource<?> propertySource = new PropertiesPropertySourceLoader().load(name, PropertySource<?> propertySource = new PropertiesPropertySourceLoader().load(name,
resource, null); resource, null, (profile) -> true);
assertThat(propertySource).isNotNull(); assertThat(propertySource).isNotNull();
return propertySource; return propertySource;
} }
......
...@@ -466,7 +466,8 @@ public class ConfigFileApplicationListener ...@@ -466,7 +466,8 @@ public class ConfigFileApplicationListener
} }
String name = "applicationConfig: [" + location + "]" String name = "applicationConfig: [" + location + "]"
+ (loadProfile == null ? "" : "#" + loadProfile); + (loadProfile == null ? "" : "#" + loadProfile);
PropertySource<?> loaded = loader.load(name, resource, loadProfile); PropertySource<?> loaded = loader.load(name, resource, loadProfile,
this.environment::acceptsProfiles);
if (loaded == null) { if (loaded == null) {
this.logger.trace("Skipped unloaded config " + description); this.logger.trace("Skipped unloaded config " + description);
return; return;
......
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -14,10 +14,28 @@ ...@@ -14,10 +14,28 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.env;
import java.util.function.Predicate;
import org.springframework.util.ObjectUtils;
/** /**
* Spring Boot extensions to Spring Framework's support for parsing YAML. * {@link SpringProfilesDocumentMatcher} that tests if a profile is accepted.
* *
* @see org.springframework.beans.factory.config.YamlPropertiesFactoryBean * @author Phillip Webb
* @see org.springframework.beans.factory.config.YamlMapFactoryBean
*/ */
package org.springframework.boot.yaml; 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);
}
}
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,9 +17,8 @@ ...@@ -17,9 +17,8 @@
package org.springframework.boot.env; package org.springframework.boot.env;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.function.Predicate;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -41,11 +40,10 @@ import org.springframework.boot.origin.Origin; ...@@ -41,11 +40,10 @@ import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginTrackedValue; import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.boot.origin.TextResourceOrigin; import org.springframework.boot.origin.TextResourceOrigin;
import org.springframework.boot.origin.TextResourceOrigin.Location; import org.springframework.boot.origin.TextResourceOrigin.Location;
import org.springframework.boot.yaml.SpringProfileDocumentMatcher;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
/** /**
* Class to load {@code .yml} files into a map of {@code String} -> * Class to load {@code .yml} files into a map of {@code String} to
* {@link OriginTrackedValue}. * {@link OriginTrackedValue}.
* *
* @author Madhura Bhave * @author Madhura Bhave
...@@ -55,16 +53,11 @@ class OriginTrackedYamlLoader extends YamlProcessor { ...@@ -55,16 +53,11 @@ class OriginTrackedYamlLoader extends YamlProcessor {
private final Resource resource; private final Resource resource;
OriginTrackedYamlLoader(Resource resource, String profile) { OriginTrackedYamlLoader(Resource resource, String profileToLoad,
Predicate<String[]> acceptsProfiles) {
this.resource = resource; this.resource = resource;
if (profile == null) { setDocumentMatchers(new ProfileToLoadDocumentMatcher(profileToLoad),
setMatchDefault(true); new AcceptsProfilesDocumentMatcher(acceptsProfiles));
setDocumentMatchers(new OriginTrackedSpringProfileDocumentMatcher());
}
else {
setMatchDefault(false);
setDocumentMatchers(new OriginTrackedSpringProfileDocumentMatcher(profile));
}
setResources(resource); setResources(resource);
} }
...@@ -164,32 +157,4 @@ class OriginTrackedYamlLoader extends YamlProcessor { ...@@ -164,32 +157,4 @@ class OriginTrackedYamlLoader extends YamlProcessor {
} }
/**
* {@link SpringProfileDocumentMatcher} that deals with {@link OriginTrackedValue
* OriginTrackedValues}.
*/
private static class OriginTrackedSpringProfileDocumentMatcher
extends SpringProfileDocumentMatcher {
OriginTrackedSpringProfileDocumentMatcher(String... profiles) {
super(profiles);
}
@Override
protected List<String> extractSpringProfiles(Properties properties) {
Properties springProperties = new Properties();
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
if (String.valueOf(entry.getKey()).startsWith("spring.")) {
Object value = entry.getValue();
if (value instanceof OriginTrackedValue) {
value = ((OriginTrackedValue) value).getValue();
}
springProperties.put(entry.getKey(), value);
}
}
return super.extractSpringProfiles(springProperties);
}
}
} }
/*
* 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("!");
}
}
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -18,6 +18,7 @@ package org.springframework.boot.env; ...@@ -18,6 +18,7 @@ package org.springframework.boot.env;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
...@@ -40,9 +41,9 @@ public class PropertiesPropertySourceLoader implements PropertySourceLoader { ...@@ -40,9 +41,9 @@ public class PropertiesPropertySourceLoader implements PropertySourceLoader {
} }
@Override @Override
public PropertySource<?> load(String name, Resource resource, String profile) public PropertySource<?> load(String name, Resource resource, String profileToLoad,
throws IOException { Predicate<String[]> acceptsProfiles) throws IOException {
if (profile == null) { if (profileToLoad == null) {
Map<String, ?> properties = loadProperties(resource); Map<String, ?> properties = loadProperties(resource);
if (!properties.isEmpty()) { if (!properties.isEmpty()) {
return new OriginTrackedMapPropertySource(name, properties); return new OriginTrackedMapPropertySource(name, properties);
......
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.env; package org.springframework.boot.env;
import java.io.IOException; import java.io.IOException;
import java.util.function.Predicate;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
...@@ -41,13 +42,14 @@ public interface PropertySourceLoader { ...@@ -41,13 +42,14 @@ public interface PropertySourceLoader {
* Load the resource into a property source. * Load the resource into a property source.
* @param name the name of the property source * @param name the name of the property source
* @param resource the resource to load * @param resource the resource to load
* @param profile the name of the profile to load or {@code null}. The profile can be * @param profileToLoad the name of the profile to load or {@code null}. The profile
* used to load multi-document files (such as YAML). Simple property formats should * can be used to load multi-document files (such as YAML). Simple property formats
* {@code null} when asked to load a profile. * should {@code null} when asked to load a profile.
* @param acceptsProfiles predicate to determine if a particular profile is accepted
* @return a property source or {@code null} * @return a property source or {@code null}
* @throws IOException if the source cannot be loaded * @throws IOException if the source cannot be loaded
*/ */
PropertySource<?> load(String name, Resource resource, String profile) PropertySource<?> load(String name, Resource resource, String profileToLoad,
throws IOException; Predicate<String[]> acceptsProfiles) throws IOException;
} }
/*
* 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;
}
}
}
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -18,6 +18,7 @@ package org.springframework.boot.env; ...@@ -18,6 +18,7 @@ package org.springframework.boot.env;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
...@@ -38,14 +39,14 @@ public class YamlPropertySourceLoader implements PropertySourceLoader { ...@@ -38,14 +39,14 @@ public class YamlPropertySourceLoader implements PropertySourceLoader {
} }
@Override @Override
public PropertySource<?> load(String name, Resource resource, String profile) public PropertySource<?> load(String name, Resource resource, String profileToLoad,
throws IOException { Predicate<String[]> acceptsProfiles) throws IOException {
if (!ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) { if (!ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
throw new IllegalStateException("Attempted to load " + name throw new IllegalStateException("Attempted to load " + name
+ " but snakeyaml was not found on the classpath"); + " but snakeyaml was not found on the classpath");
} }
Map<String, Object> source = new OriginTrackedYamlLoader(resource, profile) Map<String, Object> source = new OriginTrackedYamlLoader(resource, profileToLoad,
.load(); acceptsProfiles).load();
if (!source.isEmpty()) { if (!source.isEmpty()) {
return new OriginTrackedMapPropertySource(name, source); return new OriginTrackedMapPropertySource(name, source);
} }
......
/*
* 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;
}
}
}
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -504,6 +504,29 @@ public class ConfigFileApplicationListenerTests { ...@@ -504,6 +504,29 @@ public class ConfigFileApplicationListenerTests {
assertThat(property).isEqualTo("notempty"); assertThat(property).isEqualTo("notempty");
} }
@Test
public void yamlNegatedProfiles() {
// gh-8011
this.initializer.setSearchNames("testnegatedprofiles");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromnototherprofile");
property = this.environment.getProperty("my.notother");
assertThat(property).isEqualTo("foo");
}
@Test
public void yamlNegatedProfilesWithProfile() {
// gh-8011
this.initializer.setSearchNames("testnegatedprofiles");
this.environment.setActiveProfiles("other");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromotherprofile");
property = this.environment.getProperty("my.notother");
assertThat(property).isNull();
}
@Test @Test
public void yamlSetsProfiles() { public void yamlSetsProfiles() {
this.initializer.setSearchNames("testsetprofiles"); this.initializer.setSearchNames("testsetprofiles");
......
/*
* 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);
}
}
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -46,7 +46,7 @@ public class NoSnakeYamlPropertySourceLoaderTests { ...@@ -46,7 +46,7 @@ public class NoSnakeYamlPropertySourceLoaderTests {
"Attempted to load resource but snakeyaml was not found on the classpath"); "Attempted to load resource but snakeyaml was not found on the classpath");
ByteArrayResource resource = new ByteArrayResource( ByteArrayResource resource = new ByteArrayResource(
"foo:\n bar: spam".getBytes()); "foo:\n bar: spam".getBytes());
this.loader.load("resource", resource, null); this.loader.load("resource", resource, null, (profile) -> true);
} }
} }
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -43,7 +43,7 @@ public class OriginTrackedYamlLoaderTests { ...@@ -43,7 +43,7 @@ public class OriginTrackedYamlLoaderTests {
@Before @Before
public void setUp() { public void setUp() {
Resource resource = new ClassPathResource("test-yaml.yml", getClass()); Resource resource = new ClassPathResource("test-yaml.yml", getClass());
this.loader = new OriginTrackedYamlLoader(resource, null); this.loader = new OriginTrackedYamlLoader(resource, null, (profile) -> true);
} }
@Test @Test
...@@ -93,7 +93,8 @@ public class OriginTrackedYamlLoaderTests { ...@@ -93,7 +93,8 @@ public class OriginTrackedYamlLoaderTests {
@Test @Test
public void processWithActiveProfile() { public void processWithActiveProfile() {
Resource resource = new ClassPathResource("test-yaml.yml", getClass()); Resource resource = new ClassPathResource("test-yaml.yml", getClass());
this.loader = new OriginTrackedYamlLoader(resource, "development"); this.loader = new OriginTrackedYamlLoader(resource, "development",
(profile) -> true);
Map<String, Object> result = this.loader.load(); Map<String, Object> result = this.loader.load();
assertThat(result.get("name").toString()).isEqualTo("Test Name"); assertThat(result.get("name").toString()).isEqualTo("Test Name");
} }
......
/*
* 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);
}
}
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -42,14 +42,16 @@ public class PropertiesPropertySourceLoaderTests { ...@@ -42,14 +42,16 @@ public class PropertiesPropertySourceLoaderTests {
@Test @Test
public void loadProperties() throws Exception { public void loadProperties() throws Exception {
PropertySource<?> source = this.loader.load("test.properties", PropertySource<?> source = this.loader.load("test.properties",
new ClassPathResource("test-properties.properties", getClass()), null); new ClassPathResource("test-properties.properties", getClass()), null,
(profile) -> true);
assertThat(source.getProperty("test")).isEqualTo("properties"); assertThat(source.getProperty("test")).isEqualTo("properties");
} }
@Test @Test
public void loadXml() throws Exception { public void loadXml() throws Exception {
PropertySource<?> source = this.loader.load("test.xml", PropertySource<?> source = this.loader.load("test.xml",
new ClassPathResource("test-xml.xml", getClass()), null); new ClassPathResource("test-xml.xml", getClass()), null,
(profile) -> true);
assertThat(source.getProperty("test")).isEqualTo("xml"); assertThat(source.getProperty("test")).isEqualTo("xml");
} }
......
/*
* 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;
}
}
}
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -26,6 +26,7 @@ import org.springframework.core.env.PropertySource; ...@@ -26,6 +26,7 @@ import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.util.ObjectUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -44,7 +45,8 @@ public class YamlPropertySourceLoaderTests { ...@@ -44,7 +45,8 @@ public class YamlPropertySourceLoaderTests {
public void load() throws Exception { public void load() throws Exception {
ByteArrayResource resource = new ByteArrayResource( ByteArrayResource resource = new ByteArrayResource(
"foo:\n bar: spam".getBytes()); "foo:\n bar: spam".getBytes());
PropertySource<?> source = this.loader.load("resource", resource, null); PropertySource<?> source = this.loader.load("resource", resource, null,
(profile) -> true);
assertThat(source).isNotNull(); assertThat(source).isNotNull();
assertThat(source.getProperty("foo.bar")).isEqualTo("spam"); assertThat(source.getProperty("foo.bar")).isEqualTo("spam");
} }
...@@ -59,7 +61,7 @@ public class YamlPropertySourceLoaderTests { ...@@ -59,7 +61,7 @@ public class YamlPropertySourceLoaderTests {
} }
ByteArrayResource resource = new ByteArrayResource(yaml.toString().getBytes()); ByteArrayResource resource = new ByteArrayResource(yaml.toString().getBytes());
EnumerablePropertySource<?> source = (EnumerablePropertySource<?>) this.loader EnumerablePropertySource<?> source = (EnumerablePropertySource<?>) this.loader
.load("resource", resource, null); .load("resource", resource, null, (profile) -> true);
assertThat(source).isNotNull(); assertThat(source).isNotNull();
assertThat(source.getPropertyNames()) assertThat(source.getPropertyNames())
.isEqualTo(expected.toArray(new String[] {})); .isEqualTo(expected.toArray(new String[] {}));
...@@ -72,7 +74,8 @@ public class YamlPropertySourceLoaderTests { ...@@ -72,7 +74,8 @@ public class YamlPropertySourceLoaderTests {
yaml.append("---\n"); yaml.append("---\n");
yaml.append("foo:\n baz: wham\n"); yaml.append("foo:\n baz: wham\n");
ByteArrayResource resource = new ByteArrayResource(yaml.toString().getBytes()); ByteArrayResource resource = new ByteArrayResource(yaml.toString().getBytes());
PropertySource<?> source = this.loader.load("resource", resource, null); PropertySource<?> source = this.loader.load("resource", resource, null,
(profile) -> true);
assertThat(source).isNotNull(); assertThat(source).isNotNull();
assertThat(source.getProperty("foo.bar")).isEqualTo("spam"); assertThat(source.getProperty("foo.bar")).isEqualTo("spam");
assertThat(source.getProperty("foo.baz")).isEqualTo("wham"); assertThat(source.getProperty("foo.baz")).isEqualTo("wham");
...@@ -81,7 +84,8 @@ public class YamlPropertySourceLoaderTests { ...@@ -81,7 +84,8 @@ public class YamlPropertySourceLoaderTests {
@Test @Test
public void timestampLikeItemsDoNotBecomeDates() throws Exception { public void timestampLikeItemsDoNotBecomeDates() throws Exception {
ByteArrayResource resource = new ByteArrayResource("foo: 2015-01-28".getBytes()); ByteArrayResource resource = new ByteArrayResource("foo: 2015-01-28".getBytes());
PropertySource<?> source = this.loader.load("resource", resource, null); PropertySource<?> source = this.loader.load("resource", resource, null,
(profile) -> true);
assertThat(source).isNotNull(); assertThat(source).isNotNull();
assertThat(source.getProperty("foo")).isEqualTo("2015-01-28"); assertThat(source.getProperty("foo")).isEqualTo("2015-01-28");
} }
...@@ -89,11 +93,42 @@ public class YamlPropertySourceLoaderTests { ...@@ -89,11 +93,42 @@ public class YamlPropertySourceLoaderTests {
@Test @Test
public void loadOriginAware() throws Exception { public void loadOriginAware() throws Exception {
Resource resource = new ClassPathResource("test-yaml.yml", getClass()); Resource resource = new ClassPathResource("test-yaml.yml", getClass());
PropertySource<?> source = this.loader.load("resource", resource, null); PropertySource<?> source = this.loader.load("resource", resource, null,
(profile) -> true);
EnumerablePropertySource<?> enumerableSource = (EnumerablePropertySource<?>) source; EnumerablePropertySource<?> enumerableSource = (EnumerablePropertySource<?>) source;
for (String name : enumerableSource.getPropertyNames()) { for (String name : enumerableSource.getPropertyNames()) {
System.out.println(name + " = " + enumerableSource.getProperty(name)); System.out.println(name + " = " + enumerableSource.getProperty(name));
} }
} }
@Test
public void loadSpecificProfile() throws Exception {
StringBuilder yaml = new StringBuilder();
yaml.append("foo:\n bar: spam\n");
yaml.append("---\n");
yaml.append("spring:\n profiles: foo\n");
yaml.append("foo:\n bar: wham\n");
ByteArrayResource resource = new ByteArrayResource(yaml.toString().getBytes());
PropertySource<?> source = this.loader.load("resource", resource, "foo",
(profile) -> true);
assertThat(source).isNotNull();
assertThat(source.getProperty("foo.bar")).isEqualTo("wham");
}
@Test
public void loadWithAcceptProfile() throws Exception {
StringBuilder yaml = new StringBuilder();
yaml.append("---\n");
yaml.append("spring:\n profiles: yay,foo\n");
yaml.append("foo:\n bar: bang\n");
yaml.append("---\n");
yaml.append("spring:\n profiles: yay,!foo\n");
yaml.append("foo:\n bar: wham\n");
ByteArrayResource resource = new ByteArrayResource(yaml.toString().getBytes());
PropertySource<?> source = this.loader.load("resource", resource, "yay",
(profiles) -> ObjectUtils.containsElement(profiles, "!foo"));
assertThat(source).isNotNull();
assertThat(source.getProperty("foo.bar")).isEqualTo("wham");
}
} }
/*
* 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();
}
}
---
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
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment