Support flat jar layering with Maven

Update the Maven plugin so that layered jars now use the regular "flat"
format. The layers.idx file now describes which layer each file should
be placed.

See gh-20813

Co-authored-by: Phillip Webb <pwebb@pivotal.io>
This commit is contained in:
Madhura Bhave
2020-04-01 12:14:03 -07:00
committed by Phillip Webb
parent 3f806aa513
commit 4e3cdf936f
15 changed files with 345 additions and 200 deletions

View File

@@ -238,7 +238,7 @@ abstract class AbstractPackagerTests<P extends Packager> {
}
@Test
void layeredLayout() throws Exception {
void layersIndex() throws Exception {
TestJarFile libJar1 = new TestJarFile(this.tempDir);
libJar1.addClass("a/b/C.class", ClassWithoutMainMethod.class, JAN_1_1985);
File libJarFile1 = libJar1.getFile();
@@ -256,7 +256,6 @@ abstract class AbstractPackagerTests<P extends Packager> {
layers.addLibrary(libJarFile3, "0003");
packager.setLayers(layers);
packager.setIncludeRelevantJarModeJars(false);
packager.setLayout(new Layouts.LayeredJar());
execute(packager, (callback) -> {
callback.library(new Library(libJarFile1, LibraryScope.COMPILE));
callback.library(new Library(libJarFile2, LibraryScope.COMPILE));
@@ -264,36 +263,105 @@ abstract class AbstractPackagerTests<P extends Packager> {
});
assertThat(hasPackagedEntry("BOOT-INF/classpath.idx")).isTrue();
String classpathIndex = getPackagedEntryContent("BOOT-INF/classpath.idx");
List<String> expectedJars = new ArrayList<>();
expectedJars.add("BOOT-INF/layers/0001/lib/" + libJarFile1.getName());
expectedJars.add("BOOT-INF/layers/0002/lib/" + libJarFile2.getName());
expectedJars.add("BOOT-INF/layers/0003/lib/" + libJarFile3.getName());
assertThat(Arrays.asList(classpathIndex.split("\\n"))).containsExactly(libJarFile1.getName(),
libJarFile2.getName(), libJarFile3.getName());
assertThat(hasPackagedEntry("BOOT-INF/layers.idx")).isTrue();
String layersIndex = getPackagedEntryContent("BOOT-INF/layers.idx");
List<String> expectedLayers = new ArrayList<>();
expectedLayers.add("default");
expectedLayers.add("0001");
expectedLayers.add("0002");
expectedLayers.add("0003");
getExpectedLayers(expectedLayers);
expectedLayers.add("default " + "BOOT-INF/classpath.idx");
expectedLayers.add("default " + "BOOT-INF/layers.idx");
expectedLayers.add("0001 " + "BOOT-INF/lib/" + libJarFile1.getName());
expectedLayers.add("0002 " + "BOOT-INF/lib/" + libJarFile2.getName());
expectedLayers.add("0003 " + "BOOT-INF/lib/" + libJarFile3.getName());
assertThat(Arrays.asList(layersIndex.split("\\n"))).containsExactly(expectedLayers.toArray(new String[0]));
}
private void getExpectedLayers(List<String> expectedLayers) {
expectedLayers.add("default META-INF/MANIFEST.MF");
expectedLayers.add("default org/springframework/boot/loader/ClassPathIndexFile.class");
expectedLayers.add("default org/springframework/boot/loader/ExecutableArchiveLauncher.class");
expectedLayers.add("default org/springframework/boot/loader/JarLauncher.class");
expectedLayers.add(
"default org/springframework/boot/loader/LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class");
expectedLayers.add("default org/springframework/boot/loader/LaunchedURLClassLoader.class");
expectedLayers.add("default org/springframework/boot/loader/Launcher.class");
expectedLayers.add("default org/springframework/boot/loader/MainMethodRunner.class");
expectedLayers.add("default org/springframework/boot/loader/PropertiesLauncher$1.class");
expectedLayers.add("default org/springframework/boot/loader/PropertiesLauncher$ArchiveEntryFilter.class");
expectedLayers
.add("default org/springframework/boot/loader/PropertiesLauncher$PrefixMatchingArchiveFilter.class");
expectedLayers.add("default org/springframework/boot/loader/PropertiesLauncher.class");
expectedLayers.add("default org/springframework/boot/loader/WarLauncher.class");
expectedLayers.add("default org/springframework/boot/loader/archive/Archive$Entry.class");
expectedLayers.add("default org/springframework/boot/loader/archive/Archive$EntryFilter.class");
expectedLayers.add("default org/springframework/boot/loader/archive/Archive.class");
expectedLayers.add("default org/springframework/boot/loader/archive/ExplodedArchive$AbstractIterator.class");
expectedLayers.add("default org/springframework/boot/loader/archive/ExplodedArchive$ArchiveIterator.class");
expectedLayers.add("default org/springframework/boot/loader/archive/ExplodedArchive$EntryIterator.class");
expectedLayers.add("default org/springframework/boot/loader/archive/ExplodedArchive$FileEntry.class");
expectedLayers
.add("default org/springframework/boot/loader/archive/ExplodedArchive$SimpleJarFileArchive.class");
expectedLayers.add("default org/springframework/boot/loader/archive/ExplodedArchive.class");
expectedLayers.add("default org/springframework/boot/loader/archive/JarFileArchive$AbstractIterator.class");
expectedLayers.add("default org/springframework/boot/loader/archive/JarFileArchive$EntryIterator.class");
expectedLayers.add("default org/springframework/boot/loader/archive/JarFileArchive$JarFileEntry.class");
expectedLayers
.add("default org/springframework/boot/loader/archive/JarFileArchive$NestedArchiveIterator.class");
expectedLayers.add("default org/springframework/boot/loader/archive/JarFileArchive.class");
expectedLayers.add("default org/springframework/boot/loader/data/RandomAccessData.class");
expectedLayers.add("default org/springframework/boot/loader/data/RandomAccessDataFile$1.class");
expectedLayers.add("default org/springframework/boot/loader/data/RandomAccessDataFile$DataInputStream.class");
expectedLayers.add("default org/springframework/boot/loader/data/RandomAccessDataFile$FileAccess.class");
expectedLayers.add("default org/springframework/boot/loader/data/RandomAccessDataFile.class");
expectedLayers.add("default org/springframework/boot/loader/jar/AsciiBytes.class");
expectedLayers.add("default org/springframework/boot/loader/jar/Bytes.class");
expectedLayers.add("default org/springframework/boot/loader/jar/CentralDirectoryEndRecord$1.class");
expectedLayers.add("default org/springframework/boot/loader/jar/CentralDirectoryEndRecord$Zip64End.class");
expectedLayers.add("default org/springframework/boot/loader/jar/CentralDirectoryEndRecord$Zip64Locator.class");
expectedLayers.add("default org/springframework/boot/loader/jar/CentralDirectoryEndRecord.class");
expectedLayers.add("default org/springframework/boot/loader/jar/CentralDirectoryFileHeader.class");
expectedLayers.add("default org/springframework/boot/loader/jar/CentralDirectoryParser.class");
expectedLayers.add("default org/springframework/boot/loader/jar/CentralDirectoryVisitor.class");
expectedLayers.add("default org/springframework/boot/loader/jar/FileHeader.class");
expectedLayers.add("default org/springframework/boot/loader/jar/Handler.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarEntry.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarEntryFilter.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarFile$1.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarFile$2.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarFile$JarFileType.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarFile.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarFileEntries$1.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarFileEntries$EntryIterator.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarFileEntries.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarURLConnection$1.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarURLConnection$2.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarURLConnection$CloseAction.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarURLConnection$JarEntryName.class");
expectedLayers.add("default org/springframework/boot/loader/jar/JarURLConnection.class");
expectedLayers.add("default org/springframework/boot/loader/jar/StringSequence.class");
expectedLayers.add("default org/springframework/boot/loader/jar/ZipInflaterInputStream.class");
expectedLayers.add("default org/springframework/boot/loader/jarmode/JarMode.class");
expectedLayers.add("default org/springframework/boot/loader/jarmode/JarModeLauncher.class");
expectedLayers.add("default org/springframework/boot/loader/jarmode/TestJarMode.class");
expectedLayers.add("default org/springframework/boot/loader/util/SystemPropertyUtils.class");
expectedLayers.add("default BOOT-INF/classes/a/b/C.class");
}
@Test
void layeredLayoutAddJarModeJar() throws Exception {
void layersEnabledAddJarModeJar() throws Exception {
this.testJarFile.addClass("a/b/C.class", ClassWithMainMethod.class);
P packager = createPackager();
TestLayers layers = new TestLayers();
packager.setLayers(layers);
packager.setLayout(new Layouts.LayeredJar());
execute(packager, Libraries.NONE);
assertThat(hasPackagedEntry("BOOT-INF/classpath.idx")).isTrue();
String classpathIndex = getPackagedEntryContent("BOOT-INF/classpath.idx");
assertThat(Arrays.asList(classpathIndex.split("\\n"))).containsExactly("spring-boot-jarmode-layertools.jar");
assertThat(hasPackagedEntry("BOOT-INF/layers.idx")).isTrue();
String layersIndex = getPackagedEntryContent("BOOT-INF/layers.idx");
assertThat(Arrays.asList(layersIndex.split("\\n"))).containsExactly("default");
assertThat(Arrays.stream(layersIndex.split("\\n")).map((n) -> n.split(" ")[0]).distinct())
.containsExactly("default");
}
@Test

View File

@@ -60,6 +60,14 @@ class ImplicitLayerResolverTests {
assertThat(this.layers.getLayer("com/example/application.properties")).isEqualTo(StandardLayers.APPLICATION);
}
@Test
void getLayerWhenLoaderClassReturnsLoaderLayer() {
assertThat(this.layers.getLayer("org/springframework/boot/loader/Launcher.class"))
.isEqualTo(StandardLayers.SPRING_BOOT_LOADER);
assertThat(this.layers.getLayer("org/springframework/boot/loader/Utils.class"))
.isEqualTo(StandardLayers.SPRING_BOOT_LOADER);
}
@Test
void getLayerWhenLibraryIsSnapshotReturnsSnapshotLayer() {
assertThat(this.layers.getLayer(mockLibrary("spring-boot.2.0.0.BUILD-SNAPSHOT.jar")))