From 7b5f46d6e31bc6b6df35e3374b2f469e4c6e5a57 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 2 Apr 2019 10:11:31 +0100 Subject: [PATCH] Add Spring-Boot-* manifest attributes to jars and wars built with Gradle Closes gh-16068 --- .../tasks/bundling/BootArchiveSupport.java | 14 ++++++- .../boot/gradle/tasks/bundling/BootJar.java | 5 ++- .../boot/gradle/tasks/bundling/BootWar.java | 5 ++- .../bundling/AbstractBootArchiveTests.java | 41 +++++++++++-------- .../gradle/tasks/bundling/BootJarTests.java | 4 +- .../gradle/tasks/bundling/BootWarTests.java | 6 +-- 6 files changed, 47 insertions(+), 28 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java index 8b240dc6cc..c7fd16ed86 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootArchiveSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,10 +73,20 @@ class BootArchiveSupport { configureExclusions(); } - void configureManifest(Jar jar, String mainClassName) { + void configureManifest(Jar jar, String mainClassName, String springBootClasses, + String springBootLib) { Attributes attributes = jar.getManifest().getAttributes(); attributes.putIfAbsent("Main-Class", this.loaderMainClass); attributes.putIfAbsent("Start-Class", mainClassName); + attributes.computeIfAbsent("Spring-Boot-Version", + (key) -> determineSpringBootVersion()); + attributes.putIfAbsent("Spring-Boot-Classes", springBootClasses); + attributes.putIfAbsent("Spring-Boot-Lib", springBootLib); + } + + private String determineSpringBootVersion() { + String implementationVersion = getClass().getPackage().getImplementationVersion(); + return (implementationVersion != null) ? implementationVersion : "unknown"; } CopyAction createCopyAction(Jar jar) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java index 17516b8bad..3e353e9c96 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,7 +65,8 @@ public class BootJar extends Jar implements BootArchive { @Override public void copy() { - this.support.configureManifest(this, getMainClassName()); + this.support.configureManifest(this, getMainClassName(), "BOOT-INF/classes/", + "BOOT-INF/lib/"); super.copy(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java index 307f5d3cb5..26e786288c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootWar.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,7 +57,8 @@ public class BootWar extends War implements BootArchive { @Override public void copy() { - this.support.configureManifest(this, getMainClassName()); + this.support.configureManifest(this, getMainClassName(), "WEB-INF/classes/", + "WEB-INF/lib/"); super.copy(); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java index f4b1f28241..0725e306f5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -97,6 +97,13 @@ public abstract class AbstractBootArchiveTests { .isEqualTo(this.launcherClass); assertThat(jarFile.getManifest().getMainAttributes().getValue("Start-Class")) .isEqualTo("com.example.Main"); + assertThat(jarFile.getManifest().getMainAttributes() + .getValue("Spring-Boot-Classes")).isEqualTo(this.classesPath); + assertThat( + jarFile.getManifest().getMainAttributes().getValue("Spring-Boot-Lib")) + .isEqualTo(this.libPath); + assertThat(jarFile.getManifest().getMainAttributes() + .getValue("Spring-Boot-Version")).isNotNull(); } } @@ -106,8 +113,8 @@ public abstract class AbstractBootArchiveTests { this.task.classpath(this.temp.newFile("one.jar"), this.temp.newFile("two.jar")); this.task.execute(); try (JarFile jarFile = new JarFile(this.task.getArchivePath())) { - assertThat(jarFile.getEntry(this.libPath + "/one.jar")).isNotNull(); - assertThat(jarFile.getEntry(this.libPath + "/two.jar")).isNotNull(); + assertThat(jarFile.getEntry(this.libPath + "one.jar")).isNotNull(); + assertThat(jarFile.getEntry(this.libPath + "two.jar")).isNotNull(); } } @@ -123,7 +130,7 @@ public abstract class AbstractBootArchiveTests { this.task.execute(); try (JarFile jarFile = new JarFile(this.task.getArchivePath())) { assertThat( - jarFile.getEntry(this.classesPath + "/com/example/Application.class")) + jarFile.getEntry(this.classesPath + "com/example/Application.class")) .isNotNull(); } } @@ -136,8 +143,8 @@ public abstract class AbstractBootArchiveTests { .setClasspath(this.task.getProject().files(this.temp.newFile("two.jar"))); this.task.execute(); try (JarFile jarFile = new JarFile(this.task.getArchivePath())) { - assertThat(jarFile.getEntry(this.libPath + "/one.jar")).isNull(); - assertThat(jarFile.getEntry(this.libPath + "/two.jar")).isNotNull(); + assertThat(jarFile.getEntry(this.libPath + "one.jar")).isNull(); + assertThat(jarFile.getEntry(this.libPath + "two.jar")).isNotNull(); } } @@ -148,8 +155,8 @@ public abstract class AbstractBootArchiveTests { this.task.setClasspath(this.temp.newFile("two.jar")); this.task.execute(); try (JarFile jarFile = new JarFile(this.task.getArchivePath())) { - assertThat(jarFile.getEntry(this.libPath + "/one.jar")).isNull(); - assertThat(jarFile.getEntry(this.libPath + "/two.jar")).isNotNull(); + assertThat(jarFile.getEntry(this.libPath + "one.jar")).isNull(); + assertThat(jarFile.getEntry(this.libPath + "two.jar")).isNotNull(); } } @@ -187,9 +194,9 @@ public abstract class AbstractBootArchiveTests { this.task.requiresUnpack("**/one.jar"); this.task.execute(); try (JarFile jarFile = new JarFile(this.task.getArchivePath())) { - assertThat(jarFile.getEntry(this.libPath + "/one.jar").getComment()) + assertThat(jarFile.getEntry(this.libPath + "one.jar").getComment()) .startsWith("UNPACK:"); - assertThat(jarFile.getEntry(this.libPath + "/two.jar").getComment()).isNull(); + assertThat(jarFile.getEntry(this.libPath + "two.jar").getComment()).isNull(); } } @@ -200,9 +207,9 @@ public abstract class AbstractBootArchiveTests { this.task.requiresUnpack((element) -> element.getName().endsWith("two.jar")); this.task.execute(); try (JarFile jarFile = new JarFile(this.task.getArchivePath())) { - assertThat(jarFile.getEntry(this.libPath + "/two.jar").getComment()) + assertThat(jarFile.getEntry(this.libPath + "two.jar").getComment()) .startsWith("UNPACK:"); - assertThat(jarFile.getEntry(this.libPath + "/one.jar").getComment()).isNull(); + assertThat(jarFile.getEntry(this.libPath + "one.jar").getComment()).isNull(); } } @@ -322,7 +329,7 @@ public abstract class AbstractBootArchiveTests { this.task.execute(); assertThat(this.task.getArchivePath()).exists(); try (JarFile jarFile = new JarFile(this.task.getArchivePath())) { - assertThat(jarFile.getEntry(this.libPath + "/spring-boot-devtools-0.1.2.jar")) + assertThat(jarFile.getEntry(this.libPath + "spring-boot-devtools-0.1.2.jar")) .isNull(); } } @@ -335,7 +342,7 @@ public abstract class AbstractBootArchiveTests { this.task.execute(); assertThat(this.task.getArchivePath()).exists(); try (JarFile jarFile = new JarFile(this.task.getArchivePath())) { - assertThat(jarFile.getEntry(this.libPath + "/spring-boot-devtools-0.1.2.jar")) + assertThat(jarFile.getEntry(this.libPath + "spring-boot-devtools-0.1.2.jar")) .isNotNull(); } } @@ -377,9 +384,9 @@ public abstract class AbstractBootArchiveTests { this.task.execute(); assertThat(getEntryNames(this.task.getArchivePath())).containsSubsequence( "org/springframework/boot/loader/", - this.classesPath + "/com/example/Application.class", - this.libPath + "/first-library.jar", this.libPath + "/second-library.jar", - this.libPath + "/third-library.jar"); + this.classesPath + "com/example/Application.class", + this.libPath + "first-library.jar", this.libPath + "second-library.jar", + this.libPath + "third-library.jar"); } private T configure(T task) throws IOException { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java index 3dcb0422b0..af641c3bd8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ public class BootJarTests extends AbstractBootArchiveTests { public BootJarTests() { super(BootJar.class, "org.springframework.boot.loader.JarLauncher", - "BOOT-INF/lib", "BOOT-INF/classes"); + "BOOT-INF/lib/", "BOOT-INF/classes/"); } @Test diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootWarTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootWarTests.java index f1f8c270be..df24117e08 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootWarTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootWarTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2018 the original author or authors. + * Copyright 2012-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,8 +32,8 @@ import static org.assertj.core.api.Assertions.assertThat; public class BootWarTests extends AbstractBootArchiveTests { public BootWarTests() { - super(BootWar.class, "org.springframework.boot.loader.WarLauncher", "WEB-INF/lib", - "WEB-INF/classes"); + super(BootWar.class, "org.springframework.boot.loader.WarLauncher", + "WEB-INF/lib/", "WEB-INF/classes/"); } @Test