Support flat jar layering with layertools

Update layertools to support the flat jar format. Layers are now
determined by reading the `layers.idx` file.

Closes gh-20813
This commit is contained in:
Madhura Bhave
2020-04-01 16:47:18 -07:00
committed by Phillip Webb
parent bfa04e6574
commit d61a79d90b
7 changed files with 58 additions and 64 deletions

View File

@@ -77,10 +77,10 @@ class HelpCommandTests {
JarEntry indexEntry = new JarEntry("BOOT-INF/layers.idx");
jarOutputStream.putNextEntry(indexEntry);
Writer writer = new OutputStreamWriter(jarOutputStream, StandardCharsets.UTF_8);
writer.write("a\n");
writer.write("b\n");
writer.write("c\n");
writer.write("d\n");
writer.write("0001 BOOT-INF/lib/a.jar\n");
writer.write("0001 BOOT-INF/lib/b.jar\n");
writer.write("0002 BOOT-INF/lib/c.jar\n");
writer.write("0003 BOOT-INF/lib/d.jar\n");
writer.flush();
}
return file;

View File

@@ -16,10 +16,14 @@
package org.springframework.boot.jarmode.layertools;
import java.io.InputStreamReader;
import java.util.zip.ZipEntry;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.BDDMockito.given;
@@ -29,6 +33,7 @@ import static org.mockito.Mockito.mock;
* Tests for {@link IndexedLayers}.
*
* @author Phillip Webb
* @author Madhura Bhave
*/
class IndexedLayersTests {
@@ -39,41 +44,35 @@ class IndexedLayersTests {
}
@Test
void createWhenIndexFileHasNoApplicationLayerAddSpringBootApplication() {
IndexedLayers layers = new IndexedLayers("test");
assertThat(layers).contains("springbootapplication");
void createWhenIndexFileIsMalformedThrowsException() throws Exception {
assertThatIllegalStateException().isThrownBy(() -> new IndexedLayers("test"))
.withMessage("Layer index file is malformed");
}
@Test
void iteratorReturnsLayers() {
IndexedLayers layers = new IndexedLayers("test\napplication");
void iteratorReturnsLayers() throws Exception {
IndexedLayers layers = new IndexedLayers(getIndex());
assertThat(layers).containsExactly("test", "application");
}
@Test
void getLayerWhenMatchesLayerPatterReturnsLayer() {
IndexedLayers layers = new IndexedLayers("test");
assertThat(layers.getLayer(mockEntry("BOOT-INF/layers/test/lib/file.jar"))).isEqualTo("test");
void getLayerWhenMatchesNameReturnsLayer() throws Exception {
IndexedLayers layers = new IndexedLayers(getIndex());
assertThat(layers.getLayer(mockEntry("BOOT-INF/lib/a.jar"))).isEqualTo("test");
assertThat(layers.getLayer(mockEntry("BOOT-INF/classes/Demo.class"))).isEqualTo("application");
}
@Test
void getLayerWhenMatchesLayerPatterForMissingLayerThrowsException() {
IndexedLayers layers = new IndexedLayers("test");
assertThatIllegalStateException()
.isThrownBy(() -> layers.getLayer(mockEntry("BOOT-INF/layers/missing/lib/file.jar")))
.withMessage("Unexpected layer 'missing'");
void getLayerWhenMatchesNameForMissingLayerThrowsException() throws Exception {
IndexedLayers layers = new IndexedLayers(getIndex());
assertThatIllegalStateException().isThrownBy(() -> layers.getLayer(mockEntry("file.jar")))
.withMessage("No layer defined in index for file " + "'file.jar'");
}
@Test
void getLayerWhenDoesNotMatchLayerPatternReturnsApplication() {
IndexedLayers layers = new IndexedLayers("test\napplication");
assertThat(layers.getLayer(mockEntry("META-INF/MANIFEST.MF"))).isEqualTo("application");
}
@Test
void getLayerWhenDoesNotMatchLayerPatternAndHasNoApplicationLayerReturnsSpringApplication() {
IndexedLayers layers = new IndexedLayers("test");
assertThat(layers.getLayer(mockEntry("META-INF/MANIFEST.MF"))).isEqualTo("springbootapplication");
private String getIndex() throws Exception {
ClassPathResource resource = new ClassPathResource("test-layers.idx", getClass());
InputStreamReader reader = new InputStreamReader(resource.getInputStream());
return FileCopyUtils.copyToString(reader);
}
private ZipEntry mockEntry(String name) {

View File

@@ -85,10 +85,10 @@ class LayerToolsJarModeTests {
JarEntry indexEntry = new JarEntry("BOOT-INF/layers.idx");
jarOutputStream.putNextEntry(indexEntry);
Writer writer = new OutputStreamWriter(jarOutputStream, StandardCharsets.UTF_8);
writer.write("a\n");
writer.write("b\n");
writer.write("c\n");
writer.write("d\n");
writer.write("0001 BOOT-INF/lib/a.jar\n");
writer.write("0001 BOOT-INF/lib/b.jar\n");
writer.write("0002 BOOT-INF/lib/c.jar\n");
writer.write("0003 BOOT-INF/lib/d.jar\n");
writer.flush();
}
return file;

View File

@@ -39,6 +39,7 @@ import static org.mockito.BDDMockito.given;
* Tests for {@link ListCommand}.
*
* @author Phillip Webb
* @author Madhura Bhave
*/
class ListCommandTests {
@@ -74,7 +75,7 @@ class ListCommandTests {
File file = new File(this.temp, name);
try (ZipOutputStream jarOutputStream = new ZipOutputStream(new FileOutputStream(file))) {
writeLayersIndex(jarOutputStream);
String entryPrefix = "BOOT-INF/layers/";
String entryPrefix = "BOOT-INF/lib/";
jarOutputStream.putNextEntry(new ZipEntry(entryPrefix + "a/"));
jarOutputStream.closeEntry();
jarOutputStream.putNextEntry(new ZipEntry(entryPrefix + "a/a.jar"));
@@ -97,10 +98,10 @@ class ListCommandTests {
JarEntry indexEntry = new JarEntry("BOOT-INF/layers.idx");
out.putNextEntry(indexEntry);
Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8);
writer.write("a\n");
writer.write("b\n");
writer.write("c\n");
writer.write("d\n");
writer.write("0001 BOOT-INF/lib/a.jar\n");
writer.write("0001 BOOT-INF/lib/b.jar\n");
writer.write("0002 BOOT-INF/lib/c.jar\n");
writer.write("0003 BOOT-INF/lib/d.jar\n");
writer.flush();
}

View File

@@ -0,0 +1,3 @@
test BOOT-INF/lib/a.jar
test BOOT-INF/lib/b.jar
application BOOT-INF/classes/Demo.class