From 6f8d4778add0bbee14cd2bdad55a04f7cd8a4ddd Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 30 Jul 2014 11:07:41 +0100 Subject: [PATCH] Prevent a jar from being repackaged more than once Previously, Repackager would repackage a jar file as many times as it was asked to do so. This lead to problems if a user made a mistake when using Maven that led to the package phase being driven twice, for example by running "mvn clean install package". This commit updates Repackager so that a repackage call becomes a no-op if the source jar's manifest already contains the Spring-Boot-Version attribute which is added by repackaging. Fixes #1251 --- .../boot/loader/tools/Repackager.java | 20 ++++++++++++++++++- .../boot/loader/tools/RepackagerTests.java | 16 +++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java index eac5ff7fa16..5dba4c28396 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java @@ -107,6 +107,11 @@ public class Repackager { if (libraries == null) { throw new IllegalArgumentException("Libraries must not be null"); } + + if (alreadyRepackaged()) { + return; + } + destination = destination.getAbsoluteFile(); File workingSource = this.source; if (this.source.equals(destination)) { @@ -132,6 +137,19 @@ public class Repackager { } } + private boolean alreadyRepackaged() throws IOException { + JarFile jarFile = new JarFile(this.source); + + try { + Manifest manifest = jarFile.getManifest(); + return manifest != null + && manifest.getMainAttributes().getValue(BOOT_VERSION_ATTRIBUTE) != null; + } + finally { + jarFile.close(); + } + } + private void repackage(JarFile sourceJar, File destination, Libraries libraries) throws IOException { final JarWriter writer = new JarWriter(destination); @@ -208,7 +226,7 @@ public class Repackager { String launcherClassName = this.layout.getLauncherClassName(); if (launcherClassName != null) { manifest.getMainAttributes() - .putValue(MAIN_CLASS_ATTRIBUTE, launcherClassName); + .putValue(MAIN_CLASS_ATTRIBUTE, launcherClassName); if (startClass == null) { throw new IllegalStateException("Unable to find main class"); } diff --git a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java index 483245436bb..7dc224ca3e7 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java @@ -134,6 +134,22 @@ public class RepackagerTests { assertThat(hasLauncherClasses(file), equalTo(true)); } + @Test + public void jarIsOnlyRepackagedOnce() throws Exception { + this.testJarFile.addClass("a/b/C.class", ClassWithMainMethod.class); + File file = this.testJarFile.getFile(); + Repackager repackager = new Repackager(file); + repackager.repackage(NO_LIBRARIES); + repackager.repackage(NO_LIBRARIES); + + Manifest actualManifest = getManifest(file); + assertThat(actualManifest.getMainAttributes().getValue("Main-Class"), + equalTo("org.springframework.boot.loader.JarLauncher")); + assertThat(actualManifest.getMainAttributes().getValue("Start-Class"), + equalTo("a.b.C")); + assertThat(hasLauncherClasses(file), equalTo(true)); + } + @Test public void multipleMainClassFound() throws Exception { this.testJarFile.addClass("a/b/C.class", ClassWithMainMethod.class);