diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/Banner.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/Banner.java
index 1624982dae..eea8b02ffd 100644
--- a/spring-bootstrap/src/main/java/org/springframework/bootstrap/Banner.java
+++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/Banner.java
@@ -18,6 +18,12 @@ package org.springframework.bootstrap;
import java.io.PrintStream;
+import org.springframework.bootstrap.ansi.AnsiOutput;
+
+import static org.springframework.bootstrap.ansi.AnsiElement.DEFAULT;
+import static org.springframework.bootstrap.ansi.AnsiElement.FAINT;
+import static org.springframework.bootstrap.ansi.AnsiElement.GREEN;
+
/**
* Writes the 'Spring' banner.
*
@@ -25,7 +31,8 @@ import java.io.PrintStream;
*/
abstract class Banner {
- private static final String[] BANNER = { " . ____ _ __ _ _",
+ private static final String[] BANNER = { "",
+ " . ____ _ __ _ _",
" /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\",
"( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\",
" \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )",
@@ -37,14 +44,12 @@ abstract class Banner {
* @param printStream the output print stream
*/
public static void write(PrintStream printStream) {
- printStream.println();
for (String line : BANNER) {
printStream.println(line);
}
String version = Banner.class.getPackage().getImplementationVersion();
- printStream.println(" Spring Bootstrap"
- + (version == null ? "" : " (v" + version + ")"));
+ printStream.println(AnsiOutput.toString(GREEN, " Spring Bootstrap", DEFAULT,
+ FAINT, (version == null ? "" : " (v" + version + ")")));
printStream.println();
}
-
}
diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/ansi/AnsiElement.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/ansi/AnsiElement.java
new file mode 100644
index 0000000000..6b2846034b
--- /dev/null
+++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/ansi/AnsiElement.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.bootstrap.ansi;
+
+/**
+ * An ANSI encodable element.
+ *
+ * @author Phillip Webb
+ */
+public interface AnsiElement {
+
+ public static final AnsiElement NORMAL = new DefaultAnsiElement("0");
+ public static final AnsiElement BOLD = new DefaultAnsiElement("1");
+ public static final AnsiElement FAINT = new DefaultAnsiElement("2");
+ public static final AnsiElement ITALIC = new DefaultAnsiElement("3");
+ public static final AnsiElement UNDERLINE = new DefaultAnsiElement("4");
+
+ public static final AnsiElement BLACK = new DefaultAnsiElement("30");
+ public static final AnsiElement RED = new DefaultAnsiElement("31");
+ public static final AnsiElement GREEN = new DefaultAnsiElement("32");
+ public static final AnsiElement YELLOW = new DefaultAnsiElement("33");
+ public static final AnsiElement BLUE = new DefaultAnsiElement("34");
+ public static final AnsiElement MAGENTA = new DefaultAnsiElement("35");
+ public static final AnsiElement CYAN_FG = new DefaultAnsiElement("36");
+ public static final AnsiElement WHITE = new DefaultAnsiElement("37");
+ public static final AnsiElement DEFAULT = new DefaultAnsiElement("39");
+
+ /**
+ * @return the ANSI escape code
+ */
+ @Override
+ public String toString();
+
+ /**
+ * Internal default {@link AnsiElement} implementation.
+ */
+ static class DefaultAnsiElement implements AnsiElement {
+
+ private final String code;
+
+ public DefaultAnsiElement(String code) {
+ this.code = code;
+ }
+
+ @Override
+ public String toString() {
+ return this.code;
+ }
+ }
+
+}
diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/ansi/AnsiOutput.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/ansi/AnsiOutput.java
new file mode 100644
index 0000000000..ce544be2b5
--- /dev/null
+++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/ansi/AnsiOutput.java
@@ -0,0 +1,123 @@
+/*
+ * 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.bootstrap.ansi;
+
+import org.springframework.util.Assert;
+
+/**
+ * Generates ANSI encoded output, automatically attempting to detect if the terminal
+ * supports ANSI.
+ *
+ * @author Phillip Webb
+ */
+public abstract class AnsiOutput {
+
+ private static final String ENCODE_JOIN = ";";
+
+ private static Enabled enabled = Enabled.DETECT;
+
+ private static final String OPERATING_SYSTEM_NAME = System.getProperty("os.name")
+ .toLowerCase();
+
+ private static final Object ENCODE_START = "\033[";
+
+ private static final Object ENCODE_END = "m";
+
+ final private static String RESET = "0;" + AnsiElement.DEFAULT;
+
+ /**
+ * Sets if ANSI output is enabled.
+ * @param enabled if ANSI is enabled, disabled or detected
+ */
+ public static void setEnabled(Enabled enabled) {
+ Assert.notNull(enabled, "Enabled must not be null");
+ AnsiOutput.enabled = enabled;
+ }
+
+ /**
+ * Create a new ANSI string from the specified elements. Any {@link AnsiElement}s will
+ * be encoded as required.
+ * @param elements the elements to encode
+ * @return a string of the encoded elements
+ */
+ public static String toString(Object... elements) {
+ StringBuilder sb = new StringBuilder();
+ if (isEnabled()) {
+ buildEnabled(sb, elements);
+ }
+ else {
+ buildDisabled(sb, elements);
+ }
+ return sb.toString();
+ }
+
+ private static void buildEnabled(StringBuilder sb, Object[] elements) {
+ boolean writingAnsi = false;
+ boolean containsEncoding = false;
+ for (Object element : elements) {
+ if (element instanceof AnsiElement) {
+ containsEncoding = true;
+ if (!writingAnsi) {
+ sb.append(ENCODE_START);
+ writingAnsi = true;
+ }
+ else {
+ sb.append(ENCODE_JOIN);
+ }
+ }
+ else {
+ if (writingAnsi) {
+ sb.append(ENCODE_END);
+ writingAnsi = false;
+ }
+ }
+ sb.append(element);
+ }
+ if (containsEncoding) {
+ sb.append(writingAnsi ? ENCODE_JOIN : ENCODE_START);
+ sb.append(RESET);
+ sb.append(ENCODE_END);
+ }
+ }
+
+ private static void buildDisabled(StringBuilder sb, Object[] elements) {
+ for (Object element : elements) {
+ if (!(element instanceof AnsiElement) && element != null) {
+ sb.append(element);
+ }
+ }
+ }
+
+ private static boolean isEnabled() {
+ if (enabled == Enabled.DETECT) {
+ return detectIfEnabled();
+ }
+ return enabled == Enabled.ALWAYS;
+ }
+
+ private static boolean detectIfEnabled() {
+ if (System.console() == null) {
+ return false;
+ }
+ return !(OPERATING_SYSTEM_NAME.indexOf("win") >= 0);
+ }
+
+ public static enum Enabled {
+ DETECT, ALWAYS, NEVER
+ };
+
+}
diff --git a/spring-bootstrap/src/test/java/org/springframework/bootstrap/ansi/AnsiOutputTest.java b/spring-bootstrap/src/test/java/org/springframework/bootstrap/ansi/AnsiOutputTest.java
new file mode 100644
index 0000000000..7242769933
--- /dev/null
+++ b/spring-bootstrap/src/test/java/org/springframework/bootstrap/ansi/AnsiOutputTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.bootstrap.ansi;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.bootstrap.ansi.AnsiOutput.Enabled;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.springframework.bootstrap.ansi.AnsiElement.BOLD;
+import static org.springframework.bootstrap.ansi.AnsiElement.FAINT;
+import static org.springframework.bootstrap.ansi.AnsiElement.GREEN;
+import static org.springframework.bootstrap.ansi.AnsiElement.NORMAL;
+import static org.springframework.bootstrap.ansi.AnsiElement.RED;
+
+/**
+ * Tests for {@link AnsiOutput}.
+ *
+ * @author Phillip Webb
+ */
+public class AnsiOutputTest {
+
+ @BeforeClass
+ public static void enable() {
+ AnsiOutput.setEnabled(Enabled.ALWAYS);
+ }
+
+ @AfterClass
+ public static void reset() {
+ AnsiOutput.setEnabled(Enabled.DETECT);
+ }
+
+ @Test
+ public void encoding() throws Exception {
+ String encoded = AnsiOutput.toString("A", RED, BOLD, "B", NORMAL, "D", GREEN,
+ "E", FAINT, "F");
+ assertThat(encoded, equalTo("A[31;1mB[0mD[32mE[2mF[0;39m"));
+ }
+
+}
diff --git a/spring-starters/spring-starter/pom.xml b/spring-starters/spring-starter/pom.xml
index 14ca37d1d7..e13c6798c2 100644
--- a/spring-starters/spring-starter/pom.xml
+++ b/spring-starters/spring-starter/pom.xml
@@ -36,11 +36,6 @@
org.slf4j
jcl-over-slf4j
-
- org.slf4j
- slf4j-jdk14
- runtime
-
org.springframework
spring-beans