From 39077ee56cdf540d816a1255534fb0b9c77b6c98 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 11 Dec 2015 18:09:09 +0000 Subject: [PATCH] Extract ExitCodeGenerators class Extract exit code logic from SpringApplication to a new `ExitCodeGenerators` class so that it can be reused. Fixes gh-4757 --- .../boot/ExitCodeGenerators.java | 83 +++++++++++++++++ .../boot/SpringApplication.java | 28 ++---- .../boot/ExitCodeGeneratorsTests.java | 93 +++++++++++++++++++ 3 files changed, 182 insertions(+), 22 deletions(-) create mode 100644 spring-boot/src/main/java/org/springframework/boot/ExitCodeGenerators.java create mode 100644 spring-boot/src/test/java/org/springframework/boot/ExitCodeGeneratorsTests.java diff --git a/spring-boot/src/main/java/org/springframework/boot/ExitCodeGenerators.java b/spring-boot/src/main/java/org/springframework/boot/ExitCodeGenerators.java new file mode 100644 index 0000000000..e7567fc31e --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/ExitCodeGenerators.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012-2015 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.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.springframework.util.Assert; + +/** + * Maintains a collection of {@link ExitCodeGenerator} instances and allows the final exit + * code to be calculated. + * + * @author Dave Syer + * @author Phillip Webb + * @since 1.3.1 + * @see #getExitCode() + * @see ExitCodeGenerator + */ +public class ExitCodeGenerators implements Iterable { + + private List generators = new ArrayList(); + + public void addAll(ExitCodeGenerator... generators) { + Assert.notNull(generators, "Generators must not be null"); + addAll(Arrays.asList(generators)); + } + + public void addAll(Iterable generators) { + Assert.notNull(generators, "Generators must not be null"); + for (ExitCodeGenerator generator : generators) { + add(generator); + } + } + + public void add(ExitCodeGenerator generator) { + Assert.notNull(generator, "Generator must not be null"); + this.generators.add(generator); + } + + @Override + public Iterator iterator() { + return this.generators.iterator(); + } + + /** + * Get the final exit code that should be returned based on all contained generators. + * @return the final exit code. + */ + public int getExitCode() { + int exitCode = 0; + for (ExitCodeGenerator generator : this.generators) { + try { + int value = generator.getExitCode(); + if (value > 0 && value > exitCode || value < 0 && value < exitCode) { + exitCode = value; + } + } + catch (Exception ex) { + exitCode = (exitCode == 0 ? 1 : exitCode); + ex.printStackTrace(); + } + } + return exitCode; + } + +} 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 bfac555a65..f67c73fd9f 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -1143,11 +1143,12 @@ public class SpringApplication { int exitCode = 0; try { try { - List generators = new ArrayList(); - generators.addAll(Arrays.asList(exitCodeGenerators)); - generators - .addAll(context.getBeansOfType(ExitCodeGenerator.class).values()); - exitCode = getExitCode(generators); + ExitCodeGenerators generators = new ExitCodeGenerators(); + Collection beans = context + .getBeansOfType(ExitCodeGenerator.class).values(); + generators.addAll(exitCodeGenerators); + generators.addAll(beans); + exitCode = generators.getExitCode(); } finally { close(context); @@ -1161,23 +1162,6 @@ public class SpringApplication { return exitCode; } - private static int getExitCode(List exitCodeGenerators) { - int exitCode = 0; - for (ExitCodeGenerator exitCodeGenerator : exitCodeGenerators) { - try { - int value = exitCodeGenerator.getExitCode(); - if (value > 0 && value > exitCode || value < 0 && value < exitCode) { - exitCode = value; - } - } - catch (Exception ex) { - exitCode = (exitCode == 0 ? 1 : exitCode); - ex.printStackTrace(); - } - } - return exitCode; - } - private static void close(ApplicationContext context) { if (context instanceof ConfigurableApplicationContext) { ConfigurableApplicationContext closable = (ConfigurableApplicationContext) context; diff --git a/spring-boot/src/test/java/org/springframework/boot/ExitCodeGeneratorsTests.java b/spring-boot/src/test/java/org/springframework/boot/ExitCodeGeneratorsTests.java new file mode 100644 index 0000000000..efac9deaba --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/ExitCodeGeneratorsTests.java @@ -0,0 +1,93 @@ +/* + * Copyright 2012-2015 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.util.List; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link ExitCodeGenerators}. + * + * @author Phillip Webb + */ +public class ExitCodeGeneratorsTests { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void addAllWhenGeneratorsIsNullShouldThrowException() throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("Generators must not be null"); + List generators = null; + new ExitCodeGenerators().addAll(generators); + } + + @Test + public void addWhenGeneratorIsNullShouldThrowException() throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("Generator must not be null"); + new ExitCodeGenerators().add(null); + } + + @Test + public void getExitCodeWhenNoGeneratorsShouldReturnZero() throws Exception { + assertThat(new ExitCodeGenerators().getExitCode(), equalTo(0)); + } + + @Test + public void getExitCodeWhenGeneratorThrowsShouldReturnOne() throws Exception { + ExitCodeGenerator generator = mock(ExitCodeGenerator.class); + given(generator.getExitCode()).willThrow(new IllegalStateException()); + ExitCodeGenerators generators = new ExitCodeGenerators(); + generators.add(generator); + assertThat(generators.getExitCode(), equalTo(1)); + } + + @Test + public void getExitCodeWhenAllNegativeShouldReturnLowestValue() throws Exception { + ExitCodeGenerators generators = new ExitCodeGenerators(); + generators.add(mockGenerator(-1)); + generators.add(mockGenerator(-3)); + generators.add(mockGenerator(-2)); + assertThat(generators.getExitCode(), equalTo(-3)); + } + + @Test + public void getExitCodeWhenAllPositiveShouldReturnHighestValue() throws Exception { + ExitCodeGenerators generators = new ExitCodeGenerators(); + generators.add(mockGenerator(1)); + generators.add(mockGenerator(3)); + generators.add(mockGenerator(2)); + assertThat(generators.getExitCode(), equalTo(3)); + } + + private ExitCodeGenerator mockGenerator(int exitCode) { + ExitCodeGenerator generator = mock(ExitCodeGenerator.class); + given(generator.getExitCode()).willReturn(exitCode); + return generator; + } + +}