From 8f116f7e6fe789f4192de292984e926ecbea2a3d Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 31 Jan 2018 14:21:58 +0000 Subject: [PATCH] Align ordering of BootJar and BootWar archive entries Previously, the ordering of the entries in an archive produced by BootJar was different to the ordering of the entries in an archive produced by BootWar. The latter placed application classes before any nested jars, whereas the former was the other way around. This commit updates BootJar to use the same ordering as BootWar and adds tests to verify that the ordering is the following: 1. Loader classes 2. Application classes (BOOT-INF/classes or WEB-INF/classes) 3. Nested jars (BOOT-INF/lib or WEB-INF/lib) 4. Provided nested jars in a war (WEB-INF/lib-provided) The tests also verify that the position of a library is not affected by it requiring unpacking. See gh-11695 See gh-11696 --- .../boot/gradle/tasks/bundling/BootJar.java | 4 +-- .../bundling/AbstractBootArchiveTests.java | 34 ++++++++++++++++++- .../gradle/tasks/bundling/BootWarTests.java | 10 ++++++ 3 files changed, 45 insertions(+), 3 deletions(-) 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 7cc5e93c1a..83b7a03e3e 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-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -50,8 +50,8 @@ public class BootJar extends Jar implements BootArchive { public BootJar() { CopySpec bootInf = getRootSpec().addChildBeforeSpec(getMainSpec()) .into("BOOT-INF"); - bootInf.into("lib", classpathFiles(File::isFile)); bootInf.into("classes", classpathFiles(File::isDirectory)); + bootInf.into("lib", classpathFiles(File::isFile)); } private Action classpathFiles(Spec filter) { 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 049bb0302d..6c75c3a118 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-2017 the original author or authors. + * Copyright 2012-2018 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. @@ -336,6 +336,27 @@ public abstract class AbstractBootArchiveTests { } } + @Test + public void loaderIsWrittenFirstThenApplicationClassesThenLibraries() + throws IOException { + this.task.setMainClassName("com.example.Main"); + File classpathFolder = this.temp.newFolder(); + File applicationClass = new File(classpathFolder, + "com/example/Application.class"); + applicationClass.getParentFile().mkdirs(); + applicationClass.createNewFile(); + this.task.classpath(classpathFolder, this.temp.newFile("first-library.jar"), + this.temp.newFile("second-library.jar"), + this.temp.newFile("third-library.jar")); + this.task.requiresUnpack("second-library.jar"); + 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"); + } + private T configure(T task) throws IOException { AbstractArchiveTask archiveTask = task; archiveTask.setBaseName("test"); @@ -347,4 +368,15 @@ public abstract class AbstractBootArchiveTests { return this.task; } + protected List getEntryNames(File file) throws IOException { + List entryNames = new ArrayList<>(); + try (JarFile jarFile = new JarFile(file)) { + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + entryNames.add(entries.nextElement().getName()); + } + } + return entryNames; + } + } 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 7eb999e5c2..c40c095fc0 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 @@ -94,4 +94,14 @@ public class BootWarTests extends AbstractBootArchiveTests { } } + @Test + public void libProvidedEntriesAreWrittenAfterLibEntries() throws IOException { + getTask().setMainClassName("com.example.Main"); + getTask().classpath(this.temp.newFile("library.jar")); + getTask().providedClasspath(this.temp.newFile("provided-library.jar")); + getTask().execute(); + assertThat(getEntryNames(getTask().getArchivePath())).containsSubsequence( + "WEB-INF/lib/library.jar", "WEB-INF/lib-provided/provided-library.jar"); + } + }