diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java index 654caf45ae6b..44e132bf9b11 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootZipCopyAction.java @@ -22,7 +22,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.GregorianCalendar; @@ -59,6 +58,7 @@ import org.springframework.boot.loader.tools.Layer; import org.springframework.boot.loader.tools.LayersIndex; import org.springframework.boot.loader.tools.LibraryCoordinates; +import org.springframework.boot.loader.tools.NativeImageUtils; import org.springframework.util.Assert; import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; @@ -369,15 +369,8 @@ private void writeNativeImageArgFileIfNecessary() throws IOException { } } } - if (excludes != null) { - List args = new ArrayList<>(); - for (String exclude : excludes) { - int lastSlash = exclude.lastIndexOf('/'); - String jar = (lastSlash != -1) ? exclude.substring(lastSlash + 1) : exclude; - args.add("--exclude-config"); - args.add(Pattern.quote(jar)); - args.add("^/META-INF/native-image/.*"); - } + List args = NativeImageUtils.createExcludeConfigArguments(excludes); + if (!args.isEmpty()) { ZipEntryContentWriter writer = ZipEntryContentWriter.fromLines(BootZipCopyAction.this.encoding, args); writeEntry("META-INF/native-image/argfile", writer, true); } 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 a14dd7889354..67bba89e9085 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 @@ -201,6 +201,13 @@ void nativeImageArgFileWithExcludesIsWritten() throws IOException { } } + @Test + void nativeImageArgFileIsNotWrittenWhenExcludesAreEmpty() throws IOException { + try (JarFile jarFile = new JarFile(createLayeredJar(false))) { + assertThat(jarFile.getEntry("META-INF/native-image/argfile")).isNull(); + } + } + @Test void javaVersionIsWrittenToManifest() throws IOException { try (JarFile jarFile = new JarFile(createPopulatedJar())) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/NativeImageUtils.java b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/NativeImageUtils.java new file mode 100644 index 000000000000..712ffb2620d7 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/NativeImageUtils.java @@ -0,0 +1,52 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.loader.tools; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +/** + * Utilities for working with GraalVM native images. + * + * @author Moritz Halbritter + * @since 3.0.0 + */ +public final class NativeImageUtils { + + private NativeImageUtils() { + } + + /** + * Creates the arguments passed to native-image for the exclusion of reachability + * metadata. + * @param excludes dependencies for which the reachability metadata should be excluded + * @return arguments for native-image + */ + public static List createExcludeConfigArguments(Iterable excludes) { + List args = new ArrayList<>(); + for (String exclude : excludes) { + int lastSlash = exclude.lastIndexOf('/'); + String jar = (lastSlash != -1) ? exclude.substring(lastSlash + 1) : exclude; + args.add("--exclude-config"); + args.add(Pattern.quote(jar)); + args.add("^/META-INF/native-image/.*"); + } + return args; + } + +} 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 3304565f3e1f..b5f948c07ac9 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 @@ -37,8 +37,6 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; -import java.util.regex.Pattern; -import java.util.stream.Collectors; import java.util.zip.ZipEntry; import org.apache.commons.compress.archivers.jar.JarArchiveEntry; @@ -241,16 +239,9 @@ private void writeNativeImageArgFile(AbstractJarWriter writer, JarFile sourceJar } } } - if (!excludes.isEmpty()) { - List args = new ArrayList<>(); - for (String exclude : excludes) { - int lastSlash = exclude.lastIndexOf('/'); - String jar = (lastSlash != -1) ? exclude.substring(lastSlash + 1) : exclude; - args.add("--exclude-config"); - args.add(Pattern.quote(jar)); - args.add("^/META-INF/native-image/.*"); - } - String contents = args.stream().collect(Collectors.joining("\n")) + "\n"; + List args = NativeImageUtils.createExcludeConfigArguments(excludes); + if (!args.isEmpty()) { + String contents = String.join("\n", args) + "\n"; writer.writeEntry("META-INF/native-image/argfile", new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8))); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/NativeImageUtilsTests.java b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/NativeImageUtilsTests.java new file mode 100644 index 000000000000..2fcc846c9b27 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/NativeImageUtilsTests.java @@ -0,0 +1,41 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.loader.tools; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for @{link NativeImageUtils}. + * + * @author Moritz Halbritter + */ +class NativeImageUtilsTests { + + @Test + void shouldCreateExcludeConfigArguments() { + List arguments = NativeImageUtils + .createExcludeConfigArguments(List.of("path/to/dependency-1.jar", "dependency-2.jar")); + assertThat(arguments).containsExactly("--exclude-config", "\\Qdependency-1.jar\\E", + "^/META-INF/native-image/.*", "--exclude-config", "\\Qdependency-2.jar\\E", + "^/META-INF/native-image/.*"); + } + +}