diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsGradleBuildCustomizer.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsGradleBuildCustomizer.java new file mode 100644 index 00000000..1ea367ce --- /dev/null +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsGradleBuildCustomizer.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012-2020 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 + * + * https://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 io.spring.initializr.generator.spring.dependency.devtools; + +import io.spring.initializr.generator.buildsystem.Dependency; +import io.spring.initializr.generator.buildsystem.gradle.GradleBuild; +import io.spring.initializr.generator.buildsystem.gradle.GradleDependency; +import io.spring.initializr.generator.spring.build.BuildCustomizer; +import io.spring.initializr.generator.version.Version; +import io.spring.initializr.generator.version.VersionParser; +import io.spring.initializr.generator.version.VersionRange; + +/** + * Gradle {@link BuildCustomizer} that creates a dedicated "developmentOnly" configuration + * when devtools is selected. + * + * @author Stephane Nicoll + */ +public class DevToolsGradleBuildCustomizer implements BuildCustomizer { + + private static final VersionRange SPRING_BOOT_2_3_0_RC1_OR_LATER = VersionParser.DEFAULT.parseRange("2.3.0.RC1"); + + private final Version platformVersion; + + private final String devtoolsDependencyId; + + /** + * Create a new instance with the requested {@link Version platform version} and the + * identifier for the devtools dependency. + * @param platformVersion the version of the plateform + * @param devtoolsDependencyId the id of the devtools dependency + */ + public DevToolsGradleBuildCustomizer(Version platformVersion, String devtoolsDependencyId) { + this.platformVersion = platformVersion; + this.devtoolsDependencyId = devtoolsDependencyId; + } + + @Override + public void customize(GradleBuild build) { + Dependency devtools = build.dependencies().get(this.devtoolsDependencyId); + if (devtools == null) { + return; + } + if (!SPRING_BOOT_2_3_0_RC1_OR_LATER.match(this.platformVersion)) { + build.configurations().add("developmentOnly"); + build.configurations().customize("runtimeClasspath", + (runtimeClasspath) -> runtimeClasspath.extendsFrom("developmentOnly")); + } + build.dependencies().add(this.devtoolsDependencyId, + GradleDependency.from(devtools).configuration("developmentOnly")); + } + +} diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsMavenBuildCustomizer.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsMavenBuildCustomizer.java new file mode 100644 index 00000000..50b52199 --- /dev/null +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsMavenBuildCustomizer.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012-2019 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 + * + * https://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 io.spring.initializr.generator.spring.dependency.devtools; + +import io.spring.initializr.generator.buildsystem.Dependency; +import io.spring.initializr.generator.buildsystem.maven.MavenBuild; +import io.spring.initializr.generator.buildsystem.maven.MavenDependency; +import io.spring.initializr.generator.spring.build.BuildCustomizer; + +/** + * Maven {@link BuildCustomizer} that sets the "optional" flag when devtools is selected. + * + * @author Stephane Nicoll + */ +public class DevToolsMavenBuildCustomizer implements BuildCustomizer { + + private final String devtoolsDependencyId; + + /** + * Create a new instance with the identifier for the devtools dependency. + * @param devtoolsDependencyId the id of the devtools dependency + */ + public DevToolsMavenBuildCustomizer(String devtoolsDependencyId) { + this.devtoolsDependencyId = devtoolsDependencyId; + } + + @Override + public void customize(MavenBuild build) { + Dependency devtools = build.dependencies().get(this.devtoolsDependencyId); + if (devtools != null) { + build.dependencies().add("devtools", MavenDependency.from(devtools).optional(true)); + } + } + +} diff --git a/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/dependency/devtools/package-info.java b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/dependency/devtools/package-info.java new file mode 100644 index 00000000..0d8bcd75 --- /dev/null +++ b/initializr-generator-spring/src/main/java/io/spring/initializr/generator/spring/dependency/devtools/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2020 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 + * + * https://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. + */ + +/** + * Customizations for Spring Boot DevTools. + */ +package io.spring.initializr.generator.spring.dependency.devtools; diff --git a/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsGradleBuildCustomizerTests.java b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsGradleBuildCustomizerTests.java new file mode 100644 index 00000000..29461a7a --- /dev/null +++ b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsGradleBuildCustomizerTests.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012-2020 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 + * + * https://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 io.spring.initializr.generator.spring.dependency.devtools; + +import io.spring.initializr.generator.buildsystem.Dependency; +import io.spring.initializr.generator.buildsystem.gradle.GradleBuild; +import io.spring.initializr.generator.buildsystem.gradle.GradleDependency; +import io.spring.initializr.generator.version.Version; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link DevToolsGradleBuildCustomizer}. + * + * @author Stephane Nicoll + */ +class DevToolsGradleBuildCustomizerTests { + + private static final Dependency DEVTOOLS_DEPENDENCY = Dependency + .withCoordinates("org.springframework.boot", "spring-boot-devtools").build(); + + @Test + void gradleWithDevtoolsAndSpringBootPriorTo23RC1CreatesDevelopmentOnlyConfiguration() { + GradleBuild build = new GradleBuild(); + build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY); + new DevToolsGradleBuildCustomizer(Version.parse("2.3.0.M4"), "devtools").customize(build); + assertThat(build.configurations().names()).containsOnly("developmentOnly"); + assertThat(build.configurations().customizations()).singleElement().satisfies((configuration) -> { + assertThat(configuration.getName()).isEqualTo("runtimeClasspath"); + assertThat(configuration.getExtendsFrom()).containsOnly("developmentOnly"); + }); + Dependency devtools = build.dependencies().get("devtools"); + assertThat(devtools).isInstanceOf(GradleDependency.class); + assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly"); + } + + @Test + void gradleWithDevtoolsAndSpringBoot23RC1OrLaterDoesNotCreateDevelopmentOnlyConfiguration() { + GradleBuild build = new GradleBuild(); + build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY); + build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY); + new DevToolsGradleBuildCustomizer(Version.parse("2.3.0.RC1"), "devtools").customize(build); + assertThat(build.configurations().names()).isEmpty(); + Dependency devtools = build.dependencies().get("devtools"); + assertThat(devtools).isInstanceOf(GradleDependency.class); + assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly"); + } + + @Test + void gradleWithoutDevtoolsAndSpringBootPriorTo23RC1DoesNotCreateDevelopmentOnlyConfiguration() { + GradleBuild build = new GradleBuild(); + build.dependencies().add("web", mock(Dependency.class)); + new DevToolsGradleBuildCustomizer(Version.parse("2.3.0.M4"), "devtools").customize(build); + assertThat(build.configurations().names()).isEmpty(); + assertThat(build.dependencies().ids()).containsOnly("web"); + } + +} diff --git a/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsMavenBuildCustomizerTests.java b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsMavenBuildCustomizerTests.java new file mode 100644 index 00000000..df46b36c --- /dev/null +++ b/initializr-generator-spring/src/test/java/io/spring/initializr/generator/spring/dependency/devtools/DevToolsMavenBuildCustomizerTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2020 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 + * + * https://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 io.spring.initializr.generator.spring.dependency.devtools; + +import io.spring.initializr.generator.buildsystem.Dependency; +import io.spring.initializr.generator.buildsystem.maven.MavenBuild; +import io.spring.initializr.generator.buildsystem.maven.MavenDependency; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link DevToolsMavenBuildCustomizer}. + * + * @author Stephane Nicoll + */ +class DevToolsMavenBuildCustomizerTests { + + private static final Dependency DEVTOOLS_DEPENDENCY = Dependency + .withCoordinates("org.springframework.boot", "spring-boot-devtools").build(); + + @Test + void mavenWithDevtoolsSwitchOptionalFlag() { + MavenBuild build = new MavenBuild(); + build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY); + new DevToolsMavenBuildCustomizer("devtools").customize(build); + Dependency devtools = build.dependencies().get("devtools"); + assertThat(devtools).isInstanceOf(MavenDependency.class); + assertThat(((MavenDependency) devtools).isOptional()).isTrue(); + + } + + @Test + void mavenWithoutDevtoolsDoesNotChangeDependencies() { + MavenBuild build = new MavenBuild(); + build.dependencies().add("web", mock(Dependency.class)); + new DevToolsMavenBuildCustomizer("devtools").customize(build); + assertThat(build.dependencies().ids()).containsOnly("web"); + } + +}