Skip to content

Commit 45f298b

Browse files
committed
Merge branch '2.4.x'
Closes gh-24711
2 parents 1d30a47 + 9e389c8 commit 45f298b

File tree

19 files changed

+230
-45
lines changed

19 files changed

+230
-45
lines changed

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -243,7 +243,7 @@ private void processFile(FileCopyDetails details) throws IOException {
243243
details.copyTo(this.out);
244244
this.out.closeArchiveEntry();
245245
if (BootZipCopyAction.this.librarySpec.isSatisfiedBy(details)) {
246-
this.writtenLibraries.add(name.substring(name.lastIndexOf('/') + 1));
246+
this.writtenLibraries.add(name);
247247
}
248248
if (BootZipCopyAction.this.layerResolver != null) {
249249
Layer layer = BootZipCopyAction.this.layerResolver.getLayer(details);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2012-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.bootjar.classpath;
18+
19+
import java.net.URL;
20+
import java.net.URLClassLoader;
21+
22+
/**
23+
* Application used for testing classpath handling with BootJar.
24+
*
25+
* @author Andy Wilkinson
26+
*/
27+
public class BootJarClasspathApplication {
28+
29+
protected BootJarClasspathApplication() {
30+
31+
}
32+
33+
public static void main(String[] args) {
34+
int i = 1;
35+
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
36+
for (URL url : ((URLClassLoader) classLoader).getURLs()) {
37+
System.out.println(i++ + ". " + url.getFile());
38+
}
39+
}
40+
41+
}

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/com/example/main/CustomMainClass.java renamed to spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/com/example/bootjar/main/CustomMainClass.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package com.example.main;
17+
package com.example.bootjar.main;
1818

1919
/**
2020
* Application used for testing {@code BootRun}'s main class configuration.

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/com/example/classpath/BootRunClasspathApplication.java renamed to spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/com/example/bootrun/classpath/BootRunClasspathApplication.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package com.example.classpath;
17+
package com.example.bootrun.classpath;
1818

1919
import java.io.File;
2020
import java.lang.management.ManagementFactory;

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/com/example/jvmargs/BootRunJvmArgsApplication.java renamed to spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/com/example/bootrun/jvmargs/BootRunJvmArgsApplication.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package com.example.jvmargs;
17+
package com.example.bootrun.jvmargs;
1818

1919
import java.lang.management.ManagementFactory;
2020

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.bootrun.main;
18+
19+
/**
20+
* Application used for testing {@code BootRun}'s main class configuration.
21+
*
22+
* @author Andy Wilkinson
23+
*/
24+
public class CustomMainClass {
25+
26+
protected CustomMainClass() {
27+
28+
}
29+
30+
public static void main(String[] args) {
31+
System.out.println(CustomMainClass.class.getName());
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.bootwar.main;
18+
19+
/**
20+
* Application used for testing {@code BootRun}'s main class configuration.
21+
*
22+
* @author Andy Wilkinson
23+
*/
24+
public class CustomMainClass {
25+
26+
protected CustomMainClass() {
27+
28+
}
29+
30+
public static void main(String[] args) {
31+
System.out.println(CustomMainClass.class.getName());
32+
}
33+
34+
}

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.File;
2020
import java.io.FileOutputStream;
2121
import java.io.IOException;
22+
import java.util.Locale;
2223
import java.util.function.Consumer;
2324
import java.util.jar.Attributes;
2425
import java.util.jar.JarEntry;
@@ -196,7 +197,8 @@ void startClassIsSetByResolvingTheMainClass() throws IOException {
196197
.isEqualTo(TaskOutcome.SUCCESS);
197198
try (JarFile jarFile = new JarFile(new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0])) {
198199
Attributes mainAttributes = jarFile.getManifest().getMainAttributes();
199-
assertThat(mainAttributes.getValue("Start-Class")).isEqualTo("com.example.main.CustomMainClass");
200+
assertThat(mainAttributes.getValue("Start-Class"))
201+
.isEqualTo("com.example." + this.taskName.toLowerCase(Locale.ENGLISH) + ".main.CustomMainClass");
200202
}
201203
assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName).getOutcome())
202204
.isEqualTo(TaskOutcome.UP_TO_DATE);
@@ -206,10 +208,13 @@ private void copyMainClassApplication() throws IOException {
206208
copyApplication("main");
207209
}
208210

209-
private void copyApplication(String name) throws IOException {
210-
File output = new File(this.gradleBuild.getProjectDir(), "src/main/java/com/example/" + name);
211+
protected void copyApplication(String name) throws IOException {
212+
File output = new File(this.gradleBuild.getProjectDir(),
213+
"src/main/java/com/example/" + this.taskName.toLowerCase() + "/" + name);
211214
output.mkdirs();
212-
FileSystemUtils.copyRecursively(new File("src/test/java/com/example/" + name), output);
215+
FileSystemUtils.copyRecursively(
216+
new File("src/test/java/com/example/" + this.taskName.toLowerCase(Locale.ENGLISH) + "/" + name),
217+
output);
213218
}
214219

215220
private void createStandardJar(File location) throws IOException {

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java

+28
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,30 @@ void whenAResolvableCopyOfAnUnresolvableConfigurationIsResolvedThenResolutionSuc
296296
.isEqualTo(TaskOutcome.SUCCESS);
297297
}
298298

299+
@TestTemplate
300+
void packagedApplicationClasspath() throws IOException {
301+
copyClasspathApplication();
302+
BuildResult result = this.gradleBuild.build("launch");
303+
String output = result.getOutput();
304+
assertThat(output).containsPattern("1\\. .*classes");
305+
assertThat(output).containsPattern("2\\. .*library-1.0-SNAPSHOT.jar");
306+
assertThat(output).containsPattern("3\\. .*commons-lang3-3.9.jar");
307+
assertThat(output).containsPattern("4\\. .*spring-boot-jarmode-layertools-.*.jar");
308+
assertThat(output).doesNotContain("5. ");
309+
}
310+
311+
@TestTemplate
312+
void explodedApplicationClasspath() throws IOException {
313+
copyClasspathApplication();
314+
BuildResult result = this.gradleBuild.build("launch");
315+
String output = result.getOutput();
316+
assertThat(output).containsPattern("1\\. .*classes");
317+
assertThat(output).containsPattern("2\\. .*spring-boot-jarmode-layertools-.*.jar");
318+
assertThat(output).containsPattern("3\\. .*library-1.0-SNAPSHOT.jar");
319+
assertThat(output).containsPattern("4\\. .*commons-lang3-3.9.jar");
320+
assertThat(output).doesNotContain("5. ");
321+
}
322+
299323
private void assertExtractedLayers(List<String> layerNames, Map<String, List<String>> indexedLayers)
300324
throws IOException {
301325
Map<String, List<String>> extractedLayers = readExtractedLayers(this.gradleBuild.getProjectDir(), layerNames);
@@ -395,4 +419,8 @@ private Map<String, List<String>> readExtractedLayers(File root, List<String> la
395419
return extractedLayers;
396420
}
397421

422+
private void copyClasspathApplication() throws IOException {
423+
copyApplication("classpath");
424+
}
425+
398426
}

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -230,9 +230,10 @@ void jarsInLibAreStored() throws IOException {
230230
@Test
231231
void whenJarIsLayeredClasspathIndexPointsToLayeredLibs() throws IOException {
232232
try (JarFile jarFile = new JarFile(createLayeredJar())) {
233-
assertThat(entryLines(jarFile, "BOOT-INF/classpath.idx")).containsExactly("- \"first-library.jar\"",
234-
"- \"second-library.jar\"", "- \"third-library-SNAPSHOT.jar\"", "- \"first-project-library.jar\"",
235-
"- \"second-project-library-SNAPSHOT.jar\"");
233+
assertThat(entryLines(jarFile, "BOOT-INF/classpath.idx")).containsExactly(
234+
"- \"BOOT-INF/lib/first-library.jar\"", "- \"BOOT-INF/lib/second-library.jar\"",
235+
"- \"BOOT-INF/lib/third-library-SNAPSHOT.jar\"", "- \"BOOT-INF/lib/first-project-library.jar\"",
236+
"- \"BOOT-INF/lib/second-project-library-SNAPSHOT.jar\"");
236237
}
237238
}
238239

@@ -254,9 +255,10 @@ void classpathIndexPointsToBootInfLibs() throws IOException {
254255
try (JarFile jarFile = new JarFile(createPopulatedJar())) {
255256
assertThat(jarFile.getManifest().getMainAttributes().getValue("Spring-Boot-Classpath-Index"))
256257
.isEqualTo("BOOT-INF/classpath.idx");
257-
assertThat(entryLines(jarFile, "BOOT-INF/classpath.idx")).containsExactly("- \"first-library.jar\"",
258-
"- \"second-library.jar\"", "- \"third-library-SNAPSHOT.jar\"", "- \"first-project-library.jar\"",
259-
"- \"second-project-library-SNAPSHOT.jar\"");
258+
assertThat(entryLines(jarFile, "BOOT-INF/classpath.idx")).containsExactly(
259+
"- \"BOOT-INF/lib/first-library.jar\"", "- \"BOOT-INF/lib/second-library.jar\"",
260+
"- \"BOOT-INF/lib/third-library-SNAPSHOT.jar\"", "- \"BOOT-INF/lib/first-project-library.jar\"",
261+
"- \"BOOT-INF/lib/second-project-library-SNAPSHOT.jar\"");
260262
}
261263
}
262264

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/run/BootRunIntegrationTests.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,24 @@ void springBootExtensionMainClassNameIsUsed() throws IOException {
7171
copyMainClassApplication();
7272
BuildResult result = this.gradleBuild.build("bootRun");
7373
assertThat(result.task(":bootRun").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
74-
assertThat(result.getOutput()).contains("com.example.main.CustomMainClass");
74+
assertThat(result.getOutput()).contains("com.example.bootrun.main.CustomMainClass");
7575
}
7676

7777
@TestTemplate
7878
void applicationPluginMainClassNameIsUsed() throws IOException {
7979
copyMainClassApplication();
8080
BuildResult result = this.gradleBuild.build("bootRun");
8181
assertThat(result.task(":bootRun").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
82-
assertThat(result.getOutput()).contains("com.example.main.CustomMainClass");
82+
assertThat(result.getOutput()).contains("com.example.bootrun.main.CustomMainClass");
8383
}
8484

8585
@TestTemplate
8686
void applicationPluginMainClassNameIsNotUsedWhenItIsNull() throws IOException {
8787
copyClasspathApplication();
8888
BuildResult result = this.gradleBuild.build("bootRun");
8989
assertThat(result.task(":bootRun").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
90-
assertThat(result.getOutput()).contains("Main class name = com.example.classpath.BootRunClasspathApplication");
90+
assertThat(result.getOutput())
91+
.contains("Main class name = com.example.bootrun.classpath.BootRunClasspathApplication");
9192
}
9293

9394
@TestTemplate
@@ -150,9 +151,9 @@ private void copyJvmArgsApplication() throws IOException {
150151
}
151152

152153
private void copyApplication(String name) throws IOException {
153-
File output = new File(this.gradleBuild.getProjectDir(), "src/main/java/com/example/" + name);
154+
File output = new File(this.gradleBuild.getProjectDir(), "src/main/java/com/example/bootrun/" + name);
154155
output.mkdirs();
155-
FileSystemUtils.copyRecursively(new File("src/test/java/com/example/" + name), output);
156+
FileSystemUtils.copyRecursively(new File("src/test/java/com/example/bootrun/" + name), output);
156157
}
157158

158159
private String canonicalPathOf(String path) throws IOException {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
plugins {
2+
id 'java'
3+
id 'org.springframework.boot' version '{version}'
4+
}
5+
6+
repositories {
7+
mavenCentral()
8+
maven { url "file:repository" }
9+
}
10+
11+
dependencies {
12+
implementation("com.example:library:1.0-SNAPSHOT")
13+
implementation("org.apache.commons:commons-lang3:3.9")
14+
}
15+
16+
task explode(type: Sync) {
17+
dependsOn(bootJar)
18+
destinationDir = file("$buildDir/exploded")
19+
from zipTree(files(bootJar).singleFile)
20+
}
21+
22+
task launch(type: JavaExec) {
23+
classpath = files(explode)
24+
main = 'org.springframework.boot.loader.JarLauncher'
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
plugins {
3+
id 'java'
4+
id 'org.springframework.boot' version '{version}'
5+
}
6+
7+
task launch(type: JavaExec) {
8+
classpath = files(bootJar)
9+
}
10+
11+
repositories {
12+
mavenCentral()
13+
maven { url "file:repository" }
14+
}
15+
16+
dependencies {
17+
implementation("com.example:library:1.0-SNAPSHOT")
18+
implementation("org.apache.commons:commons-lang3:3.9")
19+
}

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/run/BootRunIntegrationTests-applicationPluginMainClassNameIsUsed.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ plugins {
33
id 'org.springframework.boot' version '{version}'
44
}
55

6-
mainClassName = 'com.example.main.CustomMainClass'
6+
mainClassName = 'com.example.bootrun.main.CustomMainClass'

Diff for: spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/run/BootRunIntegrationTests-springBootExtensionMainClassNameIsUsed.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ plugins {
44
}
55

66
springBoot {
7-
mainClass = 'com.example.main.CustomMainClass'
7+
mainClass = 'com.example.bootrun.main.CustomMainClass'
88
}

Diff for: spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Packager.java

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -479,15 +479,11 @@ private void write(AbstractJarWriter writer) throws IOException {
479479
}
480480

481481
private void writeClasspathIndex(RepackagingLayout layout, AbstractJarWriter writer) throws IOException {
482-
List<String> names = this.libraries.keySet().stream().map(this::getJarName)
483-
.map((name) -> "- \"" + name + "\"").collect(Collectors.toList());
482+
List<String> names = this.libraries.keySet().stream().map((path) -> "- \"" + path + "\"")
483+
.collect(Collectors.toList());
484484
writer.writeIndexFile(layout.getClasspathIndexFileLocation(), names);
485485
}
486486

487-
private String getJarName(String path) {
488-
return path.substring(path.lastIndexOf('/') + 1);
489-
}
490-
491487
}
492488

493489
}

0 commit comments

Comments
 (0)