Merge branch '3.0.x'

This commit is contained in:
Phillip Webb 2023-04-24 17:16:52 -07:00
commit e0b03661d4
2 changed files with 84 additions and 24 deletions

View File

@ -19,6 +19,7 @@ package org.springframework.boot;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@ -65,7 +66,6 @@ public class ResourceBanner implements Banner {
try {
String banner = StreamUtils.copyToString(this.resource.getInputStream(),
environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));
for (PropertyResolver resolver : getPropertyResolvers(environment, sourceClass)) {
banner = resolver.resolvePlaceholders(banner);
}
@ -77,15 +77,46 @@ public class ResourceBanner implements Banner {
}
}
/**
* Return a mutable list of the {@link PropertyResolver} instances that will be used
* to resolve placeholders.
* @param environment the environment
* @param sourceClass the source class
* @return a mutable list of property resolvers
*/
protected List<PropertyResolver> getPropertyResolvers(Environment environment, Class<?> sourceClass) {
MutablePropertySources propertySources = new MutablePropertySources();
MutablePropertySources sources = new MutablePropertySources();
if (environment instanceof ConfigurableEnvironment) {
((ConfigurableEnvironment) environment).getPropertySources().forEach(propertySources::addLast);
((ConfigurableEnvironment) environment).getPropertySources().forEach(sources::addLast);
}
propertySources.addLast(getTitleSource(sourceClass));
propertySources.addLast(getAnsiSource());
propertySources.addLast(getVersionSource(sourceClass));
return Collections.singletonList(new PropertySourcesPropertyResolver(propertySources));
sources.addLast(getTitleSource(sourceClass));
sources.addLast(getAnsiSource());
sources.addLast(getVersionSource(sourceClass));
List<PropertyResolver> resolvers = new ArrayList<>();
resolvers.add(new PropertySourcesPropertyResolver(sources));
return resolvers;
}
private MapPropertySource getTitleSource(Class<?> sourceClass) {
String applicationTitle = getApplicationTitle(sourceClass);
Map<String, Object> titleMap = Collections.singletonMap("application.title",
(applicationTitle != null) ? applicationTitle : "");
return new MapPropertySource("title", titleMap);
}
/**
* Return the application title that should be used for the source class. By default
* will use {@link Package#getImplementationTitle()}.
* @param sourceClass the source class
* @return the application title
*/
protected String getApplicationTitle(Class<?> sourceClass) {
Package sourcePackage = (sourceClass != null) ? sourceClass.getPackage() : null;
return (sourcePackage != null) ? sourcePackage.getImplementationTitle() : null;
}
private AnsiPropertySource getAnsiSource() {
return new AnsiPropertySource("ansi", true);
}
private MapPropertySource getVersionSource(Class<?> sourceClass) {
@ -119,20 +150,4 @@ public class ResourceBanner implements Banner {
return format ? " (v" + version + ")" : version;
}
private AnsiPropertySource getAnsiSource() {
return new AnsiPropertySource("ansi", true);
}
private MapPropertySource getTitleSource(Class<?> sourceClass) {
String applicationTitle = getApplicationTitle(sourceClass);
Map<String, Object> titleMap = Collections.singletonMap("application.title",
(applicationTitle != null) ? applicationTitle : "");
return new MapPropertySource("title", titleMap);
}
protected String getApplicationTitle(Class<?> sourceClass) {
Package sourcePackage = (sourceClass != null) ? sourceClass.getPackage() : null;
return (sourcePackage != null) ? sourcePackage.getImplementationTitle() : null;
}
}

View File

@ -19,6 +19,7 @@ package org.springframework.boot;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.AfterEach;
@ -26,8 +27,11 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.ansi.AnsiOutput;
import org.springframework.boot.ansi.AnsiOutput.Enabled;
import org.springframework.core.env.AbstractPropertyResolver;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertyResolver;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.mock.env.MockEnvironment;
@ -136,9 +140,20 @@ class ResourceBannerTests {
assertThat(banner).startsWith("banner 1 default-b 10.2 1.0");
}
@Test
void renderWithMutation() {
Resource resource = new ByteArrayResource("banner ${foo}".getBytes());
String banner = printBanner(new MutatingResourceBanner(resource, "1", "2", null));
assertThat(banner).startsWith("banner bar");
}
private String printBanner(Resource resource, String bootVersion, String applicationVersion,
String applicationTitle) {
ResourceBanner banner = new MockResourceBanner(resource, bootVersion, applicationVersion, applicationTitle);
return printBanner(new MockResourceBanner(resource, bootVersion, applicationVersion, applicationTitle));
}
private String printBanner(ResourceBanner banner) {
ConfigurableEnvironment environment = new MockEnvironment();
Map<String, Object> source = Collections.singletonMap("a", "1");
environment.getPropertySources().addLast(new MapPropertySource("map", source));
@ -179,4 +194,34 @@ class ResourceBannerTests {
}
static class MutatingResourceBanner extends MockResourceBanner {
MutatingResourceBanner(Resource resource, String bootVersion, String applicationVersion,
String applicationTitle) {
super(resource, bootVersion, applicationVersion, applicationTitle);
}
@Override
protected List<PropertyResolver> getPropertyResolvers(Environment environment, Class<?> sourceClass) {
List<PropertyResolver> resolvers = super.getPropertyResolvers(environment, sourceClass);
PropertyResolver resolver = new AbstractPropertyResolver() {
@Override
@SuppressWarnings("unchecked")
public <T> T getProperty(String key, Class<T> targetType) {
return String.class.equals(targetType) ? (T) getPropertyAsRawString(key) : null;
}
@Override
protected String getPropertyAsRawString(String key) {
return ("foo".equals(key)) ? "bar" : null;
}
};
resolvers.add(resolver);
return resolvers;
}
}
}