Commit 76715616 authored by Andy Wilkinson's avatar Andy Wilkinson

Merge pull request #21207 from PaddyDrury

* gh-21207:
  Polish "Stop limiting layer customization to external modules"
  Stop limiting layer customization to external modules

Closes gh-21207
parents fe347df5 2d769e76
...@@ -24,11 +24,10 @@ import java.util.LinkedHashMap; ...@@ -24,11 +24,10 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.gradle.api.artifacts.ArtifactCollection;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.component.ComponentIdentifier; import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.result.ResolvedArtifactResult; import org.gradle.api.artifacts.ResolvedConfiguration;
import org.gradle.api.file.FileCopyDetails; import org.gradle.api.file.FileCopyDetails;
import org.gradle.api.specs.Spec; import org.gradle.api.specs.Spec;
...@@ -43,6 +42,7 @@ import org.springframework.boot.loader.tools.LibraryCoordinates; ...@@ -43,6 +42,7 @@ import org.springframework.boot.loader.tools.LibraryCoordinates;
* @author Madhura Bhave * @author Madhura Bhave
* @author Scott Frederick * @author Scott Frederick
* @author Phillip Webb * @author Phillip Webb
* @author Paddy Drury
* @see BootZipCopyAction * @see BootZipCopyAction
*/ */
class LayerResolver { class LayerResolver {
...@@ -110,7 +110,7 @@ class LayerResolver { ...@@ -110,7 +110,7 @@ class LayerResolver {
if (configuration.isCanBeResolved() if (configuration.isCanBeResolved()
&& !DEPRECATED_FOR_RESOLUTION_CONFIGURATIONS.contains(configuration.getName())) { && !DEPRECATED_FOR_RESOLUTION_CONFIGURATIONS.contains(configuration.getName())) {
this.configurationDependencies.put(configuration, this.configurationDependencies.put(configuration,
new ResolvedConfigurationDependencies(configuration.getIncoming().getArtifacts())); new ResolvedConfigurationDependencies(configuration.getResolvedConfiguration()));
} }
} }
...@@ -133,16 +133,10 @@ class LayerResolver { ...@@ -133,16 +133,10 @@ class LayerResolver {
private final Map<File, LibraryCoordinates> artifactCoordinates = new LinkedHashMap<>(); private final Map<File, LibraryCoordinates> artifactCoordinates = new LinkedHashMap<>();
ResolvedConfigurationDependencies(ArtifactCollection resolvedDependencies) { ResolvedConfigurationDependencies(ResolvedConfiguration resolvedConfiguration) {
if (resolvedDependencies != null) { for (ResolvedArtifact resolvedArtifact : resolvedConfiguration.getResolvedArtifacts()) {
for (ResolvedArtifactResult resolvedArtifact : resolvedDependencies.getArtifacts()) { this.artifactCoordinates.put(resolvedArtifact.getFile(),
ComponentIdentifier identifier = resolvedArtifact.getId().getComponentIdentifier(); new ModuleVersionIdentifierLibraryCoordinates(resolvedArtifact.getModuleVersion().getId()));
if (identifier instanceof ModuleComponentIdentifier) {
this.artifactCoordinates.put(resolvedArtifact.getFile(),
new ModuleComponentIdentifierLibraryCoordinates(
(ModuleComponentIdentifier) identifier));
}
}
} }
} }
...@@ -153,13 +147,13 @@ class LayerResolver { ...@@ -153,13 +147,13 @@ class LayerResolver {
} }
/** /**
* Adapts a {@link ModuleComponentIdentifier} to {@link LibraryCoordinates}. * Adapts a {@link ModuleVersionIdentifier} to {@link LibraryCoordinates}.
*/ */
private static class ModuleComponentIdentifierLibraryCoordinates implements LibraryCoordinates { private static class ModuleVersionIdentifierLibraryCoordinates implements LibraryCoordinates {
private final ModuleComponentIdentifier identifier; private final ModuleVersionIdentifier identifier;
ModuleComponentIdentifierLibraryCoordinates(ModuleComponentIdentifier identifier) { ModuleVersionIdentifierLibraryCoordinates(ModuleVersionIdentifier identifier) {
this.identifier = identifier; this.identifier = identifier;
} }
...@@ -170,7 +164,7 @@ class LayerResolver { ...@@ -170,7 +164,7 @@ class LayerResolver {
@Override @Override
public String getArtifactId() { public String getArtifactId() {
return this.identifier.getModule(); return this.identifier.getName();
} }
@Override @Override
......
...@@ -53,6 +53,7 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -53,6 +53,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Madhura Bhave * @author Madhura Bhave
* @author Paddy Drury
*/ */
class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests { class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests {
...@@ -176,6 +177,64 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests { ...@@ -176,6 +177,64 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests {
assertExtractedLayers(layerNames, indexedLayers); assertExtractedLayers(layerNames, indexedLayers);
} }
@TestTemplate
void multiModuleCustomLayers() throws IOException {
writeSettingsGradle();
writeMainClass();
writeResource();
BuildResult build = this.gradleBuild.build("bootJar");
assertThat(build.task(":bootJar").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
Map<String, List<String>> indexedLayers;
String layerToolsJar = "BOOT-INF/lib/" + JarModeLibrary.LAYER_TOOLS.getName();
try (JarFile jarFile = new JarFile(new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0])) {
assertThat(jarFile.getEntry(layerToolsJar)).isNotNull();
assertThat(jarFile.getEntry("BOOT-INF/lib/alpha-1.2.3.jar")).isNotNull();
assertThat(jarFile.getEntry("BOOT-INF/lib/bravo-1.2.3.jar")).isNotNull();
assertThat(jarFile.getEntry("BOOT-INF/lib/commons-lang3-3.9.jar")).isNotNull();
assertThat(jarFile.getEntry("BOOT-INF/lib/spring-core-5.2.5.RELEASE.jar")).isNotNull();
assertThat(jarFile.getEntry("BOOT-INF/lib/spring-jcl-5.2.5.RELEASE.jar")).isNotNull();
assertThat(jarFile.getEntry("BOOT-INF/lib/commons-io-2.7-SNAPSHOT.jar")).isNotNull();
assertThat(jarFile.getEntry("BOOT-INF/classes/example/Main.class")).isNotNull();
assertThat(jarFile.getEntry("BOOT-INF/classes/static/file.txt")).isNotNull();
assertThat(jarFile.getEntry("BOOT-INF/layers.idx")).isNotNull();
indexedLayers = readLayerIndex(jarFile);
}
List<String> layerNames = Arrays.asList("dependencies", "commons-dependencies", "snapshot-dependencies",
"subproject-dependencies", "static", "app");
assertThat(indexedLayers.keySet()).containsExactlyElementsOf(layerNames);
Set<String> expectedSubprojectDependencies = new TreeSet<>();
expectedSubprojectDependencies.add("BOOT-INF/lib/alpha-1.2.3.jar");
expectedSubprojectDependencies.add("BOOT-INF/lib/bravo-1.2.3.jar");
Set<String> expectedDependencies = new TreeSet<>();
expectedDependencies.add("BOOT-INF/lib/spring-core-5.2.5.RELEASE.jar");
expectedDependencies.add("BOOT-INF/lib/spring-jcl-5.2.5.RELEASE.jar");
List<String> expectedSnapshotDependencies = new ArrayList<>();
expectedSnapshotDependencies.add("BOOT-INF/lib/commons-io-2.7-SNAPSHOT.jar");
(layerToolsJar.contains("SNAPSHOT") ? expectedSnapshotDependencies : expectedDependencies).add(layerToolsJar);
assertThat(indexedLayers.get("subproject-dependencies"))
.containsExactlyElementsOf(expectedSubprojectDependencies);
assertThat(indexedLayers.get("dependencies")).containsExactlyElementsOf(expectedDependencies);
assertThat(indexedLayers.get("commons-dependencies")).containsExactly("BOOT-INF/lib/commons-lang3-3.9.jar");
assertThat(indexedLayers.get("snapshot-dependencies")).containsExactlyElementsOf(expectedSnapshotDependencies);
assertThat(indexedLayers.get("static")).containsExactly("BOOT-INF/classes/static/");
List<String> appLayer = new ArrayList<>(indexedLayers.get("app"));
Set<String> nonLoaderEntries = new TreeSet<>();
nonLoaderEntries.add("BOOT-INF/classes/example/");
nonLoaderEntries.add("BOOT-INF/classpath.idx");
nonLoaderEntries.add("BOOT-INF/layers.idx");
nonLoaderEntries.add("META-INF/");
assertThat(appLayer).containsSubsequence(nonLoaderEntries);
appLayer.removeAll(nonLoaderEntries);
assertThat(appLayer).containsExactly("org/");
BuildResult listLayers = this.gradleBuild.build("listLayers");
assertThat(listLayers.task(":listLayers").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
String listLayersOutput = listLayers.getOutput();
assertThat(new BufferedReader(new StringReader(listLayersOutput)).lines()).containsSequence(layerNames);
BuildResult extractLayers = this.gradleBuild.build("extractLayers");
assertThat(extractLayers.task(":extractLayers").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertExtractedLayers(layerNames, indexedLayers);
}
private void assertExtractedLayers(List<String> layerNames, Map<String, List<String>> indexedLayers) private void assertExtractedLayers(List<String> layerNames, Map<String, List<String>> indexedLayers)
throws IOException { throws IOException {
Map<String, List<String>> extractedLayers = readExtractedLayers(this.gradleBuild.getProjectDir(), layerNames); Map<String, List<String>> extractedLayers = readExtractedLayers(this.gradleBuild.getProjectDir(), layerNames);
...@@ -201,6 +260,16 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests { ...@@ -201,6 +260,16 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests {
return false; return false;
} }
private void writeSettingsGradle() {
try (PrintWriter writer = new PrintWriter(
new FileWriter(new File(this.gradleBuild.getProjectDir(), "settings.gradle")))) {
writer.println("include 'alpha', 'bravo'");
}
catch (IOException ex) {
throw new RuntimeException(ex);
}
}
private void writeMainClass() { private void writeMainClass() {
File examplePackage = new File(this.gradleBuild.getProjectDir(), "src/main/java/example"); File examplePackage = new File(this.gradleBuild.getProjectDir(), "src/main/java/example");
examplePackage.mkdirs(); examplePackage.mkdirs();
......
plugins {
id 'java'
id 'org.springframework.boot' version '{version}'
}
subprojects {
apply plugin: 'java'
group = 'org.example.projects'
version = '1.2.3'
}
bootJar {
mainClassName = 'com.example.Application'
layered {
application {
intoLayer("static") {
include "META-INF/resources/**", "resources/**", "static/**", "public/**"
}
intoLayer("app")
}
dependencies {
intoLayer("subproject-dependencies") {
include "org.example.projects:*"
}
intoLayer("snapshot-dependencies") {
include "*:*:*SNAPSHOT"
}
intoLayer("commons-dependencies") {
include "org.apache.commons:*"
}
intoLayer("dependencies")
}
layerOrder = ["dependencies", "commons-dependencies", "snapshot-dependencies", "subproject-dependencies", "static", "app"]
}
}
repositories {
mavenCentral()
maven { url "https://repository.apache.org/content/repositories/snapshots" }
}
dependencies {
implementation(project(':alpha'))
implementation(project(':bravo'))
implementation("commons-io:commons-io:2.7-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"
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment