diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java index 37971ba11bb1..c53e42f40059 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java @@ -27,10 +27,12 @@ import org.gradle.api.file.FileCopyDetails; import org.gradle.api.file.FileTreeElement; import org.gradle.api.internal.file.copy.CopyAction; +import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.specs.Spec; import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Nested; import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.bundling.Jar; /** @@ -103,7 +105,12 @@ public void copy() { @Override protected CopyAction createCopyAction() { if (this.layered != null) { - LayerResolver layerResolver = new LayerResolver(getConfigurations(), this.layered, this::isLibrary); + JavaPluginConvention javaPluginConvention = getProject().getConvention() + .findPlugin(JavaPluginConvention.class); + Iterable sourceSets = (javaPluginConvention != null) ? javaPluginConvention.getSourceSets() + : Collections.emptySet(); + LayerResolver layerResolver = new LayerResolver(sourceSets, getConfigurations(), this.layered, + this::isLibrary); String layerToolsLocation = this.layered.isIncludeLayerTools() ? LIB_DIRECTORY : null; return this.support.createCopyAction(this, layerResolver, layerToolsLocation); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LayerResolver.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LayerResolver.java index 2fc47fd68200..bbeee6d6e44a 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LayerResolver.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/LayerResolver.java @@ -17,8 +17,6 @@ package org.springframework.boot.gradle.tasks.bundling; import java.io.File; -import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; @@ -30,6 +28,7 @@ import org.gradle.api.artifacts.ResolvedConfiguration; import org.gradle.api.file.FileCopyDetails; import org.gradle.api.specs.Spec; +import org.gradle.api.tasks.SourceSet; import org.springframework.boot.loader.tools.Layer; import org.springframework.boot.loader.tools.Library; @@ -53,9 +52,9 @@ class LayerResolver { private final Spec librarySpec; - LayerResolver(Iterable configurations, LayeredSpec layeredConfiguration, - Spec librarySpec) { - this.resolvedDependencies = new ResolvedDependencies(configurations); + LayerResolver(Iterable sourceSets, Iterable configurations, + LayeredSpec layeredConfiguration, Spec librarySpec) { + this.resolvedDependencies = new ResolvedDependencies(sourceSets, configurations); this.layeredConfiguration = layeredConfiguration; this.librarySpec = librarySpec; } @@ -96,19 +95,41 @@ private Library asLibrary(FileCopyDetails details) { */ private static class ResolvedDependencies { - private static final Set DEPRECATED_FOR_RESOLUTION_CONFIGURATIONS = Collections - .unmodifiableSet(new HashSet<>(Arrays.asList("archives", "compile", "compileOnly", "default", "runtime", - "testCompile", "testCompileOnly", "testRuntime"))); + private final Set deprecatedForResolutionConfigurationNames; private final Map configurationDependencies = new LinkedHashMap<>(); - ResolvedDependencies(Iterable configurations) { + ResolvedDependencies(Iterable sourceSets, Iterable configurations) { + this.deprecatedForResolutionConfigurationNames = deprecatedForResolutionConfigurationNames(sourceSets); configurations.forEach(this::processConfiguration); } + @SuppressWarnings("deprecation") + private Set deprecatedForResolutionConfigurationNames(Iterable sourceSets) { + Set configurationNames = new HashSet<>(); + configurationNames.add("archives"); + configurationNames.add("default"); + for (SourceSet sourceSet : sourceSets) { + try { + configurationNames.add(sourceSet.getCompileConfigurationName()); + } + catch (NoSuchMethodError ex) { + // Continue + } + configurationNames.add(sourceSet.getCompileOnlyConfigurationName()); + try { + configurationNames.add(sourceSet.getRuntimeConfigurationName()); + } + catch (NoSuchMethodError ex) { + // Continue + } + } + return configurationNames; + } + private void processConfiguration(Configuration configuration) { if (configuration.isCanBeResolved() - && !DEPRECATED_FOR_RESOLUTION_CONFIGURATIONS.contains(configuration.getName())) { + && !this.deprecatedForResolutionConfigurationNames.contains(configuration.getName())) { this.configurationDependencies.put(configuration, new ResolvedConfigurationDependencies(configuration.getResolvedConfiguration())); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java index a3f7459bddb3..ada979dd2f56 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java @@ -86,6 +86,11 @@ void notUpToDateWhenBuiltWithLayersAndToolsAndThenWithLayersAndWithoutTools() .getOutcome()).isEqualTo(TaskOutcome.SUCCESS); } + @TestTemplate + void layersWithCustomSourceSet() throws IOException { + assertThat(this.gradleBuild.build("bootJar").task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + } + @TestTemplate void implicitLayers() throws IOException { writeMainClass(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-layersWithCustomSourceSet.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-layersWithCustomSourceSet.gradle new file mode 100644 index 000000000000..2cbb899f1c5c --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-layersWithCustomSourceSet.gradle @@ -0,0 +1,36 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '{version}' +} + +sourceSets { + custom +} + +bootJar { + mainClassName = 'com.example.Application' + layered() +} + +repositories { + mavenCentral() + maven { url "file:repository" } +} + +dependencies { + implementation("com.example:library:1.0-SNAPSHOT") + implementation("org.apache.commons:commons-lang3:3.9") + implementation("org.springframework:spring-core:5.2.5.RELEASE") +} + +task listLayers(type: JavaExec) { + classpath = bootJar.outputs.files + systemProperties = [ "jarmode": "layertools" ] + args "list" +} + +task extractLayers(type: JavaExec) { + classpath = bootJar.outputs.files + systemProperties = [ "jarmode": "layertools" ] + args "extract" +}