1616
1717package org .springframework .boot .gradle .tasks .bundling ;
1818
19+ import java .io .BufferedReader ;
1920import java .io .File ;
2021import java .io .IOException ;
21- import java .io .InputStream ;
22+ import java .io .InputStreamReader ;
2223import java .util .List ;
2324import java .util .jar .JarFile ;
25+ import java .util .stream .Collectors ;
2426
2527import org .junit .jupiter .api .Test ;
2628
@@ -61,10 +63,79 @@ void contentCanBeAddedToBootInfUsingCopySpecAction() throws IOException {
6163 }
6264
6365 @ Test
64- void layers () throws IOException {
66+ void whenJarIsLayeredThenBootInfContainsOnlyLayersAndIndexFiles () throws IOException {
67+ List <String > entryNames = getEntryNames (createLayeredJar ());
68+ assertThat (entryNames .stream ().filter ((name ) -> name .startsWith ("BOOT-INF/" ))
69+ .filter ((name ) -> !name .startsWith ("BOOT-INF/layers/" ))).contains ("BOOT-INF/layers.idx" ,
70+ "BOOT-INF/classpath.idx" );
71+ }
72+
73+ @ Test
74+ void whenJarIsLayeredThenManifestContainsEntryForLayersIndexInPlaceOfClassesAndLib () throws IOException {
75+ try (JarFile jarFile = new JarFile (createLayeredJar ())) {
76+ assertThat (jarFile .getManifest ().getMainAttributes ().getValue ("Spring-Boot-Classes" )).isEqualTo (null );
77+ assertThat (jarFile .getManifest ().getMainAttributes ().getValue ("Spring-Boot-Lib" )).isEqualTo (null );
78+ assertThat (jarFile .getManifest ().getMainAttributes ().getValue ("Spring-Boot-Layers-Index" ))
79+ .isEqualTo ("BOOT-INF/layers.idx" );
80+ }
81+ }
82+
83+ @ Test
84+ void whenJarIsLayeredThenLayersIndexIsPresentAndListsLayersInOrder () throws IOException {
85+ try (JarFile jarFile = new JarFile (createLayeredJar ())) {
86+ assertThat (entryLines (jarFile , "BOOT-INF/layers.idx" )).containsExactly ("dependencies" ,
87+ "snapshot-dependencies" , "resources" , "application" );
88+ }
89+ }
90+
91+ @ Test
92+ void whenJarIsLayeredThenContentsAreMovedToLayerDirectories () throws IOException {
93+ List <String > entryNames = getEntryNames (createLayeredJar ());
94+ assertThat (entryNames )
95+ .containsSubsequence ("BOOT-INF/layers/dependencies/lib/first-library.jar" ,
96+ "BOOT-INF/layers/dependencies/lib/second-library.jar" )
97+ .contains ("BOOT-INF/layers/snapshot-dependencies/lib/third-library-SNAPSHOT.jar" )
98+ .containsSubsequence ("BOOT-INF/layers/application/classes/com/example/Application.class" ,
99+ "BOOT-INF/layers/application/classes/application.properties" )
100+ .contains ("BOOT-INF/layers/resources/classes/static/test.css" );
101+ }
102+
103+ @ Test
104+ void whenJarIsLayeredClasspathIndexPointsToLayeredLibs () throws IOException {
105+ try (JarFile jarFile = new JarFile (createLayeredJar ())) {
106+ assertThat (entryLines (jarFile , "BOOT-INF/classpath.idx" )).containsExactly (
107+ "BOOT-INF/layers/dependencies/lib/first-library.jar" ,
108+ "BOOT-INF/layers/dependencies/lib/second-library.jar" ,
109+ "BOOT-INF/layers/snapshot-dependencies/lib/third-library-SNAPSHOT.jar" );
110+ }
111+ }
112+
113+ @ Test
114+ void classpathIndexPointsToBootInfLibs () throws IOException {
115+ try (JarFile jarFile = new JarFile (createPopulatedJar ())) {
116+ assertThat (jarFile .getManifest ().getMainAttributes ().getValue ("Spring-Boot-Classpath-Index" ))
117+ .isEqualTo ("BOOT-INF/classpath.idx" );
118+ assertThat (entryLines (jarFile , "BOOT-INF/classpath.idx" )).containsExactly ("BOOT-INF/lib/first-library.jar" ,
119+ "BOOT-INF/lib/second-library.jar" , "BOOT-INF/lib/third-library-SNAPSHOT.jar" );
120+ }
121+ }
122+
123+ private File createPopulatedJar () throws IOException {
124+ addContent ();
125+ executeTask ();
126+ return getTask ().getArchiveFile ().get ().getAsFile ();
127+ }
128+
129+ private File createLayeredJar () throws IOException {
130+ addContent ();
131+ getTask ().layered ();
132+ executeTask ();
133+ return getTask ().getArchiveFile ().get ().getAsFile ();
134+ }
135+
136+ private void addContent () throws IOException {
65137 BootJar bootJar = getTask ();
66138 bootJar .setMainClassName ("com.example.Main" );
67- bootJar .layered ();
68139 File classesJavaMain = new File (this .temp , "classes/java/main" );
69140 File applicationClass = new File (classesJavaMain , "com/example/Application.class" );
70141 applicationClass .getParentFile ().mkdirs ();
@@ -79,54 +150,12 @@ void layers() throws IOException {
79150 css .createNewFile ();
80151 bootJar .classpath (classesJavaMain , resourcesMain , jarFile ("first-library.jar" ), jarFile ("second-library.jar" ),
81152 jarFile ("third-library-SNAPSHOT.jar" ));
82- bootJar .requiresUnpack ("second-library.jar" );
83- executeTask ();
84- List <String > entryNames = getEntryNames (bootJar .getArchiveFile ().get ().getAsFile ());
85- assertThat (entryNames ).containsSubsequence ("org/springframework/boot/loader/" ,
86- "BOOT-INF/layers/application/classes/com/example/Application.class" ,
87- "BOOT-INF/layers/resources/classes/static/test.css" ,
88- "BOOT-INF/layers/application/classes/application.properties" ,
89- "BOOT-INF/layers/dependencies/lib/first-library.jar" ,
90- "BOOT-INF/layers/dependencies/lib/second-library.jar" ,
91- "BOOT-INF/layers/snapshot-dependencies/lib/third-library-SNAPSHOT.jar" );
92- assertThat (entryNames ).doesNotContain ("BOOT-INF/classes" ).doesNotContain ("BOOT-INF/lib" )
93- .doesNotContain ("BOOT-INF/com/" );
94- try (JarFile jarFile = new JarFile (bootJar .getArchiveFile ().get ().getAsFile ())) {
95- assertThat (jarFile .getManifest ().getMainAttributes ().getValue ("Spring-Boot-Classes" )).isEqualTo (null );
96- assertThat (jarFile .getManifest ().getMainAttributes ().getValue ("Spring-Boot-Lib" )).isEqualTo (null );
97- assertThat (jarFile .getManifest ().getMainAttributes ().getValue ("Spring-Boot-Layers-Index" ))
98- .isEqualTo ("BOOT-INF/layers.idx" );
99- assertThat (jarFile .getManifest ().getMainAttributes ().getValue ("Spring-Boot-Classpath-Index" ))
100- .isEqualTo ("BOOT-INF/classpath.idx" );
101- try (InputStream input = jarFile .getInputStream (jarFile .getEntry ("BOOT-INF/layers.idx" ))) {
102- assertThat (input ).hasContent ("dependencies\n snapshot-dependencies\n resources\n application\n " );
103- }
104- try (InputStream input = jarFile .getInputStream (jarFile .getEntry ("BOOT-INF/classpath.idx" ))) {
105- assertThat (input ).hasContent (
106- "BOOT-INF/layers/dependencies/lib/first-library.jar\n BOOT-INF/layers/dependencies/lib/second-library.jar\n BOOT-INF/layers/snapshot-dependencies/lib/third-library-SNAPSHOT.jar\n " );
107- }
108- }
109153 }
110154
111- @ Test
112- void classpathIndex () throws IOException {
113- BootJar bootJar = getTask ();
114- bootJar .setMainClassName ("com.example.Main" );
115- File classesJavaMain = new File (this .temp , "classes/java/main" );
116- File applicationClass = new File (classesJavaMain , "com/example/Application.class" );
117- applicationClass .getParentFile ().mkdirs ();
118- applicationClass .createNewFile ();
119- bootJar .classpath (classesJavaMain , jarFile ("first-library.jar" ), jarFile ("second-library.jar" ),
120- jarFile ("third-library-SNAPSHOT.jar" ));
121- bootJar .requiresUnpack ("second-library.jar" );
122- executeTask ();
123- try (JarFile jarFile = new JarFile (bootJar .getArchiveFile ().get ().getAsFile ())) {
124- assertThat (jarFile .getManifest ().getMainAttributes ().getValue ("Spring-Boot-Classpath-Index" ))
125- .isEqualTo ("BOOT-INF/classpath.idx" );
126- try (InputStream input = jarFile .getInputStream (jarFile .getEntry ("BOOT-INF/classpath.idx" ))) {
127- assertThat (input ).hasContent (
128- "BOOT-INF/lib/first-library.jar\n BOOT-INF/lib/second-library.jar\n BOOT-INF/lib/third-library-SNAPSHOT.jar\n " );
129- }
155+ private List <String > entryLines (JarFile jarFile , String entryName ) throws IOException {
156+ try (BufferedReader reader = new BufferedReader (
157+ new InputStreamReader (jarFile .getInputStream (jarFile .getEntry (entryName ))))) {
158+ return reader .lines ().collect (Collectors .toList ());
130159 }
131160 }
132161
0 commit comments