From a35a79e1a3798dbe9c8f118b22e7df215eff30a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raphael=20von=20der=20Gr=C3=BCn?= Date: Sun, 20 Jul 2014 00:43:38 +0200 Subject: [PATCH] Allow ANSI output to be configured by properties Add AnsiOutputApplicationListener which configures AnsiOutput.enabled based on a `spring.output.ansi.enabled` property. Fixes gh-1243 --- .../main/asciidoc/spring-boot-features.adoc | 5 +- .../springframework/boot/ansi/AnsiOutput.java | 26 +++++- .../ansi/AnsiOutputApplicationListener.java | 53 ++++++++++++ .../main/resources/META-INF/spring.factories | 2 +- .../AnsiOutputApplicationListenerTests.java | 85 +++++++++++++++++++ .../src/test/resources/ansi.properties | 1 + 6 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutputApplicationListener.java create mode 100644 spring-boot/src/test/java/org/springframework/boot/ansi/AnsiOutputApplicationListenerTests.java create mode 100644 spring-boot/src/test/resources/ansi.properties diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 2cf4df88d2d..0268a91fcb4 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -711,7 +711,10 @@ messages to the console you can start your application with a `--debug` flag. $ java -jar myapp.jar --debug ---- -If your terminal supports ANSI, color output will be used to aid readability. +If your terminal supports ANSI, color output will be used to aid readability. You can set +`spring.output.ansi.enabled` to a +{dc-spring-boot}/ansi/AnsiOutput.Enabled.{dc-ext}[supported value] to override the auto +detection. diff --git a/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java b/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java index 9a8411534d0..10a9579abc8 100644 --- a/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java +++ b/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutput.java @@ -48,6 +48,10 @@ public abstract class AnsiOutput { AnsiOutput.enabled = enabled; } + static Enabled getEnabled() { + return AnsiOutput.enabled; + } + /** * Create a new ANSI string from the specified elements. Any {@link AnsiElement}s will * be encoded as required. @@ -121,8 +125,28 @@ public abstract class AnsiOutput { } } + /** + * Possible values to pass to {@link AnsiOutput#setEnabled}. Determines when to output + * ANSI escape sequences for coloring application output. + */ public static enum Enabled { - DETECT, ALWAYS, NEVER + + /** + * Try to detect whether ANSI coloring capabilities are available. The default + * value for {@link AnsiOutput}. + */ + DETECT, + + /** + * Enable ANSI-colored output + */ + ALWAYS, + + /** + * Disable ANSI-colored output + */ + NEVER + }; } diff --git a/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutputApplicationListener.java b/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutputApplicationListener.java new file mode 100644 index 00000000000..ee106dd1b1f --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/ansi/AnsiOutputApplicationListener.java @@ -0,0 +1,53 @@ +/* + * 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. + * 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.ansi; + +import org.springframework.boot.ansi.AnsiOutput.Enabled; +import org.springframework.boot.bind.RelaxedPropertyResolver; +import org.springframework.boot.context.config.ConfigFileApplicationListener; +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.Ordered; + +/** + * An {@link ApplicationListener} that configures {@link AnsiOutput} depending on the the + * value of the property spring.output.ansi.enabled. See + * {@link AnsiOutput.Enabled} for valid values. + * + * @author Raphael von der GrĂ¼n + * @since 1.2.0 + */ +public class AnsiOutputApplicationListener implements + ApplicationListener, Ordered { + + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { + RelaxedPropertyResolver resolver = new RelaxedPropertyResolver( + event.getEnvironment(), "spring.output.ansi."); + if (resolver.containsProperty("enabled")) { + String enabled = resolver.getProperty("enabled"); + AnsiOutput.setEnabled(Enum.valueOf(Enabled.class, enabled.toUpperCase())); + } + } + + @Override + public int getOrder() { + // Apply after the ConfigFileApplicationListener + return ConfigFileApplicationListener.DEFAULT_ORDER + 1; + } + +} diff --git a/spring-boot/src/main/resources/META-INF/spring.factories b/spring-boot/src/main/resources/META-INF/spring.factories index 46229bdfb2e..fb942f5087a 100644 --- a/spring-boot/src/main/resources/META-INF/spring.factories +++ b/spring-boot/src/main/resources/META-INF/spring.factories @@ -14,6 +14,7 @@ org.springframework.boot.context.config.DelegatingApplicationContextInitializer # Application Listeners org.springframework.context.ApplicationListener=\ +org.springframework.boot.ansi.AnsiOutputApplicationListener,\ org.springframework.boot.builder.ParentContextCloserApplicationListener,\ org.springframework.boot.cloudfoundry.VcapApplicationListener,\ org.springframework.boot.context.FileEncodingApplicationListener,\ @@ -22,4 +23,3 @@ org.springframework.boot.context.config.DelegatingApplicationListener,\ org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\ org.springframework.boot.logging.ClasspathLoggingApplicationListener,\ org.springframework.boot.logging.LoggingApplicationListener - diff --git a/spring-boot/src/test/java/org/springframework/boot/ansi/AnsiOutputApplicationListenerTests.java b/spring-boot/src/test/java/org/springframework/boot/ansi/AnsiOutputApplicationListenerTests.java new file mode 100644 index 00000000000..61a320d74b4 --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/ansi/AnsiOutputApplicationListenerTests.java @@ -0,0 +1,85 @@ +/* + * 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. + * 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.ansi; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.ansi.AnsiOutput.Enabled; +import org.springframework.boot.test.EnvironmentTestUtils; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.StandardEnvironment; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link AnsiOutputApplicationListener}. + * + * @author Phillip Webb + */ +public class AnsiOutputApplicationListenerTests { + + @Before + @After + public void resetAnsi() { + AnsiOutput.setEnabled(Enabled.DETECT); + } + + @Test + public void enabled() { + SpringApplication application = new SpringApplication(Config.class); + application.setWebEnvironment(false); + Map props = new HashMap(); + props.put("spring.output.ansi.enabled", "ALWAYS"); + application.setDefaultProperties(props); + application.run(); + assertThat(AnsiOutput.getEnabled(), equalTo(Enabled.ALWAYS)); + } + + @Test + public void disabled() throws Exception { + SpringApplication application = new SpringApplication(Config.class); + application.setWebEnvironment(false); + Map props = new HashMap(); + props.put("spring.output.ansi.enabled", "never"); + application.setDefaultProperties(props); + application.run(); + assertThat(AnsiOutput.getEnabled(), equalTo(Enabled.NEVER)); + } + + @Test + public void disabledViaApplcationProperties() throws Exception { + ConfigurableEnvironment environment = new StandardEnvironment(); + EnvironmentTestUtils.addEnvironment(environment, "spring.config.name:ansi"); + SpringApplication application = new SpringApplication(Config.class); + application.setWebEnvironment(false); + application.setEnvironment(environment); + application.run(); + assertThat(AnsiOutput.getEnabled(), equalTo(Enabled.NEVER)); + } + + @Configuration + public static class Config { + } + +} diff --git a/spring-boot/src/test/resources/ansi.properties b/spring-boot/src/test/resources/ansi.properties new file mode 100644 index 00000000000..d99e75a60b9 --- /dev/null +++ b/spring-boot/src/test/resources/ansi.properties @@ -0,0 +1 @@ +spring.output.ansi.enabled=never