Skip to content

Commit 309f848

Browse files
cjstehnophilwebb
authored andcommitted
Fix remote shell to support custom banners
Update the remote shell to use the `Banner` interface when possible. Fixes spring-projectsgh-3988 Closes spring-projectsgh-5453
1 parent b567959 commit 309f848

File tree

4 files changed

+77
-6
lines changed

4 files changed

+77
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
,--. ,--.
2+
\ /-~-\ /
3+
)' a a `(
4+
( ,---. )
5+
`(_o_o_)'
6+
)`-'(
7+
8+
Spring Boot${spring-boot.formatted-version}

spring-boot-starters/spring-boot-starter-remote-shell/src/main/resources/commands/crash/login.groovy

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
welcome = { ->
2-
if (!crash.context.attributes['spring.environment'].getProperty("spring.main.show_banner", Boolean.class, Boolean.TRUE)) {
2+
3+
def environment = crash.context.attributes['spring.environment']
4+
def propertyResolver = new org.springframework.boot.bind.RelaxedPropertyResolver(environment, "spring.main.");
5+
def beanFactory = crash.context.attributes['spring.beanfactory']
6+
7+
if (!propertyResolver.getProperty("show-banner", Boolean.class, Boolean.TRUE)) {
38
return ""
49
}
510

11+
// Try to print using the banner interface
12+
if (beanFactory != null) {
13+
try {
14+
def banner = beanFactory.getBean("springBootBanner")
15+
def out = new java.io.ByteArrayOutputStream()
16+
banner.printBanner(environment, null, new java.io.PrintStream(out))
17+
return out.toString()
18+
} catch (Exception ex) {
19+
// Ignore
20+
}
21+
}
22+
623
// Resolve hostname
724
def hostName;
825
try {

spring-boot/src/main/java/org/springframework/boot/SpringApplicationBannerPrinter.java

+26-2
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@ public Banner print(Environment environment, Class<?> sourceClass, Log logger) {
6363
catch (UnsupportedEncodingException ex) {
6464
logger.warn("Failed to create String for banner", ex);
6565
}
66-
return banner;
66+
return new PrintedBanner(banner, sourceClass);
6767
}
6868

6969
public Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
7070
Banner banner = getBanner(environment, this.fallbackBanner);
7171
banner.printBanner(environment, sourceClass, out);
72-
return banner;
72+
return new PrintedBanner(banner, sourceClass);
7373
}
7474

7575
private Banner getBanner(Environment environment, Banner definedBanner) {
@@ -145,4 +145,28 @@ public void printBanner(Environment environment, Class<?> sourceClass,
145145

146146
}
147147

148+
/**
149+
* Decorator that allows a {@link Banner} to be printed again without needing to
150+
* specify the source class.
151+
*/
152+
private static class PrintedBanner implements Banner {
153+
154+
private final Banner banner;
155+
156+
private final Class<?> sourceClass;
157+
158+
PrintedBanner(Banner banner, Class<?> sourceClass) {
159+
this.banner = banner;
160+
this.sourceClass = sourceClass;
161+
}
162+
163+
@Override
164+
public void printBanner(Environment environment, Class<?> sourceClass,
165+
PrintStream out) {
166+
sourceClass = (sourceClass == null ? this.sourceClass : sourceClass);
167+
this.banner.printBanner(environment, sourceClass, out);
168+
}
169+
170+
}
171+
148172
}

spring-boot/src/test/java/org/springframework/boot/BannerTests.java

+25-3
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,24 @@
2121
import org.junit.After;
2222
import org.junit.Rule;
2323
import org.junit.Test;
24+
import org.junit.runner.RunWith;
25+
import org.mockito.ArgumentCaptor;
26+
import org.mockito.Captor;
27+
import org.mockito.runners.MockitoJUnitRunner;
2428

2529
import org.springframework.boot.Banner.Mode;
2630
import org.springframework.boot.testutil.InternalOutputCapture;
2731
import org.springframework.context.ConfigurableApplicationContext;
2832
import org.springframework.context.annotation.Configuration;
2933
import org.springframework.core.env.Environment;
34+
import org.springframework.test.util.ReflectionTestUtils;
3035

3136
import static org.assertj.core.api.Assertions.assertThat;
37+
import static org.mockito.Matchers.any;
38+
import static org.mockito.Matchers.eq;
39+
import static org.mockito.Mockito.mock;
40+
import static org.mockito.Mockito.reset;
41+
import static org.mockito.Mockito.verify;
3242

3343
/**
3444
* Tests for {@link Banner} and its usage by {@link SpringApplication}.
@@ -37,6 +47,7 @@
3747
* @author Michael Stummvoll
3848
* @author Michael Simons
3949
*/
50+
@RunWith(MockitoJUnitRunner.class)
4051
public class BannerTests {
4152

4253
private ConfigurableApplicationContext context;
@@ -51,6 +62,9 @@ public void cleanUp() {
5162
@Rule
5263
public InternalOutputCapture out = new InternalOutputCapture();
5364

65+
@Captor
66+
private ArgumentCaptor<Class<?>> sourceClassCaptor;
67+
5468
@Test
5569
public void testDefaultBanner() throws Exception {
5670
SpringApplication application = new SpringApplication(Config.class);
@@ -88,10 +102,18 @@ public void testBannerInContext() throws Exception {
88102
public void testCustomBannerInContext() throws Exception {
89103
SpringApplication application = new SpringApplication(Config.class);
90104
application.setWebEnvironment(false);
91-
final DummyBanner dummyBanner = new DummyBanner();
92-
application.setBanner(dummyBanner);
105+
Banner banner = mock(Banner.class);
106+
application.setBanner(banner);
93107
this.context = application.run();
94-
assertThat(this.context.getBean("springBootBanner")).isEqualTo(dummyBanner);
108+
Banner printedBanner = (Banner) this.context.getBean("springBootBanner");
109+
assertThat(ReflectionTestUtils.getField(printedBanner, "banner"))
110+
.isEqualTo(banner);
111+
verify(banner).printBanner(any(Environment.class),
112+
this.sourceClassCaptor.capture(), any(PrintStream.class));
113+
reset(banner);
114+
printedBanner.printBanner(this.context.getEnvironment(), null, System.out);
115+
verify(banner).printBanner(any(Environment.class),
116+
eq(this.sourceClassCaptor.getValue()), any(PrintStream.class));
95117
}
96118

97119
@Test

0 commit comments

Comments
 (0)