From 36ab01c048a64066495d761f55e954bb696a7995 Mon Sep 17 00:00:00 2001 From: Michael Stummvoll Date: Mon, 11 Aug 2014 10:17:10 +0200 Subject: [PATCH] Support programmatic banners via setter Introduce an easy way for the user to provide an custom programmatic banner to the Application as alternative to the static banner.txt file, without the need to override SpringApplication class. Fixes gh-1363 --- .../java/org/springframework/boot/Banner.java | 46 +++---------- .../boot/SpringApplication.java | 51 +++++++++++---- .../boot/SpringBootBanner.java | 65 +++++++++++++++++++ .../builder/SpringApplicationBuilder.java | 11 ++++ .../org/springframework/boot/BannerTests.java | 45 ++++++++++++- 5 files changed, 165 insertions(+), 53 deletions(-) create mode 100644 spring-boot/src/main/java/org/springframework/boot/SpringBootBanner.java diff --git a/spring-boot/src/main/java/org/springframework/boot/Banner.java b/spring-boot/src/main/java/org/springframework/boot/Banner.java index b5e9dfcc17..c32af83815 100644 --- a/spring-boot/src/main/java/org/springframework/boot/Banner.java +++ b/spring-boot/src/main/java/org/springframework/boot/Banner.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2014 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. @@ -18,50 +18,22 @@ package org.springframework.boot; import java.io.PrintStream; -import org.springframework.boot.ansi.AnsiOutput; - -import static org.springframework.boot.ansi.AnsiElement.DEFAULT; -import static org.springframework.boot.ansi.AnsiElement.FAINT; -import static org.springframework.boot.ansi.AnsiElement.GREEN; +import org.springframework.core.env.Environment; /** - * Writes the 'Spring' banner. + * Interface class for writing a banner programmatically. * * @author Phillip Webb + * @author Michael Stummvoll + * @since 1.2.0 */ -abstract class Banner { - - private static final String[] BANNER = { "", - " . ____ _ __ _ _", - " /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\", - "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\", - " \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )", - " ' |____| .__|_| |_|_| |_\\__, | / / / /", - " =========|_|==============|___/=/_/_/_/" }; - - private static final String SPRING_BOOT = " :: Spring Boot :: "; - - private static final int STRAP_LINE_SIZE = 42; +public interface Banner { /** * Write the banner to the specified print stream. - * @param printStream the output print stream + * @param environment the spring environment + * @param out the output print stream */ - public static void write(PrintStream printStream) { - for (String line : BANNER) { - printStream.println(line); - } - String version = Banner.class.getPackage().getImplementationVersion(); - version = (version == null ? "" : " (v" + version + ")"); - String padding = ""; - while (padding.length() < STRAP_LINE_SIZE - - (version.length() + SPRING_BOOT.length())) { - padding += " "; - } - - printStream.println(AnsiOutput.toString(GREEN, SPRING_BOOT, DEFAULT, padding, - FAINT, version)); - printStream.println(); - } + void write(Environment environment, PrintStream out); } diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index b307aceaa5..ca6c50988d 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -157,6 +157,8 @@ public class SpringApplication { private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless"; + private static final Banner DEFAULT_BANNER = new SpringBootBanner(); + private final Log log = LogFactory.getLog(getClass()); private final Set sources = new LinkedHashSet(); @@ -169,6 +171,8 @@ public class SpringApplication { private boolean addCommandLineProperties = true; + private Banner banner; + private ResourceLoader resourceLoader; private BeanNameGenerator beanNameGenerator; @@ -478,30 +482,42 @@ public class SpringApplication { : new DefaultResourceLoader(getClassLoader()); Resource resource = resourceLoader.getResource(location); if (resource.exists()) { - try { - String banner = StreamUtils.copyToString( - resource.getInputStream(), - environment.getProperty("banner.charset", Charset.class, - Charset.forName("UTF-8"))); - System.out.println(environment.resolvePlaceholders(banner)); - return; - } - catch (Exception ex) { - this.log.warn("Banner not printable: " + resource + " (" + ex.getClass() - + ": '" + ex.getMessage() + "')", ex); - } + printBannerResource(environment, resource); + return; + } + + if (this.banner != null) { + this.banner.write(environment, System.out); + return; } + printBanner(); } + private void printBannerResource(Environment environment, Resource resource) { + try { + String banner = StreamUtils.copyToString( + resource.getInputStream(), + environment.getProperty("banner.charset", Charset.class, + Charset.forName("UTF-8"))); + System.out.println(environment.resolvePlaceholders(banner)); + } + catch (Exception ex) { + this.log.warn("Banner not printable: " + resource + " (" + ex.getClass() + + ": '" + ex.getMessage() + "')", ex); + } + } + /** * Print a simple banner message to the console. Subclasses can override this method * to provide additional or alternative banners. * @see #setShowBanner(boolean) * @see #printBanner(Environment) + * @deprecated since 1.2.0 in favor of {@link #setBanner(Banner)} */ + @Deprecated protected void printBanner() { - Banner.write(System.out); + DEFAULT_BANNER.write(null, System.out); } /** @@ -749,6 +765,15 @@ public class SpringApplication { this.registerShutdownHook = registerShutdownHook; } + /** + * Sets the {@link Banner} instance which will be used to print the banner when no + * static banner file is provided. + * @param banner The Banner instance to use + */ + public void setBanner(Banner banner) { + this.banner = banner; + } + /** * Sets if the Spring banner should be displayed when the application runs. Defaults * to {@code true}. diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringBootBanner.java b/spring-boot/src/main/java/org/springframework/boot/SpringBootBanner.java new file mode 100644 index 0000000000..1fb5645210 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/SpringBootBanner.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012-2013 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; + +import java.io.PrintStream; + +import org.springframework.boot.ansi.AnsiOutput; +import org.springframework.core.env.Environment; + +import static org.springframework.boot.ansi.AnsiElement.DEFAULT; +import static org.springframework.boot.ansi.AnsiElement.FAINT; +import static org.springframework.boot.ansi.AnsiElement.GREEN; + +/** + * Default Banner implementation which writes the 'Spring' banner. + * + * @author Phillip Webb + */ +class SpringBootBanner implements Banner { + + private static final String[] BANNER = { "", + " . ____ _ __ _ _", + " /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\", + "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\", + " \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )", + " ' |____| .__|_| |_|_| |_\\__, | / / / /", + " =========|_|==============|___/=/_/_/_/" }; + + private static final String SPRING_BOOT = " :: Spring Boot :: "; + + private static final int STRAP_LINE_SIZE = 42; + + @Override + public void write(Environment environment, PrintStream printStream) { + for (String line : BANNER) { + printStream.println(line); + } + String version = Banner.class.getPackage().getImplementationVersion(); + version = (version == null ? "" : " (v" + version + ")"); + String padding = ""; + while (padding.length() < STRAP_LINE_SIZE + - (version.length() + SPRING_BOOT.length())) { + padding += " "; + } + + printStream.println(AnsiOutput.toString(GREEN, SPRING_BOOT, DEFAULT, padding, + FAINT, version)); + printStream.println(); + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java b/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java index 5aeb6b1b8f..bdeb84cfb0 100644 --- a/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java +++ b/spring-boot/src/main/java/org/springframework/boot/builder/SpringApplicationBuilder.java @@ -28,6 +28,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; @@ -293,6 +294,16 @@ public class SpringApplicationBuilder { return this; } + /** + * Sets the {@link Banner} instance which will be used to print the banner when no + * static banner file is provided. + * @param banner The banner to use + */ + public SpringApplicationBuilder banner(Banner banner) { + this.application.setBanner(banner); + return this; + } + /** * Flag to indicate the startup banner should be printed. * @param showBanner the flag to set. Default true. diff --git a/spring-boot/src/test/java/org/springframework/boot/BannerTests.java b/spring-boot/src/test/java/org/springframework/boot/BannerTests.java index 9890e6969b..eb2a4caa8d 100644 --- a/spring-boot/src/test/java/org/springframework/boot/BannerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/BannerTests.java @@ -16,18 +16,57 @@ package org.springframework.boot; +import java.io.PrintStream; + +import org.junit.Rule; import org.junit.Test; +import org.springframework.boot.test.OutputCapture; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThat; /** - * Tests for {@link Banner}. + * Tests for {@link Banner} and its usage by {@link SpringApplication}. * * @author Phillip Webb + * @author Michael Stummvoll */ public class BannerTests { + @Rule + public OutputCapture out = new OutputCapture(); + @Test - public void visualBannder() throws Exception { - Banner.write(System.out); + public void testDefaultBanner() throws Exception { + SpringApplication application = new SpringApplication(Config.class); + application.setWebEnvironment(false); + application.run(); + assertThat(this.out.toString(), containsString(":: Spring Boot ::")); + } + + @Test + public void testCustomBanner() throws Exception { + SpringApplication application = new SpringApplication(Config.class); + application.setWebEnvironment(false); + application.setBanner(new DummyBanner()); + application.run(); + assertThat(this.out.toString(), containsString("My Banner")); + } + + static class DummyBanner implements Banner { + + @Override + public void write(Environment environment, PrintStream out) { + out.println("My Banner"); + } + + } + + @Configuration + public static class Config { + } }