From 193ef9a06dd4c32dbb921c2c69c724efb472975e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 25 Apr 2022 14:32:47 +0100 Subject: [PATCH] Package META-INF/services/ files beneath BOOT-INF/classes/ Closes gh-30413 --- .../boot/gradle/tasks/bundling/BootJar.java | 3 ++- .../gradle/tasks/bundling/BootJarTests.java | 21 +++++++++++++++++++ .../boot/loader/tools/Packager.java | 5 +++-- .../loader/tools/AbstractPackagerTests.java | 14 ++++++++++++- 4 files changed, 39 insertions(+), 4 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 229ee3fb813d..20999abf73ec 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 @@ -110,7 +110,8 @@ private Iterable classpathEntries(Spec filter) { private void moveMetaInfToRoot(CopySpec spec) { spec.eachFile((file) -> { String path = file.getRelativeSourcePath().getPathString(); - if (path.startsWith("META-INF/") && !path.equals("META-INF/aop.xml") && !path.endsWith(".kotlin_module")) { + if (path.startsWith("META-INF/") && !path.equals("META-INF/aop.xml") && !path.endsWith(".kotlin_module") + && !path.startsWith("META-INF/services/")) { this.support.moveToRoot(file); } }); 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 8e3bf128b4a8..75e31b17f35a 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 @@ -163,6 +163,27 @@ void kotlinModuleIsPackagedBeneathClassesDirectory() throws IOException { } } + @Test + void metaInfServicesEntryIsPackagedBeneathClassesDirectory() throws IOException { + getTask().getMainClass().set("com.example.Main"); + File classpathDirectory = new File(this.temp, "classes"); + File service = new File(classpathDirectory, "META-INF/services/com.example.Service"); + service.getParentFile().mkdirs(); + service.createNewFile(); + File applicationClass = new File(classpathDirectory, "com/example/Application.class"); + applicationClass.getParentFile().mkdirs(); + applicationClass.createNewFile(); + getTask().classpath(classpathDirectory); + executeTask(); + try (JarFile jarFile = new JarFile(getTask().getArchiveFile().get().getAsFile())) { + assertThat(jarFile.getEntry("BOOT-INF/classes/com/example/Application.class")).isNotNull(); + assertThat(jarFile.getEntry("com/example/Application.class")).isNull(); + assertThat(jarFile.getEntry("BOOT-INF/classes/META-INF/services/com.example.Service")).isNotNull(); + assertThat(jarFile.getEntry("META-INF/services/com.example.Service")).isNull(); + } + + } + private File createPopulatedJar() throws IOException { addContent(); executeTask(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Packager.java b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Packager.java index 5a1f5b68aece..1ebe26cd8f03 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Packager.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Packager.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -446,7 +446,8 @@ private String transformName(String name) { private boolean isTransformable(JarArchiveEntry entry) { String name = entry.getName(); if (name.startsWith("META-INF/")) { - return name.equals("META-INF/aop.xml") || name.endsWith(".kotlin_module"); + return name.equals("META-INF/aop.xml") || name.endsWith(".kotlin_module") + || name.startsWith("META-INF/services/"); } return !name.startsWith("BOOT-INF/") && !name.equals("module-info.class"); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/AbstractPackagerTests.java b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/AbstractPackagerTests.java index 83389a6e18a0..09c4e16757c5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/AbstractPackagerTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/AbstractPackagerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -484,6 +484,18 @@ void metaInfAopXmlIsMovedBeneathBootInfClassesWhenRepackaged() throws Exception assertThat(getPackagedEntry("BOOT-INF/classes/META-INF/aop.xml")).isNotNull(); } + @Test + void metaInfServicesFilesAreMovedBeneathBootInfClassesWhenRepackaged() throws Exception { + this.testJarFile.addClass("A.class", ClassWithMainMethod.class); + File service = new File(this.tempDir, "com.example.Service"); + service.createNewFile(); + this.testJarFile.addFile("META-INF/services/com.example.Service", service); + P packager = createPackager(); + execute(packager, NO_LIBRARIES); + assertThat(getPackagedEntry("META-INF/services/com.example.Service")).isNull(); + assertThat(getPackagedEntry("BOOT-INF/classes/META-INF/services/com.example.Service")).isNotNull(); + } + @Test void allEntriesUseUnixPlatformAndUtf8NameEncoding() throws IOException { this.testJarFile.addClass("A.class", ClassWithMainMethod.class);